
NixClap
Simple, lightweight, flexible, and comprehensive Un*x Command Line Argument Parsing for NodeJS.
Features
- Lightweight with minimal dependencies.
- Comprehensive and flexible parsing capabilities similar to conventional Un*x parsing.
- Flexible handling of options and commands that can take variadic params.
- A simple and straightforward JSON interface for specifying options and commands.
- Very informative result that tells you where each option came from.
- Webpack friendly - allows bundling your cli into a single JS file with webpack.
Examples
Options only:
const NixClap = require("nix-clap");
const options = {
names: {
desc: "specify names",
alias: ["n", "m"],
type: "string array"
}
};
const parsed = new NixClap()
.version("1.0.0")
.usage("$0 [options]")
.init(options)
.parse();
console.log("names", parsed.opts.names);
With commands:
const NixClap = require("nix-clap");
const options = {
verbose: {
desc: "enable verbose mode",
alias: "v",
type: "boolean",
default: false
}
};
const commands = {
compile: {
desc: "run compile on the files",
args: "<string files...>",
exec: parsed => {
console.log("compile", parsed.args.files, "verbose", parsed.opts.verbose);
}
}
};
const parsed = new NixClap()
.version("1.0.0")
.usage("$0 [options] <command> [options]")
.init(options, commands)
.parse();
version
, help
, and usage
must be called before init
Usage:
$ my-prog compile --verbose file1.jsx file2.jsx file3.jsx
More Examples
See examples folder for more working samples.
Parsing Capabilities
Options
Example: prog -xazvf=hello --foo-option hello bar -. --enable-blah
- Support
-
single char options or --
long form options. - Options can have aliases.
- Both option forms can have argument specified with
=
or space.
- ie: long form
--foo-option=bar
or --foo-option bar
- ie: short form
-f=bar
or -f bar
- Both option forms can have variadic array args.
- ie:
--foo-option hello bar
or -f hello bar
- array args can have an optional type
-
options can be compounded, like -xazvf
.
- Last char can have args, like
-xazvf=hello
or -xazvf hello
. - Other chars are treated as
boolean
options automatically.
- Variadic array args are terminated by any other options such as
-x
or --xyz
, or explicitly with -.
or --.
- ie:
cmd1 arg1 arg2 --some-array abc def ghi -. cmd2 arg1 arg2
.
- Allow arbitrary unknown options but with arguments specified through
=
only.
- Since it's ambiguous whether to take a non-option arg following an unknown option as an argument or a command.
- Counting number of option occurrences.
- Boolean option can be negated with
--no-
prefix. - Allow custom value type coercions with a function or RegExp.
Commands
Example: prog sum 1 2 3 4
- Commands can have optional or required arguments.
- Each argument type defaults to
string
, but can have an optional type
- Commands can have aliases.
- Possible to specify multiple commands.
- Commands can have variadic array arguments.
- Variadic array args are terminated by any other options such as
-x
or --xyz
, or explicitly with -.
or --.
- ie:
prog order pizza soda -. pickup
(specifies two commands: order
and pickup
)
- Command can have its own options that are binded to it only.
- Top level options can be binded to specific commands only.
- Unbind top level options can be specified before or after commands.
- Allow arbitrary unknown commands that do not have arguments.
- Allow multiple custom value type coercions for each command.
Terminating and Resuming
--
terminates parsing, with remaining args returned in parsed._
.- Parsing can be resumed after it's terminated.
-.
or --.
can terminate variadic params for commands and options.
Install
npm i nix-clap --save
Interface
This module exposes a class with a few methods.
See APIs for more details.
options spec
const options = {
"some-option": {
alias: ["s", "so"],
type: "string",
desc: "description",
default: "foo",
require: true,
requireArg: true,
allowCmd: ["cmd1", "cmd2"]
},
"another-option": {}
};
Where:
field | description |
---|
alias | Specify aliases for the option, as a single string or an array of strings. |
type | Type of argument for the option, one of: string , number , float , boolean , array , count , or coercion |
| array can set type of elements as one of string , number , float , boolean like this: number array or float array |
desc | Description for the option - a string or a function that returns string. |
default | Default value to use for argument |
require | true /false whether this option must be specified. |
requireArg | true /false whether argument for the option is required. |
allowCmd | list of command names this option is allow to follow only. |
commands spec
const commands = {
cmd1: {
alias: ["c"],
args: "<arg1> [arg2..]",
usage: "$0 $1",
desc: "description",
exec: argv => {},
default: true,
options: {}
},
cmd2: {}
};
Where:
field | description |
---|
alias | Specify aliases for the command, as a single string or an array of strings. |
args | Specify arguments for the command. <> means it's required and [] optional. See rules for more info. |
usage | usage message when help for the command is invoked - a string or a function that returns a string. |
| $0 will be replaced with program name and $1 with command name. |
desc | Description for the command - can be a string or a function that returns a string. |
exec | The callback handler for the command - see here for more details. |
default | If true , set the command as default, which is invoked when no command was given in command line. |
| - Only one command can be default. |
| - Default command cannot have required args and must have the exec handler |
options | List of options arguments private to the command. Follows the same spec as top level options |
Rules for Command args
Rules for when specifying args
for the command:
- all required args must be before optional args
- last one can specify variadic args with
..
, like <names..>
or [names..]
- If you just want to get the list of args without naming it, you can specify with
<..>
or [..]
- named args can have an optional type like
<number value>
or [number values..]
- supported types are
number
, float
, string
, boolean
, or coercion
Value Coercion
If none of the predefined types work for you, you can specify your own as a function or a RegExp, or any value.
You use any valid identifier for the value type, and then you define a field with the same name in your spec that can be:
function
- will be called with the value to convertRegExp
- will be used to match the value. undefined
is returned if it didn't match.- Anything else - will be used as the converted value.
For example:
const options = {
customFn: {
type: "fnval",
fnval: value => {
return value.substr(0, 1);
}
},
customRegex: {
type: "rx",
rx: /^test$/i
},
customAny: {
type: "foo",
foo: "bar"
}
};
const commands = {
foo: {
args: "<type1 value1> <type2 value2>",
type1: value => `test-${value}`,
type2: /^test$/i
}
};
Parse Result
Use the method parse
to parse command line arguments. It will return a parse result object.
{
source: {},
opts: {},
verbatim: {},
commands: [],
index: 5,
error,
_: [],
argv: []
}
Where:
index
- the index in argv
parse stoppederror
- If parse failed and your parse-fail
event handler throws, then this will contain the parse error. See skip default event behaviors for more details.source
, opts
, verbatim
- objects containing info for the options. See details herecommands
- array of parsed command objects. See commands
for more details.argv
- original array of argv_
- remaining args in the argv
array in case parsing was terminated by --
.
If any command with exec
handlers were specified, then parse
will invoke them before returning the parse result object.
Parse Result source
and opts
objects
-
opts
- contains actual value for each option
-
source
- contains info about where the option value came from
cli
- option specified by user in the command linedefault
- default value in your options specuser
- values you applied by calling the applyConfig
method
-
verbatim
- contains original unprocessed value as given by the user in the command line
- This is an array of values if there was actual values from the user
- If there's no explicit value (ie. boolean or counting options), then this doesn't contain a field for the option.
- If it's a boolean but the user specified with
--no-
prefix, then this contains a field with the value ["no-"]
For example, with the following conditions:
- User specified
--foo-bar=test
in the command line - You have an option
fooDefault
with default value bar
- You called
applyConfig
with applyConfig({fooConfig: 1, fooBar: "oops"}, parsed)
You would get the following in the parse result object:
{
source: {
fooBar: "cli",
fooDefault: "default",
fooConfig: "user"
},
opts: {
fooBar: "test",
fooDefault: "bar",
fooConfig: 1
},
verbatim: {
fooBar: ["test"]
}
}
Note that the value oops
for fooBar
passed to applyConfig
is not used since user's specified value is used.
Parse Result commands
object
The commands
object is an array of parsed commands:
{
commands: [
{
name: "cmdName",
long: "cmdName",
unknown: false,
args: {
foo: "bar",
variadic: ["a", "b"]
},
argList: ["bar", "a", "b"],
opts: {},
source: {},
verbatim: {}
}
];
}
name
is the name of the command used by the user in the command line that could be an aliaslong
is the original form of the command name (not the alias)unknown
- true
if the command is not knownargs
- the processed named argumentsargList
- list of all the arguments in unprocessed string formopts
, source
, verbatim
- info for the options private to the command
Command exec
handler
If the command has an exec
handler, then it will be called with two arguments:
exec(result, parsed);
- First one is the object for the command
- Second one is the overall parsed object
Info about the command object:
{
name: "cmdName",
long: "cmdName",
args: {
foo: "bar",
variadic: [ "a", "b" ]
},
argList: [ "bar", "a", "b" ],
opts: {},
source: {},
verbatim: {}
}
Where opts
and source
contain both the command's private options and top level options.
You can turn this off with the skipExec
config flag passed to NixClap
constructor
Events
NixClap
emits these events:
help
- when --help
is invoked, emitted with the parse result object.pre-help
- before output for --help
post-help
- after output for --help
help
- when --help
is invoked, emitted with the parse result object.version
- when --version
is invoked, emitted with the parse result object.parsed
- when all parsing is done but before command exec
are invoked, emitted with { nixClap, parsed }
where nixClap
is the NixClap instance.parse-fail
- when parse failed, emitted with parse result object, which has error
field.unknown-option
- when an unknown option is found, emitted with option nameunknown-command
- when an unknown command is found, emitted with command context, which has name
field.no-action
- when you have commands with exec
and user specified no command that triggered an exec
call.exit
- When program is expected to terminate, emit with exit code.
Default Event Handlers
NixClap has default handlers for these events:
help
- Output help and emit exit
version
- If version
has been set, then output version and emit exit
.parse-fail
- Output help and error message, and emit exit
.unknown-option
- Throws Error Unknown option ${name}
unknown-command
- Throws Error Unkown command ${ctx.name}
no-action
- Output help with error No command given
and emit exit
exit
- calls process.exit(code)
Skip Default Event Behaviors
You can remove the default event handlers with one of these approaches:
For example, using removeDefaultHandlers
:
const nc = new NixClap().init(options, commands);
const parsed = nc.removeDefaultHandlers("parse-fail").parse();
if (parsed.error) {
}
Using constructor config.
const parsed = new NixClap({ handlers: { "parse-fail": false } }).parse();
if (parsed.error) {
}
APIs
These are methods NixClap
class supports.
- NixClap
- Features
- Examples
- Parsing Capabilities
- Install
- Interface
options spec
commands spec
- Value Coercion
- Parse Result
- Events
- APIs
constructor(config)
version(v)
help(setting)
usage(msg)
, cmdUsage(msg)
init(options, commands)
parse(argv, start, parsed)
parseAsync(argv, start, parsed)
showHelp(err, cmdName)
removeDefaultHandlers()
applyConfig(config, parsed, src)
runExec(parsed, skipDefault)
runExecAsync(parsed, skipDefault)
- Others
constructor(config)
config
is object with:
name
- set the program name. Will auto detect from process.argv
if not specified.version
- set the program version. Can also set with version
method.help
- custom help option setting. Can also set with help
method.usage
- usage message. Can also set with usage
method.cmdUsage
- generic usage message for commands. Can also set with cmdUsage
method.skipExec
- If true, will not call command exec
handlers after parse.skipExecDefault
- if true, will not call default command exec
handler after parse.
- In case you need to do something before invoking the
exec
handlers, you can set these flags and call the runExec(parsed, skipDefault)
method yourself.
output
- callback for printing to console. Should take string as param. Default to calling process.stdout.write
handlers
- custom event handlers.
The handlers
object can specify a function for each of the events or set it to false
to turn off the default handler.
For example, this config will replace handler for parse-fail
and turn off the default unknown-option
handler.
const nc = new NixClap({
handlers: {
"parse-fail": (parsed) => { ... },
"unknown-option": false
}
});
version(v)
Set program version with a string. ie: 1.0.0
Return: The NixClap
instance itself.
Must be called before the init
method.
help(setting)
Set a custom option setting for invoking help. Default is:
Return: The NixClap
instance itself.
{
alias: "h",
desc: "Show help"
}
Option name is always help
. Call help(false)
to turn off the default --help
option.
Must be called before the init
method.
usage(msg)
, cmdUsage(msg)
Set usage message for the program or command, which can be override by individual command's own usage.
msg
format is any string. $0
will be replaced with program name and $1
with command name.
Return: The NixClap
instance itself.
Must be called before the init
method.
init(options, commands)
Initialize your options and commands
Return: The NixClap
instance itself.
parse(argv, start, parsed)
Parse command line. Call without any params to parse process.argv
.
Return: The parse result object.
argv
- array of CLI args. Defaults to process.argv
.start
- index for argv from where to start parsingparsed
- previous result from parse
. If passed, then parsing will add new data to it.
parseAsync(argv, start, parsed)
async version of parse.
- It will use runExecAsync to invoke command
exec
handlers serially. - The command handler can return a Promise, which will be awaited.
Return: A promise the resolve with the parse result object.
showHelp(err, cmdName)
Show help message and then emit exit
.
err
- if valid, then err.message
will be printed after help message and exit with code 1
.cmdName
- if valid, then will print help for the specific command.
removeDefaultHandlers()
Remove NixClap's default handlers for the list of event names.
If you've replaced the handler through specifying handlers
in config
for the constructor, then this will not remove your handler.
Return: The NixClap
instance itself.
- You can pass in
"*"
to remove all default handlers. - You can pass in the event names you want to remove.
ie:
nc.removeDefaultHandlers("parse-fail", "unknown-option", "unknown-command");
applyConfig(config, parsed, src)
Allow you to apply extra config to the parsed object, overriding any opts
with source
not equal to cli
.
For example, you can allow user to specify options in their package.json
file, and apply those after the command line is parsed.
config
- Config object containing user options configparsed
- The parse result object from NixClap.src
- String, source to set if override. Default to user
Example on applying user config from package.json
:
const pkg = require(path.resolve("package.json"));
const parsed = nc.parse();
nc.applyConfig(pkg.cliConfig, parsed);
runExec(parsed, skipDefault)
Go through the commands in parsed and call their exec
handler.
The parse
method will call this at the end unless skipExec
flag is set.
Return: The number of commands with exec
was invoked.
parsed
- The parse result object.skipDefault
- boolean
, if true
then do not invoke default command's exec
handler when no command with exec
handler was given.
runExecAsync(parsed, skipDefault)
async version of runExec
Return: A promise that resolve with the number of commands with exec
invoked.
Others