Socket
Socket
Sign inDemoInstall

command-line-args

Package Overview
Dependencies
Maintainers
1
Versions
74
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

command-line-args - npm Package Compare versions

Comparing version 0.5.9 to 1.0.0-0

bin/cli.js

288

lib/command-line-args.js
"use strict";
var a = require("array-tools");
var o = require("object-tools");
var s = require("string-tools");
var util = require("util");
var Definitions = require("./definitions");
var option = require("./option");
var cliUsage = require("command-line-usage");
var findReplace = require("find-replace");
var t = require("typical");
var util = require("util");
var Design = require("nature").Design;
var handlebars = require("handlebars");
var fs = require("fs");
var path = require("path");
var helpers = require("../template/helpers/helpers");
var handlebarsAnsi = require("handlebars-ansi");
var wrap = require("word-wrap");
/**
@module
@example
```js
var cliArgs = require("command-line-args");
var cli = cliArgs([
{ name: "help", type: Boolean, alias: "h" },
{ name: "files", type: Array, defaultOption: true}
]);
var argv = cli.parse();
```
@alias cli
@module command-line-args
*/
module.exports = CliArgs;
handlebars.registerHelper(helpers);
handlebars.registerHelper(handlebarsAnsi);
handlebars.registerPartial(
"columns",
fs.readFileSync(path.resolve(__dirname, "../template/partials/columns.hbs"), "utf8")
);
handlebars.logger.level = 1;
/**
A constructor function, taking your desired command-line option definitions as input, returning an instance of `command-line-args` which you can `parse()` or `getUsage()`.
@class
@param {module:command-line-args~OptionDefinition[]} - list of option definitions
@param {module:command-line-args.argDefType}
@param {string[]}
@returns {object}
@alias module:command-line-args
*/
function CliArgs(options){
if (!(this instanceof CliArgs)) return new CliArgs(options);
options.forEach(function(option){
if (option.options) option.attributes = option.options;
});
Design.call(this, options);
function CliArgs(definitions, argv){
if (!(this instanceof CliArgs)) return new CliArgs(definitions, argv);
this.definitions = new Definitions(definitions);
}
util.inherits(CliArgs, Design);
/**
Returns a flat, or grouped object containing the values set at the command-line
@param [argv=process.argv] {object} - Optional argv array, pass to override the default `process.argv`.
@returns {object}
@example
Output from `parse()` looks something like this:
```js
{
delete: "thisfile.txt",
force: true
}
```
or, if the option definitions are grouped:
```js
{
standard: {
delete: "thisfile.txt",
force: true
},
extra: {
intentions: "bad"
CliArgs.prototype.parse = function(argv){
var self = this;
/* if no argv supplied, assume we are parsing process.argv */
argv = argv || process.argv;
if (argv === process.argv){
argv.splice(0, 2);
} else {
argv = a.arrayify(argv);
}
}
```
*/
CliArgs.prototype.parse = function(argv, options){
var shortArg = /^-(\w)/,
longArg = /^--([\w-]+)/,
model = this.create(),
defaultValues = [],
self = this,
arg;
if (t.isPlainObject(argv) && options === undefined){
options = argv;
argv = null;
/* validate input */
var invalidMessage = this.definitions.validate(argv);
if (invalidMessage){
throw Error(invalidMessage);
}
if (argv){
argv = argv === process.argv ? process.argv.slice(2) : argv.slice(0);
} else {
argv = process.argv.slice(2);
/* split getopt-style combined options */
var combinedArg = option.combined;
var hasGetopt = argv.some(combinedArg.test.bind(combinedArg));
if (hasGetopt){
findReplace(argv, combinedArg.re, function(arg){
arg = arg.slice(1);
return arg.split("").map(function(letter){
return "-" + letter;
});
});
}
function isOption(input){
return longArg.test(input) || shortArg.test(input);
}
/* initialise output structure */
var output = this.definitions.applyInitialValues();
var def;
output = argv.reduce(function(output, item){
if (option.isOption(item)){
var arg = item;
def = self.definitions.get(arg);
output[def.name] = getDefaultOptionValue(def);
function setOutputValue(option, value){
model[option.name] = value;
}
function setOutput(optionName){
var option = a.findWhere(self._attributes, { name: optionName })
|| a.findWhere(self._attributes, { alias: optionName });
if (option){
if(option.type === Boolean){
setOutputValue(option, true);
} else if (argv.length) {
var value;
if (typeof option.type === "function" && option.type === Array){
value = a.spliceWhile(argv, 0, /^[^\-]/);
} else {
if (isOption(argv[0])){
value = null;
} else {
value = argv.shift();
value = typeof option.type === "function" ? option.type(value) : value;
}
}
setOutputValue(option, value);
} else {
setOutputValue(option, null);
}
} else {
if (options && options.unexpectedType){
self.define({ name: optionName, type: options.unexpectedType });
setOutput(optionName);
} else {
throw new Error("Unexpected option: " + optionName);
var value = item;
if (!def){
def = self.definitions.getDefault();
output[def.name] = getDefaultOptionValue(def);
}
}
};
while (typeof(arg = argv.shift()) !== "undefined"){
if (longArg.test(arg)){
setOutput(arg.match(longArg)[1]);
} else if (shortArg.test(arg)){
setOutput(arg.match(shortArg)[1]);
} else {
defaultValues.push(arg);
}
}
var outputValue = def.type ? def.type(value) : value;
if (defaultValues.length > 0){
var defaultOption = a.findWhere(this._attributes, { defaultOption: true });
if (defaultOption){
if (defaultOption.type === Array){
if (Array.isArray(model[defaultOption.name])){
model[defaultOption.name] = model[defaultOption.name].concat(defaultValues);
} else {
model[defaultOption.name] = defaultValues;
}
if (Array.isArray(output[def.name])){
output[def.name].push(outputValue);
} else {
model[defaultOption.name] = defaultValues[0];
output[def.name] = outputValue;
}
}
}
return output;
}, output);
if (this.groups().length){
var output = {};
this.groups().forEach(function(groupName){
var filter = "return attribute.groups && attribute.groups.indexOf('" + groupName + "') > -1;";
var optionGroup = defined(self.where(filter, model));
output[groupName] = optionGroup;
/* group the output values */
if (this.definitions.isGrouped()){
var grouped = {
_all: output,
_none: {}
};
this.definitions.whereGrouped().forEach(function(def){
a.arrayify(def.group).forEach(function(groupName){
grouped[groupName] = grouped[groupName] || {};
if (t.isDefined(output[def.name])){
grouped[groupName][def.name] = output[def.name];
}
});
});
this.definitions.whereNotGrouped().forEach(function(def){
if (t.isDefined(output[def.name])){
grouped._none[def.name] = output[def.name];
}
});
return grouped;
} else {
return output;
} else {
return defined(model);
}
};
function defined(object){
return o.where(object, function(val){
return val !== undefined;
});
}
/**
@param {object} [options] - options for template
@param {string} [options.title] - a title
@param {string} [options.header] - a header
@param {string} [options.footer] - a footer
@param {array} [options.forms] - the invocation forms
@param {array} [options.groups] - the groups to display in usage
@returns {string}
*/
CliArgs.prototype.getUsage = function(options){
var self = this;
options = options || {};
var template = fs.readFileSync(path.resolve(__dirname, "..", "template", "usage.hbs"), "utf8");
options.options = this._attributes.map(function(option){
var type = option.type && option.type.name.toLowerCase();
type = type === "boolean" ? "" : "<" + type + ">";
option.column1 = util.format("%s--%s %s", option.alias ? "-" + option.alias + ", " : "", option.name, type);
return option;
});
return cliUsage(this.definitions.val(), options);
};
var groups = options.groups || this.groups();
options.groups = groups.map(function(group){
return {
name: group,
options: self._attributes.filter(function(option){
return option.groups && option.groups.indexOf(group) > -1;
})
}
});
if (!options.columns) {
var width = options.options.reduce(function(prev, curr){
return curr.column1.length > prev ? curr.column1.length : prev;
}, 0);
options.columns = [ width + 2 ];
}
options.options = options.options.map(function(option){
var column2Width = process.stdout.columns - options.columns[0] - 8;
option.description = wrap(option.description, { width: column2Width });
option.description = option.description && option.description.replace(/\n/g, "\n" + s.fill(" ", options.columns[0] + 2))
return option;
});
return handlebars.compile(template, { preventIndent: true })(options);
CliArgs.prototype.setUsage = function(usageGenerator){
cliUsage = usageGenerator;
};
/**
Defines an option
@typedef {object} module:command-line-args~OptionDefinition
@property {string} name - the option name, used as the long option (e.g. `--name`)
@property {function} type - an optional function (e.g. `Number` or a custom function) used as a setter to enforce type.
@property {string} alias - a single character alias, used as the short option (e.g. `-n`)
@property {boolean} defaultOption - if values are specified without an option name, they are assigned to the defaultOption
@property {string} description - used in the usage guide
*/
function getDefaultOptionValue(def, output){
if (def.multiple){
return [];
} else if (def.type === Boolean || !def.type){
return true;
} else {
return null;
}
}
{
"name": "command-line-args",
"version": "0.5.9",
"version": "1.0.0-0",
"description": "Command-line parser, usage text producer",
"repository": "https://github.com/75lb/command-line-args.git",
"main": "lib/command-line-args",
"cla": "bin.cli.js",
"scripts": {

@@ -25,14 +26,12 @@ "test": "tape test/*.js",

"devDependencies": {
"tape": "^3.5.0"
"jsdoc-to-markdown": "^1.1.1",
"tape": "^4"
},
"dependencies": {
"array-tools": "^1.1.0",
"handlebars": "^3",
"handlebars-ansi": "~0.2.0",
"nature": "~0.5",
"object-tools": "^1.2.0",
"string-tools": "^0.1.4",
"typical": "^1.0.0",
"word-wrap": "^1.0.2"
"array-tools": "^2.0.0-5",
"command-line-usage": "^1.0.0-0",
"find-replace": "~0.2.0",
"object-tools": "^2",
"typical": "^2.3.0"
}
}
[![view on npm](http://img.shields.io/npm/v/command-line-args.svg)](https://www.npmjs.org/package/command-line-args)
[![npm module downloads per month](http://img.shields.io/npm/dm/command-line-args.svg)](https://www.npmjs.org/package/command-line-args)
[![Build Status](https://travis-ci.org/75lb/command-line-args.svg?branch=master)](https://travis-ci.org/75lb/command-line-args)
[![Build Status](https://travis-ci.org/75lb/command-line-args.svg?branch=rewrite)](https://travis-ci.org/75lb/command-line-args)
[![Dependency Status](https://david-dm.org/75lb/command-line-args.svg)](https://david-dm.org/75lb/command-line-args)
**work in progress, draft documentation**
# command-line-args
A command-line parser and usage-guide producer.. Particularly good at organising large sets of options.
Collect command-line options, generate a usage guide..
- Support most option notation styles
- long options (`--find lib.js`)
- short options (`-f lib.js`)
- getopt-style combinations (`-xvf lib.js`)
- option=val style (`--find=lib.js`)
- Customisable usage guide generator
- Modular - define reusage option sets.
- Split options into groups, for apps with a large set of options.
- Fine control over validation, type
## Install

@@ -16,149 +24,16 @@ ```sh

## Synopsis
the following `app.js`...
```js
var cliArgs = require("command-line-args");
/* define the command-line options */
var cli = cliArgs([
{ name: "verbose", type: Boolean, alias: "v", description: "Write plenty output" },
{ name: "help", type: Boolean, description: "Print usage instructions" },
{ name: "files", type: Array, defaultOption: true, description: "The input files" }
]);
/* parse the supplied command-line values */
var options = cli.parse();
/* generate a usage guide */
var usage = cli.getUsage({
header: "A synopsis application.",
footer: "For more information, visit http://example.com"
});
console.log(options.help ? usage : options);
```
...returns this output at the command line:
```sh
$ node app.js
{}
$ node app.js -v
{ verbose: true }
$ node app.js README.md package.json
{ files: [ 'README.md', 'package.json' ] }
$ node app.js README.md package.json -v
{ verbose: true, files: [ 'README.md', 'package.json' ] }
$ node app.js --help
A synopsis application.
Usage
-v, --verbose Write plenty output
--help Print usage instructions
--files <array> The input files
For more information, visit http://example.com
```
# API Reference
<a name="module_command-line-args"></a>
## command-line-args
**Example**
```js
var cliArgs = require("command-line-args");
var cli = cliArgs([
{ name: "help", type: Boolean, alias: "h" },
{ name: "files", type: Array, defaultOption: true}
]);
var argv = cli.parse();
```
* [command-line-args](#module_command-line-args)
* [CliArgs](#exp_module_command-line-args--CliArgs) ⏏
* [new CliArgs(options)](#new_module_command-line-args--CliArgs_new)
* _instance_
* [.parse([argv])](#module_command-line-args--CliArgs#parse) ⇒ <code>object</code>
* [.getUsage([options])](#module_command-line-args--CliArgs#getUsage) ⇒ <code>string</code>
* _inner_
* [~OptionDefinition](#module_command-line-args--CliArgs..OptionDefinition) : <code>object</code>
## API Reference
<a name="exp_module_command-line-args--CliArgs"></a>
### CliArgs ⏏
**Kind**: Exported class
<a name="new_module_command-line-args--CliArgs_new"></a>
#### new CliArgs(options)
A constructor function, taking your desired command-line option definitions as input, returning an instance of `command-line-args` which you can `parse()` or `getUsage()`.
### CliArgs(definitions, argv) ⇒ <code>object</code> ⏏
**Kind**: Exported function
| Param | Type |
| --- | --- |
| definitions | <code>module:command-line-args.argDefType</code> |
| argv | <code>Array.&lt;string&gt;</code> |
| Param | Type | Description |
| --- | --- | --- |
| options | <code>[Array.&lt;OptionDefinition&gt;](#module_command-line-args--CliArgs..OptionDefinition)</code> | list of option definitions |
<a name="module_command-line-args--CliArgs#parse"></a>
#### cliArgs.parse([argv]) ⇒ <code>object</code>
Returns a flat, or grouped object containing the values set at the command-line
**Kind**: instance method of <code>[CliArgs](#exp_module_command-line-args--CliArgs)</code>
| Param | Type | Default | Description |
| --- | --- | --- | --- |
| [argv] | <code>object</code> | <code>process.argv</code> | Optional argv array, pass to override the default `process.argv`. |
**Example**
Output from `parse()` looks something like this:
```js
{
delete: "thisfile.txt",
force: true
}
```
or, if the option definitions are grouped:
```js
{
standard: {
delete: "thisfile.txt",
force: true
},
extra: {
intentions: "bad"
}
}
```
<a name="module_command-line-args--CliArgs#getUsage"></a>
#### cliArgs.getUsage([options]) ⇒ <code>string</code>
**Kind**: instance method of <code>[CliArgs](#exp_module_command-line-args--CliArgs)</code>
| Param | Type | Description |
| --- | --- | --- |
| [options] | <code>object</code> | options for template |
| [options.title] | <code>string</code> | a title |
| [options.header] | <code>string</code> | a header |
| [options.footer] | <code>string</code> | a footer |
| [options.forms] | <code>array</code> | the invocation forms |
| [options.groups] | <code>array</code> | the groups to display in usage |
<a name="module_command-line-args--CliArgs..OptionDefinition"></a>
#### CliArgs~OptionDefinition : <code>object</code>
Defines an option
**Kind**: inner typedef of <code>[CliArgs](#exp_module_command-line-args--CliArgs)</code>
**Properties**
| Name | Type | Description |
| --- | --- | --- |
| name | <code>string</code> | the option name, used as the long option (e.g. `--name`) |
| type | <code>function</code> | an optional function (e.g. `Number` or a custom function) used as a setter to enforce type. |
| alias | <code>string</code> | a single character alias, used as the short option (e.g. `-n`) |
| defaultOption | <code>boolean</code> | if values are specified without an option name, they are assigned to the defaultOption |
| description | <code>string</code> | used in the usage guide |
* * *
&copy; 2015 Lloyd Brookes \<75pound@gmail.com\>. Documented by [jsdoc-to-markdown](https://github.com/75lb/jsdoc-to-markdown).
var test = require("tape");
var cliArgs = require("../lib/command-line-args");
var cliArgs = require("../");
var optionDefinitions = [
{ name: "verbose", alias: "v", type: Boolean },
{ name: "dry", alias: "d", type: Boolean },
{ name: "colour", alias: "c", value: "orange" },
{ name: "number", alias: "n", type: Number },
{ name: "files", defaultOption: true },
{ name: "colours", type: Array },
{ name: "tramps", type: Array }
];
test("default colour", function(t){
var argv = [ "--verbose" ];
t.deepEqual(cliArgs(optionDefinitions).parse(argv), {
verbose: true,
colour: "orange"
test("default value", function(t){
t.deepEqual(cliArgs([ { name: "one" }, { name: "two", value: "two" } ]).parse([ "--one", "1" ]), {
one: "1",
two: "two"
});
t.deepEqual(cliArgs([{ name: "two", value: "two" }]).parse([]), {
two: "two"
});
t.deepEqual(cliArgs([{ name: "two", value: "two" }]).parse([ "--two", "zwei" ]), {
two: "zwei"
});
t.deepEqual(cliArgs([{ name: "two", multiple: true, value: ["two", "zwei"] }]).parse([ ]), {
two: [ "two", "zwei" ]
});
t.deepEqual(cliArgs([{ name: "two", multiple: true, value: ["two", "zwei"] }]).parse([ "--two", "zwei" ]), {
two: [ "zwei" ]
});
t.end();
});
var test = require("tape");
var cliArgs = require("../lib/command-line-args");
var cliArgs = require("../");
test("default option", function(t){
test("defaultOption: string", function(t){
var optionDefinitions = [

@@ -11,3 +10,3 @@ { name: "files", defaultOption: true }

t.deepEqual(cliArgs(optionDefinitions).parse(argv), {
files: "file1"
files: "file2"
});

@@ -17,5 +16,5 @@ t.end();

test("default option, Array", function(t){
test("defaultOption: multiple string", function(t){
var optionDefinitions = [
{ name: "files", defaultOption: true, type: Array }
{ name: "files", defaultOption: true, multiple: true }
];

@@ -22,0 +21,0 @@ var argv = [ "file1", "file2" ];

var test = require("tape");
var cliArgs = require("../lib/command-line-args");
var cliArgs = require("../");
var optionDefinitions = [
{
groups: "group1",
options: [
{ name: "verbose", alias: "v", type: Boolean },
{ name: "dry", alias: "d", type: Boolean },
{ name: "colour", alias: "c" }
]
},
{
groups: "group2",
options: [
{ name: "number", alias: "n", type: Number },
{ name: "files", defaultOption: true },
{ name: "colours", type: Array },
{ name: "tramps", type: Array }
]
}
{ name: "one", group: "a" },
{ name: "two", group: "a" },
{ name: "three", group: "b" },
];
var optionDefinitions2 = [
{
groups: ["group1", "all"],
options: [
{ name: "verbose", alias: "v", type: Boolean },
{ name: "dry", alias: "d", type: Boolean },
{ name: "colour", alias: "c" }
]
},
{
groups: ["group2", "all"],
options: [
{ name: "number", alias: "n", type: Number },
{ name: "files", defaultOption: true },
{ name: "colours", type: Array },
{ name: "tramps", type: Array }
]
}
];
test("groups", function(t){
var cli = cliArgs(optionDefinitions);
t.deepEqual(cli.parse([ "--one", "1", "--two", "2", "--three", "3" ]), {
a: {
one: "1",
two: "2"
},
b: {
three: "3"
},
_none: {},
_all: {
one: "1",
two: "2",
three: "3"
}
});
// test("grouping, one boolean", function(t){
// var argv = [ "--verbose" ];
// t.deepEqual(cliArgs(optionDefinitions).parse(argv), {
// group1: {
// verbose: true
// },
// group2: {}
// });
// t.end();
// });
//
// test("one boolean, one string", function(t){
// var argv = [ "--verbose", "--colour", "red" ];
// t.deepEqual(cliArgs(optionDefinitions).parse(argv), {
// group1: {
// verbose: true,
// colour: "red"
// },
// group2: {}
// });
// t.end();
// });
//
// test("one boolean, one string, one number", function(t){
// var argv = [ "--verbose", "--colour", "red", "--number", "3" ];
// var result = cliArgs(optionDefinitions).parse(argv);
// t.equal(result.group1.verbose, true);
// t.equal(result.group1.colour, "red");
// t.equal(result.group2.number, 3);
// t.end();
// });
//
// test("one array", function(t){
// var argv = [ "--colours", "green", "red", "yellow" ];
// var result = cliArgs(optionDefinitions).parse(argv);
// t.deepEqual(result, {
// group1: {},
// group2: {
// colours: [ "green", "red", "yellow" ]
// }
// });
// t.end();
// });
//
// test("two arrays", function(t){
// var argv = [ "--colours", "green", "red", "yellow", "--tramps", "mike", "colin" ];
// var result = cliArgs(optionDefinitions).parse(argv);
// t.deepEqual(result, {
// group1: {},
// group2: {
// colours: [ "green", "red", "yellow" ],
// tramps: [ "mike", "colin" ]
// }
// });
// t.end();
// });
t.end();
});
test("multi-grouping, one boolean", function(t){
var argv = [ "--verbose" ];
t.deepEqual(cliArgs(optionDefinitions2).parse(argv), {
group1: {
verbose: true
test("groups: multiple and _none", function(t){
var optionDefinitions = [
{ name: "one", group: ["a", "f"] },
{ name: "two", group: ["a", "g"] },
{ name: "three" },
];
var cli = cliArgs(optionDefinitions);
t.deepEqual(cli.parse([ "--one", "1", "--two", "2", "--three", "3" ]), {
a: {
one: "1",
two: "2"
},
group2: {},
all: {
verbose: true
f: {
one: "1",
},
g: {
two: "2"
},
_none: {
three: "3"
},
_all: {
one: "1",
two: "2",
three: "3"
}
});
t.end();
});
var test = require("tape");
var cliArgs = require("../lib/command-line-args");
var cliArgs = require("../");
var optionDefinitions = [
{ name: "verbose", alias: "v", type: Boolean },
{ name: "dry", alias: "d", type: Boolean },
{ name: "colour", alias: "c" },
{ name: "number", alias: "n", type: Number },
{ name: "files", defaultOption: true }
{ name: "one", type: Boolean }
];
test("returns string", function(t){
var usage = cliArgs(optionDefinitions).getUsage();
t.equal(typeof usage, "string");
test("type-boolean: different values", function(t){
var cli = cliArgs(optionDefinitions);
var usage = cli.getUsage({ title: "test" });
t.ok(/test/.test(usage));
t.end();
});

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc