Easily make command line interfaces using git style subcommand executables
A common setup for command line applications is <command> <subcommand> <arguments/options>
(for example: git commit -m 'message'
). Rather than
having a giant file that switch
es or if else
s over each potential
subcommand, it's much neater to store each subcommand in it's own file
(bin/command
,bin/command-subcomand
, bin/command-subcommand2
, etc).
Helmsman makes it easy to add, modify or delete subcommands without having to
do housekeeping steps in your root command file or package.json
- Helmsman is automatically aware of all the
<command>-<subcommand>
files in your modulesbin/
(or any folder you tell it to look at) <command> --help
automatically generates help output, telling you all the subcommands that are available to you<command> --version
prints the version from package.json of the module requiring helmsman- Running
<command> <subcommand>
automatically executes the<command>-<subcommand>
file, passing along all the arguments & options - Helmsman is capable of smart command completion including dynamic shorthands
and spelling correction (eg:
<command> st
=><command> status
or<command> isntall
=><command> install
) - Use whatever option parsing library you want for your subcommands (optimist, commander, etc)
- Helmsman is minimally intrusive in your subcommands
In your command line application folder:
npm install helmsman --save
In your main executable, add helmsman
:
#!/usr/bin/env node
var helmsman = require('helmsman');
helmsman().parse();
Want to append in additional help messaging or modify the arguments that are parsed?
#!/usr/bin/env node
var helmsman = require('helmsman');
var cli = helmsman()
cli.on('--help', function(){
console.log('EXTRA HELPFUL!');
});
var argv = process.argv;
argv.push('--pizza');
// parse() can accept modified arguments, otherwise it defaults to process.argv
cli.parse(argv);
For your sub-executables to work with helmsman
you need to do two things: 1.
Expose metadata about the task, like its description and 2. Make sure the meat
& potatoes of the script only runs when it's directly called
#!/usr/bin/env node
// 1. Expose the metadata
exports.command = {
description: 'Show current worker counts and their pids'
};
// 2. Make sure it only runs when it's directly called:
if (require.main === module) {
// Parse options and run the magic
}
Note: If you're not putting each script in package.json
's bin
object,
make sure that the sub-commands are executable by running `chmod +x
bin/-
options
{Object}
Create an instance of helmsman
. It is an EventEmitter
and will also begin
searching for files once it's instantiated.
--help
: Emitted when--help
is passed as the first option or no commands or options are passed
localDir
: The local module folder where to search for executable files. Defaults to the directory of the executable (eg: If you execute<module folder>/bin/<command>
thelocalDir
will be<module folder>/bin
)prefix
: The prefix of the subcommands to search for. Defaults to the executed file (eg: If you run<command>
it will search for files in thelocalDir
that start with<command>-
metadata
: An object containing keys of command names and sub-objects containing the keysdescription
and optionallyarguments
usePath
: Iftrue
helmsman will search the PATH for commands matching the prefixfillCommandData
: An optional function to use to retrieve metadata from a command file; takes a defaults object, a filename, and an extensionfallbackCommandData
: Iftrue
helmsman will use its default function to retrieve metadata from a command file if the user-specified fuction returns a falsy valueignoreRequireFail
: Iftrue
helmsman will ignore failures to require an extensionless or.js
-extensioned command filenodePath
: The path to the node executable on Windows, defaults to'node'
parse([argv])
Parseargv
orprocess.argv
if there is no argv and either display the help or run the subcommand
description
: A one line description of the command. Required.arguments
: A shorthand for options the subcommand accepts. Generated help will include it next to command. Seehelp <command>
"
Much of this was inspired by TJ Holowaychuk's commander and component