nodejs, як читати натискання клавіш із stdin


118

Чи можна слухати вхідні натискання клавіш у запущеному сценарії nodejs? Якщо я використовую process.openStdin()та слухаю його 'data'подію, тоді вхід буферизується до наступного нового рядка, наприклад:

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

Запустивши це, я отримую:

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

Що я хотів би побачити:

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

Я шукаю вузли, еквівалентні, наприклад, getcу рубіні

Чи можливо це?


(Додавши цей коментар, щоб це питання було легше знайти; мені знадобилося кілька днів, щоб знайти потрібні слова для нього): Ось як читати символ stdin за символом, перш ніж символ нового рядка (нового рядка) буде надісланий у введення.
— запаморочення

Відповіді:


62

Ви можете досягти цього таким чином, якщо перейти в неочищений режим:

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
Не хвилюйтеся, я дізнався про себе,process.stdin.resume(); process.stdin.on('data', function (chunk) { process.stdout.write('data: ' + chunk); });
— JamesM-SiteGen

3
Перемістіть на, setRawModeщоб бути нижче openStdin(), тому що ви можете встановити режим лише у випадку stdinініціалізації.
— Вежа

4
Здається, stdin більше не випромінює подію натискання клавіші, а натомість випробовує подію даних з різними параметрами.
— skeggse

2
Гей, openStdin()це застарілий і старий API? (Я дізнався шлях до вузла після 2011 року ...)
— Стівен Лу

3
Ага, так. Фактично stdin.on('keypress',function(chunk,key))було видалено в останніх версіях. І я впевнений, що openStdin()його або видалено, або застаріло. Тепер ви можете отримати доступ до stdin якprocess.stdin
— Електра

132

Для тих, хто знайшов цю відповідь, оскільки ця можливість була позбавлена tty, ось як отримати сирий потік символів від 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 );
});

досить просто - в основному так само, як документація process.stdin, але використовуючи setRawMode( true )для отримання необробленого потоку, який важче визначити в документації.


2
Дякую .. це було просто і легко здійснити одразу .. :) саме те, що я хотів.
— Кушаль Ліхі

2
Не працює з Node.js 0.8+. Ви повинні імпортувати "натискання клавіші". Дивіться відповідь Пітера Ліонса.
— G-Wiz

2
це зробило роботу з 0,8, але весело , як це такий мінливою апі.
— Ден Хеберден

слід використовувати ключ == '\ u0003' (подвійний замість подвійного знака рівності), щоб він працював
— WHITECOLOR

1
Чи є спосіб зробити це також записати вгору, вниз, вліво, вправо?
— Том Р

46

У вузлі> = 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)
})

Див. Https://github.com/nodejs/node/isissue/6626


3
Спробую це на 7, і я отримую process.stdin.setRawMode is not a function. Спробуємо пірнути трохи глибше пізніше.
— Метт Молнар

3
@MattMolnar Функція присутня лише в тому випадку, якщо вона є TTY, тому перевірте це спочатку
— curiousdannii

@MattMolnar вам потрібно запустити додаток в якості зовнішнього терміналу см stackoverflow.com/questions/17309749 / ...
— Максим Shamihulau

29

Ця версія використовує модуль натискання клавіш і підтримує node.js версії 0.10, 0.8 і 0.6, а також iojs 2.3. Обов’язково бігайте 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();

Це не працює на вузлі v0.10.25, він говорить про використання, process.stdin.setRawMode()але це помилки і говорить, що немає методу setRawMode, дуже дратує
— Plentybinary

@Plentybinary Я підозрюю, що ви насправді не працює вузол v0.10.25. Я перевірив це на v0.10.25, і він працює належним чином. і process.stdin.setRawModeіснує, є функцією та працює належним чином. Я також тестував на iojs-2.3.1, і він все ще працює там.
— Пітер Ліонс

FWIW, це продовжує працювати принаймні до v0.10.40
— Джон Рікс

8

З тестованими nodejs 0.6.4 ( тест не вдався у версії 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);

якщо запустити його та:

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

Важливий код №1:

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

Важливий код №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...);
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.