In the last article, we saw a few tools to access arguments from the command line. In this article, we are going to discuss a few more useful tools to work with command-line applications. 

Inquirer

Inquirer.js offers a useful collection of command-line interfaces, and frequent interaction flows for a Node.js CLI application. While it claims not to be a full command-line utility, like Commander, it brings a lot of capabilities to the table if you want to access a lot of different types of inputs for your CLI. Here is the code for Inquirer;


var inquirer = require('inquirer');

var questions = [

    {

      type: 'input',

      name: 'topicToLearn',

      message: 'What topic do you want to learn today?',

      default: 'Node.js'

    },

    {

      type: 'list',

      name: 'medium',

      message: 'What is your preferred medium?',

      choices: ['Video', 'Text', 'Exercises'],

      filter: function(val) {

        return val.toLowerCase();

      }

    },

    {

      type: 'expand',

      name: 'timeOfDay',

      message: 'What is your preferred time to receive the lessons(Morning, Afternoon, Evenings)?',

      choices: [

        {

          key: 'm',

          name: 'Morning',

          value: 'morning'

        },

        {

          key: 'a',

          name: 'Afternoon',

          value: 'afternoon'

        },

        {

          key: 'e',

          name: 'Evenings',

          value: 'evenings'

        }

      ]

    },

    {

      type: 'rawlist',

      name: 'delivery',

      message: 'How would you access the learning material?',

      choices: ['Email', 'Our Website', 'Slack', 'Telegram', 'WhatsApp']

    },

    {

      type: 'input',

      name: 'email',

      message: "What's your email?",

      validate: function(value) {

        var pass = value.match(

          /^([a-zA-Z0-9_\-\.]+)@([a-zA-Z0-9_\-\.]+)\.([a-zA-Z]{2,5})$/i

        );

        if (pass) {

          return true;

        }

  

        return 'Please enter a valid email address';

      }

    },

    {

      type: 'input',

      name: 'comments',

      message: 'Any additional comments?',

      default: 'Nope, all good!'

    },

    {

        type: 'checkbox',

        message: 'Would you refer our services to your friends, colleagues, or business associates?',

        name: 'referral',

        choices: [

          {

            name: 'Yes'

          },

          {

            name: 'No'

          },

          {

            name: 'Can\'t Say'

          }

        ]

    }, {

      type: 'list',

      name: 'prize',

      message: 'If you provide a referral, you get a week\'s access to our training content for free',

      choices: ['Sure, I would love the access against a referral.', 'No, thanks! I don\'t want the free access.'],

      when: function(answers) {

        return answers.referral !== 'Yes' ;

      }

    }

  ];

inquirer

  .prompt(questions)

  .then(answers => {

    console.log("============Your Answers============");

    console.log(JSON.stringify(answers, null, ' '));

  })

  .catch(error => {

    if(error.isTtyError) {

      // Prompt couldn't be rendered in the current environment

    } else {

      // Something else when wrong

    }

  });

Prompt

While inquirer.js provides extensive capabilities, you might not need it every time, depending on your use case. Prompt provides a straightforward way to ask for inputs from the users. 

 

const prompt = require(‘prompt’);

 

prompt.start();

 

const schema = {

 

properties: {

 

topic: {

 

description:’Which topic you want to learn today?’,

 

pattern: /^[a-zA-Z\.\s\-]+$/,

 

message:’Topic must be only letters, spaces,dots, or dashes’,

 

required:true

 

},

 

password: {

 

description:’Enter your password.’,

 

hidden:true,

 

replace:’*’, // If `hidden` is set it will replace each hidden character with the specified string.

 

default:’badpassword’, // Default value to use if no value is entered.

 

required:true

 

}

 

}

 

};

 

prompt.get(schema, function (err, result) {

 

console.log(‘=============Your Inputs=============’);

 

console.log(‘ You have chosen ‘ + result.topic + ‘ to learn.’);

 

console.log(‘ password: ‘ + result.password);

 

});

 

 

 

Clear

Clear is a small but nifty module to clear your console. 


const clear = require('clear');

console.log('Printing first line to the console.');

console.log('Then the second line,');

console.log(' and then the third.');

console.log('Now clearing the console after three seconds.');

setTimeout(function() {

    clear();

}, 3000); 

clui

The project that started this two-part post was made possible because of clui. As we had mentioned at the start of part I, this was a Proof of Concept (POC) for an analytics project. The client is an EdTech startup. And they are building an engine to capture a user’s performance on many dimensions. They used the CLI for multiple intermediate demonstrations of their algorithm as they progressed. 

Here is the sample code to demonstrate how to implement gauges and sparklines. Apart from this, you can also use progress bar and loading indicators using clui.


const clui = require('clui'),

    clc = require('cli-color');

const os = require('os');

const Sparkline = require('clui').Sparkline;

const printTable = () => {

    var Line = clui.Line,

        LineBuffer = clui.LineBuffer;

    var outputBuffer = new LineBuffer({

        x: 0,

        y: 0,

        width: 'console',

        height: 'console'

    });

    var message = new Line(outputBuffer)

        .column('Test Scores', 20, [clc.green])

        .fill()

        .store();

    var blankLine = new Line(outputBuffer)

        .fill()

        .store();

    var header = new Line(outputBuffer)

        .column('Students', 15, [clc.cyan])

        .column('Test 1', 15, [clc.cyan])

        .column('Test 2', 15, [clc.cyan])

        .column('Test 3', 15, [clc.cyan])

        .column('Test 4', 11, [clc.cyan])

        .fill()

        .store();

    var line;

    for (var l = 0; l < 20; l++) {

        line = new Line(outputBuffer)

            .column('Student '.concat(+l + 1), 15)

            .column((Math.random() * 100).toFixed(3), 15)

            .column((Math.random() * 100).toFixed(3), 15)

            .column((Math.random() * 100).toFixed(3), 15)

            .column((Math.random() * 100).toFixed(3), 11)

            .fill()

            .store();

    }

    outputBuffer.output();

};

const printGauge = () => {

    var Gauge = clui.Gauge;

    var total = os.totalmem();

    var free = os.freemem();

    var used = total - free;

    var mbytes = Math.ceil(used / 1000000) + ' MB';

    var total_mbytes = Math.ceil(total / 1000000) + ' MB';

    console.log(Gauge(used, total, 20, total * 0.8, mbytes));

    console.log('Used ' + mbytes + ' of ' + total_mbytes);

}

const printSparkLine = () => {

    var studentsPerHour = [10,12,3,7,12,9,23,10,9,19,16,18,12,12];

    console.log(Sparkline(studentsPerHour, ' Students/Hour'));

}

console.log('==================Printing Table of Test Scores==================');

printTable();

console.log('==================Printing Memory Used==================');

printGauge();

console.log('==================Printing Test Taking Students Per Hour==================');

printSparkLine();

Conclusion

With this, we conclude the introduction to a few of the excellent Node.js modules when you want to work on a CLI application development. Of course, there will be many other modules. We will continue to share with you when we come across those. Have you used any other modules which were very helpful for you? Do share in the comments. 

P.S.: You can find the code of all the modules described in Part-I and Part-II of this article from here.