Reading command line arguments & User input in nodeJS.

If you want to write a console script in NodeJS, which takes a command line argument and ask the user some questions, how you are going to do it?

How can you access the input/output stream? Where can you find the argument vector?

Node’s global object process has two properties called .stdin and .stdout, which are essentially streams. You can write things into the stdout and listen to the ‘data’ event in the stdin stream. You need to call that .resume() method first, it initializes the STDIN reading process.

process.stdin.resume();
process.stdin.setEncoding('utf8');
 
process.stdin.on('data', function (chunk) {
	process.stdout.write('data: ' + chunk);
});

It is pretty straightforward, but it’s almost useless when you need to ask the user several questions, async nature of javascript is going to screw you.

The basic trouble here is that .on(‘data’ handler that will fire every time the user hits the Enter, so you’ll have to figure out which question is currently asked and where to put the data.

Fortunately for us, there is another event handler in NodeJS called ‘.once’ it’s basically same as ‘.on’, but it detaches the listener after the first event received. Knowing that, we can write a little helper function.

function ask(question, format, callback) {
	var stdin = process.stdin;
	var stdout = process.stdout;

	stdin.resume();
	stdout.write(question + ": ");

	stdin.once('data', function(data) {
		data = data.toString().trim();
		console.log(data);
		if (format.test(data)) {
			callback(data);
		} else {
			stdout.write("It should match: " + format + "\n");
			ask(question, format, callback);
		}
	});
}

ask("Name", /.+/, function (name) {
	ask("Email", /^.+@.+$/, function (email) {
		console.log("Your name is: " + name);
		console.log("Your email is: " + email);
		process.exit();
	});
});

Note that you should call .toString() and .trim() on your data, the first one to convert the data from a stream into an actual string, the second one is needed because the string will have a trailing new line symbol at the end after the user hits the Enter key. And don’t forget to call the process.exit() when you done.

To read command line arguments, you can find the  argument vector in process object. Here the first element is node, second element is the file and rest will be arguments. Try out the following code snippet.

process.argv.forEach(function (val, index, array) {
  console.log(index + ': ' + val);
});


Leave a comment