Cline and creating an interactive command line application

No matter how great your love of the command line is, you must admit that the simple and convenient console interface, history support, auto-addition, simple commands are very impressive. Without going into discussion about the advantages and disadvantages of "darkness", I want to submit to the Habra community for trial my little craft from the world of Node.js, whose main task is to improve the life of the developer who decided to write a console utility.

Cline Review


Cline is a small library based on the node's readline module, so we have history support, auto-completion, user polling and, with my easy hand, additions in the form of a password mask, the ability to listen to user input as separate commands described as simple or regular expressions, help output, simplified work with history, interactive mode.

With all this, creating an application that, after starting, will wait for user input from the user is greatly simplified.


Example


For those who have enough code to understand the capabilities of the library, here is an example:
Example
var cli = require('cline')();
cli.command('start', 'starts program', function () {
    cli.password('Password:', function (str) {
        console.log(str);
    })
});
cli.command('stop', function () {
    cli.confirm('Sure?', function (ok) {
        if (ok) {
            console.log('done');
        }
    })
});
cli.command('{string}', '', {string: '[A-Za-z]+'});
cli.command('{number}', '', {number: '\\d+'});
cli.on('command', function (input, cmd) {
    if ('start' !== cmd && 'stop' != cmd) {
        cli.prompt('More details on ' + cmd + ':');
    }
});
cli.history(['start', 'stop']);
cli.interact('>');
cli.on('history', function (item) {
    console.log('New history item ' + item);
});
cli.on('close', function () {
    console.log('History:' + cli.history());
    process.exit();
});



Using


Cline uses Interface in its work or something similar to it, if you have your own implementation of Interface you can pass it as a parameter (testing support):
var cli = require('cline')(myInterface);

The central feature of cline is the addition of commands.
cli.command(expression, description, parameters, callback);

expression is the expression that we expect from the user, it can contain dynamic parameters, for example, kill {id}, here id is the name of the dynamic parameter, I will remind you about it later.

description - an additional explanation for the command, used to generate help.

parameters - an object containing the names of dynamic parameters mentioned in expressions as keys, and regular expressions as values. For example, {id: '\\ d +'} - id will mean any number.

callback is a function that will be called when the user enters a string corresponding to expression. It is called with two arguments: a string from the user and an object with values ​​of dynamic parameters.
cli.command('kill {id}', 'kill task by id', {id: '\\d{1,3}'}, function (input, args) {
    console.log(input) // kill 12
    console.log(args.id) // 12
});

All cli.command parameters, except expression, are optional, and you can skip as you like.
cli.command(expression, description, callback);
cli.command(expression, parameters, callback);
cli.command(expression, description);
cli.command(expression, parameters);

All of these options are absolutely valid.

User interaction


There are 3 things you can expect from a user:

1.Input
cli.prompt('Your turn:');

2.Confirmation
cli.confirm('Sure?', function (ok) {});

3.Password
cli.password('Password:', ‘*’, function (pass) {});


Or you can simply go online
cli.interact('>');

In this mode, the library expects input from the user and tries to interpret each line as a command, looking for matches in the list of described commands, and after executing the listener function on the command, it again expects input. Recalling the interactive mode simply changes the prompt line.

System commands, history and events


Without any additional manipulations when using cline, 3 commands are immediately available:
clear or \ c - clears the

help screen or \? - displays help

exit or \ q - exit

With the history everything is simple, no files or streams, just fill the history like this:
cli.history(['start', 'stop']);

the order of the elements corresponds to the limitation, the first element in the list will be the oldest.
Well, you can read the story like this:
cli.history();

get the list. You can also subscribe to the event an item is added to the story. Well, then you decide how to save this list.

Since cline inherits an EventEmitter, the event model is widely used here, you can subscribe to such events:
close - the user called the exit command or stopped the process using Ctrl + C

history - when adding a new element to the history, the new element is passed to the listener as a parameter.

command - user input coincided from one of the commands (except for system ones), the line from the user and the command expression are passed as a parameter to the listener.

In the end


If you do not want to be silent silently when the user enters something other than the commands that you described, we do this:
cli.command('*', function (input) {       
   console.log(input + ' is not correct');
   cli.usage();     
});

Thank you very much for your attention, I hope you find cline useful, or maybe even inspire you to write your console utility, or at least fork in the github .

PS Special thanks to UFO for invite.

Also popular now: