For the purposes of this document, switchit
refers to command line arguments (a.k.a. positional arguments) as parameters
while it uses switches
to refer to command line switches (like --foo , -f).
A switchit
command can process positional arguments passed to it. For example:
Note the use of type: 'number'
, more information on the Type system section.
const Command = require('switchit').Command;
class Divide extends Command {
execute (params) {
console.log(params.numerator / params.denominator);
}
}
Divide.define({
// The order of these properties defines the expected position of the arguments
parameters: {
numerator: {
type: 'number'
},
denominator: {
type: 'number'
}
}
});
new Divide().run();
This command will need to be invoked like this: command <numerator> <denominator>
. Check it out:
$ node ../../examples/divide.js 10 2
5
$ node ../../examples/divide.js 2 10
0.2
A switchit
command can process command line switches passed to it. For example:
const Command = require('switchit').Command;
class SayHi extends Command {
execute (params) {
console.log(`Hi, ${params.name}!`);
}
}
SayHi.define({
switches: 'name'
});
new SayHi().run();
More information on the shorthand syntax (switches: 'name'
) below.
In this example, the switch --name
is available:
$ node ../../examples/switch.js --name John
Hi, John!
You can also use -n
:
$ node ../../examples/switch.js -n John
Hi, John!
More information about alternate names of switches in the sections Shortest unique prefix matching and Custom single-character alias
Both switches and parameters are required by default, but can be made optional by defining a default value
for them:
const Command = require('switchit').Command;
class SayHi extends Command {
execute (params) {
console.log(`Hi, ${params.name}!`);
}
}
SayHi.define({
switches: {
name: {
value: 'Ringo'
}
}
});
new SayHi().run();
Sample output:
$ node ../../examples/optional.js
Hi, Ringo!
Switches and parameters can take one or more values if configured with vargs: true
.
Here's an example with variadic parameters:
const Command = require('switchit').Command;
class Sum extends Command {
execute (params) {
console.log(params.summand.reduce((a, b) => a + b, 0))
}
}
Sum.define({
parameters: {
summand: {
type: 'number',
vargs: true
}
}
});
new Sum().run();
When run with no switches this command prints a simple message:
$ node ../../examples/sum.js 1 2 3
6
Do note that variadic string
parameters will consume all remaining positional arguments regardless of their type.
The only way of moving past a variadic parameter is if it is of a type different to string
, in which case, the first argument that doesn't
convert to the parameter type will be assigned to the next parameter (if any).
For example:
const Command = require('switchit').Command;
class Sum extends Command {
execute (params) {
console.log(`Hi, ${params.name}!`);
console.log(params.summand.reduce((a, b) => a + b, 0));
}
}
Sum.define({
parameters: {
summand: {
type: 'number',
vargs: true
},
name: {
type: 'string'
}
}
});
new Sum().run();
Sample output:
$ node ../../examples/past-variadic.js 1 2 3 Bart
Hi, Bart!
6
Parameters can also expose themselves as switches with the property switch: true
,
giving the user the possibility of specifying them either way. Here's an example:
const Command = require('switchit').Command;
class SayHi extends Command {
execute (params) {
console.log(`Hi, ${params.name}!`);
}
}
SayHi.define({
parameters: {
name: {
switch: true
}
}
});
new SayHi().run();
Now you can specify name
both as a positional argument and a switch:
$ node ../../examples/switchy.js Homer
Hi, Homer!
$ node ../../examples/switchy.js --name Marge
Hi, Marge!
switchit
understands switches like: --no-color
and treats them as --color=false
, check it out:
const Command = require('switchit').Command;
class Program extends Command {
execute (params) {
if (params.output) {
console.log("Some output here!");
}
}
}
Program.define({
switches: {
output: {
type: "boolean",
value: true
}
}
});
new Program().run();
Sample output:
$ node ../../examples/no-prefix.js
Some output here!
$ node ../../examples/no-prefix.js --no-output
switchit
is able to identify a switch by its shortest unique prefix. For example:
const Command = require('switchit').Command;
class Program extends Command {
execute (params) {
console.log(params);
}
}
Program.define({
switches: {
detach: {
type: 'boolean',
value: false
},
debug: {
type: 'boolean',
value: true
}
}
});
new Program().run();
The shortest unique prefix for detach
is det
and for debug
is deb
in this case:
$ node ../../examples/sup.js --det --deb
{ detach: true, debug: false }
Trying to use a non-unique prefix results in an error:
$ node ../../examples/sup.js --d
"d" matches multiple switches for Program: detach, debug
In the example above, you can break the ambiguity by specifying a case sensitive single-character alias for one or more
switches using the char
property:
const Command = require('switchit').Command;
class Program extends Command {
execute (params) {
console.log(params);
}
}
Program.define({
switches: {
detach: {
type: 'boolean',
value: false,
char: 'd'
},
debug: {
type: 'boolean',
value: true,
char: 'D'
}
}
});
new Program().run().catch((e) => {
console.log(e.message);
});
Sample output:
$ node ../../examples/char.js -D -d
{ debug: false, detach: true }
Specifying switches and parameters can be way less verbose using a shorthand syntax, where all configurations above can be specified using a string with special notation.
You can find an outline of each possible case below.
The minimal specification for a switch or parameter is to just define its name:
Program.define({
switches: 'foo',
parameters: 'bar'
});
Which is equivalent to (all other properties use their default values):
Program.define({
switches: [{
name: 'foo',
type: 'string',
required: true
vargs: false,
switch: false
char: null,
confirmable: false
}],
parameters: [{
name: 'bar',
type: 'string',
required: true
vargs: false,
switch: false
char: null,
confirmable: false
}]
});
Moving forward in this section, only the shorthand string will be showcased.
A semicolon after the name announces the start of the type name. (Same as specifying type
).
switches: 'foo:boolean bar:number baz:semver xyz:string',
parameters: 'foo:boolean bar:number baz:semver xyz:string'
More information about built-in types here.
Wrapping each declaration with square brackets marks this switch or parameter indicates that a default value will be provided.
switches: '[foo:boolean=true] [bar:number=42] [baz:semver=1.2.3-alpha] [xyz=test]',
parameters: '[foo:boolean=true] [bar:number=42] [baz:semver=1.2.3-alpha] [xyz=test]'
Omitting the :type
part will default it to :string
Variadic switches and parameters are indicated with []
or ...
after the type name:
switches: 'foo:boolean[] bar:number... baz:semver[] xyz:string[]',
parameters: 'foo:boolean[] bar:number... baz:semver[] xyz:string[]'
Only applicable to parameters
Wrapping a declaration in curly braces indicates this is a 'Switchy' parameter, meaning that is also available as a switch.
parameters '{foo:boolean} {[bar:number=42]} [{baz:semver=1.2.3-alpha}] {xyz:string[]}'
Note that it can be combined with the syntax for specific type, optional and variadic.
Only applicable to switches
The custom single character alias for a switch can be specified with the help of the #
character:
switches: 'f#foo:boolean b#bar:number=42 {B#baz:semver} [x#xyz:string...]'
When using interactive mode, if you want an optional switch to be included in the list of prompted items, add a ?
character
before the =
sign:
switches: '[foo:boolean?=true] [bar:number?=42] [baz:semver?=1.2.3-alpha] [xyz?=test]',
parameters: '[foo:boolean?=true] [bar:number?=42] [baz:semver?=1.2.3-alpha] [xyz?=test]'
More information about confirmable switches and parameters can be found in the Interactive.md file
If your command contains some feature flags to enable experimental or private features, you can always prevent the
switch from appearing in help output using the private: true
configuration.
const {
Container,
Help
} = require('switchit');
class Bar extends Container {}
Bar.define({
switches: {
foo: {
value: false,
private: true
}
},
commands: {
help: Help
}
});
new Bar().run();
(If this example doesn't make a lot of sense yet, check the Command containers feature.) When running the help command, private switches are not visible:
$ node ../../examples/private.js help
Bar
Syntax
bar [options] [command] Executes a command
Do note that when passing the -a / --all
switch to the help
command, these are visible:
$ node ../../examples/private.js help -a
Bar
Syntax
bar Display help for a given command
bar [options] [command] Executes a command
Available commands:
· help Display help for a given command
Run Bar help [command] for more information on a command.
More information about the built in help command here.