nodejs cách đọc tổ hợp phím từ stdin


118

Có thể lắng nghe các lần gõ phím đến trong tập lệnh nodejs đang chạy không? Nếu tôi sử dụng process.openStdin()và nghe 'data'sự kiện của nó thì đầu vào sẽ được lưu vào bộ đệm cho đến dòng mới tiếp theo, như sau:

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

Chạy cái này, tôi nhận được:

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

Những gì tôi muốn là xem:

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

Tôi đang tìm kiếm một nodejs tương đương với, ví dụ: getcbằng ruby

Điều này có khả thi không?


(Thêm nhận xét này để câu hỏi này dễ tìm hơn; tôi đã mất vài ngày để tìm từ phù hợp cho nó): Đây là cách đọc ký tự stdin theo ký tự trước khi ký tự dòng mới (dòng mới) được gửi vào đầu vào.
chóng mặt

Câu trả lời:


62

Bạn có thể đạt được nó theo cách này, nếu bạn chuyển sang chế độ thô:

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
Đừng lo lắng, tôi đã tìm ra bản thân của mình,process.stdin.resume(); process.stdin.on('data', function (chunk) { process.stdout.write('data: ' + chunk); });
JamesM-SiteGen

3
Di chuyển setRawModeđến bên dưới openStdin(), bởi vì bạn chỉ có thể đặt chế độ nếu chế độ stdinđược khởi tạo.
Tháp

4
Có vẻ như stdin không còn phát ra sự kiện nhấn phím nữa mà thay vào đó là phát ra một sự kiện dữ liệu, với các tham số khác nhau.
xiên

2
Này có phải là openStdin()một API cũ và không dùng nữa không? (Tôi đã học cách nút sau năm 2011 ...)
Steven Lu

3
Ừ. Trên thực tế stdin.on('keypress',function(chunk,key))đã bị loại bỏ trong các phiên bản gần đây. Và tôi khá chắc chắn openStdin()đã bị xóa hoặc không được dùng nữa. Bây giờ, bạn có thể truy cập stdin bằngprocess.stdin
Élektra

132

Đối với những người tìm thấy câu trả lời này vì khả năng này đã bị loại bỏ tty, đây là cách lấy luồng ký tự thô từ 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 );
});

khá đơn giản - về cơ bản giống như tài liệu của process.stdin nhưng sử dụng setRawMode( true )để lấy luồng thô, khó xác định hơn trong tài liệu.


2
Cảm ơn .. nó rất đơn giản và dễ thực hiện ngay lập tức .. :) chính xác những gì tôi muốn.
Kushal Likhi

2
Không hoạt động với Node.js 0.8+. Bạn phải nhập 'phím bấm'. Hãy xem câu trả lời của Peter Lyons.
G-Wiz

2
điều này đã hoạt động với 0.8, nhưng thật vui vì nó là một api luôn thay đổi như vậy.
Dan Heberden

nên sử dụng phím == '\ u0003' (double thay vì dấu triply bình đẳng) để có được nó làm việc
WHITECOLOR

1
Có cách nào để viết cả phím lên, xuống, trái, phải không?
Tom R

46

Trong nút> = 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)
})

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


3
Thử cái này vào ngày 7 và tôi nhận được process.stdin.setRawMode is not a function. Sẽ cố gắng lặn sâu hơn một chút sau.
Matt Molnar

3
@MattMolnar Chức năng chỉ xuất hiện nếu nó là một TTY, vì vậy kiểm tra cho rằng đầu tiên
curiousdannii

@MattMolnar, bạn cần chạy ứng dụng của mình dưới dạng thiết bị đầu cuối bên ngoài, xem stackoverflow.com/questions/17309749/…
Maksim Shamihulau,

29

Phiên bản này sử dụng mô-đun nhấn phím và hỗ trợ phiên bản node.js 0.10, 0.8 và 0.6 cũng như iojs 2.3. Hãy chắc chắn để chạy 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();

Đây không phải làm việc trên nút v0.10.25 nó nói sử dụng process.stdin.setRawMode()thay vì nhưng điều đó lỗi và nói rằng không có phương pháp setRawMode, rất khó chịu
Plentybinary

@Plentybinary Tôi nghi ngờ rằng bạn không thực sự chạy nút v0.10.25. Tôi đã thử nghiệm điều này so với v0.10.25 và nó hoạt động bình thường. và process.stdin.setRawModetồn tại, là một chức năng và hoạt động bình thường. Tôi cũng đã thử nghiệm trên iojs-2.3.1 và nó vẫn hoạt động ở đó.
Peter Lyons

FWIW, điều này tiếp tục hoạt động tốt ít nhất lên đến v0.10.40
John Rix

8

Với nodejs 0.6.4 được thử nghiệm ( Thử nghiệm không thành công trong phiên bản 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);

nếu bạn chạy nó và:

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

Mã quan trọng # 1:

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

Mã quan trọng # 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...);
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.