nodejs come leggere le sequenze di tasti da stdin


118

È possibile ascoltare le sequenze di tasti in arrivo in uno script nodejs in esecuzione? Se uso process.openStdin()e ascolto il suo 'data'evento, l'input viene bufferizzato fino alla nuova riga successiva, in questo modo:

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

Eseguendo questo, ottengo:

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

Quello che mi piacerebbe è vedere:

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

Sto cercando un nodejs equivalente, ad esempio, getcin ruby

È possibile?


(Aggiungendo questo commento in modo che questa domanda sia più facile da trovare; mi ci sono voluti alcuni giorni per trovare le parole giuste per esso): Questo è come leggere stdin carattere per carattere prima che il carattere di nuova riga (nuova riga) venga inviato in input.
vertigini

Risposte:


62

Puoi ottenerlo in questo modo, se passi alla modalità raw:

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
Non preoccuparti, ho scoperto me stesso,process.stdin.resume(); process.stdin.on('data', function (chunk) { process.stdout.write('data: ' + chunk); });
JamesM-SiteGen

3
Spostare il setRawModeper essere sotto a openStdin(), perché è possibile impostare la modalità solo se stdinè inizializzato.
Torre

4
Sembra che stdin non emetta più un evento di pressione dei tasti, ma invece emetta un evento dati, con parametri diversi.
skeggse

2
Hey è openStdin()un'API obsoleta e vecchia? (Ho imparato il nodo molto dopo il 2011 ...)
Steven Lu

3
Sì, sì. Infatti stdin.on('keypress',function(chunk,key))è stato rimosso nelle versioni recenti. E sono abbastanza sicuro che openStdin()sia stato rimosso o sia deprecato. Ora puoi accedere a stdin asprocess.stdin
Élektra

132

Per coloro che trovano questa risposta poiché questa capacità è stata rimossa tty, ecco come ottenere un flusso di caratteri non elaborato da stdin:

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 );
});

piuttosto semplice - fondamentalmente proprio come la documentazione di process.stdin ma utilizzato setRawMode( true )per ottenere un flusso grezzo, che è più difficile da identificare nella documentazione.


2
Grazie .. è stato semplice e facile da implementare subito .. :) esattamente quello che volevo.
Kushal Likhi

2
Non funziona con Node.js 0.8+. Devi importare 'keypress'. Vedi la risposta di Peter Lyons.
G-Wiz

2
questo ha funzionato con 0.8, ma divertente come è un'API in continua evoluzione.
Dan Heberden

dovrebbe usare la chiave == '\ u0003' (doppio invece del triplo segno di uguale) per farlo funzionare
WHITECOLOR

1
C'è un modo per scrivere anche i tasti su, giù, sinistra e destra?
Tom R

46

Nel nodo> = 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)
})

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


3
Provando questo su 7 e ottengo process.stdin.setRawMode is not a function. Proverò ad approfondire un po 'più tardi.
Matt Molnar

3
@MattMolnar La funzione è presente solo se è un TTY, quindi controlla prima quella
curiosodannii

@MattMolnar è necessario eseguire la vostra applicazione, come terminale esterno, vedere stackoverflow.com/questions/17309749/...
Maksim Shamihulau

29

Questa versione utilizza la pressione di un tasto del modulo e supporti Node.JS versione 0.10, 0.8 e 0.6, così come iojs 2.3. Assicurati di correre 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();

Questo non funziona sul nodo v0.10.25, dice process.stdin.setRawMode()invece usa, ma dice errori e dice nessun metodo setRawMode, molto fastidioso
Plentybinary

@ Plentybinary Sospetto che tu non stia effettivamente eseguendo il nodo v0.10.25. L'ho testato con la v0.10.25 e funziona correttamente. ed process.stdin.setRawModeesiste, è una funzione e funziona correttamente. Ho provato anche su iojs-2.3.1 e funziona ancora anche lì.
Peter Lyons

FWIW, continua a funzionare bene almeno fino alla v0.10.40
John Rix

8

Con nodejs 0.6.4 testato ( test non riuscito nella versione 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);

se lo esegui e:

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

Codice importante n. 1:

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

Codice importante n. 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...);
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.