While the web has now evolved to be a capable medium to interact with the backend, command-line tools are still powering the development. Node.js not only brought the JavaScript to the server-side, but it also bought it to the command line.

We recently worked on a PoC for a startup, which wanted to quickly setup command-line capabilities for their analytics solution. While the ultimate goal is to build a complete web-solution, they didn’t have the time to develop the front-end before a crucial demo that was coming up. We are not going into the details of what we did. But we are sharing a list of few tools which facilitate the development of such command-line tools.

The Inbuilt Modules

Node.js itself has a very capable API to ask for and handle command line inputs. Using the “Readline” module, you can provide the prompt as well as accept the input, using standard input (stdin) and output (stdout). Here is the code to do that.


const readline = require ('readline');

const rl = readeline.createInferface({
input: process.stdin,
output: process.stdout
});

rl.question('Please enter your name:', (name) => {
console.log(`How are you, ${answer}?`);
rl.close();
});

https://nodejs.org/api/readline.html

And then there is the “process” module. It is available globally available, so you can access it without explicitly requiring it. “process.argv” provides an array of values. The first element is the path of the node executable. In contrast, the second is the path of the JS file that you are executing. The rest of the elements contain the data provided on the prompt.


process.argv.forEach((value, index) => {
console.log(`${index}: ${val}`);
});

https://nodejs.org/api/process.html#process_process_arch

While process.argv provides all the information needed parsing the captured input becomes a big issue.

We are going to examine two simple tools to handle the command line arguments better. With these tools, developers can specify the options or the commands to understand what action the program should take. Let’s see those tools.

Commander

Here are the commands and the code to use the commander module. A brief explanation follows the code to clarify all the options. However, using the commander is very straightforward.


npm install commander

const program = require('commander')
program.version("0.0.1")

program
.option('-t, --learning-topic <topic>', 'The topic that you want to learn today')
.option('-p, --learning-period <period>', 'The time that you will spend learning the topic')
.option('-v, --video', 'Learn from online video')
.option('-t, --text', 'Learn using text material');

program.parse(process.argv);

console.log(`Your today's learning plan:`);

if (program.learningTopic) {
console.log(`You are going to learn ${program.learningTopic} today.`);
} else {
console.log(`You have not chosen any learning topic.`);
}

if (program.learningPeriod) {
console.log(`You are going to spend ${program.learningPeriod} for learning your today's topic.`);
} else {
console.log(`You have not set aside any time for your learning. Planning is the first step to success.`);
}

if (program.video) {
console.log(`You will use video lessons.`);
}

if (program.text) {
console.log(`You will learn this topic by reading.`);
}

Now that we have some code in place let’s see what it does. You must have guessed most of the things already, but let us mention the critical parts for the sake of completeness.

program.options define your commands. You can control your program flow based on their presence or absence. You can also accept a value for specific commands using the angular brackets (<>).

In case you want to mandate a command or input, use the program.requiredOption instead of program.option.

We have covered the basics of the commander module. As the assignment, here are two things for you to find out.

How to provide a default value for the option?
How to provide a boolean option?
Do let us know if you could find the answers to these questions in the comments.

yargs

Another easy to use module, yargs & commander both are almost neck-to-neck when it comes to the downloads count. Let’s quickly get on to the yargs.


npm install yargs

const yargs = require('yargs')

yargs.command ({
command: 'topic',
description: 'The topic that you want to learn today.',
builder: {
title: {
description: 'The topic title',
demandOption: true,
type: 'string'
},
time: {
description: 'The time that you will spend learning the topic',
demandOption: true,
type: 'string'
},
video: {
description: 'Whether you will use video lessons.',
demandOption: true,
type: 'boolean'
},
text: {
description: 'Whether you will use textual content.',
demandOption: true,
type: 'boolean'
}
},
handler: function (argv) {
console.log(`You are going to learn ${argv.title} today.`);
console.log(`You are going to spend ${argv.time} for learning your today's topic.`);
if (argv.video) {
console.log(`You will use video content.`);
}
if (argv.text) {
console.log(`You will use textual content.`);
}

}
});

yargs.parse();

minimist

The third module is minimist. As the name suggests, the module exposes the minimum configuration to capture and parse the command line arguments.


npm i minimist

const parseArgs = require('minimist')

const argv = parseArgs(process.argv)

console.log('Run the program and provide following options.');
console.log('-t OR --topic <space/=> <your topic name>');
console.log('-p OR --time <space/=> <time you are going to spend on the topic>');
console.log('-v OR --video <space/=> <true if you are going to view videos, false if you are not.>');
console.log('-x OR --text <space/=> <true if you are going to read, false if you are not.>');

if (argv.title || argv.t) {
var topic = argv.title ? argv.title : argv.t;
console.log(`You are going to learn ${topic} today.`);
}
if (argv.time || argv.p) {
var timePeriod = argv.time ? argv.time : argv.p;
console.log(`You are going to spend ${timePeriod} for learning your today's topic.`);
}

if (argv.video || argv.v) {
console.log(`You will use video content.`);
}

if (argv.text || argv.x) {
console.log(`You will use textual content.`);
}

Conclusion

As you can see, while al three of the above modules do the same things, their approach to capturing and parsing command line arguments is entirely different. Which one you choose depends on your comfort level, the complexity of your inputs, the comfort of the users, and the specific use case. No matter what’s your choice, you are in a good company.

Asking for user inputs

Both the commander and yargs feel a lot techie. But what if you want to provide more straightforward cues to the user for taking their input? Let’s explore a couple of modules that allow us to do that in the next article. Stay tuned till then.

Privacy Preference Center