Skip to content

Instantly share code, notes, and snippets.

@Jeff-Russ
Last active May 14, 2019 11:55
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Jeff-Russ/76ea94f2c05059859ffc8e616b66b669 to your computer and use it in GitHub Desktop.
Save Jeff-Russ/76ea94f2c05059859ffc8e616b66b669 to your computer and use it in GitHub Desktop.
A synchronous & blocking readline prompt solution for Node.js that's not a huge node package

node-readline-sync

a synchronous & blocking readline prompt solution for Node.js that's not a huge node package

Why ask the user for input if you're just going to go ahead and continue executing anyway? Usually when you prompt the user for a response, everything that transpires depends on the answer they give. When you ask the user "are you sure" before changing their legal name to "Diarrhea Jones", blocking is a GOOD THING.

Luckily there is a workaround that's so simple it doesn't actually need it's own git repository.

Installation Instructions

Select the code below, copy and then paste it in your code. Done.

YOU'RE WELCOME.

// a SYNCHRONOUS & BLOCKING readline prompt solution that's not a huge node package
// https://github.com/Jeff-Russ/node-readline-sync
var readln = function () {
  return require('child_process')
                .execSync('read reply </dev/tty; echo "$reply"',{stdio:'pipe'})
                .toString().replace(/\n$/, '');
};

Take a Test Drive

console.log("type 'y' to delete all of your childhood photos forever:");
var ans = readln();

if (ans === "y") { console.log("Okay, deleted."); }
else { console.log("crisis averted thanks to the miracle of synchronous code!"); }

A Full Prompt Function

#!/usr/bin/env node

prompt = function(array, dfault) {

  if (dfault === undefined) {
    var ret = "";
    var repeat = true;
  } else { 
    var ret = dfault;
    var dfault = dfault.toLowerCase();
    repeat = false;
  }

  if (array === undefined) {
    array = ["y", "n"];
    var msg = "   | y | n |   ";
  } else {
    var msg = "   |";
    var array = array.map(function(e) {
      msg = msg+" "+e+" |";
      return e.toLowerCase();
    });
    msg = msg+"   ";
  }

  var go = true, no_op = 0; 
  const execSync = require('child_process').execSync;

  process.stdout.write(msg);

  while(go) {
    var reply = execSync('read reply </dev/tty; echo "$reply"',{stdio:'pipe'})
                  .toString().replace(/\n$/, '').toLowerCase();

    for (var i = 0; i < array.length; i++) {
      if (array[i] === reply) {
        ret = reply;
        repeat = false;
        break;
      }
    }
    go = repeat;
    go ? process.stdout.write("invalid reply, try again "+msg) : no_op;
  }
  return ret;
}

/* TEST IT OUT!


var reply;
process.stdout.write("I will keep asking until valid");
reply = prompt(["y", "n"]); 
console.log("reply is "+reply);

process.stdout.write("Same deal, since this is the default");
reply = prompt();
console.log("reply is "+reply);

process.stdout.write("Now we have a default so you can just hit enter");
reply = prompt(["yes","No"], "No");// if you see "no", the user entered it
console.log("reply is "+reply);    // and if you see "No", they hit enter.

*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment