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

ฉันกำลังมองหา nodejs ที่เทียบเท่ากับเช่นgetcในทับทิม

เป็นไปได้หรือไม่


(การเพิ่มความคิดเห็นนี้เพื่อให้คำถามนี้ง่ายต่อการค้นหาใช้เวลาสองสามวันในการค้นหาคำที่เหมาะสม): นี่คือวิธีการอ่านอักขระ stdin ทีละอักขระก่อนที่จะส่งอักขระขึ้นบรรทัดใหม่ (บรรทัดใหม่) ในการป้อนข้อมูล
เวียนหัว

คำตอบ:


63

คุณสามารถบรรลุได้ด้วยวิธีนี้หากคุณเปลี่ยนเป็นโหมดดิบ:

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 ... )
Steven Lu

3
เอ่อใช่ ในความเป็นจริงstdin.on('keypress',function(chunk,key))ได้ถูกลบออกในเวอร์ชันล่าสุด และฉันค่อนข้างแน่ใจว่าopenStdin()ถูกลบหรือเลิกใช้แล้ว ตอนนี้คุณสามารถเข้าถึง stdin ได้ที่process.stdin
Élektra

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
ขอบคุณ .. มันง่ายและง่ายต่อการนำไปใช้ทันที .. :) ตรงตามที่ฉันต้องการ
Kushal Likhi

2
ไม่ทำงานกับ Node.js 0.8+ คุณต้องนำเข้า "การกดแป้น" ดูคำตอบของ Peter Lyons
G-Wiz

2
นี้ได้ทำงานร่วมกับ 0.8 แต่สนุกว่าเป็นเช่น API เคยเปลี่ยน
Dan Heberden

ควรใช้คีย์ == '\ u0003' (สองเท่าแทนที่จะเป็นเครื่องหมายเท่ากับสามเท่า) เพื่อให้ทำงานได้
WHITECOLOR

1
มีวิธีทำให้ปุ่มนี้เขียนขึ้นลงซ้ายขวาด้วยหรือไม่?
Tom R

47

ในโหนด> = 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/issues/6626


3
พยายามที่นี้ในวันที่ 7 process.stdin.setRawMode is not a functionและฉันได้รับ จะพยายามดำน้ำให้ลึกขึ้นในภายหลัง
Matt Molnar

3
@MattMolnar ฟังก์ชั่นนี้จะมีอยู่เฉพาะในกรณีที่เป็น TTY ดังนั้นให้ตรวจสอบก่อน
อยากรู้อยากเห็น

@MattMolnar คุณต้องเรียกใช้แอปของคุณเป็นเทอร์มินัลภายนอกโปรดดูstackoverflow.com/questions/17309749/…
Maksim 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 และมันก็ยังใช้งานได้เช่นกัน
Peter Lyons

FWIW สิ่งนี้ยังคงทำงานได้ดีอย่างน้อยถึง v0.10.40
John Rix

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...);
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.