commander 2.9.0 → 2.12.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.
@@ -1,4 +1,64 @@
1
1
 
2
+ 2.12.1 / 2017-11-23
3
+ ==================
4
+
5
+ * Move @types/node to dev dependency
6
+
7
+ 2.12.0 / 2017-11-22
8
+ ==================
9
+
10
+ * add attributeName() method to Option objects
11
+ * Documentation updated for options with --no prefix
12
+ * typings: `outputHelp` takes a string as the first parameter
13
+ * typings: use overloads
14
+ * feat(typings): update to match js api
15
+ * Print default value in option help
16
+ * Fix translation error
17
+ * Fail when using same command and alias (#491)
18
+ * feat(typings): add help callback
19
+ * fix bug when description is add after command with options (#662)
20
+ * Format js code
21
+ * Rename History.md to CHANGELOG.md (#668)
22
+ * feat(typings): add typings to support TypeScript (#646)
23
+ * use current node
24
+
25
+ 2.11.0 / 2017-07-03
26
+ ==================
27
+
28
+ * Fix help section order and padding (#652)
29
+ * feature: support for signals to subcommands (#632)
30
+ * Fixed #37, --help should not display first (#447)
31
+ * Fix translation errors. (#570)
32
+ * Add package-lock.json
33
+ * Remove engines
34
+ * Upgrade package version
35
+ * Prefix events to prevent conflicts between commands and options (#494)
36
+ * Removing dependency on graceful-readlink
37
+ * Support setting name in #name function and make it chainable
38
+ * Add .vscode directory to .gitignore (Visual Studio Code metadata)
39
+ * Updated link to ruby commander in readme files
40
+
41
+ 2.10.0 / 2017-06-19
42
+ ==================
43
+
44
+ * Update .travis.yml. drop support for older node.js versions.
45
+ * Fix require arguments in README.md
46
+ * On SemVer you do not start from 0.0.1
47
+ * Add missing semi colon in readme
48
+ * Add save param to npm install
49
+ * node v6 travis test
50
+ * Update Readme_zh-CN.md
51
+ * Allow literal '--' to be passed-through as an argument
52
+ * Test subcommand alias help
53
+ * link build badge to master branch
54
+ * Support the alias of Git style sub-command
55
+ * added keyword commander for better search result on npm
56
+ * Fix Sub-Subcommands
57
+ * test node.js stable
58
+ * Fixes TypeError when a command has an option called `--description`
59
+ * Update README.md to make it beginner friendly and elaborate on the difference between angled and square brackets.
60
+ * Add chinese Readme file
61
+
2
62
  2.9.0 / 2015-10-13
3
63
  ==================
4
64
 
package/Readme.md CHANGED
@@ -1,18 +1,18 @@
1
1
  # Commander.js
2
2
 
3
3
 
4
- [![Build Status](https://api.travis-ci.org/tj/commander.js.svg)](http://travis-ci.org/tj/commander.js)
4
+ [![Build Status](https://api.travis-ci.org/tj/commander.js.svg?branch=master)](http://travis-ci.org/tj/commander.js)
5
5
  [![NPM Version](http://img.shields.io/npm/v/commander.svg?style=flat)](https://www.npmjs.org/package/commander)
6
6
  [![NPM Downloads](https://img.shields.io/npm/dm/commander.svg?style=flat)](https://www.npmjs.org/package/commander)
7
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)
8
8
 
9
- 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/commander-rb/commander).
10
10
  [API documentation](http://tj.github.com/commander.js/)
11
11
 
12
12
 
13
13
  ## Installation
14
14
 
15
- $ npm install commander
15
+ $ npm install commander --save
16
16
 
17
17
  ## Option parsing
18
18
 
@@ -28,7 +28,7 @@
28
28
  var program = require('commander');
29
29
 
30
30
  program
31
- .version('0.0.1')
31
+ .version('0.1.0')
32
32
  .option('-p, --peppers', 'Add peppers')
33
33
  .option('-P, --pineapple', 'Add pineapple')
34
34
  .option('-b, --bbq-sauce', 'Add bbq sauce')
@@ -44,6 +44,25 @@ console.log(' - %s cheese', program.cheese);
44
44
 
45
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.
46
46
 
47
+ Note that multi-word options starting with `--no` prefix negate the boolean value of the following word. For example, `--no-sauce` sets the value of `program.sauce` to false.
48
+
49
+ ```js
50
+ #!/usr/bin/env node
51
+
52
+ /**
53
+ * Module dependencies.
54
+ */
55
+
56
+ var program = require('commander');
57
+
58
+ program
59
+ .option('--no-sauce', 'Remove sauce')
60
+ .parse(process.argv);
61
+
62
+ console.log('you ordered a pizza');
63
+ if (program.sauce) console.log(' with sauce');
64
+ else console.log(' without sauce');
65
+ ```
47
66
 
48
67
  ## Coercion
49
68
 
@@ -66,7 +85,7 @@ function increaseVerbosity(v, total) {
66
85
  }
67
86
 
68
87
  program
69
- .version('0.0.1')
88
+ .version('0.1.0')
70
89
  .usage('[options] <file ...>')
71
90
  .option('-i, --integer <n>', 'An integer argument', parseInt)
72
91
  .option('-f, --float <n>', 'A float argument', parseFloat)
@@ -91,7 +110,7 @@ console.log(' args: %j', program.args);
91
110
  ## Regular Expression
92
111
  ```js
93
112
  program
94
- .version('0.0.1')
113
+ .version('0.1.0')
95
114
  .option('-s --size <size>', 'Pizza size', /^(large|medium|small)$/i, 'medium')
96
115
  .option('-d --drink [drink]', 'Drink', /^(coke|pepsi|izze)$/i)
97
116
  .parse(process.argv);
@@ -115,7 +134,7 @@ console.log(' drink: %j', program.drink);
115
134
  var program = require('commander');
116
135
 
117
136
  program
118
- .version('0.0.1')
137
+ .version('0.1.0')
119
138
  .command('rmdir <dir> [otherDirs...]')
120
139
  .action(function (dir, otherDirs) {
121
140
  console.log('rmdir %s', dir);
@@ -137,10 +156,10 @@ program.parse(process.argv);
137
156
  ```js
138
157
  #!/usr/bin/env node
139
158
 
140
- var program = require('../');
159
+ var program = require('commander');
141
160
 
142
161
  program
143
- .version('0.0.1')
162
+ .version('0.1.0')
144
163
  .arguments('<cmd> [env]')
145
164
  .action(function (cmd, env) {
146
165
  cmdValue = cmd;
@@ -156,15 +175,16 @@ if (typeof cmdValue === 'undefined') {
156
175
  console.log('command:', cmdValue);
157
176
  console.log('environment:', envValue || "no environment given");
158
177
  ```
178
+ Angled brackets (e.g. `<cmd>`) indicate required input. Square brackets (e.g. `[env]`) indicate optional input.
159
179
 
160
180
  ## Git-style sub-commands
161
181
 
162
182
  ```js
163
183
  // file: ./examples/pm
164
- var program = require('..');
184
+ var program = require('commander');
165
185
 
166
186
  program
167
- .version('0.0.1')
187
+ .version('0.1.0')
168
188
  .command('install [name]', 'install one or more packages')
169
189
  .command('search [query]', 'search with optional query')
170
190
  .command('list', 'list packages installed', {isDefault: true})
@@ -226,7 +246,7 @@ You can enable `--harmony` option in two ways:
226
246
  var program = require('commander');
227
247
 
228
248
  program
229
- .version('0.0.1')
249
+ .version('0.1.0')
230
250
  .option('-f, --foo', 'enable some foo')
231
251
  .option('-b, --bar', 'enable some bar')
232
252
  .option('-B, --baz', 'enable some baz');
@@ -280,13 +300,13 @@ var program = require('commander');
280
300
  var colors = require('colors');
281
301
 
282
302
  program
283
- .version('0.0.1')
303
+ .version('0.1.0')
284
304
  .command('getstream [url]', 'get stream URL')
285
305
  .parse(process.argv);
286
306
 
287
- if (!process.argv.slice(2).length) {
288
- program.outputHelp(make_red);
289
- }
307
+ if (!process.argv.slice(2).length) {
308
+ program.outputHelp(make_red);
309
+ }
290
310
 
291
311
  function make_red(txt) {
292
312
  return colors.red(txt); //display the help text in red on the console
@@ -304,10 +324,10 @@ function make_red(txt) {
304
324
  var program = require('commander');
305
325
 
306
326
  program
307
- .version('0.0.1')
327
+ .version('0.1.0')
308
328
  .option('-C, --chdir <path>', 'change the working directory')
309
329
  .option('-c, --config <path>', 'set config path. defaults to ./deploy.conf')
310
- .option('-T, --no-tests', 'ignore test hook')
330
+ .option('-T, --no-tests', 'ignore test hook');
311
331
 
312
332
  program
313
333
  .command('setup [env]')
@@ -348,4 +368,3 @@ More Demos can be found in the [examples](https://github.com/tj/commander.js/tre
348
368
  ## License
349
369
 
350
370
  MIT
351
-
package/index.js CHANGED
@@ -4,7 +4,6 @@
4
4
 
5
5
  var EventEmitter = require('events').EventEmitter;
6
6
  var spawn = require('child_process').spawn;
7
- var readlink = require('graceful-readlink').readlinkSync;
8
7
  var path = require('path');
9
8
  var dirname = path.dirname;
10
9
  var basename = path.basename;
@@ -60,6 +59,18 @@ Option.prototype.name = function() {
60
59
  .replace('no-', '');
61
60
  };
62
61
 
62
+ /**
63
+ * Return option name, in a camelcase format that can be used
64
+ * as a object attribute key.
65
+ *
66
+ * @return {String}
67
+ * @api private
68
+ */
69
+
70
+ Option.prototype.attributeName = function() {
71
+ return camelcase( this.name() );
72
+ };
73
+
63
74
  /**
64
75
  * Check if `arg` matches the short or long flag.
65
76
  *
@@ -156,6 +167,10 @@ Command.prototype.__proto__ = EventEmitter.prototype;
156
167
  */
157
168
 
158
169
  Command.prototype.command = function(name, desc, opts) {
170
+ if(typeof desc === 'object' && desc !== null){
171
+ opts = desc;
172
+ desc = null;
173
+ }
159
174
  opts = opts || {};
160
175
  var args = name.split(/ +/);
161
176
  var cmd = new Command(args.shift());
@@ -166,7 +181,6 @@ Command.prototype.command = function(name, desc, opts) {
166
181
  this._execs[cmd._name] = true;
167
182
  if (opts.isDefault) this.defaultExecutable = cmd._name;
168
183
  }
169
-
170
184
  cmd._noHelp = !!opts.noHelp;
171
185
  this.commands.push(cmd);
172
186
  cmd.parseExpectedArgs(args);
@@ -302,8 +316,8 @@ Command.prototype.action = function(fn) {
302
316
  };
303
317
  var parent = this.parent || this;
304
318
  var name = parent === this ? '*' : this._name;
305
- parent.on(name, listener);
306
- if (this._alias) parent.on(this._alias, listener);
319
+ parent.on('command:' + name, listener);
320
+ if (this._alias) parent.on('command:' + this._alias, listener);
307
321
  return this;
308
322
  };
309
323
 
@@ -350,8 +364,8 @@ Command.prototype.action = function(fn) {
350
364
  *
351
365
  * @param {String} flags
352
366
  * @param {String} description
353
- * @param {Function|Mixed} fn or default
354
- * @param {Mixed} defaultValue
367
+ * @param {Function|*} [fn] or default
368
+ * @param {*} [defaultValue]
355
369
  * @return {Command} for chaining
356
370
  * @api public
357
371
  */
@@ -360,7 +374,7 @@ Command.prototype.option = function(flags, description, fn, defaultValue) {
360
374
  var self = this
361
375
  , option = new Option(flags, description)
362
376
  , oname = option.name()
363
- , name = camelcase(oname);
377
+ , name = option.attributeName();
364
378
 
365
379
  // default as 3rd arg
366
380
  if (typeof fn != 'function') {
@@ -382,7 +396,10 @@ Command.prototype.option = function(flags, description, fn, defaultValue) {
382
396
  // when --no-* we make sure default is true
383
397
  if (false == option.bool) defaultValue = true;
384
398
  // preassign only if we have a default
385
- if (undefined !== defaultValue) self[name] = defaultValue;
399
+ if (undefined !== defaultValue) {
400
+ self[name] = defaultValue;
401
+ option.defaultValue = defaultValue;
402
+ }
386
403
  }
387
404
 
388
405
  // register the option
@@ -390,7 +407,7 @@ Command.prototype.option = function(flags, description, fn, defaultValue) {
390
407
 
391
408
  // when it's passed assign the value
392
409
  // and conditionally invoke the callback
393
- this.on(oname, function(val) {
410
+ this.on('option:' + oname, function(val) {
394
411
  // coercion
395
412
  if (null !== val && fn) val = fn(val, undefined === self[name]
396
413
  ? defaultValue
@@ -459,11 +476,24 @@ Command.prototype.parse = function(argv) {
459
476
 
460
477
  // executable sub-commands
461
478
  var name = result.args[0];
479
+
480
+ var aliasCommand = null;
481
+ // check alias of sub commands
482
+ if (name) {
483
+ aliasCommand = this.commands.filter(function(command) {
484
+ return command.alias() === name;
485
+ })[0];
486
+ }
487
+
462
488
  if (this._execs[name] && typeof this._execs[name] != "function") {
463
489
  return this.executeSubCommand(argv, args, parsed.unknown);
490
+ } else if (aliasCommand) {
491
+ // is alias of a subCommand
492
+ args[0] = aliasCommand._name;
493
+ return this.executeSubCommand(argv, args, parsed.unknown);
464
494
  } else if (this.defaultExecutable) {
465
495
  // use the default subcommand
466
- args.unshift(name = this.defaultExecutable);
496
+ args.unshift(this.defaultExecutable);
467
497
  return this.executeSubCommand(argv, args, parsed.unknown);
468
498
  }
469
499
 
@@ -500,7 +530,7 @@ Command.prototype.executeSubCommand = function(argv, args, unknown) {
500
530
  // In case of globally installed, get the base dir where executable
501
531
  // subcommand file should be located at
502
532
  var baseDir
503
- , link = readlink(f);
533
+ , link = fs.lstatSync(f).isSymbolicLink() ? fs.readlinkSync(f) : f;
504
534
 
505
535
  // when symbolink is relative path
506
536
  if (link !== f && link.charAt(0) !== '/') {
@@ -525,19 +555,27 @@ Command.prototype.executeSubCommand = function(argv, args, unknown) {
525
555
  var proc;
526
556
  if (process.platform !== 'win32') {
527
557
  if (isExplicitJS) {
528
- args.unshift(localBin);
558
+ args.unshift(bin);
529
559
  // add executable arguments to spawn
530
560
  args = (process.execArgv || []).concat(args);
531
561
 
532
- proc = spawn('node', args, { stdio: 'inherit', customFds: [0, 1, 2] });
562
+ proc = spawn(process.argv[0], args, { stdio: 'inherit', customFds: [0, 1, 2] });
533
563
  } else {
534
564
  proc = spawn(bin, args, { stdio: 'inherit', customFds: [0, 1, 2] });
535
565
  }
536
566
  } else {
537
- args.unshift(localBin);
567
+ args.unshift(bin);
538
568
  proc = spawn(process.execPath, args, { stdio: 'inherit'});
539
569
  }
540
570
 
571
+ var signals = ['SIGUSR1', 'SIGUSR2', 'SIGTERM', 'SIGINT', 'SIGHUP'];
572
+ signals.forEach(function(signal) {
573
+ process.on(signal, function(){
574
+ if ((proc.killed === false) && (proc.exitCode === null)){
575
+ proc.kill(signal);
576
+ }
577
+ });
578
+ });
541
579
  proc.on('close', process.exit.bind(process));
542
580
  proc.on('error', function(err) {
543
581
  if (err.code == "ENOENT") {
@@ -611,10 +649,10 @@ Command.prototype.parseArgs = function(args, unknown) {
611
649
 
612
650
  if (args.length) {
613
651
  name = args[0];
614
- if (this.listeners(name).length) {
615
- this.emit(args.shift(), args, unknown);
652
+ if (this.listeners('command:' + name).length) {
653
+ this.emit('command:' + args.shift(), args, unknown);
616
654
  } else {
617
- this.emit('*', args);
655
+ this.emit('command:*', args);
618
656
  }
619
657
  } else {
620
658
  outputHelpIfNecessary(this, unknown);
@@ -668,13 +706,13 @@ Command.prototype.parseOptions = function(argv) {
668
706
  arg = argv[i];
669
707
 
670
708
  // literal args after --
671
- if ('--' == arg) {
672
- literal = true;
709
+ if (literal) {
710
+ args.push(arg);
673
711
  continue;
674
712
  }
675
713
 
676
- if (literal) {
677
- args.push(arg);
714
+ if ('--' == arg) {
715
+ literal = true;
678
716
  continue;
679
717
  }
680
718
 
@@ -687,7 +725,7 @@ Command.prototype.parseOptions = function(argv) {
687
725
  if (option.required) {
688
726
  arg = argv[++i];
689
727
  if (null == arg) return this.optionMissingArgument(option);
690
- this.emit(option.name(), arg);
728
+ this.emit('option:' + option.name(), arg);
691
729
  // optional arg
692
730
  } else if (option.optional) {
693
731
  arg = argv[i+1];
@@ -696,10 +734,10 @@ Command.prototype.parseOptions = function(argv) {
696
734
  } else {
697
735
  ++i;
698
736
  }
699
- this.emit(option.name(), arg);
737
+ this.emit('option:' + option.name(), arg);
700
738
  // bool
701
739
  } else {
702
- this.emit(option.name());
740
+ this.emit('option:' + option.name());
703
741
  }
704
742
  continue;
705
743
  }
@@ -735,7 +773,7 @@ Command.prototype.opts = function() {
735
773
  , len = this.options.length;
736
774
 
737
775
  for (var i = 0 ; i < len; i++) {
738
- var key = camelcase(this.options[i].name());
776
+ var key = this.options[i].attributeName();
739
777
  result[key] = key === 'version' ? this._version : this[key];
740
778
  }
741
779
  return result;
@@ -810,7 +848,7 @@ Command.prototype.variadicArgNotLast = function(name) {
810
848
  * which will print the version number when passed.
811
849
  *
812
850
  * @param {String} str
813
- * @param {String} flags
851
+ * @param {String} [flags]
814
852
  * @return {Command} for chaining
815
853
  * @api public
816
854
  */
@@ -820,7 +858,7 @@ Command.prototype.version = function(str, flags) {
820
858
  this._version = str;
821
859
  flags = flags || '-V, --version';
822
860
  this.option(flags, 'output the version number');
823
- this.on('version', function() {
861
+ this.on('option:version', function() {
824
862
  process.stdout.write(str + '\n');
825
863
  process.exit(0);
826
864
  });
@@ -850,8 +888,16 @@ Command.prototype.description = function(str) {
850
888
  */
851
889
 
852
890
  Command.prototype.alias = function(alias) {
853
- if (0 == arguments.length) return this._alias;
854
- this._alias = alias;
891
+ var command = this;
892
+ if(this.commands.length !== 0) {
893
+ command = this.commands[this.commands.length - 1]
894
+ }
895
+
896
+ if (arguments.length === 0) return command._alias;
897
+
898
+ if (alias === command._name) throw new Error('Command alias can\'t be the same as its name');
899
+
900
+ command._alias = alias;
855
901
  return this;
856
902
  };
857
903
 
@@ -879,15 +925,17 @@ Command.prototype.usage = function(str) {
879
925
  };
880
926
 
881
927
  /**
882
- * Get the name of the command
928
+ * Get or set the name of the command
883
929
  *
884
- * @param {String} name
930
+ * @param {String} str
885
931
  * @return {String|Command}
886
932
  * @api public
887
933
  */
888
934
 
889
- Command.prototype.name = function() {
890
- return this._name;
935
+ Command.prototype.name = function(str) {
936
+ if (0 === arguments.length) return this._name;
937
+ this._name = str;
938
+ return this;
891
939
  };
892
940
 
893
941
  /**
@@ -913,12 +961,12 @@ Command.prototype.largestOptionLength = function() {
913
961
  Command.prototype.optionHelp = function() {
914
962
  var width = this.largestOptionLength();
915
963
 
916
- // Prepend the help information
917
- return [pad('-h, --help', width) + ' ' + 'output usage information']
918
- .concat(this.options.map(function(option) {
919
- return pad(option.flags, width) + ' ' + option.description;
920
- }))
921
- .join('\n');
964
+ // Append the help information
965
+ return this.options.map(function(option) {
966
+ return pad(option.flags, width) + ' ' + option.description
967
+ + (option.defaultValue !== undefined ? ' (default: ' + option.defaultValue + ')' : '');
968
+ }).concat([pad('-h, --help', width) + ' ' + 'output usage information'])
969
+ .join('\n');
922
970
  };
923
971
 
924
972
  /**
@@ -943,7 +991,7 @@ Command.prototype.commandHelp = function() {
943
991
  + (cmd._alias ? '|' + cmd._alias : '')
944
992
  + (cmd.options.length ? ' [options]' : '')
945
993
  + ' ' + args
946
- , cmd.description()
994
+ , cmd._description
947
995
  ];
948
996
  });
949
997
 
@@ -994,17 +1042,17 @@ Command.prototype.helpInformation = function() {
994
1042
  if (commandHelp) cmds = [commandHelp];
995
1043
 
996
1044
  var options = [
997
- ' Options:'
1045
+ ''
1046
+ , ' Options:'
998
1047
  , ''
999
1048
  , '' + this.optionHelp().replace(/^/gm, ' ')
1000
1049
  , ''
1001
- , ''
1002
1050
  ];
1003
1051
 
1004
1052
  return usage
1005
- .concat(cmds)
1006
1053
  .concat(desc)
1007
1054
  .concat(options)
1055
+ .concat(cmds)
1008
1056
  .join('\n');
1009
1057
  };
1010
1058
 
package/package.json CHANGED
@@ -1,8 +1,9 @@
1
1
  {
2
2
  "name": "commander",
3
- "version": "2.9.0",
3
+ "version": "2.12.1",
4
4
  "description": "the complete solution for node.js command-line programs",
5
5
  "keywords": [
6
+ "commander",
6
7
  "command",
7
8
  "option",
8
9
  "parser"
@@ -13,21 +14,20 @@
13
14
  "type": "git",
14
15
  "url": "https://github.com/tj/commander.js.git"
15
16
  },
16
- "devDependencies": {
17
- "should": ">= 0.0.1",
18
- "sinon": ">=1.17.1"
19
- },
20
17
  "scripts": {
21
- "test": "make test"
18
+ "test": "make test && npm run test-typings",
19
+ "test-typings": "node_modules/typescript/bin/tsc -p tsconfig.json"
22
20
  },
23
21
  "main": "index",
24
- "engines": {
25
- "node": ">= 0.6.x"
26
- },
27
22
  "files": [
28
23
  "index.js"
29
24
  ],
30
- "dependencies": {
31
- "graceful-readlink": ">= 1.0.0"
32
- }
25
+ "dependencies": {},
26
+ "devDependencies": {
27
+ "@types/node": "^7.0.48",
28
+ "should": "^11.2.1",
29
+ "sinon": "^2.4.1",
30
+ "typescript": "^2.6.1"
31
+ },
32
+ "typings": "typings/index.d.ts"
33
33
  }