commander.js - nodejs command-line interfaces made easy

Commander.js is a small node.js module allowing you to define options and interacte with the user’s terminal in a simple and natural way, inspired by the Ruby library of the same name.

Features

  • self-documenting code
  • auto-generated help
  • combined short flags (“-abc” == “-a -b -c”)
  • option defaults
  • option coercion
  • command parsing
  • prompts

Example

A basic commander program looks something like the following (taken from serve). It’s extremely easy to see what’s going on, all the options provided by the executable are laid out infront of you.

program
  .version('0.0.1')
  .option('-p, --port <port>', 'specify the port [3000]', Number, 3000)
  .option('-H, --hidden', 'enable hidden file serving')
  .option('-I, --no-icons', 'disable file icons')
  .option('-L, --no-logs', 'disable request logging')
  .parse(process.argv);

In the previous example only --port accepts an argument, and the value of program.port defaults to 3000. The options --no-icons and --no-logs default their properties to true, only when --no-icons is specified will program.icons be false.

The usage information is free!:

$ serve --help

  Usage: serve [options]

  Options:

    -v, --version      output the version number
    -p, --port <port>  specify the port [3000]
    -H, --hidden       enable hidden file serving
    -I, --no-icons     disable file icons
    -L, --no-logs      disable request logging
    -h, --help         output usage information

Utilities

Commander is bundled with some utilities for prompting user input, confirmations, passwords, lists of choices etc. Most of these utilities will ask for input if the user simply hits enter and should respond.

Below is an example of asking for a name using a single-line input prompt:

program.prompt('name: ', function(name){
  console.log('hi %s', name);
});

Multi-line input is easy too, just leave out the trailing space in the message:

program.prompt('description:', function(name){
  console.log('hi %s', name);
});

Coercion is useful for dates, numbers etc:

 program.prompt('Age: ', Number, function(age){
  console.log('age: %j', age);
});

Password prompts masking off input:

program.password('Password: ', function(pass){
  console.log('got "%s"', pass);
});

Or providing a mask char:

program.password('Password: ', '*', function(pass){
  console.log('got "%s"', pass);
});

Confirmations require “yes” or “y” to result in true:

 program.confirm('continue? ', function(ok){
   console.log(' got %j', ok);
 });

There’s also choice support, so users can select from a list:

var list = ['tobi', 'loki', 'jane', 'manny', 'luna'];

console.log('Choose the coolest pet:');
program.choose(list, function(i){
  console.log('you chose %d "%s"', i, list[i]);
});

presenting:

Choose the coolest pet:
  1) tobi
  2) loki
  3) jane
  4) manny
  5) luna

Commands

Though I haven’t had time to polish them up yet, commander supports the idea of .. well… “commands”. The “root” executable is an instanceof Command, and well you can recursively define these to create a rich interface. GIT is a great example of this, many larger utilities use sub-command such as git remote to accept arguments, and may all then have their own options etc, using the same API as the root command. The following is a simple example:

#!/usr/bin/env node

var program = require('../');

program
  .version('0.0.1')
  .option('-C, --chdir <path>', 'change the working directory')
  .option('-c, --config <path>', 'set config path [./deploy.conf]')
  .option('-T, --no-tests', 'ignore test hook')

// $ deploy setup stage
// $ deploy setup
program
  .command('setup [env]')
  .description('run setup commands for all envs')
  .action(function(env){
    env = env || 'all';
    console.log('setup for %s env(s)', env);
  });

// $ deploy stage
// $ deploy production
program
  .command('*')
  .action(function(env){
    console.log('deploying "%s"', env);
  });

program.parse(process.argv);

Moar Libraries!

Dont forget to check out these other great CLI-related libraries:

Express vs Sinatra Benchmarks

So I have been setting up benchmark scripts for Express today, and so far some of the results have been quite interesting! The numbers shown should be taken lightly, however they consistently show that Express is quite fast.

If you are interested in benchmarking your own web applications you might want to read my last article ApacheBench Gnuplot Graphing Benchmarks.

All of the following benchmarks were generated using ApacheBench with a concurrency of 50 and performs 2000 requests. Keep in mind that Thin is used to serve Sinatra requests.

Express vs Sinatra

For those who dont know Express is a NodeJS framework inspired by Ruby’s Sinatra. Below we have the benchmark results for a typical “Hello World” response, which include nodejs benchmarks without the overhead of features provided by Express:

express vs sinatraexpress sinatra requests per second

Haml.js vs Ruby Haml

Next up is my JavaScript Haml implementation. Below are the results of running Express & haml.js vs Sinatra & Haml. Both serve a layout template, as well as a page specific template.

javascript haml vs ruby hamlrequests per second

Sass.js vs Ruby Sass

Finally we have JavaScript Sass vs the regular Ruby implementation packaged with haml. Both implementations serve the same 80 line stylesheet.

sass js vs ruby sasssass benchmarks

Stay tuned for more benchmarks!