commander 1.1.0 → 1.3.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.
package/History.md CHANGED
@@ -1,4 +1,27 @@
1
1
 
2
+ 1.3.1 / 2013-07-18
3
+ ==================
4
+
5
+ * add quick .runningCommand hack so you can opt-out of other logic when running a sub command
6
+
7
+ 1.3.0 / 2013-07-09
8
+ ==================
9
+
10
+ * add EACCES error handling
11
+ * fix sub-command --help
12
+
13
+ 1.2.0 / 2013-06-13
14
+ ==================
15
+
16
+ * allow "-" hyphen as an option argument
17
+ * support for RegExp coercion
18
+
19
+ 1.1.1 / 2012-11-20
20
+ ==================
21
+
22
+ * add more sub-command padding
23
+ * fix .usage() when args are present. Closes #106
24
+
2
25
  1.1.0 / 2012-11-16
3
26
  ==================
4
27
 
package/Readme.md CHANGED
@@ -31,7 +31,7 @@ program
31
31
 
32
32
  console.log('you ordered a pizza with:');
33
33
  if (program.peppers) console.log(' - peppers');
34
- if (program.pineapple) console.log(' - pineappe');
34
+ if (program.pineapple) console.log(' - pineapple');
35
35
  if (program.bbq) console.log(' - bbq');
36
36
  console.log(' - %s cheese', program.cheese);
37
37
  ```
@@ -51,7 +51,7 @@ console.log(' - %s cheese', program.cheese);
51
51
 
52
52
  -V, --version output the version number
53
53
  -p, --peppers Add peppers
54
- -P, --pineapple Add pineappe
54
+ -P, --pineapple Add pineapple
55
55
  -b, --bbq Add bbq sauce
56
56
  -c, --cheese <type> Add the specified type of cheese [marble]
57
57
  -h, --help output usage information
@@ -185,6 +185,12 @@ program.prompt('Birthdate: ', Date, function(date){
185
185
  });
186
186
  ```
187
187
 
188
+ ```js
189
+ program.prompt('Email: ', /^.+@.+\..+$/, function(email){
190
+ console.log('email: %j', email);
191
+ });
192
+ ```
193
+
188
194
  ## .password(msg[, mask], fn)
189
195
 
190
196
  Prompt for password without echoing:
@@ -267,4 +273,4 @@ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
267
273
  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
268
274
  CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
269
275
  TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
270
- SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
276
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
package/index.js CHANGED
@@ -91,7 +91,7 @@ Option.prototype.is = function(arg){
91
91
  function Command(name) {
92
92
  this.commands = [];
93
93
  this.options = [];
94
- this.args = [];
94
+ this._args = [];
95
95
  this._name = name;
96
96
  }
97
97
 
@@ -189,10 +189,10 @@ Command.prototype.parseExpectedArgs = function(args){
189
189
  args.forEach(function(arg){
190
190
  switch (arg[0]) {
191
191
  case '<':
192
- self.args.push({ required: true, name: arg.slice(1, -1) });
192
+ self._args.push({ required: true, name: arg.slice(1, -1) });
193
193
  break;
194
194
  case '[':
195
- self.args.push({ required: false, name: arg.slice(1, -1) });
195
+ self._args.push({ required: false, name: arg.slice(1, -1) });
196
196
  break;
197
197
  }
198
198
  });
@@ -236,7 +236,7 @@ Command.prototype.action = function(fn){
236
236
  // Leftover arguments need to be pushed back. Fixes issue #56
237
237
  if (parsed.args.length) args = parsed.args.concat(args);
238
238
 
239
- self.args.forEach(function(arg, i){
239
+ self._args.forEach(function(arg, i){
240
240
  if (arg.required && null == args[i]) {
241
241
  self.missingArgument(arg.name);
242
242
  }
@@ -245,8 +245,8 @@ Command.prototype.action = function(fn){
245
245
  // Always append ourselves to the end of the arguments,
246
246
  // to make sure we match the number of arguments the user
247
247
  // expects
248
- if (self.args.length) {
249
- args[self.args.length] = self;
248
+ if (self._args.length) {
249
+ args[self._args.length] = self;
250
250
  } else {
251
251
  args.push(self);
252
252
  }
@@ -372,10 +372,12 @@ Command.prototype.parse = function(argv){
372
372
  var parsed = this.parseOptions(this.normalize(argv.slice(2)));
373
373
  var args = this.args = parsed.args;
374
374
 
375
+ var result = this.parseArgs(this.args, parsed.unknown);
376
+
375
377
  // executable sub-commands, skip .parseArgs()
376
378
  if (this.executables) return this.executeSubCommand(argv, args, parsed.unknown);
377
379
 
378
- return this.parseArgs(this.args, parsed.unknown);
380
+ return result;
379
381
  };
380
382
 
381
383
  /**
@@ -405,16 +407,19 @@ Command.prototype.executeSubCommand = function(argv, args, unknown) {
405
407
 
406
408
  // check for ./<bin> first
407
409
  var local = path.join(dir, bin);
408
- if (exists(local)) bin = local;
409
410
 
410
411
  // run it
411
412
  args = args.slice(1);
412
- var proc = spawn(bin, args, { stdio: 'inherit', customFds: [0, 1, 2] });
413
- proc.on('exit', function(code){
414
- if (code == 127) {
415
- console.error('\n %s(1) does not exist\n', bin);
413
+ var proc = spawn(local, args, { stdio: 'inherit', customFds: [0, 1, 2] });
414
+ proc.on('error', function(err){
415
+ if (err.code == "ENOENT") {
416
+ console.error('\n %s(1) does not exist, try --help\n', bin);
417
+ } else if (err.code == "EACCES") {
418
+ console.error('\n %s(1) not executable. try chmod or run with root\n', bin);
416
419
  }
417
420
  });
421
+
422
+ this.runningCommand = proc;
418
423
  };
419
424
 
420
425
  /**
@@ -543,12 +548,12 @@ Command.prototype.parseOptions = function(argv){
543
548
  if (option.required) {
544
549
  arg = argv[++i];
545
550
  if (null == arg) return this.optionMissingArgument(option);
546
- if ('-' == arg[0]) return this.optionMissingArgument(option, arg);
551
+ if ('-' == arg[0] && '-' != arg) return this.optionMissingArgument(option, arg);
547
552
  this.emit(option.name(), arg);
548
553
  // optional arg
549
554
  } else if (option.optional) {
550
555
  arg = argv[i+1];
551
- if (null == arg || '-' == arg[0]) {
556
+ if (null == arg || ('-' == arg[0] && '-' != arg)) {
552
557
  arg = null;
553
558
  } else {
554
559
  ++i;
@@ -676,7 +681,7 @@ Command.prototype.description = function(str){
676
681
  */
677
682
 
678
683
  Command.prototype.usage = function(str){
679
- var args = this.args.map(function(arg){
684
+ var args = this._args.map(function(arg){
680
685
  return arg.required
681
686
  ? '<' + arg.name + '>'
682
687
  : '[' + arg.name + ']';
@@ -685,7 +690,8 @@ Command.prototype.usage = function(str){
685
690
  var usage = '[options'
686
691
  + (this.commands.length ? '] [command' : '')
687
692
  + ']'
688
- + (this.args.length ? ' ' + args : '');
693
+ + (this._args.length ? ' ' + args : '');
694
+
689
695
  if (0 == arguments.length) return this._usage || usage;
690
696
  this._usage = str;
691
697
 
@@ -738,7 +744,7 @@ Command.prototype.commandHelp = function(){
738
744
  , ' Commands:'
739
745
  , ''
740
746
  , this.commands.map(function(cmd){
741
- var args = cmd.args.map(function(arg){
747
+ var args = cmd._args.map(function(arg){
742
748
  return arg.required
743
749
  ? '<' + arg.name + '>'
744
750
  : '[' + arg.name + ']';
@@ -747,7 +753,7 @@ Command.prototype.commandHelp = function(){
747
753
  return pad(cmd._name
748
754
  + (cmd.options.length
749
755
  ? ' [options]'
750
- : '') + ' ' + args, 18)
756
+ : '') + ' ' + args, 22)
751
757
  + (cmd.description()
752
758
  ? ' ' + cmd.description()
753
759
  : '');
@@ -810,6 +816,25 @@ Command.prototype.promptForDate = function(str, fn){
810
816
  });
811
817
  };
812
818
 
819
+
820
+ /**
821
+ * Prompt for a `Regular Expression`.
822
+ *
823
+ * @param {String} str
824
+ * @param {Object} pattern regular expression object to test
825
+ * @param {Function} fn
826
+ * @api private
827
+ */
828
+
829
+ Command.prototype.promptForRegexp = function(str, pattern, fn){
830
+ var self = this;
831
+ this.promptSingleLine(str, function parseRegexp(val){
832
+ if(!pattern.test(val)) return self.promptSingleLine(str + '(regular expression mismatch) ', parseRegexp);
833
+ fn(val);
834
+ });
835
+ };
836
+
837
+
813
838
  /**
814
839
  * Single-line prompt.
815
840
  *
@@ -819,7 +844,10 @@ Command.prototype.promptForDate = function(str, fn){
819
844
  */
820
845
 
821
846
  Command.prototype.promptSingleLine = function(str, fn){
822
- if ('function' == typeof arguments[2]) {
847
+ // determine if the 2nd argument is a regular expression
848
+ if (arguments[1].global !== undefined && arguments[1].multiline !== undefined) {
849
+ return this.promptForRegexp(str, arguments[1], arguments[2]);
850
+ } else if ('function' == typeof arguments[2]) {
823
851
  return this['promptFor' + (fn.name || fn)](str, arguments[2]);
824
852
  }
825
853
 
@@ -878,7 +906,6 @@ Command.prototype.promptMultiLine = function(str, fn){
878
906
 
879
907
  Command.prototype.prompt = function(str, fn){
880
908
  var self = this;
881
-
882
909
  if ('string' == typeof str) {
883
910
  if (/ $/.test(str)) return this.promptSingleLine.apply(this, arguments);
884
911
  this.promptMultiLine(str, fn);
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "commander"
3
- , "version": "1.1.0"
3
+ , "version": "1.3.1"
4
4
  , "description": "the complete solution for node.js command-line programs"
5
5
  , "keywords": ["command", "option", "parser", "prompt", "stdin"]
6
6
  , "author": "TJ Holowaychuk <tj@vision-media.ca>"
7
- , "repository": { "type": "git", "url": "https://github.com/visionmedia/commander.js.git" }
7
+ , "repository": { "type": "git", "url": "https://github.com/visionmedia/commander.js.git" }
8
8
  , "dependencies": { "keypress": "0.1.x"}
9
9
  , "devDependencies": { "should": ">= 0.0.1" }
10
10
  , "scripts": { "test": "make test" }
package/.npmignore DELETED
@@ -1,4 +0,0 @@
1
- support
2
- test
3
- examples
4
- *.sock
package/.travis.yml DELETED
@@ -1,4 +0,0 @@
1
- language: node_js
2
- node_js:
3
- - 0.4
4
- - 0.6
package/Makefile DELETED
@@ -1,7 +0,0 @@
1
-
2
- TESTS = $(shell find test/test.*.js)
3
-
4
- test:
5
- @./test/run $(TESTS)
6
-
7
- .PHONY: test