commander 1.3.0 → 2.1.0

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 (4) hide show
  1. package/Readme.md +0 -81
  2. package/index.js +20 -324
  3. package/package.json +2 -2
  4. package/History.md +0 -164
package/Readme.md CHANGED
@@ -153,87 +153,6 @@ Examples:
153
153
 
154
154
  ```
155
155
 
156
- ## .prompt(msg, fn)
157
-
158
- Single-line prompt:
159
-
160
- ```js
161
- program.prompt('name: ', function(name){
162
- console.log('hi %s', name);
163
- });
164
- ```
165
-
166
- Multi-line prompt:
167
-
168
- ```js
169
- program.prompt('description:', function(name){
170
- console.log('hi %s', name);
171
- });
172
- ```
173
-
174
- Coercion:
175
-
176
- ```js
177
- program.prompt('Age: ', Number, function(age){
178
- console.log('age: %j', age);
179
- });
180
- ```
181
-
182
- ```js
183
- program.prompt('Birthdate: ', Date, function(date){
184
- console.log('date: %s', date);
185
- });
186
- ```
187
-
188
- ```js
189
- program.prompt('Email: ', /^.+@.+\..+$/, function(email){
190
- console.log('email: %j', email);
191
- });
192
- ```
193
-
194
- ## .password(msg[, mask], fn)
195
-
196
- Prompt for password without echoing:
197
-
198
- ```js
199
- program.password('Password: ', function(pass){
200
- console.log('got "%s"', pass);
201
- process.stdin.destroy();
202
- });
203
- ```
204
-
205
- Prompt for password with mask char "*":
206
-
207
- ```js
208
- program.password('Password: ', '*', function(pass){
209
- console.log('got "%s"', pass);
210
- process.stdin.destroy();
211
- });
212
- ```
213
-
214
- ## .confirm(msg, fn)
215
-
216
- Confirm with the given `msg`:
217
-
218
- ```js
219
- program.confirm('continue? ', function(ok){
220
- console.log(' got %j', ok);
221
- });
222
- ```
223
-
224
- ## .choose(list, fn)
225
-
226
- Let the user choose from a `list`:
227
-
228
- ```js
229
- var list = ['tobi', 'loki', 'jane', 'manny', 'luna'];
230
-
231
- console.log('Choose the coolest pet:');
232
- program.choose(list, function(i){
233
- console.log('you chose %d "%s"', i, list[i]);
234
- });
235
- ```
236
-
237
156
  ## .outputHelp()
238
157
 
239
158
  Output help information without exiting.
package/index.js CHANGED
@@ -1,22 +1,15 @@
1
- /*!
2
- * commander
3
- * Copyright(c) 2011 TJ Holowaychuk <tj@vision-media.ca>
4
- * MIT Licensed
5
- */
6
1
 
7
2
  /**
8
3
  * Module dependencies.
9
4
  */
10
5
 
11
- var EventEmitter = require('events').EventEmitter
12
- , spawn = require('child_process').spawn
13
- , keypress = require('keypress')
14
- , fs = require('fs')
15
- , exists = fs.existsSync
16
- , path = require('path')
17
- , tty = require('tty')
18
- , dirname = path.dirname
19
- , basename = path.basename;
6
+ var EventEmitter = require('events').EventEmitter;
7
+ var spawn = require('child_process').spawn;
8
+ var fs = require('fs');
9
+ var exists = fs.existsSync;
10
+ var path = require('path');
11
+ var dirname = path.dirname;
12
+ var basename = path.basename;
20
13
 
21
14
  /**
22
15
  * Expose the root command.
@@ -91,6 +84,7 @@ Option.prototype.is = function(arg){
91
84
  function Command(name) {
92
85
  this.commands = [];
93
86
  this.options = [];
87
+ this._execs = [];
94
88
  this._args = [];
95
89
  this._name = name;
96
90
  }
@@ -155,6 +149,7 @@ Command.prototype.command = function(name, desc){
155
149
  var cmd = new Command(args.shift());
156
150
  if (desc) cmd.description(desc);
157
151
  if (desc) this.executables = true;
152
+ if (desc) this._execs[cmd._name] = true;
158
153
  this.commands.push(cmd);
159
154
  cmd.parseExpectedArgs(args);
160
155
  cmd.parent = this;
@@ -374,8 +369,9 @@ Command.prototype.parse = function(argv){
374
369
 
375
370
  var result = this.parseArgs(this.args, parsed.unknown);
376
371
 
377
- // executable sub-commands, skip .parseArgs()
378
- if (this.executables) return this.executeSubCommand(argv, args, parsed.unknown);
372
+ // executable sub-commands
373
+ var name = result.args[0];
374
+ if (this._execs[name]) return this.executeSubCommand(argv, args, parsed.unknown);
379
375
 
380
376
  return result;
381
377
  };
@@ -418,6 +414,8 @@ Command.prototype.executeSubCommand = function(argv, args, unknown) {
418
414
  console.error('\n %s(1) not executable. try chmod or run with root\n', bin);
419
415
  }
420
416
  });
417
+
418
+ this.runningCommand = proc;
421
419
  };
422
420
 
423
421
  /**
@@ -433,11 +431,16 @@ Command.prototype.executeSubCommand = function(argv, args, unknown) {
433
431
  Command.prototype.normalize = function(args){
434
432
  var ret = []
435
433
  , arg
434
+ , lastOpt
436
435
  , index;
437
436
 
438
437
  for (var i = 0, len = args.length; i < len; ++i) {
439
438
  arg = args[i];
440
- if (arg.length > 1 && '-' == arg[0] && '-' != arg[1]) {
439
+ i > 0 && (lastOpt = this.optionFor(args[i-1]));
440
+
441
+ if (lastOpt && lastOpt.required) {
442
+ ret.push(arg);
443
+ } else if (arg.length > 1 && '-' == arg[0] && '-' != arg[1]) {
441
444
  arg.slice(1).split('').forEach(function(c){
442
445
  ret.push('-' + c);
443
446
  });
@@ -546,7 +549,6 @@ Command.prototype.parseOptions = function(argv){
546
549
  if (option.required) {
547
550
  arg = argv[++i];
548
551
  if (null == arg) return this.optionMissingArgument(option);
549
- if ('-' == arg[0] && '-' != arg) return this.optionMissingArgument(option, arg);
550
552
  this.emit(option.name(), arg);
551
553
  // optional arg
552
554
  } else if (option.optional) {
@@ -780,300 +782,6 @@ Command.prototype.helpInformation = function(){
780
782
  ].join('\n');
781
783
  };
782
784
 
783
- /**
784
- * Prompt for a `Number`.
785
- *
786
- * @param {String} str
787
- * @param {Function} fn
788
- * @api private
789
- */
790
-
791
- Command.prototype.promptForNumber = function(str, fn){
792
- var self = this;
793
- this.promptSingleLine(str, function parseNumber(val){
794
- val = Number(val);
795
- if (isNaN(val)) return self.promptSingleLine(str + '(must be a number) ', parseNumber);
796
- fn(val);
797
- });
798
- };
799
-
800
- /**
801
- * Prompt for a `Date`.
802
- *
803
- * @param {String} str
804
- * @param {Function} fn
805
- * @api private
806
- */
807
-
808
- Command.prototype.promptForDate = function(str, fn){
809
- var self = this;
810
- this.promptSingleLine(str, function parseDate(val){
811
- val = new Date(val);
812
- if (isNaN(val.getTime())) return self.promptSingleLine(str + '(must be a date) ', parseDate);
813
- fn(val);
814
- });
815
- };
816
-
817
-
818
- /**
819
- * Prompt for a `Regular Expression`.
820
- *
821
- * @param {String} str
822
- * @param {Object} pattern regular expression object to test
823
- * @param {Function} fn
824
- * @api private
825
- */
826
-
827
- Command.prototype.promptForRegexp = function(str, pattern, fn){
828
- var self = this;
829
- this.promptSingleLine(str, function parseRegexp(val){
830
- if(!pattern.test(val)) return self.promptSingleLine(str + '(regular expression mismatch) ', parseRegexp);
831
- fn(val);
832
- });
833
- };
834
-
835
-
836
- /**
837
- * Single-line prompt.
838
- *
839
- * @param {String} str
840
- * @param {Function} fn
841
- * @api private
842
- */
843
-
844
- Command.prototype.promptSingleLine = function(str, fn){
845
- // determine if the 2nd argument is a regular expression
846
- if (arguments[1].global !== undefined && arguments[1].multiline !== undefined) {
847
- return this.promptForRegexp(str, arguments[1], arguments[2]);
848
- } else if ('function' == typeof arguments[2]) {
849
- return this['promptFor' + (fn.name || fn)](str, arguments[2]);
850
- }
851
-
852
- process.stdout.write(str);
853
- process.stdin.setEncoding('utf8');
854
- process.stdin.once('data', function(val){
855
- fn(val.trim());
856
- }).resume();
857
- };
858
-
859
- /**
860
- * Multi-line prompt.
861
- *
862
- * @param {String} str
863
- * @param {Function} fn
864
- * @api private
865
- */
866
-
867
- Command.prototype.promptMultiLine = function(str, fn){
868
- var buf = [];
869
- console.log(str);
870
- process.stdin.setEncoding('utf8');
871
- process.stdin.on('data', function(val){
872
- if ('\n' == val || '\r\n' == val) {
873
- process.stdin.removeAllListeners('data');
874
- fn(buf.join('\n'));
875
- } else {
876
- buf.push(val.trimRight());
877
- }
878
- }).resume();
879
- };
880
-
881
- /**
882
- * Prompt `str` and callback `fn(val)`
883
- *
884
- * Commander supports single-line and multi-line prompts.
885
- * To issue a single-line prompt simply add white-space
886
- * to the end of `str`, something like "name: ", whereas
887
- * for a multi-line prompt omit this "description:".
888
- *
889
- *
890
- * Examples:
891
- *
892
- * program.prompt('Username: ', function(name){
893
- * console.log('hi %s', name);
894
- * });
895
- *
896
- * program.prompt('Description:', function(desc){
897
- * console.log('description was "%s"', desc.trim());
898
- * });
899
- *
900
- * @param {String|Object} str
901
- * @param {Function} fn
902
- * @api public
903
- */
904
-
905
- Command.prototype.prompt = function(str, fn){
906
- var self = this;
907
- if ('string' == typeof str) {
908
- if (/ $/.test(str)) return this.promptSingleLine.apply(this, arguments);
909
- this.promptMultiLine(str, fn);
910
- } else {
911
- var keys = Object.keys(str)
912
- , obj = {};
913
-
914
- function next() {
915
- var key = keys.shift()
916
- , label = str[key];
917
-
918
- if (!key) return fn(obj);
919
- self.prompt(label, function(val){
920
- obj[key] = val;
921
- next();
922
- });
923
- }
924
-
925
- next();
926
- }
927
- };
928
-
929
- /**
930
- * Prompt for password with `str`, `mask` char and callback `fn(val)`.
931
- *
932
- * The mask string defaults to '', aka no output is
933
- * written while typing, you may want to use "*" etc.
934
- *
935
- * Examples:
936
- *
937
- * program.password('Password: ', function(pass){
938
- * console.log('got "%s"', pass);
939
- * process.stdin.destroy();
940
- * });
941
- *
942
- * program.password('Password: ', '*', function(pass){
943
- * console.log('got "%s"', pass);
944
- * process.stdin.destroy();
945
- * });
946
- *
947
- * @param {String} str
948
- * @param {String} mask
949
- * @param {Function} fn
950
- * @api public
951
- */
952
-
953
- Command.prototype.password = function(str, mask, fn){
954
- var self = this
955
- , buf = '';
956
-
957
- // default mask
958
- if ('function' == typeof mask) {
959
- fn = mask;
960
- mask = '';
961
- }
962
-
963
- keypress(process.stdin);
964
-
965
- function setRawMode(mode) {
966
- if (process.stdin.setRawMode) {
967
- process.stdin.setRawMode(mode);
968
- } else {
969
- tty.setRawMode(mode);
970
- }
971
- };
972
- setRawMode(true);
973
- process.stdout.write(str);
974
-
975
- // keypress
976
- process.stdin.on('keypress', function(c, key){
977
- if (key && 'enter' == key.name) {
978
- console.log();
979
- process.stdin.pause();
980
- process.stdin.removeAllListeners('keypress');
981
- setRawMode(false);
982
- if (!buf.trim().length) return self.password(str, mask, fn);
983
- fn(buf);
984
- return;
985
- }
986
-
987
- if (key && key.ctrl && 'c' == key.name) {
988
- console.log('%s', buf);
989
- process.exit();
990
- }
991
-
992
- process.stdout.write(mask);
993
- buf += c;
994
- }).resume();
995
- };
996
-
997
- /**
998
- * Confirmation prompt with `str` and callback `fn(bool)`
999
- *
1000
- * Examples:
1001
- *
1002
- * program.confirm('continue? ', function(ok){
1003
- * console.log(' got %j', ok);
1004
- * process.stdin.destroy();
1005
- * });
1006
- *
1007
- * @param {String} str
1008
- * @param {Function} fn
1009
- * @api public
1010
- */
1011
-
1012
-
1013
- Command.prototype.confirm = function(str, fn, verbose){
1014
- var self = this;
1015
- this.prompt(str, function(ok){
1016
- if (!ok.trim()) {
1017
- if (!verbose) str += '(yes or no) ';
1018
- return self.confirm(str, fn, true);
1019
- }
1020
- fn(parseBool(ok));
1021
- });
1022
- };
1023
-
1024
- /**
1025
- * Choice prompt with `list` of items and callback `fn(index, item)`
1026
- *
1027
- * Examples:
1028
- *
1029
- * var list = ['tobi', 'loki', 'jane', 'manny', 'luna'];
1030
- *
1031
- * console.log('Choose the coolest pet:');
1032
- * program.choose(list, function(i){
1033
- * console.log('you chose %d "%s"', i, list[i]);
1034
- * process.stdin.destroy();
1035
- * });
1036
- *
1037
- * @param {Array} list
1038
- * @param {Number|Function} index or fn
1039
- * @param {Function} fn
1040
- * @api public
1041
- */
1042
-
1043
- Command.prototype.choose = function(list, index, fn){
1044
- var self = this
1045
- , hasDefault = 'number' == typeof index;
1046
-
1047
- if (!hasDefault) {
1048
- fn = index;
1049
- index = null;
1050
- }
1051
-
1052
- list.forEach(function(item, i){
1053
- if (hasDefault && i == index) {
1054
- console.log('* %d) %s', i + 1, item);
1055
- } else {
1056
- console.log(' %d) %s', i + 1, item);
1057
- }
1058
- });
1059
-
1060
- function again() {
1061
- self.prompt(' : ', function(val){
1062
- val = parseInt(val, 10) - 1;
1063
- if (hasDefault && isNaN(val)) val = index;
1064
-
1065
- if (null == list[val]) {
1066
- again();
1067
- } else {
1068
- fn(val, list[val]);
1069
- }
1070
- });
1071
- }
1072
-
1073
- again();
1074
- };
1075
-
1076
-
1077
785
  /**
1078
786
  * Output help information for this command
1079
787
  *
@@ -1110,18 +818,6 @@ function camelcase(flag) {
1110
818
  });
1111
819
  }
1112
820
 
1113
- /**
1114
- * Parse a boolean `str`.
1115
- *
1116
- * @param {String} str
1117
- * @return {Boolean}
1118
- * @api private
1119
- */
1120
-
1121
- function parseBool(str) {
1122
- return /^y|yes|ok|true$/i.test(str);
1123
- }
1124
-
1125
821
  /**
1126
822
  * Pad `str` to `width`.
1127
823
  *
package/package.json CHANGED
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "name": "commander"
3
- , "version": "1.3.0"
3
+ , "version": "2.1.0"
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
7
  , "repository": { "type": "git", "url": "https://github.com/visionmedia/commander.js.git" }
8
- , "dependencies": { "keypress": "0.1.x"}
9
8
  , "devDependencies": { "should": ">= 0.0.1" }
10
9
  , "scripts": { "test": "make test" }
11
10
  , "main": "index"
12
11
  , "engines": { "node": ">= 0.6.x" }
12
+ , "files": ["index.js"]
13
13
  }
package/History.md DELETED
@@ -1,164 +0,0 @@
1
-
2
- 1.3.0 / 2013-07-09
3
- ==================
4
-
5
- * add EACCES error handling
6
- * fix sub-command --help
7
-
8
- 1.2.0 / 2013-06-13
9
- ==================
10
-
11
- * allow "-" hyphen as an option argument
12
- * support for RegExp coercion
13
-
14
- 1.1.1 / 2012-11-20
15
- ==================
16
-
17
- * add more sub-command padding
18
- * fix .usage() when args are present. Closes #106
19
-
20
- 1.1.0 / 2012-11-16
21
- ==================
22
-
23
- * add git-style executable subcommand support. Closes #94
24
-
25
- 1.0.5 / 2012-10-09
26
- ==================
27
-
28
- * fix `--name` clobbering. Closes #92
29
- * fix examples/help. Closes #89
30
-
31
- 1.0.4 / 2012-09-03
32
- ==================
33
-
34
- * add `outputHelp()` method.
35
-
36
- 1.0.3 / 2012-08-30
37
- ==================
38
-
39
- * remove invalid .version() defaulting
40
-
41
- 1.0.2 / 2012-08-24
42
- ==================
43
-
44
- * add `--foo=bar` support [arv]
45
- * fix password on node 0.8.8. Make backward compatible with 0.6 [focusaurus]
46
-
47
- 1.0.1 / 2012-08-03
48
- ==================
49
-
50
- * fix issue #56
51
- * fix tty.setRawMode(mode) was moved to tty.ReadStream#setRawMode() (i.e. process.stdin.setRawMode())
52
-
53
- 1.0.0 / 2012-07-05
54
- ==================
55
-
56
- * add support for optional option descriptions
57
- * add defaulting of `.version()` to package.json's version
58
-
59
- 0.6.1 / 2012-06-01
60
- ==================
61
-
62
- * Added: append (yes or no) on confirmation
63
- * Added: allow node.js v0.7.x
64
-
65
- 0.6.0 / 2012-04-10
66
- ==================
67
-
68
- * Added `.prompt(obj, callback)` support. Closes #49
69
- * Added default support to .choose(). Closes #41
70
- * Fixed the choice example
71
-
72
- 0.5.1 / 2011-12-20
73
- ==================
74
-
75
- * Fixed `password()` for recent nodes. Closes #36
76
-
77
- 0.5.0 / 2011-12-04
78
- ==================
79
-
80
- * Added sub-command option support [itay]
81
-
82
- 0.4.3 / 2011-12-04
83
- ==================
84
-
85
- * Fixed custom help ordering. Closes #32
86
-
87
- 0.4.2 / 2011-11-24
88
- ==================
89
-
90
- * Added travis support
91
- * Fixed: line-buffered input automatically trimmed. Closes #31
92
-
93
- 0.4.1 / 2011-11-18
94
- ==================
95
-
96
- * Removed listening for "close" on --help
97
-
98
- 0.4.0 / 2011-11-15
99
- ==================
100
-
101
- * Added support for `--`. Closes #24
102
-
103
- 0.3.3 / 2011-11-14
104
- ==================
105
-
106
- * Fixed: wait for close event when writing help info [Jerry Hamlet]
107
-
108
- 0.3.2 / 2011-11-01
109
- ==================
110
-
111
- * Fixed long flag definitions with values [felixge]
112
-
113
- 0.3.1 / 2011-10-31
114
- ==================
115
-
116
- * Changed `--version` short flag to `-V` from `-v`
117
- * Changed `.version()` so it's configurable [felixge]
118
-
119
- 0.3.0 / 2011-10-31
120
- ==================
121
-
122
- * Added support for long flags only. Closes #18
123
-
124
- 0.2.1 / 2011-10-24
125
- ==================
126
-
127
- * "node": ">= 0.4.x < 0.7.0". Closes #20
128
-
129
- 0.2.0 / 2011-09-26
130
- ==================
131
-
132
- * Allow for defaults that are not just boolean. Default peassignment only occurs for --no-*, optional, and required arguments. [Jim Isaacs]
133
-
134
- 0.1.0 / 2011-08-24
135
- ==================
136
-
137
- * Added support for custom `--help` output
138
-
139
- 0.0.5 / 2011-08-18
140
- ==================
141
-
142
- * Changed: when the user enters nothing prompt for password again
143
- * Fixed issue with passwords beginning with numbers [NuckChorris]
144
-
145
- 0.0.4 / 2011-08-15
146
- ==================
147
-
148
- * Fixed `Commander#args`
149
-
150
- 0.0.3 / 2011-08-15
151
- ==================
152
-
153
- * Added default option value support
154
-
155
- 0.0.2 / 2011-08-15
156
- ==================
157
-
158
- * Added mask support to `Command#password(str[, mask], fn)`
159
- * Added `Command#password(str, fn)`
160
-
161
- 0.0.1 / 2010-01-03
162
- ==================
163
-
164
- * Initial release