yumparse
v0.0.6
Published
A simple, lightweight and flexible command line argument parser.
Downloads
6
Maintainers
Readme
Yumparse
A simple, lightweight and flexible command line argument parser.
Basic usage
Yumparse is both simple and very flexible. Here is a simple example:
var yum = require('yumparse');
var parser = new yum.Parser({
// Enter command line options: shortFlag, type, and description are required parameters
options: [
{ shortFlag: '-f',
longFlag: '--foo',
type: String,
description: 'The foo string' }
]
});
parser.parse(); // Parse the options. The parser type checks to see if a String is passed
var fooString = parser.parsedOptions.foo || parser.parsedOptions.f; // Get the option if it was passed
if (fooString) // Do something with the option if it exists
console.log('Hello ' + fooString.value + '!');
Save it as basic.js
, and then in the shell:
$ node basic.js
$ node basic.js -h
Usage
basic.js [options]
Options
--foo, -f The foo string
$ node basic.js -f "Mr. Bubbles"
Hello Mr. Bubbles!
$ node basic.js -f
/usr/lib/node_modules/yumparse/src/yumparse.js:452
throw new YumparseError(JSON.stringify(option.value) + ' is not
^
YumparseError: undefined is not a string
See more examples below or in the examples folder from the project's GitHub page.
Changing the error message
Suppose you wanted to pretty up the error message. You could wrap a try block around parser.parse()
:
try {
parser.parse();
}
catch (error) {
console.error(error.name + ': ' + error.message);
process.exit(1);
}
Which would look like this in the shell:
$ node basic.js -f
YumparseError: undefined is not a string
Or you could change the message to your tastes:
try {
parser.parse();
}
catch (error) {
if (error.message.match(/\w is not a string/))
console.error(error.name + ': Please enter a string');
else
console.error(error.name + ': ' + error.message);
process.exit(1);
}
$ node basic.js -f
YumparseError: Please enter a string
Creating a rule
This example introduces the use of rules. Some of the power of Yumparse comes from its powerful built-in type checking abilities, but it really shines when rules are introduced.
Here is a simple example rule:
var myRule = {
message: function() {
return 'You must pass the flag "-f" with the value "foo"'
},
check: function() {
return this.parsedOptions.f ? this.parsedOptions.f.value === 'foo' : true;
}
}
As you can see in this example, the rule checks to see if the flag -f
has the value foo
. If it doesn't then it fails the rule and an error is thrown. You can add the rule like this:
parser.addRule(myRule);
Yumparse fortunately already comes with several rule factory functions that will return a rule object that you can add to your parser. They are available under yumparse
.rules
, and they use helper functions from yumparse
.helpers
. See the API, JSDoc and source code for more information.
An example with a rule
The example walks through the built-in rule factory yumparse
.rules
.requiredOrFlags
:
// yumparse.rules.requiredOrFlags
requiredOrFlags: function() {
'use strict';
var args = Array.prototype.slice.call(arguments);
return {
message: function() {
return 'You must pass either ' + helpers.argsToOptions.call(this, args) +
' as a parameter.';
},
check: function() {
return helpers.oneFlagPassed.call(this, args);
}
};
},
As you can see, the built-in rules from yumparse
.rules
are not actually rule objects: they are factories that return rule objects. This is so that a user can supply a variable number of arguments
that will return the rule in the proper format.
The call to Array.prototype.slice.call(arguments)
converts the function arguments from the arguments
keyword into an Array. Note also that it calls the helper functions in message
and call
with call(this, args)
, so that the parser instance is available in those functions as this
.
To learn more about what's going on under the hood, we need to see the helper functions it calls:
// yumparse.helpers.argsToOptions
argsToOptions: function(args, delimiter) {
'use strict';
if (!delimiter) {
delimiter = ' or ';
}
return args.map(function(arg) {
return this.options[this.flagToName(arg)];
}, this)
.reduce(function(previous, current) {
return (previous ? previous + delimiter : '') +
(current ? '['+ current.shortFlag +' | '+ current.longFlag +']' : '');
}, '');
},
// yumparse.helpers.oneFlagPassed
oneFlagPassed: function(flags) {
'use strict';
var numFlagsPassed = 0;
flags.forEach(function(flag) {
var option = this.options[this.flagToName(flag)];
if (option) {
if (this.parsedOptions[option.shortFlagName] !== undefined ||
this.parsedOptions[option.longFlagName] !== undefined) {
numFlagsPassed += 1;
}
}
}, this);
return numFlagsPassed === 1;
},
You can see that argsToOptions
first maps the list of flags to their corresponding options
objects, and then reduces it into a string that display the short and long forms of the flags.
The oneFlagPassed
helper function gets the flags and checks to see if one and only one flag is passed from the given list of flags.
So if we call something like yumparse.rules.requiredOrFlags('-i', '-o')
, it will find and check both the shortFlag
and longFlag
values for those flags, and if exactly one of these flags is passed it will return true
. Otherwise it will return false
, which is exactly what is needed for an OR rule that required a flag to be given.
Tying it all together
Here is the example that ties it all together. It uses the the built-in yumparse
.rules
.requiredOrFlags
rule:
// temperature.js
var yum = require('yumparse');
var parser = new yum.Parser({
options: [
{ shortFlag: '-v',
longFlag: '--verbose',
type: Boolean,
description: 'Verbose output' },
{ shortFlag: '-f',
longFlag: '--fahrenheit',
type: Number,
description: 'Convert celsius to fahrenheit' },
{ shortFlag: '-c',
longFlag: '--celsius',
type: Number,
description: 'Convert fahrenheit to celsius' },
{ shortFlag: '-k',
longFlag: '--kelvin',
type: Number,
description: 'Convert kelvin to fahrenheit' }
],
program: {
name: 'foobar',
description: 'a very fooish barish bazish program'
}
});
parser.addRule(yum.rules.requiredOrFlags('--fahrenheit', '--celsius', '--kelvin'));
try {
parser.parse();
}
catch (e) {
console.error(e.name + ': ' + e.message);
}
if (parser.parsedOptions.v || parser.parsedOptions.verbose) {
console.log('parser.options:\n', parser.options, '\n');
console.log('parser.parsedOptions:\n', parser.parsedOptions, '\n');
}
var fahrenheit = parser.parsedOptions.f || parser.parsedOptions.fahrenheit;
var celsius = parser.parsedOptions.celsius || parser.parsedOptions.c;
var kelvin = parser.parsedOptions.kelvin || parser.parsedOptions.k;
if (fahrenheit)
console.log((fahrenheit.value - 32) * 5/9 + '° celsius');
else if (celsius)
console.log(celsius.value * 9/5 + 32 + '° fahrenheit');
else if (kelvin)
console.log((kelvin.value - 273.15) * 9/5 + 32 + '° fahrenheit');
And then in the shell:
$ node temperature.js -h
foobar - a very fooish barish bazish program
Usage
foobar [options]
Options
--verbose, -v Verbose output
--fahrenheit, -f Convert celsius to fahrenheit
--celsius, -c Convert fahrenheit to celsius
--kelvin, -k Convert kelvin to fahrenheit
$ node temperature.js -c 0
32° fahrenheit
$ node temperature.js -f 32
0° celsius
$ node temperature.js -k 273.15
31.73000000000004° fahrenheit
$ node temperature.js
YumparseError: You must pass either [-f | --fahrenheit] or [-c | --celsius] or [-k | --kelvin] as a parameter.
The help/usage menu
The help/usage menu is also customizable. The built-in default template looks like this:
this.template = '' +
'{{#program.description}}' +
_B+'{{{program.name}}}'+B_ + ' - {{{program.description}}}\n' +
'{{/program.description}}' +
'\n\n' +
_U+'Usage'+U_+'\n' +
' {{{program.name}}} [options]\n\n' +
_U+'Options'+U_+'\n' +
'{{#optionsList}}' +
' {{{flagBlock}}} {{{description}}}\n' +
'{{/optionsList}}' +
'{{#example}}' +
'\n\n' +
_U+'Example'+U_+'\n' +
' {{{example}}}\n' +
'{{/example}}';
...
this.flagBlock = function() {
return (this.longFlag ?
(new Array(longestFlag - this.longFlag.length + 1)).join(' ') +
this.longFlag + ', ' :
(new Array(longestFlag + 1)).join(' ') + ' ') +
this.shortFlag;
};
As you can see, the Mustache template has access to the parser instance (this
). You might wonder what _B
, B_
, _U
and U_
are: They are xterm colors that refer to opening and closing bold and underline, respectively.
Feel free the overwrite the template string parser
.template
to your liking. You can also append your own Mustache functions (like this
.flagBlock
) to the parser by adding the property to your Parser object instance.
API
Module yumparse
Function yumparse
.Parser
(Object args)
The parser object. Takes a JSON object args
:
String args
.template
- The Mustache template to use for the help/usage menu. (optional)
Array args
.options
- The options array that the parser should use when parsing arguments. (required)
Object args
.options
:
String args
.options
.shortFlag
- The short flag to use for the option (e.g. '-i'
). (required)
Object args
.options
.type
- The type to typecheck for. (required)
Available options are in yumparse.flagTypeOptions: Boolean
, Number
, String
, Array
, Object
.
String args
.options
.description
- The description of the option (used in the help/usage menu). (required)
String args
.options
.longFlag
- The long flag to use for the option (e.g. '--input-file'
). (optional)
Boolean args
.options
.required
- Set to true to make the option required. (optional)
Object args
.options
.defaultValue
- The default value for the option. (optional)
Object yumparse
.rules
An alias that fetches the rules
module. It contains built-in rule factory functions that can be used by the parser.
Object yumparse
.helpers
An alias that fetches the helpers
module. It contains the helper functions that are used for the built-in rules.
Class Parser
Array Parser
.optionsList
The original list of obtions that were passed into the constructor in its original Array
form.
Object Parser
.options
The list of options that were passed into the constructor in Object
form. Allows for quick access to options by accessing them through their (camel-cased) variable form (e.g. Parser.options.inputFile
or Parser.options.i
for the option with flags -i
and --input-file
).
Object Parser
.parsedOptions
The successfully parsed options that the user gave from the command line. Contains a subset of the items in Parser
.options
.
Function Parser
.parse
()
Parse the command line parameters from process
.argv
. If the function succeeds, it will populate Parser
.parsedOptions
with the parsed options. If it fails, it will throw an error.
Function Parser
.addRule
(Object rule)
The function that is used to add rules to the rules array. It wraps the rule into a function that throws an error if the rule returns false
or continues it the rule returns true
.
Object rule
:
Function rule
.message
-> String - A function that creates the user message. this
refers to the Parser instance.
Function rule
.check
-> Boolean - A checking function that performs the checks for the rule. It should return true
when it succeeds and false
otherwise. this
refers to the Parser instance.
Array Parser
.rules
A list of rule functions to be checked during parsing. Rules are added using the Parser
.addRule
function.
Array Parser
.flagTypeOptions
The list of types that are available for args.options.type: Boolean
, Number
, String
, Array
, Object
.
Array Parser
.requiredList
The list of options from Parser
.optionsList
that have the option
.required
field set to true
.
String Parser
.template
The default Mustache template used for the help/usage menu. this
refers to the Parser instance (e.g. {{program.name}} - {{program.description}}
, {{#optionsList}}
, etc).
Function Parser
.flagBlock
() -> String
A Mustache helper function for formatting the list of options in the help/usage menu. References an option in Parser
.optionsList
. Returns a formatted String.
Function Parser
.flagToName
(String flag) -> String
A helper function that converts a flag name (spinal case) to a variable name (camel case) for accessing options from Parser
.options
or Parser
.parsedOptions
(e.g. -i
returns i
, --input-file
returns inputFile
).
Function Parser
.nameToFlag
(String name) -> String
A helper function that converts a variable name (camel case) to a flag name (spinal case) (e.g. i
returns -i
, inputFile
returns --input-file
).
Function Parser
.displayHelp
()
Displays the help/usage menu.
Function Parser
.helpString
() -> String
Returns the rendered Mustache template for the help/usage menu as a String.
Object yumparse
.rules
Contains built-in rule factory functions that return a rule object, which can then be passed to parser
.addRule
.
Function yumparse
.rules
.requiredOrFlags
(String flags...) -> Object
A rule factory that takes a variable number of Strings in shortFlag
or longFlag
format.
Returns a rule that checks if one and exactly one flag from the list of flags passed was parsed.
Function yumparse
.rules
.orFlags
(String flags...) -> Object
A rule factory that takes a variable number of Strings in shortFlag
or longFlag
format.
Returns a rule that checks if zero or only one flag from the list of flags passed was parsed. It will not fail if no flags are passed.
Function yumparse
.rules
.andFlagSets
(Array flagSets...) -> Object
A rule factory that takes a variable number of Arrays containing a variable number of Strings in shortFlag
or longFlag
format.
Returns a rule that checks if one and exactly one flag from each array passed was parsed and a flag from every array passed was parsed. It can be thought of as a combination of the rules yumparse
.rules
.andFlags
and yumparse
.rules
.requiredOrFlags
.
Function yumparse
.rules
.andFlags
(String flags...) -> Object
A rule factory that takes a variable number of Strings in shortFlag
or longFlag
format.
Returns a rule that checks if every flag from the list of flags passed was parsed.
Function yumparse
.rules
.fileExists
(String flags...) -> Object
A rule factory that takes a variable number of Strings in shortFlag
or longFlag
format.
Returns a rule that checks if the value from each of the list of flags passed is a path to a file that exists.
Object yumparse
.helpers
Function yumparse
.helpers
.argsToOptions
(String[] args, String delimiter) -> String
A helper function that takes a array of flags and a delimiter, and returns a String display of the shortFlag
and longFlag
of each of the passed options, delimited by the passed delimiter
string.
Function yumparse
.helpers
.allFlagsPassed
(String[] flags) -> Boolean
A helper function that takes an array of flags, and returns true
if all of those flags were parsed (i.e. they exist in parser
.parsedOptions
), and false
otherwise.
Function yumparse
.helpers
.allFlagSetsPassed
(String[][] flagSets) -> Boolean
A helper function that takes an array of an array of flags (a flagSet is an array of flag Strings), and returns true
if exactly one flag from each flagSet was parsed.
Function yumparse
.helpers
.oneFlagPassed
(String[] flags) -> Boolean
A helper function that takes an array of flags, and returns true
if one and exactly one flag was passed, and false
otherwise.
Function yumparse
.helpers
.fileExists
(String[] flags) -> Boolean
A helper function that takes an array of flags, and returns true
if the value from each of the flags is a path to a file that exists.
Copyright © 2014, Risto Stevcev