Skip to content

Instantly share code, notes, and snippets.

@kuno
Forked from DTrejo/.gitignore
Created April 4, 2011 06:26
Show Gist options
  • Save kuno/901208 to your computer and use it in GitHub Desktop.
Save kuno/901208 to your computer and use it in GitHub Desktop.

Readline

To use this module, do require('readline').

rl.createInterface(input, output, completer)

Takes two streams and creates a readline interface. The completer function is used for autocompletion. When given a substring, it returns [substr, completedStr]. TODO: write some code to make sure I'm right.

createInterface is commonly used with process.stdin and process.stdout in order to accept user input:

var readline = require('readline'),
  rl = readline.createInterface(process.stdin, process.stdout);

rl.setPrompt(indicator, length)

Sets the prompt, for example when you run node on the command line, you see > , which is node's indicator. TODO: look in readline's code and see what word it uses for the prefix to the line.

rl.prompt()

Readies readline for input from the user, putting the current setPrompt options on a new line, giving the user a new spot to write.

rl.getColumns()

rl.question()

rl.close()

rl.pause()

rl.resume()

rl.write()

TODO: Write the above

Event: 'line'

function (line) {}

Emitted whenever the in stream receives a \n, usually received when the user hits enter, or return. This is a good hook to listen user input.

Example of listening for line:

rl.on('line', function (cmd) {
  console.log('You just typed: '+cmd);
});

Event: 'close'

function () {}

Emitted whenever the in stream receives a ^C or ^D, respectively known as SIGINT and EOT. This is a good way to know the user is finished using your program.

Example of listening for close, and exiting the program afterward:

rl.on('close', function() {
  console.log('goodbye!');
  process.exit(0);
});

Here's an example of how to use all these together to craft a tiny command line interface:

var readline = require('readline'),
  rl = readline.createInterface(process.stdin, process.stdout),
  prefix = 'OHAI> ';

rl.on('line', function(line) {
  switch(line.trim()) {
    case 'hello':
      console.log('world!');
      break;
    default:
      console.log('Say what? I might have heard `' + line.trim() + '`');
      break;
  }
  rl.setPrompt(prefix, prefix.length);
  rl.prompt();
}).on('close', function() {
  console.log('Have a great day!');
  process.exit(0);
});
console.log(prefix + 'Good to see you. Try typing stuff.');
rl.setPrompt(prefix, prefix.length);
rl.prompt();

Take a look at this slightly more complicated example, and http-console for a real-life use case.

//
// Based on github.com/cloudhead/http-console
// An attempt at a simplified readline example.
//
var readline = require('readline')
, util = require('util')
, colors = require('colors') // npm install colors
, rl = readline.createInterface(process.stdin, process.stdout)
, help = [ '.help ' + 'display this message.'.grey
, '.error ' + 'display an example error'.grey
, '.q[uit] ' + 'exit console.'.grey
].join('\n')
;
function welcome() {
util.puts([ "= readline-demo "
, "= Welcome, enter .help if you're lost."
, "= Try counting from 1 to 5!"
].join('\n').grey);
prompt();
}
function prompt() {
var arrow = '> '
, length = arrow.length
;
rl.setPrompt(arrow.grey, length);
rl.prompt();
}
var state = 1;
function exec(command) {
var num = parseInt(command, 10);
if (1 <= num && num <= 5) {
if (state === num) {
state++;
console.log('WIN'.green);
} else {
console.log(('Try entering a different number, like '
+ state + ' for example').red);
}
if (state === 6) {
console.log('WOW YOU ROCKS A LOT!'.rainbow);
process.exit(0);
}
} else if (command[0] === '.') {
switch (command.slice(1)) {
case 'help':
util.puts(help.yellow);
prompt();
break;
case 'error':
console.log("Here's what an error might look like");
JSON.parse('{ a: "bad JSON" }');
break;
case 'exit':
case 'quit':
case 'q':
process.exit(0);
break;
}
} else {
// only print if they typed something
if (command !== '') {
console.log(('\'' + command
+ '\' is not a command dude, sorryz').yellow);
}
}
prompt();
}
//
// Set things up
//
rl.on('line', function(cmd) {
exec(cmd.trim());
}).on('close', function() {
// only gets triggered by ^C or ^D
util.puts('goodbye!'.green);
process.exit(0);
});
process.on('uncaughtException', function(e) {
util.puts(e.stack.red);
rl.prompt();
});
welcome();
// Helpful thing I didn't get around to using:
// Make sure the buffer is flushed before
// we display the prompt.
function flush(callback) {
if (process.stdout.write('')) {
callback();
} else {
process.stdout.once('drain', function() {
callback();
});
}
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment