A tiny cli framework for node.js.
Features
- tbd
Installation
Node
electron
package is available through npm.
npm install electron
Argument Parsing
The electron argument parser takes the node.js standard
process.argv
array and constructs an object with helpers
that can easily be queried. This helper is publicly exposed
so it can be used independant of the cli framework.
var electron = require('electron')
, argv = electron.argv(process.argv);
When constructed, the electron argv parser recognizes three types command line arguments: commands, modes, and parameters.
Each of these types also has a helper that will provide quick access to whether a command or mode is present, or the value of a parameter.
Commands
Commands are the simplest of arguments. They are any arguments
that are listed to that do not start with the -
prefix. Essentially,
they are a list of keys.
// $ node cli.js hello universe
argv.commands === [ 'hello', 'universe' ];
Modes
Modes are also a non-value list of keys, but they can be expressed
differently by using the -
or --
prefix. When using modes, if
it begins with a single -
, each letter will be parsed as its own mode.
// $ node cli.js --universe -abc
argv.modes === [ 'universe', 'a', 'b', 'c' ];
Parameters
Paremeters are key:value pairs that are declared in a similiar manner as modes. They can be declared in any of the following ways.
// $ node cli.js --noun unverse -v say --topic=hello -w=now
argv.params === {
noun: 'universe'
, v: 'say'
, topic: 'hello'
, w: 'now'
};
.command (cmd, [cmd], [...])
The command
helper takes a list of commands and will
return true
if any of them exist in the commands list.
// node cli.js hello universe
var greeting = argv.command('hi', 'hello') // true
, world = argv.command('world', 'earth'); // false
.mode (mode, [mode], [...])
The mode
helper takes a list of modes and will
return true
if any of them exist in the modes list.
// node cli.js --hello -abc
var greeting = argv.mode('h', 'hello') // true
, world = argv.mode('w', 'world'); // false
.param (param, [param], [...])
The param
helper takes a list of parameters and will
return the value of the first parameter that matches, or
null
if none of the parameters exist in the params list.
// node cli.js --hello universe
var greeting = argv.param('h', 'hello') // 'universe'
, world = argv.param('w', 'world'); // null
Program Framework
.command (name)
The most important aspect of an application is defining the different commands that can be executed for it. Some people prefer a CLI tool that does one thing based on a set of options. Others prefer a command line tool that can pivot based on a command string. Electron supports both.
When using the command
method, it will return a constructed
command object with a different set of methods for chaining.
Please read the "Constructing Commands" section for all available
chainable methods and their respective purpose.
Single Command
As you understand how Electron parses command-line options,
you know that a command is any option that does
not start with -
or --
. Therefor, a single-command electron
application is one that does not require any commands
, but
will execute a single action. Best demonstrated...
$ node app.js -p 8080
In the case of single-command applications, we will define
a default
command for electron to run.
program
.command('default')
.action(function (argv) {
var port = argv.param('p', 'port');
// something cool
});
The default
command will run when no commands are passed in,
but it will not run if a command is provided.
Multiple Commands
You can also create many different commands for your application
based on a simple string. These can be used in conjunction
with default
if you would like.
$ node app.js hello --universe
In this case we want to only run an action when the comamnd
hello
is present. This can easily be achieved.
program
.command('hello')
.action(fn);
There are also cases where you might want to have multipe layers of commands.
$ node app.js hello universe
Using the same mechanism, we can easily define this action.
program
.command('hello universe')
.action(fn);
One final option to explore with multiple commands is wildcards. Wildcards can exist at any level in a multi-word command, but they only work for entire words, not substrings.
program
.command('hello *')
.action(function (argv) {
var where = argv.commands[1];
});
Would respond for any command starting with hello
and is two
commands long, such as...
$ node app.js hello world
$ node app.js hello universe
Absent Commands
Should you want to notify your users when they attempt to use
a command is not support, you may use the absent
command. This
is also useful if you want to have a single command app but
support a list of items as "options", such as a list of files or
directories.
$ node build.js file1.js files2.js
program
.command('absent')
.action(function (argv) {
var files = argv.commands.slice(0);
// something cool
});
.parse (process.argv)
The parse
method will initiate the program with
selection of arguments and run a matching action. It
should be used once all commands and settings have
been propogated.
program.parse();
program.parse(process.argv);
program.parse([ 'node', 'app.js', '--hello', '--universe' ]);
If no parameter is provided, parse
will default to using
the current processes process.argv
array. You may alse
provide your own array of commands if you like. Note that
argv parsing expectes the first item to be the executing program
and the second argument to be the script (as is with all node argv).
These will be discarded.
.name (name)
Provide a formal name to be used when displaying the help for the given program. Returns the program for chaining.
program.name('Electron Framework');
.version (version)
Provide a program version to be used when displaying the version for the given program. Returns the program for chaining.
program.version(electron.version);
.desc (description)
Provide a program discription to be used when displaying the the help for the given program. Returns the program for chaining.
program.desc('https://github.com/logicalparadox/electron');
.cwd (fqp)
Provide an alternative current working directory to be
passed as part of the argv
parameter to the action that has
been executed. Returns the program for chaining.
// set
program.cwd(__dirname);
// get
program
.command('universe')
.action(function (argv) {
var cwd = argv.cwd;
// something cool
});
.theme (theme, specifications)
You may change the appearance of the --help
using
a simple theming mechanism. Electron comes bundled with
two themes. Each theme also supports minor tweaks. Returns
the program for chaining.
clean (default)
A colorful and verbose theme useful for multi-command applications.
program
.theme('clean', {
noColor: false // set to true to disable color coding
, prefix: '' // prefix written before each line, such as 'help:'
});
simple
An "options only" theme useful for single command applications.
program
.theme('simple', {
noColor: false // set to true to disable color coding
, command: 'default' // which command to show options for
, usage: '<options>' // special usage instructions
});
Use Your Own Function
You may also provide a function to theme
to provide your own output.
The following example will list all of the commands present in your
program.
program.theme(function () {
this.colorize();
console.log('Usage: %s <command>', this.opts.base);
this.commands.forEach(functioni (cmd) {
console.log(' %s - %s', cmd.cmd, cmd.desc);
});
});
Those interesting in building custom themes should view Electron on GitHub and explore lib/electron/themes.
.colorize ()
The colorize
helper is available if you wish you implement
a colorized but lightweight logging mechanism in your actions,
or if you are building a custom help theme. colorize
works
by extending String.prototype
with a number of color options.
Just in case, if the current program is not running as a TTY,
no string changes will be made.
console.log('hello universe'.green);
Colors
- red
- green
- yellow
- blue
- magenta
- cyan
- gray
Constructing Commands
Once you have decided to construct a command through program.command
you will be returned a command object that you can manipulate through
chainable methods.
.desc (description)
Provide a description for this command to be used when being display in help.
program
.command('hello universe')
.desc('Say "Hello" to the Universe.');
.option (opts, description, required)
You may define any number of options for
each command. The opts
string expects a comma delimited
list of commands with an optional default value or
indicator surrounded by brackets. You may
also provide a description of the option and whether
it is required.
This command may be called multiple times to define multiple options.
program
.command('build')
.option('-m, --minify', 'Flag to build minify version')
.option('-f, --file [build.js]', 'Save filename', true);
.action (function)
Provide the action to be used should this command be
called. The function will receive one parameter of the
parsed process.argv object. Multiple calls to action
will
replace the previous defined action.
program
.command('build')
.action(function (argv) {
var minify = argv.mode('m', 'minify')
, file = argv.param('f', 'file');
// go!
});