Parse User Input in Node.js with readline

Share this video with your friends

Send Tweet

Reading user input is a big aspect of this project because we will be asking for a question or an answer for the CLI to work with.

Node has some internal options for parsing user input. We will check out the readline module and how it parses input. We will also see the promise driven version of the module and use a top level await to ask questions in the CLI.

This package has some limitations in how you present questions to your user though so if presentation is important to you, you will want to consider using a 3rd party library.

Andrew
~ 2 years ago

don't understand how u used rl.input

I can't find .input even in documentation

Andrew
~ 2 years ago

oh, I think I have to make an extended interface, listener must be put on stdin. Sorry for misunderstanding. Typescript sometimes is tricky ))

Xavier Glab
~ 2 years ago

I am using node v18.13.0 and copied your code example with promisified readline from the github and got an error. Started googing around and found example on this page https://www.typeerror.org/docs/node/readline which changes your import:

import readline from "node:readline/promises";

to

import * as readline from "node:readline/promises";

and it worked.

Just a note for future self and others.

Xavier Glab
~ 2 years ago

Ok - the import was not a problem, in your code example you have

const rl = readline.createInterface({ terminal: true, input: process.stdin, output: process.stdin, });

So both input and output maps to process.stdin, the output should be mapped to process.stdout.

~ 2 years ago

I can't get this example to work, and show keypress events. The only way I got it to show keypress events was:

import readline from "node:readline"; import { stdin as input, stdout as output } from "node:process";

const rl = readline.createInterface({ terminal: true, input, output }); readline.emitKeypressEvents(input, rl); process.stdin.on("keypress", (key, seq) => console.log(key, seq));

Kevin Cunninghaminstructor
~ 2 years ago

I have rebuilt this using v18.13.0. And you're right Xavier, although in the video I correctly had output mapped to stdout, in the repo it's mapped to stdin - I've fixed that now!

Here's the version using event listeners and not promises that is in the middle of the video. Hopefully that helps the last commenter.

import readline from "node:readline";

const rl = readline.createInterface({
  terminal: true,
  input: process.stdin,
  output: process.stdout,
});

let input = "";

rl.input.on("keypress", (event, rl) => {
  if (rl.name === "return") {
    console.log(`Your name is ${input}.`);
  } else {
    input += event;
  }
});

and here is the promises version (which is also available in the repo but the output is fixed now)

import readline from "node:readline/promises";

const rl = readline.createInterface({
  terminal: true,
  input: process.stdin,
  output: process.stdout,
});

const answer = await rl.question("What is your name?");

console.log(`Your name is ${answer}.`);

const answer2 = await rl.question("Where do you live? ");

console.log(`You live in ${answer2}.`);
rl.close();

Hope that helps and reach out again if I can help more!

Kevin.