nodejs, jak czytać naciśnięcia klawiszy ze standardowego wejścia


118

Czy można nasłuchiwać nadchodzących naciśnięć klawiszy w działającym skrypcie nodejs? Jeśli używam process.openStdin()i słucham jego 'data'zdarzenia, dane wejściowe są buforowane do następnej nowej linii, na przykład:

// stdin_test.js
var stdin = process.openStdin();
stdin.on('data', function(chunk) { console.log("Got chunk: " + chunk); });

Uruchamiając to, otrzymuję:

$ node stdin_test.js
                <-- type '1'
                <-- type '2'
                <-- hit enter
Got chunk: 12

Chciałbym zobaczyć:

$ node stdin_test.js
                <-- type '1' (without hitting enter yet)
 Got chunk: 1

Szukam odpowiednika nodejs np. getcW rubinie

czy to możliwe?


(Dodanie tego komentarza, aby było łatwiej znaleźć to pytanie; znalezienie odpowiednich słów zajęło mi kilka dni): Oto jak czytać standardowe wejście znak po znaku przed wysłaniem znaku nowej linii (nowej linii) na wejściu.
— zawrotny

Odpowiedzi:


62

Możesz to osiągnąć w ten sposób, jeśli przełączysz się na tryb surowy:

var stdin = process.openStdin(); 
require('tty').setRawMode(true);    

stdin.on('keypress', function (chunk, key) {
  process.stdout.write('Get Chunk: ' + chunk + '\n');
  if (key && key.ctrl && key.name == 'c') process.exit();
});

6
Nie martw się, dowiedziałem się o sobieprocess.stdin.resume(); process.stdin.on('data', function (chunk) { process.stdout.write('data: ' + chunk); });
— JamesM-SiteGen,

3
Przesuń, setRawModeaby znajdował się poniżej openStdin(), ponieważ możesz ustawić tryb tylko wtedy, gdy stdinjest zainicjowany.
— Wieża

4
Wygląda na to, że stdin nie emituje już zdarzenia naciśnięcia klawisza, ale zamiast tego emituje zdarzenie danych z różnymi parametrami.
— skeggse

2
Hej, openStdin()czy interfejs API jest przestarzały i stary? (Nauczyłem się węzła dużo po 2011 ...)
— Steven Lu

3
O Tak. W rzeczywistości stdin.on('keypress',function(chunk,key))został usunięty w ostatnich wersjach. I jestem prawie pewien, openStdin()że został usunięty lub jest przestarzały. Teraz możesz uzyskać dostęp do stdin asprocess.stdin
— Élektra

132

Dla tych, którzy znaleźli tę odpowiedź, ponieważ ta możliwość została pozbawiona tty, oto jak uzyskać surowy strumień znaków ze standardowego wejścia:

var stdin = process.stdin;

// without this, we would only get streams once enter is pressed
stdin.setRawMode( true );

// resume stdin in the parent process (node app won't quit all by itself
// unless an error or process.exit() happens)
stdin.resume();

// i don't want binary, do you?
stdin.setEncoding( 'utf8' );

// on any data into stdin
stdin.on( 'data', function( key ){
  // ctrl-c ( end of text )
  if ( key === '\u0003' ) {
    process.exit();
  }
  // write the key to stdout all normal like
  process.stdout.write( key );
});

całkiem proste - w zasadzie tak jak w dokumentacji procesu.stdin, ale używa się go setRawMode( true )do uzyskania surowego strumienia, który jest trudniejszy do zidentyfikowania w dokumentacji.


2
Dzięki… to było proste i łatwe do wykonania od razu… :) dokładnie to czego chciałem.
— Kushal Likhi

2
Nie działa z Node.js 0.8+. Musisz zaimportować „keypress”. Zobacz odpowiedź Petera Lyonsa.
— G-Wiz

2
to zrobił pracę z 0,8, ale zabawa jak to takie ciągle zmieniających api.
— Dan Heberden

należy użyć klucza == '\ u0003' (podwójny zamiast potrójnego znaku równości), aby to zadziałało
— WHITECOLOR

1
Czy istnieje sposób, aby to zapisać klawisze w górę, w dół, w lewo, w prawo?
— Tom R

46

W węźle> = v6.1.0:

const readline = require('readline');

readline.emitKeypressEvents(process.stdin);
process.stdin.setRawMode(true);

process.stdin.on('keypress', (str, key) => {
  console.log(str)
  console.log(key)
})

Zobacz https://github.com/nodejs/node/issues/6626


3
Próbuję tego na 7 i otrzymuję process.stdin.setRawMode is not a function. Spróbuje później zanurkować nieco głębiej.
— Matt Molnar

3
@MattMolnar Funkcja jest obecna tylko wtedy, gdy jest to TTY, więc najpierw sprawdź to
— curiousdannii

@MattMolnar musisz uruchomić swoją aplikację jako terminal zewnętrzny, patrz stackoverflow.com/questions/17309749/…
— Maksim Shamihulau

29

Ta wersja wykorzystuje przyciśnięcie modułu i podpory node.js wersja 0.10, 0.8 i 0.6 jak również iojs 2.3. Pamiętaj, aby biegać npm install --save keypress.

var keypress = require('keypress')
  , tty = require('tty');

// make `process.stdin` begin emitting "keypress" events
keypress(process.stdin);

// listen for the "keypress" event
process.stdin.on('keypress', function (ch, key) {
  console.log('got "keypress"', key);
  if (key && key.ctrl && key.name == 'c') {
    process.stdin.pause();
  }
});

if (typeof process.stdin.setRawMode == 'function') {
  process.stdin.setRawMode(true);
} else {
  tty.setRawMode(true);
}
process.stdin.resume();

To nie działa na węźle v0.10.25, process.stdin.setRawMode()zamiast tego mówi użyj, ale to błędy i mówi, że nie ma metody setRawMode, bardzo denerwujące
— Plentybinary

@Plentybinary Podejrzewam, że w rzeczywistości nie używasz Node v0.10.25. Przetestowałem to z wersją0.10.25 i działa poprawnie. i process.stdin.setRawModeistnieje, jest funkcją i działa prawidłowo. Testowałem również na iojs-2.3.1 i nadal tam działa.
— Peter Lyons

FWIW, to nadal działa dobrze, przynajmniej do wersji 0.40.40
— John Rix

8

Po przetestowaniu nodejs 0.6.4 ( test nie powiódł się w wersji 0.8.14 ):

rint = require('readline').createInterface( process.stdin, {} ); 
rint.input.on('keypress',function( char, key) {
    //console.log(key);
    if( key == undefined ) {
        process.stdout.write('{'+char+'}')
    } else {
        if( key.name == 'escape' ) {
            process.exit();
        }
        process.stdout.write('['+key.name+']');
    }

}); 
require('tty').setRawMode(true);
setTimeout(process.exit, 10000);

jeśli go uruchomisz i:

  <--type '1'
{1}
  <--type 'a'
{1}[a]

Ważny kod nr 1:

require('tty').setRawMode( true );

Ważny kod nr 2:

.createInterface( process.stdin, {} );

2
if(Boolean(process.stdout.isTTY)){
  process.stdin.on("readable",function(){
    var chunk = process.stdin.read();
    if(chunk != null)
      doSomethingWithInput(chunk);
  });
  process.stdin.setRawMode(true);
} else {
  console.log("You are not using a tty device...);
}
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.