commander 2.5.0 → 2.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (5) hide show
  1. package/History.md +239 -0
  2. package/LICENSE +22 -0
  3. package/Readme.md +146 -74
  4. package/index.js +96 -26
  5. package/package.json +30 -12
package/History.md ADDED
@@ -0,0 +1,239 @@
1
+
2
+ 2.7.1 / 2015-03-11
3
+ ==================
4
+
5
+ * Revert #347 (fix collisions when option and first arg have same name) which causes a bug in #367.
6
+
7
+ 2.7.0 / 2015-03-09
8
+ ==================
9
+
10
+ * Fix git-style bug when installed globally. Close #335 #349 @zhiyelee
11
+ * Fix collisions when option and first arg have same name. Close #346 #347 @tonylukasavage
12
+ * Add support for camelCase on `opts()`. Close #353 @nkzawa
13
+ * Add node.js 0.12 and io.js to travis.yml
14
+ * Allow RegEx options. #337 @palanik
15
+ * Fixes exit code when sub-command failing. Close #260 #332 @pirelenito
16
+ * git-style `bin` files in $PATH make sense. Close #196 #327 @zhiyelee
17
+
18
+ 2.6.0 / 2014-12-30
19
+ ==================
20
+
21
+ * added `Command#allowUnknownOption` method. Close #138 #318 @doozr @zhiyelee
22
+ * Add application description to the help msg. Close #112 @dalssoft
23
+
24
+ 2.5.1 / 2014-12-15
25
+ ==================
26
+
27
+ * fixed two bugs incurred by variadic arguments. Close #291 @Quentin01 #302 @zhiyelee
28
+
29
+ 2.5.0 / 2014-10-24
30
+ ==================
31
+
32
+ * add support for variadic arguments. Closes #277 @whitlockjc
33
+
34
+ 2.4.0 / 2014-10-17
35
+ ==================
36
+
37
+ * fixed a bug on executing the coercion function of subcommands option. Closes #270
38
+ * added `Command.prototype.name` to retrieve command name. Closes #264 #266 @tonylukasavage
39
+ * added `Command.prototype.opts` to retrieve all the options as a simple object of key-value pairs. Closes #262 @tonylukasavage
40
+ * fixed a bug on subcommand name. Closes #248 @jonathandelgado
41
+ * fixed function normalize doesn’t honor option terminator. Closes #216 @abbr
42
+
43
+ 2.3.0 / 2014-07-16
44
+ ==================
45
+
46
+ * add command alias'. Closes PR #210
47
+ * fix: Typos. Closes #99
48
+ * fix: Unused fs module. Closes #217
49
+
50
+ 2.2.0 / 2014-03-29
51
+ ==================
52
+
53
+ * add passing of previous option value
54
+ * fix: support subcommands on windows. Closes #142
55
+ * Now the defaultValue passed as the second argument of the coercion function.
56
+
57
+ 2.1.0 / 2013-11-21
58
+ ==================
59
+
60
+ * add: allow cflag style option params, unit test, fixes #174
61
+
62
+ 2.0.0 / 2013-07-18
63
+ ==================
64
+
65
+ * remove input methods (.prompt, .confirm, etc)
66
+
67
+ 1.3.2 / 2013-07-18
68
+ ==================
69
+
70
+ * add support for sub-commands to co-exist with the original command
71
+
72
+ 1.3.1 / 2013-07-18
73
+ ==================
74
+
75
+ * add quick .runningCommand hack so you can opt-out of other logic when running a sub command
76
+
77
+ 1.3.0 / 2013-07-09
78
+ ==================
79
+
80
+ * add EACCES error handling
81
+ * fix sub-command --help
82
+
83
+ 1.2.0 / 2013-06-13
84
+ ==================
85
+
86
+ * allow "-" hyphen as an option argument
87
+ * support for RegExp coercion
88
+
89
+ 1.1.1 / 2012-11-20
90
+ ==================
91
+
92
+ * add more sub-command padding
93
+ * fix .usage() when args are present. Closes #106
94
+
95
+ 1.1.0 / 2012-11-16
96
+ ==================
97
+
98
+ * add git-style executable subcommand support. Closes #94
99
+
100
+ 1.0.5 / 2012-10-09
101
+ ==================
102
+
103
+ * fix `--name` clobbering. Closes #92
104
+ * fix examples/help. Closes #89
105
+
106
+ 1.0.4 / 2012-09-03
107
+ ==================
108
+
109
+ * add `outputHelp()` method.
110
+
111
+ 1.0.3 / 2012-08-30
112
+ ==================
113
+
114
+ * remove invalid .version() defaulting
115
+
116
+ 1.0.2 / 2012-08-24
117
+ ==================
118
+
119
+ * add `--foo=bar` support [arv]
120
+ * fix password on node 0.8.8. Make backward compatible with 0.6 [focusaurus]
121
+
122
+ 1.0.1 / 2012-08-03
123
+ ==================
124
+
125
+ * fix issue #56
126
+ * fix tty.setRawMode(mode) was moved to tty.ReadStream#setRawMode() (i.e. process.stdin.setRawMode())
127
+
128
+ 1.0.0 / 2012-07-05
129
+ ==================
130
+
131
+ * add support for optional option descriptions
132
+ * add defaulting of `.version()` to package.json's version
133
+
134
+ 0.6.1 / 2012-06-01
135
+ ==================
136
+
137
+ * Added: append (yes or no) on confirmation
138
+ * Added: allow node.js v0.7.x
139
+
140
+ 0.6.0 / 2012-04-10
141
+ ==================
142
+
143
+ * Added `.prompt(obj, callback)` support. Closes #49
144
+ * Added default support to .choose(). Closes #41
145
+ * Fixed the choice example
146
+
147
+ 0.5.1 / 2011-12-20
148
+ ==================
149
+
150
+ * Fixed `password()` for recent nodes. Closes #36
151
+
152
+ 0.5.0 / 2011-12-04
153
+ ==================
154
+
155
+ * Added sub-command option support [itay]
156
+
157
+ 0.4.3 / 2011-12-04
158
+ ==================
159
+
160
+ * Fixed custom help ordering. Closes #32
161
+
162
+ 0.4.2 / 2011-11-24
163
+ ==================
164
+
165
+ * Added travis support
166
+ * Fixed: line-buffered input automatically trimmed. Closes #31
167
+
168
+ 0.4.1 / 2011-11-18
169
+ ==================
170
+
171
+ * Removed listening for "close" on --help
172
+
173
+ 0.4.0 / 2011-11-15
174
+ ==================
175
+
176
+ * Added support for `--`. Closes #24
177
+
178
+ 0.3.3 / 2011-11-14
179
+ ==================
180
+
181
+ * Fixed: wait for close event when writing help info [Jerry Hamlet]
182
+
183
+ 0.3.2 / 2011-11-01
184
+ ==================
185
+
186
+ * Fixed long flag definitions with values [felixge]
187
+
188
+ 0.3.1 / 2011-10-31
189
+ ==================
190
+
191
+ * Changed `--version` short flag to `-V` from `-v`
192
+ * Changed `.version()` so it's configurable [felixge]
193
+
194
+ 0.3.0 / 2011-10-31
195
+ ==================
196
+
197
+ * Added support for long flags only. Closes #18
198
+
199
+ 0.2.1 / 2011-10-24
200
+ ==================
201
+
202
+ * "node": ">= 0.4.x < 0.7.0". Closes #20
203
+
204
+ 0.2.0 / 2011-09-26
205
+ ==================
206
+
207
+ * Allow for defaults that are not just boolean. Default peassignment only occurs for --no-*, optional, and required arguments. [Jim Isaacs]
208
+
209
+ 0.1.0 / 2011-08-24
210
+ ==================
211
+
212
+ * Added support for custom `--help` output
213
+
214
+ 0.0.5 / 2011-08-18
215
+ ==================
216
+
217
+ * Changed: when the user enters nothing prompt for password again
218
+ * Fixed issue with passwords beginning with numbers [NuckChorris]
219
+
220
+ 0.0.4 / 2011-08-15
221
+ ==================
222
+
223
+ * Fixed `Commander#args`
224
+
225
+ 0.0.3 / 2011-08-15
226
+ ==================
227
+
228
+ * Added default option value support
229
+
230
+ 0.0.2 / 2011-08-15
231
+ ==================
232
+
233
+ * Added mask support to `Command#password(str[, mask], fn)`
234
+ * Added `Command#password(str, fn)`
235
+
236
+ 0.0.1 / 2010-01-03
237
+ ==================
238
+
239
+ * Initial release
package/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ (The MIT License)
2
+
3
+ Copyright (c) 2011 TJ Holowaychuk <tj@vision-media.ca>
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ 'Software'), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
20
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
package/Readme.md CHANGED
@@ -1,10 +1,13 @@
1
1
  # Commander.js
2
2
 
3
- [![Build Status](https://api.travis-ci.org/tj/commander.js.svg)](http://travis-ci.org/tj/commander.js)
3
+
4
+ [![Build Status](https://api.travis-ci.org/tj/commander.js.svg)](http://travis-ci.org/tj/commander.js)
4
5
  [![NPM Version](http://img.shields.io/npm/v/commander.svg?style=flat)](https://www.npmjs.org/package/commander)
5
6
  [![NPM Downloads](https://img.shields.io/npm/dm/commander.svg?style=flat)](https://www.npmjs.org/package/commander)
7
+ [![Join the chat at https://gitter.im/tj/commander.js](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/tj/commander.js?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
6
8
 
7
- The complete solution for [node.js](http://nodejs.org) command-line interfaces, inspired by Ruby's [commander](https://github.com/tj/commander).
9
+ The complete solution for [node.js](http://nodejs.org) command-line interfaces, inspired by Ruby's [commander](https://github.com/tj/commander).
10
+ [API documentation](http://tj.github.com/commander.js/)
8
11
 
9
12
 
10
13
  ## Installation
@@ -41,6 +44,62 @@ console.log(' - %s cheese', program.cheese);
41
44
 
42
45
  Short flags may be passed as a single arg, for example `-abc` is equivalent to `-a -b -c`. Multi-word options such as "--template-engine" are camel-cased, becoming `program.templateEngine` etc.
43
46
 
47
+
48
+ ## Coercion
49
+
50
+ ```js
51
+ function range(val) {
52
+ return val.split('..').map(Number);
53
+ }
54
+
55
+ function list(val) {
56
+ return val.split(',');
57
+ }
58
+
59
+ function collect(val, memo) {
60
+ memo.push(val);
61
+ return memo;
62
+ }
63
+
64
+ function increaseVerbosity(v, total) {
65
+ return total + 1;
66
+ }
67
+
68
+ program
69
+ .version('0.0.1')
70
+ .usage('[options] <file ...>')
71
+ .option('-i, --integer <n>', 'An integer argument', parseInt)
72
+ .option('-f, --float <n>', 'A float argument', parseFloat)
73
+ .option('-r, --range <a>..<b>', 'A range', range)
74
+ .option('-l, --list <items>', 'A list', list)
75
+ .option('-o, --optional [value]', 'An optional value')
76
+ .option('-c, --collect [value]', 'A repeatable value', collect, [])
77
+ .option('-v, --verbose', 'A value that can be increased', increaseVerbosity, 0)
78
+ .parse(process.argv);
79
+
80
+ console.log(' int: %j', program.integer);
81
+ console.log(' float: %j', program.float);
82
+ console.log(' optional: %j', program.optional);
83
+ program.range = program.range || [];
84
+ console.log(' range: %j..%j', program.range[0], program.range[1]);
85
+ console.log(' list: %j', program.list);
86
+ console.log(' collect: %j', program.collect);
87
+ console.log(' verbosity: %j', program.verbose);
88
+ console.log(' args: %j', program.args);
89
+ ```
90
+
91
+ ## Regular Expression
92
+ ```js
93
+ program
94
+ .version('0.0.1')
95
+ .option('-s --size <size>', 'Pizza size', /^(large|medium|small)$/i, 'medium')
96
+ .option('-d --drink [drink]', 'Drink', /^(coke|pepsi|izze)$/i)
97
+ .parse(process.argv);
98
+
99
+ console.log(' size: %j', program.size);
100
+ console.log(' drink: %j', program.drink);
101
+ ```
102
+
44
103
  ## Variadic arguments
45
104
 
46
105
  The last argument of a command can be variadic, and only the last argument. To make an argument variadic you have to
@@ -73,6 +132,25 @@ program.parse(process.argv);
73
132
  An `Array` is used for the value of a variadic argument. This applies to `program.args` as well as the argument passed
74
133
  to your action as demonstrated above.
75
134
 
135
+ ## Git-style sub-commands
136
+
137
+ ```js
138
+ // file: ./examples/pm
139
+ var program = require('..');
140
+
141
+ program
142
+ .version('0.0.1')
143
+ .command('install [name]', 'install one or more packages')
144
+ .command('search [query]', 'search with optional query')
145
+ .command('list', 'list packages installed')
146
+ .parse(process.argv);
147
+ ```
148
+
149
+ When `.command()` is invoked with a description argument, no `.action(callback)` should be called to handle sub-commands, otherwise there will be an error. This tells commander that you're going to use separate executables for sub-commands, much like `git(1)` and other popular tools.
150
+ The commander will try to search the executables in the directory of the entry script (like `./examples/pm`) with the name `program-command`, like `pm-install`, `pm-search`.
151
+
152
+ If the program is designed to installed globally, make sure the executables have proper modes, like `755`.
153
+
76
154
  ## Automated --help
77
155
 
78
156
  The help information is auto-generated based on the information commander already knows about your program, so the following `--help` info is for free:
@@ -82,60 +160,20 @@ program.parse(process.argv);
82
160
 
83
161
  Usage: pizza [options]
84
162
 
163
+ An application for pizzas ordering
164
+
85
165
  Options:
86
166
 
167
+ -h, --help output usage information
87
168
  -V, --version output the version number
88
169
  -p, --peppers Add peppers
89
170
  -P, --pineapple Add pineapple
90
171
  -b, --bbq Add bbq sauce
91
172
  -c, --cheese <type> Add the specified type of cheese [marble]
92
- -h, --help output usage information
173
+ -C, --no-cheese You do not want any cheese
93
174
 
94
175
  ```
95
176
 
96
- ## Coercion
97
-
98
- ```js
99
- function range(val) {
100
- return val.split('..').map(Number);
101
- }
102
-
103
- function list(val) {
104
- return val.split(',');
105
- }
106
-
107
- function collect(val, memo) {
108
- memo.push(val);
109
- return memo;
110
- }
111
-
112
- function increaseVerbosity(v, total) {
113
- return total + 1;
114
- }
115
-
116
- program
117
- .version('0.0.1')
118
- .usage('[options] <file ...>')
119
- .option('-i, --integer <n>', 'An integer argument', parseInt)
120
- .option('-f, --float <n>', 'A float argument', parseFloat)
121
- .option('-r, --range <a>..<b>', 'A range', range)
122
- .option('-l, --list <items>', 'A list', list)
123
- .option('-o, --optional [value]', 'An optional value')
124
- .option('-c, --collect [value]', 'A repeatable value', collect, [])
125
- .option('-v, --verbose', 'A value that can be increased', increaseVerbosity, 0)
126
- .parse(process.argv);
127
-
128
- console.log(' int: %j', program.integer);
129
- console.log(' float: %j', program.float);
130
- console.log(' optional: %j', program.optional);
131
- program.range = program.range || [];
132
- console.log(' range: %j..%j', program.range[0], program.range[1]);
133
- console.log(' list: %j', program.list);
134
- console.log(' collect: %j', program.collect);
135
- console.log(' verbosity: %j', program.verbose);
136
- console.log(' args: %j', program.args);
137
- ```
138
-
139
177
  ## Custom help
140
178
 
141
179
  You can display arbitrary `-h, --help` information
@@ -152,7 +190,7 @@ console.log(' args: %j', program.args);
152
190
  * Module dependencies.
153
191
  */
154
192
 
155
- var program = require('../');
193
+ var program = require('commander');
156
194
 
157
195
  program
158
196
  .version('0.0.1')
@@ -176,7 +214,7 @@ program.parse(process.argv);
176
214
  console.log('stuff');
177
215
  ```
178
216
 
179
- yielding the following help output:
217
+ Yields the following help output when `node script-name.js -h` or `node script-name.js --help` are run:
180
218
 
181
219
  ```
182
220
 
@@ -199,41 +237,75 @@ Examples:
199
237
 
200
238
  ## .outputHelp()
201
239
 
202
- Output help information without exiting.
240
+ Output help information without exiting.
241
+
242
+ If you want to display help by default (e.g. if no command was provided), you can use something like:
243
+
244
+ ```js
245
+ var program = require('commander');
246
+
247
+ program
248
+ .version('0.0.1')
249
+ .command('getstream [url]', 'get stream URL')
250
+ .parse(process.argv);
251
+
252
+ if (!process.argv.slice(2).length) {
253
+ program.outputHelp();
254
+ }
255
+ ```
203
256
 
204
257
  ## .help()
205
258
 
206
259
  Output help information and exit immediately.
207
260
 
208
- ## Links
261
+ ## Examples
209
262
 
210
- - [API documentation](http://tj.github.com/commander.js/)
211
- - [ascii tables](https://github.com/LearnBoost/cli-table)
212
- - [progress bars](https://github.com/tj/node-progress)
213
- - [more progress bars](https://github.com/substack/node-multimeter)
214
- - [examples](https://github.com/tj/commander.js/tree/master/examples)
263
+ ```js
264
+ var program = require('commander');
215
265
 
216
- ## License
266
+ program
267
+ .version('0.0.1')
268
+ .option('-C, --chdir <path>', 'change the working directory')
269
+ .option('-c, --config <path>', 'set config path. defaults to ./deploy.conf')
270
+ .option('-T, --no-tests', 'ignore test hook')
271
+
272
+ program
273
+ .command('setup [env]')
274
+ .description('run setup commands for all envs')
275
+ .option("-s, --setup_mode [mode]", "Which setup mode to use")
276
+ .action(function(env, options){
277
+ var mode = options.setup_mode || "normal";
278
+ env = env || 'all';
279
+ console.log('setup for %s env(s) with %s mode', env, mode);
280
+ });
281
+
282
+ program
283
+ .command('exec <cmd>')
284
+ .alias('ex')
285
+ .description('execute the given remote cmd')
286
+ .option("-e, --exec_mode <mode>", "Which exec mode to use")
287
+ .action(function(cmd, options){
288
+ console.log('exec "%s" using %s mode', cmd, options.exec_mode);
289
+ }).on('--help', function() {
290
+ console.log(' Examples:');
291
+ console.log();
292
+ console.log(' $ deploy exec sequential');
293
+ console.log(' $ deploy exec async');
294
+ console.log();
295
+ });
296
+
297
+ program
298
+ .command('*')
299
+ .action(function(env){
300
+ console.log('deploying "%s"', env);
301
+ });
217
302
 
218
- (The MIT License)
303
+ program.parse(process.argv);
304
+ ```
219
305
 
220
- Copyright (c) 2011 TJ Holowaychuk &lt;tj@vision-media.ca&gt;
306
+ More Demos can be found in the [examples](https://github.com/tj/commander.js/tree/master/examples) directory.
221
307
 
222
- Permission is hereby granted, free of charge, to any person obtaining
223
- a copy of this software and associated documentation files (the
224
- 'Software'), to deal in the Software without restriction, including
225
- without limitation the rights to use, copy, modify, merge, publish,
226
- distribute, sublicense, and/or sell copies of the Software, and to
227
- permit persons to whom the Software is furnished to do so, subject to
228
- the following conditions:
308
+ ## License
229
309
 
230
- The above copyright notice and this permission notice shall be
231
- included in all copies or substantial portions of the Software.
310
+ MIT
232
311
 
233
- THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
234
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
235
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
236
- IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
237
- CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
238
- TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
239
- SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
package/index.js CHANGED
@@ -5,9 +5,11 @@
5
5
 
6
6
  var EventEmitter = require('events').EventEmitter;
7
7
  var spawn = require('child_process').spawn;
8
+ var readlink = require('graceful-readlink').readlinkSync;
8
9
  var path = require('path');
9
10
  var dirname = path.dirname;
10
11
  var basename = path.basename;
12
+ var fs = require('fs');
11
13
 
12
14
  /**
13
15
  * Expose the root command.
@@ -82,6 +84,7 @@ function Command(name) {
82
84
  this.commands = [];
83
85
  this.options = [];
84
86
  this._execs = [];
87
+ this._allowUnknownOption = false;
85
88
  this._args = [];
86
89
  this._name = name;
87
90
  }
@@ -148,7 +151,7 @@ Command.prototype.__proto__ = EventEmitter.prototype;
148
151
  * program.parse(process.argv);
149
152
  *
150
153
  * @param {String} name
151
- * @param {String} [desc]
154
+ * @param {String} [desc] for git-style sub-commands
152
155
  * @return {Command} the new command
153
156
  * @api public
154
157
  */
@@ -156,12 +159,17 @@ Command.prototype.__proto__ = EventEmitter.prototype;
156
159
  Command.prototype.command = function(name, desc) {
157
160
  var args = name.split(/ +/);
158
161
  var cmd = new Command(args.shift());
159
- if (desc) cmd.description(desc);
160
- if (desc) this.executables = true;
161
- if (desc) this._execs[cmd._name] = true;
162
+
163
+ if (desc) {
164
+ cmd.description(desc);
165
+ this.executables = true;
166
+ this._execs[cmd._name] = true;
167
+ }
168
+
162
169
  this.commands.push(cmd);
163
170
  cmd.parseExpectedArgs(args);
164
171
  cmd.parent = this;
172
+
165
173
  if (desc) return this;
166
174
  return cmd;
167
175
  };
@@ -207,11 +215,10 @@ Command.prototype.parseExpectedArgs = function(args) {
207
215
  break;
208
216
  }
209
217
 
210
- if (argDetails.name.indexOf('...') === argDetails.name.length - 3) {
218
+ if (argDetails.name.length > 3 && argDetails.name.slice(-3) === '...') {
211
219
  argDetails.variadic = true;
212
220
  argDetails.name = argDetails.name.slice(0, -3);
213
221
  }
214
-
215
222
  if (argDetails.name) {
216
223
  self._args.push(argDetails);
217
224
  }
@@ -266,7 +273,7 @@ Command.prototype.action = function(fn) {
266
273
  self.variadicArgNotLast(arg.name);
267
274
  }
268
275
 
269
- args[i] = args.slice(i);
276
+ args[i] = args.splice(i);
270
277
  }
271
278
  });
272
279
 
@@ -343,8 +350,17 @@ Command.prototype.option = function(flags, description, fn, defaultValue) {
343
350
 
344
351
  // default as 3rd arg
345
352
  if (typeof fn != 'function') {
346
- defaultValue = fn;
347
- fn = null;
353
+ if (fn instanceof RegExp) {
354
+ var regex = fn;
355
+ fn = function(val, def) {
356
+ var m = regex.exec(val);
357
+ return m ? m[0] : def;
358
+ }
359
+ }
360
+ else {
361
+ defaultValue = fn;
362
+ fn = null;
363
+ }
348
364
  }
349
365
 
350
366
  // preassign default value only for --no-*, [optional], or <required>
@@ -385,6 +401,18 @@ Command.prototype.option = function(flags, description, fn, defaultValue) {
385
401
  return this;
386
402
  };
387
403
 
404
+ /**
405
+ * Allow unknown options on the command line.
406
+ *
407
+ * @param {Boolean} arg if `true` or omitted, no error will be thrown
408
+ * for unknown options.
409
+ * @api public
410
+ */
411
+ Command.prototype.allowUnknownOption = function(arg) {
412
+ this._allowUnknownOption = arguments.length === 0 || arg;
413
+ return this;
414
+ };
415
+
388
416
  /**
389
417
  * Parse `argv`, settings options and invoking commands when defined.
390
418
  *
@@ -440,22 +468,42 @@ Command.prototype.executeSubCommand = function(argv, args, unknown) {
440
468
  }
441
469
 
442
470
  // executable
443
- var dir = dirname(argv[1]);
444
- var bin = basename(argv[1], '.js') + '-' + args[0];
471
+ var f = argv[1];
472
+ var link = readlink(f);
473
+ if (link !== f && link.charAt(0) !== '/') {
474
+ link = path.join(dirname(f), link)
475
+ }
476
+ var dir = dirname(link);
477
+ var bin = basename(f, '.js') + '-' + args[0];
445
478
 
446
- // check for ./<bin> first
479
+ // prefer local `./<bin>` to bin in the $PATH
447
480
  var local = path.join(dir, bin);
481
+ try {
482
+ // for versions before node v0.8 when there weren't `fs.existsSync`
483
+ if (fs.statSync(local).isFile()) {
484
+ bin = local;
485
+ }
486
+ } catch (e) {}
448
487
 
449
488
  // run it
450
489
  args = args.slice(1);
451
- args.unshift(local);
452
- var proc = spawn('node', args, { stdio: 'inherit', customFds: [0, 1, 2] });
490
+
491
+ var proc;
492
+ if (process.platform !== 'win32') {
493
+ proc = spawn(bin, args, { stdio: 'inherit', customFds: [0, 1, 2] });
494
+ } else {
495
+ args.unshift(local);
496
+ proc = spawn(process.execPath, args, { stdio: 'inherit'});
497
+ }
498
+
499
+ proc.on('close', process.exit.bind(process));
453
500
  proc.on('error', function(err) {
454
501
  if (err.code == "ENOENT") {
455
502
  console.error('\n %s(1) does not exist, try --help\n', bin);
456
503
  } else if (err.code == "EACCES") {
457
504
  console.error('\n %s(1) not executable. try chmod or run with root\n', bin);
458
505
  }
506
+ process.exit(1);
459
507
  });
460
508
 
461
509
  this.runningCommand = proc;
@@ -644,7 +692,7 @@ Command.prototype.opts = function() {
644
692
  , len = this.options.length;
645
693
 
646
694
  for (var i = 0 ; i < len; i++) {
647
- var key = this.options[i].name();
695
+ var key = camelcase(this.options[i].name());
648
696
  result[key] = key === 'version' ? this._version : this[key];
649
697
  }
650
698
  return result;
@@ -691,6 +739,7 @@ Command.prototype.optionMissingArgument = function(option, flag) {
691
739
  */
692
740
 
693
741
  Command.prototype.unknownOption = function(flag) {
742
+ if (this._allowUnknownOption) return;
694
743
  console.error();
695
744
  console.error(" error: unknown option `%s'", flag);
696
745
  console.error();
@@ -794,7 +843,7 @@ Command.prototype.usage = function(str) {
794
843
  * @api public
795
844
  */
796
845
 
797
- Command.prototype.name = function(name) {
846
+ Command.prototype.name = function() {
798
847
  return this._name;
799
848
  };
800
849
 
@@ -880,20 +929,41 @@ Command.prototype.commandHelp = function() {
880
929
  */
881
930
 
882
931
  Command.prototype.helpInformation = function() {
883
- return [
884
- ''
885
- , ' Usage: ' + this._name
886
- + (this._alias
887
- ? '|' + this._alias
888
- : '')
889
- + ' ' + this.usage()
890
- , '' + this.commandHelp()
891
- , ' Options:'
932
+ var desc = [];
933
+ if (this._description) {
934
+ desc = [
935
+ ' ' + this._description
936
+ , ''
937
+ ];
938
+ }
939
+
940
+ var cmdName = this._name;
941
+ if (this._alias) {
942
+ cmdName = cmdName + '|' + this._alias;
943
+ }
944
+ var usage = [
945
+ ''
946
+ ,' Usage: ' + cmdName + ' ' + this.usage()
947
+ , ''
948
+ ];
949
+
950
+ var cmds = [];
951
+ var commandHelp = this.commandHelp();
952
+ if (commandHelp) cmds = [commandHelp];
953
+
954
+ var options = [
955
+ ' Options:'
892
956
  , ''
893
957
  , '' + this.optionHelp().replace(/^/gm, ' ')
894
958
  , ''
895
959
  , ''
896
- ].join('\n');
960
+ ];
961
+
962
+ return usage
963
+ .concat(cmds)
964
+ .concat(desc)
965
+ .concat(options)
966
+ .join('\n');
897
967
  };
898
968
 
899
969
  /**
package/package.json CHANGED
@@ -1,14 +1,32 @@
1
1
  {
2
- "name": "commander"
3
- , "version": "2.5.0"
4
- , "description": "the complete solution for node.js command-line programs"
5
- , "keywords": ["command", "option", "parser", "prompt"]
6
- , "author": "TJ Holowaychuk <tj@vision-media.ca>"
7
- , "license": "MIT"
8
- , "repository": { "type": "git", "url": "https://github.com/tj/commander.js.git" }
9
- , "devDependencies": { "should": ">= 0.0.1" }
10
- , "scripts": { "test": "make test" }
11
- , "main": "index"
12
- , "engines": { "node": ">= 0.6.x" }
13
- , "files": ["index.js"]
2
+ "name": "commander",
3
+ "version": "2.7.1",
4
+ "description": "the complete solution for node.js command-line programs",
5
+ "keywords": [
6
+ "command",
7
+ "option",
8
+ "parser"
9
+ ],
10
+ "author": "TJ Holowaychuk <tj@vision-media.ca>",
11
+ "license": "MIT",
12
+ "repository": {
13
+ "type": "git",
14
+ "url": "https://github.com/tj/commander.js.git"
15
+ },
16
+ "devDependencies": {
17
+ "should": ">= 0.0.1"
18
+ },
19
+ "scripts": {
20
+ "test": "make test"
21
+ },
22
+ "main": "index",
23
+ "engines": {
24
+ "node": ">= 0.6.x"
25
+ },
26
+ "files": [
27
+ "index.js"
28
+ ],
29
+ "dependencies": {
30
+ "graceful-readlink": ">= 1.0.0"
31
+ }
14
32
  }