Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to signal EOF to node.js stdin from console?

I have a simple node.js app to echo stdin. When I run it interactively on the Windows console, I expected control-Z to be recognised as an EOF signal. But it isn't. So how do I get a node app to treat control-Z as EOF?

// testEcho.js

process.stdin.setEncoding('utf-8');
console.log("input is a TTY?:",process.stdin.isTTY);

process.stdin.on('readable',function() {
    var vText = process.stdin.read();
    if (vText != null)
        console.log('echo: "%s"',vText);
    process.stdout.write('> '); // prompt for next
    });

process.stdin.on('end',function() { // Works for redirected input but not triggered by ^Z on TTY
    console.log('end of input reached');
    });

```

like image 923
Michael Lemaire Avatar asked Jun 03 '15 05:06

Michael Lemaire


2 Answers

the problem is you're using process.stdin.on instead of process.on()

See the fix I made here and everything should be fine and dandy :) Enjoy!

process.stdin.setEncoding('utf-8');
console.log("input is a TTY?:", process.stdin.isTTY);

process.stdin.on('readable',function() {
    var vText = process.stdin.read();
    if (vText != null)
        console.log('echo: "%s"',vText);
    process.stdout.write('> '); // prompt for next
});

process.on('SIGINT', function () {
  console.log('Over and Out!');
  process.exit(0);
});

Also I replaced 'end' with 'SIGINT' as that's the signal that is caught by CTRL+C

You can read about the signal events here: https://nodejs.org/api/process.html#process_signal_events

like image 140
Datsik Avatar answered Nov 13 '22 01:11

Datsik


It would appear the solution is to use readline. This is more terminal-aware, and treats an interactive TTY ctrl-D as EOF, while also handling redirected input streams correctly. Also, being line oriented/aware, it conveniently strips newlines from the input strings.

var readline = require('readline');
process.stdin.setEncoding('utf-8');
console.log("input is a TTY?",process.stdin.isTTY);

var rl = readline.createInterface({input: process.stdin, output: process.stdout});
rl.setPrompt('> ');
rl.prompt();
rl.on('line' ,function(aText) { console.log('echo: "%s"',aText); rl.prompt(); });
rl.on('close',function()      { console.log('input has closed'); /* ... */ });
like image 45
Michael Lemaire Avatar answered Nov 13 '22 02:11

Michael Lemaire