commander
Advanced tools
Comparing version 2.7.1 to 2.8.0
2.8.0 / 2015-04-07 | ||
================== | ||
* Add `process.execArg` support, execution args like `--harmony` will be passed to sub-commands #387 @DigitalIO @zhiyelee | ||
* Fix bug in Git-style sub-commands #372 @zhiyelee | ||
* Allow commands to be hidden from help #383 @tonylukasavage | ||
* When git-style sub-commands are in use, yet none are called, display help #382 @claylo | ||
* Add ability to specify arguments syntax for top-level command #258 @rrthomas | ||
* Support multiline descriptions #208 @zxqfox | ||
2.7.1 / 2015-03-11 | ||
@@ -3,0 +13,0 @@ ================== |
112
index.js
@@ -159,3 +159,4 @@ | ||
Command.prototype.command = function(name, desc) { | ||
Command.prototype.command = function(name, desc, opts) { | ||
opts = opts || {}; | ||
var args = name.split(/ +/); | ||
@@ -170,2 +171,3 @@ var cmd = new Command(args.shift()); | ||
cmd._noHelp = !!opts.noHelp; | ||
this.commands.push(cmd); | ||
@@ -180,2 +182,12 @@ cmd.parseExpectedArgs(args); | ||
/** | ||
* Define argument syntax for the top-level command. | ||
* | ||
* @api public | ||
*/ | ||
Command.prototype.arguments = function (desc) { | ||
return this.parseExpectedArgs(desc.split(/ +/)); | ||
} | ||
/** | ||
* Add an implicit `help [cmd]` subcommand | ||
@@ -294,4 +306,6 @@ * which invokes `--help` for the given command. | ||
}; | ||
this.parent.on(this._name, listener); | ||
if (this._alias) this.parent.on(this._alias, listener); | ||
var parent = this.parent || this; | ||
var name = parent === this ? '*' : this._name; | ||
parent.on(name, listener); | ||
if (this._alias) parent.on(this._alias, listener); | ||
return this; | ||
@@ -438,2 +452,8 @@ }; | ||
// github-style sub-commands with no sub-command | ||
if (this.executables && argv.length < 3) { | ||
// this user needs help | ||
argv.push('--help'); | ||
} | ||
// process argv | ||
@@ -477,19 +497,29 @@ var parsed = this.parseOptions(this.normalize(argv.slice(2))); | ||
var f = argv[1]; | ||
var link = readlink(f); | ||
// name of the subcommand, link `pm-install` | ||
var bin = basename(f, '.js') + '-' + args[0]; | ||
// In case of globally installed, get the base dir where executable | ||
// subcommand file should be located at | ||
var baseDir | ||
, link = readlink(f); | ||
// when symbolink is relative path | ||
if (link !== f && link.charAt(0) !== '/') { | ||
link = path.join(dirname(f), link) | ||
} | ||
var dir = dirname(link); | ||
var bin = basename(f, '.js') + '-' + args[0]; | ||
baseDir = dirname(link); | ||
// prefer local `./<bin>` to bin in the $PATH | ||
var local = path.join(dir, bin); | ||
try { | ||
// for versions before node v0.8 when there weren't `fs.existsSync` | ||
if (fs.statSync(local).isFile()) { | ||
bin = local; | ||
} | ||
} catch (e) {} | ||
var localBin = path.join(baseDir, bin); | ||
// run it | ||
// whether bin file is a js script with explicit `.js` extension | ||
var isExplicitJS = false; | ||
if (exists(localBin + '.js')) { | ||
bin = localBin + '.js'; | ||
isExplicitJS = true; | ||
} else if (exists(localBin)) { | ||
bin = localBin; | ||
} | ||
args = args.slice(1); | ||
@@ -499,5 +529,13 @@ | ||
if (process.platform !== 'win32') { | ||
proc = spawn(bin, args, { stdio: 'inherit', customFds: [0, 1, 2] }); | ||
if (isExplicitJS) { | ||
args.unshift(localBin); | ||
// add executable arguments to spawn | ||
args = (process.execArgv || []).concat(args); | ||
proc = spawn('node', args, { stdio: 'inherit', customFds: [0, 1, 2] }); | ||
} else { | ||
proc = spawn(bin, args, { stdio: 'inherit', customFds: [0, 1, 2] }); | ||
} | ||
} else { | ||
args.unshift(local); | ||
args.unshift(localBin); | ||
proc = spawn(process.execPath, args, { stdio: 'inherit'}); | ||
@@ -883,3 +921,3 @@ } | ||
.concat(this.options.map(function(option) { | ||
return pad(option.flags, width) + ' ' + option.description; | ||
return pad(option.flags, width) + ' ' + offset(option.description, width + 2); | ||
})) | ||
@@ -899,3 +937,5 @@ .join('\n'); | ||
var commands = this.commands.map(function(cmd) { | ||
var commands = this.commands.filter(function(cmd) { | ||
return !cmd._noHelp; | ||
}).map(function(cmd) { | ||
var args = cmd._args.map(function(arg) { | ||
@@ -927,3 +967,3 @@ return humanReadableArgName(arg); | ||
, commands.map(function(cmd) { | ||
return pad(cmd[0], width) + ' ' + cmd[1]; | ||
return pad(cmd[0], width) + ' ' + offset(cmd[1], width + 2); | ||
}).join('\n').replace(/^/gm, ' ') | ||
@@ -956,3 +996,3 @@ , '' | ||
'' | ||
,' Usage: ' + cmdName + ' ' + this.usage() | ||
,' Usage: ' + cmdName + ' ' + offset(this.usage(), 9) | ||
, '' | ||
@@ -1031,2 +1071,19 @@ ]; | ||
/** | ||
* Prepend to each line of `str` spaced string of `offset` length. | ||
* | ||
* @param {String} str | ||
* @param {Number} offset | ||
* @param {Boolean} skipFirstLine | ||
* @return {String} | ||
* @api private | ||
*/ | ||
function offset(str, offset, skipFirstLine) { | ||
var res = String(str || '').replace(/^/gm, pad('', offset)); | ||
if (!skipFirstLine) { | ||
res = res.replace(/^\s+/, ''); | ||
} | ||
return res; | ||
} | ||
/** | ||
* Output help information if necessary | ||
@@ -1045,2 +1102,5 @@ * | ||
process.exit(0); | ||
// used for test flow only | ||
options.splice(i, 1); | ||
} | ||
@@ -1065,1 +1125,13 @@ } | ||
} | ||
// for versions before node v0.8 when there weren't `fs.existsSync` | ||
function exists(file) { | ||
try { | ||
if (fs.statSync(file).isFile()) { | ||
return true; | ||
} | ||
} catch (e) { | ||
return false; | ||
} | ||
} | ||
{ | ||
"name": "commander", | ||
"version": "2.7.1", | ||
"version": "2.8.0", | ||
"description": "the complete solution for node.js command-line programs", | ||
@@ -17,3 +17,4 @@ "keywords": [ | ||
"devDependencies": { | ||
"should": ">= 0.0.1" | ||
"should": ">= 0.0.1", | ||
"sinon": ">= 1.13.0" | ||
}, | ||
@@ -20,0 +21,0 @@ "scripts": { |
@@ -34,3 +34,3 @@ # Commander.js | ||
.option('-P, --pineapple', 'Add pineapple') | ||
.option('-b, --bbq', 'Add bbq sauce') | ||
.option('-b, --bbq-sauce', 'Add bbq sauce') | ||
.option('-c, --cheese [type]', 'Add the specified type of cheese [marble]', 'marble') | ||
@@ -42,3 +42,3 @@ .parse(process.argv); | ||
if (program.pineapple) console.log(' - pineapple'); | ||
if (program.bbq) console.log(' - bbq'); | ||
if (program.bbqSauce) console.log(' - bbq'); | ||
console.log(' - %s cheese', program.cheese); | ||
@@ -137,2 +137,27 @@ ``` | ||
## Specify the argument syntax | ||
```js | ||
#!/usr/bin/env node | ||
var program = require('../'); | ||
program | ||
.version('0.0.1') | ||
.arguments('<cmd> [env]') | ||
.action(function (cmd, env) { | ||
cmdValue = cmd; | ||
envValue = env; | ||
}); | ||
program.parse(process.argv); | ||
if (typeof cmdValue === 'undefined') { | ||
console.error('no command given!'); | ||
process.exit(1); | ||
} | ||
console.log('command:', cmdValue); | ||
console.log('environment:', envValue || "no environment given"); | ||
``` | ||
## Git-style sub-commands | ||
@@ -155,4 +180,10 @@ | ||
If the program is designed to installed globally, make sure the executables have proper modes, like `755`. | ||
If the program is designed to be installed globally, make sure the executables have proper modes, like `755`. | ||
### `--harmony` | ||
You can enable `--harmony` option in two ways: | ||
* Use `#! /usr/bin/env node --harmony` in the sub-commands scripts. Note some os version don’t support this pattern. | ||
* Use the `--harmony` option when call the command, like `node --harmony examples/pm publish`. The `--harmony` option will be preserved when spawning sub-command process. | ||
## Automated --help | ||
@@ -176,3 +207,4 @@ | ||
-b, --bbq Add bbq sauce | ||
-c, --cheese <type> Add the specified type of cheese [marble] | ||
-c, --cheese <type> Add the specified type | ||
of cheese [marble] | ||
-C, --no-cheese You do not want any cheese | ||
@@ -179,0 +211,0 @@ |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
42263
968
344
2