nodejs cara membaca penekanan tombol dari stdin


118

Apakah mungkin untuk mendengarkan penekanan tombol yang masuk dalam skrip nodejs yang sedang berjalan? Jika saya menggunakan process.openStdin()dan mendengarkan 'data'acaranya maka input akan di-buffer hingga baris baru berikutnya, seperti:

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

Menjalankan ini, saya mendapatkan:

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

Yang ingin saya lihat adalah:

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

Saya mencari nodejs yang setara dengan, misalnya, getcdi ruby

Apakah ini mungkin?


(Menambahkan komentar ini sehingga pertanyaan ini lebih mudah ditemukan; butuh beberapa hari untuk menemukan kata yang tepat untuk itu): Ini adalah cara membaca karakter stdin demi karakter sebelum karakter baris baru (baris baru) dikirim sebagai masukan.
pusing

Jawaban:


63

Anda dapat mencapainya dengan cara ini, jika Anda beralih ke mode mentah:

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
Jangan khawatir, saya menemukan diri saya,process.stdin.resume(); process.stdin.on('data', function (chunk) { process.stdout.write('data: ' + chunk); });
JamesM-SiteGen

3
Pindahkan setRawModeke bawah openStdin(), karena Anda hanya dapat mengatur mode jika stdindiinisialisasi.
Menara

4
Tampaknya stdin tidak lagi memancarkan peristiwa penekanan tombol, melainkan memancarkan peristiwa data, dengan parameter perbedaan.
skeggse

2
Hai, apakah openStdin()API lama dan usang? (Saya belajar cara node setelah 2011 ...)
Steven Lu

3
Uh, ya. Faktanya stdin.on('keypress',function(chunk,key))telah dihapus dalam versi terbaru. Dan saya cukup yakin openStdin()telah dihapus atau tidak digunakan lagi. Sekarang, Anda dapat mengakses stdin sebagaiprocess.stdin
Élektra

132

Bagi mereka yang menemukan jawaban ini karena kemampuan ini dilucuti tty, berikut ini cara mendapatkan aliran karakter mentah dari 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 );
});

cukup sederhana - pada dasarnya seperti dokumentasi process.stdin tetapi menggunakan setRawMode( true )untuk mendapatkan aliran mentah, yang lebih sulit untuk diidentifikasi dalam dokumentasi.


2
Terima kasih .. itu sederhana dan mudah diterapkan sekarang .. :) persis apa yang saya inginkan.
Kushal Likhi

2
Tidak bekerja dengan Node.js 0.8+. Anda harus mengimpor 'penekanan tombol'. Lihat jawaban Peter Lyons.
G-Wiz

2
ini melakukan pekerjaan dengan 0,8, tapi menyenangkan bagaimana hal itu seperti api yang terus berubah.
Dan Heberden

harus menggunakan kunci == '\ u0003' (dua kali lipat bukan tanda sama dengan tiga kali lipat) untuk membuatnya berfungsi
WHITECOLOR

1
Adakah cara untuk membuat tombol ini menulis ke atas, bawah, kiri, kanan juga?
Tom R

47

Dalam node> = 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)
})

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


3
Mencoba ini pada 7 dan saya mendapatkan process.stdin.setRawMode is not a function. Akan mencoba menyelam lebih dalam nanti.
Matt Molnar

3
@MattMolnar Fungsi ini hanya ada jika itu adalah TTY, jadi periksa dulu
penasarandannii

@MattMolnar Anda perlu menjalankan aplikasi Anda sebagai terminal eksternal, lihat stackoverflow.com/questions/17309749/…
Maksim Shamihulau

29

Versi ini menggunakan modul keypress dan mendukung node.js versi 0.10, 0.8 dan 0.6 serta iojs 2.3. Pastikan untuk lari 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();

Ini tidak berfungsi pada node v0.10.25 ia mengatakan gunakan process.stdin.setRawMode()sebagai gantinya tetapi kesalahan itu dan mengatakan tidak ada metode setRawMode, sangat mengganggu
Plentybinary

@Plentybinary Saya curiga Anda tidak benar-benar menjalankan node v0.10.25. Saya menguji ini terhadap v0.10.25 dan berfungsi dengan baik. dan process.stdin.setRawModeada, merupakan fungsi, dan bekerja dengan baik. Saya juga menguji iojs-2.3.1 dan masih berfungsi di sana juga.
Peter Lyons

FWIW, ini terus bekerja dengan baik setidaknya hingga v0.10.40
John Rix

8

Dengan nodejs 0.6.4 diuji ( Pengujian gagal di versi 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);

jika Anda menjalankannya dan:

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

Kode penting # 1:

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

Kode penting # 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...);
}
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.