commander 1.3.1 → 2.2.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.
- package/Readme.md +13 -81
- package/index.js +46 -351
- package/package.json +2 -2
- package/History.md +0 -169
package/Readme.md
CHANGED
|
@@ -69,6 +69,15 @@ function list(val) {
|
|
|
69
69
|
return val.split(',');
|
|
70
70
|
}
|
|
71
71
|
|
|
72
|
+
function collect(val, memo) {
|
|
73
|
+
memo.push(val);
|
|
74
|
+
return memo;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function increaseVerbosity(v, total) {
|
|
78
|
+
return total + 1;
|
|
79
|
+
}
|
|
80
|
+
|
|
72
81
|
program
|
|
73
82
|
.version('0.0.1')
|
|
74
83
|
.usage('[options] <file ...>')
|
|
@@ -77,6 +86,8 @@ program
|
|
|
77
86
|
.option('-r, --range <a>..<b>', 'A range', range)
|
|
78
87
|
.option('-l, --list <items>', 'A list', list)
|
|
79
88
|
.option('-o, --optional [value]', 'An optional value')
|
|
89
|
+
.option('-c, --collect [value]', 'A repeatable value', [])
|
|
90
|
+
.option('-v, --verbose', 'A value that can be increased', increaseVerbosity, 0)
|
|
80
91
|
.parse(process.argv);
|
|
81
92
|
|
|
82
93
|
console.log(' int: %j', program.integer);
|
|
@@ -85,6 +96,8 @@ console.log(' optional: %j', program.optional);
|
|
|
85
96
|
program.range = program.range || [];
|
|
86
97
|
console.log(' range: %j..%j', program.range[0], program.range[1]);
|
|
87
98
|
console.log(' list: %j', program.list);
|
|
99
|
+
console.log(' collect: %j', program.collect);
|
|
100
|
+
console.log(' verbosity: %j', program.verbose);
|
|
88
101
|
console.log(' args: %j', program.args);
|
|
89
102
|
```
|
|
90
103
|
|
|
@@ -153,87 +166,6 @@ Examples:
|
|
|
153
166
|
|
|
154
167
|
```
|
|
155
168
|
|
|
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
169
|
## .outputHelp()
|
|
238
170
|
|
|
239
171
|
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
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
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
|
}
|
|
@@ -120,28 +114,28 @@ Command.prototype.__proto__ = EventEmitter.prototype;
|
|
|
120
114
|
* .option('-C, --chdir <path>', 'change the working directory')
|
|
121
115
|
* .option('-c, --config <path>', 'set config path. defaults to ./deploy.conf')
|
|
122
116
|
* .option('-T, --no-tests', 'ignore test hook')
|
|
123
|
-
*
|
|
117
|
+
*
|
|
124
118
|
* program
|
|
125
119
|
* .command('setup')
|
|
126
120
|
* .description('run remote setup commands')
|
|
127
121
|
* .action(function(){
|
|
128
122
|
* console.log('setup');
|
|
129
123
|
* });
|
|
130
|
-
*
|
|
124
|
+
*
|
|
131
125
|
* program
|
|
132
126
|
* .command('exec <cmd>')
|
|
133
127
|
* .description('run the given remote command')
|
|
134
128
|
* .action(function(cmd){
|
|
135
129
|
* console.log('exec "%s"', cmd);
|
|
136
130
|
* });
|
|
137
|
-
*
|
|
131
|
+
*
|
|
138
132
|
* program
|
|
139
133
|
* .command('*')
|
|
140
134
|
* .description('deploy the given env')
|
|
141
135
|
* .action(function(env){
|
|
142
136
|
* console.log('deploying "%s"', env);
|
|
143
137
|
* });
|
|
144
|
-
*
|
|
138
|
+
*
|
|
145
139
|
* program.parse(process.argv);
|
|
146
140
|
*
|
|
147
141
|
* @param {String} name
|
|
@@ -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;
|
|
@@ -218,30 +213,30 @@ Command.prototype.parseExpectedArgs = function(args){
|
|
|
218
213
|
|
|
219
214
|
Command.prototype.action = function(fn){
|
|
220
215
|
var self = this;
|
|
221
|
-
this.parent.on(this._name, function(args, unknown){
|
|
216
|
+
this.parent.on(this._name, function(args, unknown){
|
|
222
217
|
// Parse any so-far unknown options
|
|
223
218
|
unknown = unknown || [];
|
|
224
219
|
var parsed = self.parseOptions(unknown);
|
|
225
|
-
|
|
220
|
+
|
|
226
221
|
// Output help if necessary
|
|
227
222
|
outputHelpIfNecessary(self, parsed.unknown);
|
|
228
|
-
|
|
229
|
-
// If there are still any unknown options, then we simply
|
|
223
|
+
|
|
224
|
+
// If there are still any unknown options, then we simply
|
|
230
225
|
// die, unless someone asked for help, in which case we give it
|
|
231
226
|
// to them, and then we die.
|
|
232
|
-
if (parsed.unknown.length > 0) {
|
|
227
|
+
if (parsed.unknown.length > 0) {
|
|
233
228
|
self.unknownOption(parsed.unknown[0]);
|
|
234
229
|
}
|
|
235
|
-
|
|
230
|
+
|
|
236
231
|
// Leftover arguments need to be pushed back. Fixes issue #56
|
|
237
232
|
if (parsed.args.length) args = parsed.args.concat(args);
|
|
238
|
-
|
|
233
|
+
|
|
239
234
|
self._args.forEach(function(arg, i){
|
|
240
235
|
if (arg.required && null == args[i]) {
|
|
241
236
|
self.missingArgument(arg.name);
|
|
242
237
|
}
|
|
243
238
|
});
|
|
244
|
-
|
|
239
|
+
|
|
245
240
|
// Always append ourselves to the end of the arguments,
|
|
246
241
|
// to make sure we match the number of arguments the user
|
|
247
242
|
// expects
|
|
@@ -250,7 +245,7 @@ Command.prototype.action = function(fn){
|
|
|
250
245
|
} else {
|
|
251
246
|
args.push(self);
|
|
252
247
|
}
|
|
253
|
-
|
|
248
|
+
|
|
254
249
|
fn.apply(this, args);
|
|
255
250
|
});
|
|
256
251
|
return this;
|
|
@@ -258,7 +253,7 @@ Command.prototype.action = function(fn){
|
|
|
258
253
|
|
|
259
254
|
/**
|
|
260
255
|
* Define option with `flags`, `description` and optional
|
|
261
|
-
* coercion `fn`.
|
|
256
|
+
* coercion `fn`.
|
|
262
257
|
*
|
|
263
258
|
* The `flags` string should contain both the short and long flags,
|
|
264
259
|
* separated by comma, a pipe or space. The following are all valid
|
|
@@ -329,7 +324,7 @@ Command.prototype.option = function(flags, description, fn, defaultValue){
|
|
|
329
324
|
// and conditionally invoke the callback
|
|
330
325
|
this.on(oname, function(val){
|
|
331
326
|
// coercion
|
|
332
|
-
if (null
|
|
327
|
+
if (null !== val && fn) val = fn(val, undefined === self[name] ? defaultValue : self[name]);
|
|
333
328
|
|
|
334
329
|
// unassigned or bool
|
|
335
330
|
if ('boolean' == typeof self[name] || 'undefined' == typeof self[name]) {
|
|
@@ -366,16 +361,17 @@ Command.prototype.parse = function(argv){
|
|
|
366
361
|
this.rawArgs = argv;
|
|
367
362
|
|
|
368
363
|
// guess name
|
|
369
|
-
this._name = this._name || basename(argv[1]);
|
|
364
|
+
this._name = this._name || basename(argv[1], '.js');
|
|
370
365
|
|
|
371
366
|
// process argv
|
|
372
367
|
var parsed = this.parseOptions(this.normalize(argv.slice(2)));
|
|
373
368
|
var args = this.args = parsed.args;
|
|
374
|
-
|
|
369
|
+
|
|
375
370
|
var result = this.parseArgs(this.args, parsed.unknown);
|
|
376
371
|
|
|
377
|
-
// executable sub-commands
|
|
378
|
-
|
|
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
|
};
|
|
@@ -403,14 +399,15 @@ Command.prototype.executeSubCommand = function(argv, args, unknown) {
|
|
|
403
399
|
|
|
404
400
|
// executable
|
|
405
401
|
var dir = dirname(argv[1]);
|
|
406
|
-
var bin = basename(argv[1]) + '-' + args[0];
|
|
402
|
+
var bin = basename(argv[1], '.js') + '-' + args[0];
|
|
407
403
|
|
|
408
404
|
// check for ./<bin> first
|
|
409
405
|
var local = path.join(dir, bin);
|
|
410
406
|
|
|
411
407
|
// run it
|
|
412
408
|
args = args.slice(1);
|
|
413
|
-
|
|
409
|
+
args.unshift(local);
|
|
410
|
+
var proc = spawn('node', args, { stdio: 'inherit', customFds: [0, 1, 2] });
|
|
414
411
|
proc.on('error', function(err){
|
|
415
412
|
if (err.code == "ENOENT") {
|
|
416
413
|
console.error('\n %s(1) does not exist, try --help\n', bin);
|
|
@@ -435,11 +432,16 @@ Command.prototype.executeSubCommand = function(argv, args, unknown) {
|
|
|
435
432
|
Command.prototype.normalize = function(args){
|
|
436
433
|
var ret = []
|
|
437
434
|
, arg
|
|
435
|
+
, lastOpt
|
|
438
436
|
, index;
|
|
439
437
|
|
|
440
438
|
for (var i = 0, len = args.length; i < len; ++i) {
|
|
441
439
|
arg = args[i];
|
|
442
|
-
|
|
440
|
+
i > 0 && (lastOpt = this.optionFor(args[i-1]));
|
|
441
|
+
|
|
442
|
+
if (lastOpt && lastOpt.required) {
|
|
443
|
+
ret.push(arg);
|
|
444
|
+
} else if (arg.length > 1 && '-' == arg[0] && '-' != arg[1]) {
|
|
443
445
|
arg.slice(1).split('').forEach(function(c){
|
|
444
446
|
ret.push('-' + c);
|
|
445
447
|
});
|
|
@@ -479,10 +481,10 @@ Command.prototype.parseArgs = function(args, unknown){
|
|
|
479
481
|
}
|
|
480
482
|
} else {
|
|
481
483
|
outputHelpIfNecessary(this, unknown);
|
|
482
|
-
|
|
484
|
+
|
|
483
485
|
// If there were no args and we have unknown options,
|
|
484
486
|
// then they are extraneous and we need to error.
|
|
485
|
-
if (unknown.length > 0) {
|
|
487
|
+
if (unknown.length > 0) {
|
|
486
488
|
this.unknownOption(unknown[0]);
|
|
487
489
|
}
|
|
488
490
|
}
|
|
@@ -548,7 +550,6 @@ Command.prototype.parseOptions = function(argv){
|
|
|
548
550
|
if (option.required) {
|
|
549
551
|
arg = argv[++i];
|
|
550
552
|
if (null == arg) return this.optionMissingArgument(option);
|
|
551
|
-
if ('-' == arg[0] && '-' != arg) return this.optionMissingArgument(option, arg);
|
|
552
553
|
this.emit(option.name(), arg);
|
|
553
554
|
// optional arg
|
|
554
555
|
} else if (option.optional) {
|
|
@@ -565,11 +566,11 @@ Command.prototype.parseOptions = function(argv){
|
|
|
565
566
|
}
|
|
566
567
|
continue;
|
|
567
568
|
}
|
|
568
|
-
|
|
569
|
+
|
|
569
570
|
// looks like an option
|
|
570
571
|
if (arg.length > 1 && '-' == arg[0]) {
|
|
571
572
|
unknownOptions.push(arg);
|
|
572
|
-
|
|
573
|
+
|
|
573
574
|
// If the next argument looks like it might be
|
|
574
575
|
// an argument for this option, we pass it on.
|
|
575
576
|
// If it isn't, then it'll simply be ignored
|
|
@@ -578,11 +579,11 @@ Command.prototype.parseOptions = function(argv){
|
|
|
578
579
|
}
|
|
579
580
|
continue;
|
|
580
581
|
}
|
|
581
|
-
|
|
582
|
+
|
|
582
583
|
// arg
|
|
583
584
|
args.push(arg);
|
|
584
585
|
}
|
|
585
|
-
|
|
586
|
+
|
|
586
587
|
return { args: args, unknown: unknownOptions };
|
|
587
588
|
};
|
|
588
589
|
|
|
@@ -720,7 +721,7 @@ Command.prototype.largestOptionLength = function(){
|
|
|
720
721
|
|
|
721
722
|
Command.prototype.optionHelp = function(){
|
|
722
723
|
var width = this.largestOptionLength();
|
|
723
|
-
|
|
724
|
+
|
|
724
725
|
// Prepend the help information
|
|
725
726
|
return [pad('-h, --help', width) + ' ' + 'output usage information']
|
|
726
727
|
.concat(this.options.map(function(option){
|
|
@@ -751,7 +752,7 @@ Command.prototype.commandHelp = function(){
|
|
|
751
752
|
}).join(' ');
|
|
752
753
|
|
|
753
754
|
return pad(cmd._name
|
|
754
|
-
+ (cmd.options.length
|
|
755
|
+
+ (cmd.options.length
|
|
755
756
|
? ' [options]'
|
|
756
757
|
: '') + ' ' + args, 22)
|
|
757
758
|
+ (cmd.description()
|
|
@@ -782,300 +783,6 @@ Command.prototype.helpInformation = function(){
|
|
|
782
783
|
].join('\n');
|
|
783
784
|
};
|
|
784
785
|
|
|
785
|
-
/**
|
|
786
|
-
* Prompt for a `Number`.
|
|
787
|
-
*
|
|
788
|
-
* @param {String} str
|
|
789
|
-
* @param {Function} fn
|
|
790
|
-
* @api private
|
|
791
|
-
*/
|
|
792
|
-
|
|
793
|
-
Command.prototype.promptForNumber = function(str, fn){
|
|
794
|
-
var self = this;
|
|
795
|
-
this.promptSingleLine(str, function parseNumber(val){
|
|
796
|
-
val = Number(val);
|
|
797
|
-
if (isNaN(val)) return self.promptSingleLine(str + '(must be a number) ', parseNumber);
|
|
798
|
-
fn(val);
|
|
799
|
-
});
|
|
800
|
-
};
|
|
801
|
-
|
|
802
|
-
/**
|
|
803
|
-
* Prompt for a `Date`.
|
|
804
|
-
*
|
|
805
|
-
* @param {String} str
|
|
806
|
-
* @param {Function} fn
|
|
807
|
-
* @api private
|
|
808
|
-
*/
|
|
809
|
-
|
|
810
|
-
Command.prototype.promptForDate = function(str, fn){
|
|
811
|
-
var self = this;
|
|
812
|
-
this.promptSingleLine(str, function parseDate(val){
|
|
813
|
-
val = new Date(val);
|
|
814
|
-
if (isNaN(val.getTime())) return self.promptSingleLine(str + '(must be a date) ', parseDate);
|
|
815
|
-
fn(val);
|
|
816
|
-
});
|
|
817
|
-
};
|
|
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
|
-
|
|
838
|
-
/**
|
|
839
|
-
* Single-line prompt.
|
|
840
|
-
*
|
|
841
|
-
* @param {String} str
|
|
842
|
-
* @param {Function} fn
|
|
843
|
-
* @api private
|
|
844
|
-
*/
|
|
845
|
-
|
|
846
|
-
Command.prototype.promptSingleLine = function(str, fn){
|
|
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]) {
|
|
851
|
-
return this['promptFor' + (fn.name || fn)](str, arguments[2]);
|
|
852
|
-
}
|
|
853
|
-
|
|
854
|
-
process.stdout.write(str);
|
|
855
|
-
process.stdin.setEncoding('utf8');
|
|
856
|
-
process.stdin.once('data', function(val){
|
|
857
|
-
fn(val.trim());
|
|
858
|
-
}).resume();
|
|
859
|
-
};
|
|
860
|
-
|
|
861
|
-
/**
|
|
862
|
-
* Multi-line prompt.
|
|
863
|
-
*
|
|
864
|
-
* @param {String} str
|
|
865
|
-
* @param {Function} fn
|
|
866
|
-
* @api private
|
|
867
|
-
*/
|
|
868
|
-
|
|
869
|
-
Command.prototype.promptMultiLine = function(str, fn){
|
|
870
|
-
var buf = [];
|
|
871
|
-
console.log(str);
|
|
872
|
-
process.stdin.setEncoding('utf8');
|
|
873
|
-
process.stdin.on('data', function(val){
|
|
874
|
-
if ('\n' == val || '\r\n' == val) {
|
|
875
|
-
process.stdin.removeAllListeners('data');
|
|
876
|
-
fn(buf.join('\n'));
|
|
877
|
-
} else {
|
|
878
|
-
buf.push(val.trimRight());
|
|
879
|
-
}
|
|
880
|
-
}).resume();
|
|
881
|
-
};
|
|
882
|
-
|
|
883
|
-
/**
|
|
884
|
-
* Prompt `str` and callback `fn(val)`
|
|
885
|
-
*
|
|
886
|
-
* Commander supports single-line and multi-line prompts.
|
|
887
|
-
* To issue a single-line prompt simply add white-space
|
|
888
|
-
* to the end of `str`, something like "name: ", whereas
|
|
889
|
-
* for a multi-line prompt omit this "description:".
|
|
890
|
-
*
|
|
891
|
-
*
|
|
892
|
-
* Examples:
|
|
893
|
-
*
|
|
894
|
-
* program.prompt('Username: ', function(name){
|
|
895
|
-
* console.log('hi %s', name);
|
|
896
|
-
* });
|
|
897
|
-
*
|
|
898
|
-
* program.prompt('Description:', function(desc){
|
|
899
|
-
* console.log('description was "%s"', desc.trim());
|
|
900
|
-
* });
|
|
901
|
-
*
|
|
902
|
-
* @param {String|Object} str
|
|
903
|
-
* @param {Function} fn
|
|
904
|
-
* @api public
|
|
905
|
-
*/
|
|
906
|
-
|
|
907
|
-
Command.prototype.prompt = function(str, fn){
|
|
908
|
-
var self = this;
|
|
909
|
-
if ('string' == typeof str) {
|
|
910
|
-
if (/ $/.test(str)) return this.promptSingleLine.apply(this, arguments);
|
|
911
|
-
this.promptMultiLine(str, fn);
|
|
912
|
-
} else {
|
|
913
|
-
var keys = Object.keys(str)
|
|
914
|
-
, obj = {};
|
|
915
|
-
|
|
916
|
-
function next() {
|
|
917
|
-
var key = keys.shift()
|
|
918
|
-
, label = str[key];
|
|
919
|
-
|
|
920
|
-
if (!key) return fn(obj);
|
|
921
|
-
self.prompt(label, function(val){
|
|
922
|
-
obj[key] = val;
|
|
923
|
-
next();
|
|
924
|
-
});
|
|
925
|
-
}
|
|
926
|
-
|
|
927
|
-
next();
|
|
928
|
-
}
|
|
929
|
-
};
|
|
930
|
-
|
|
931
|
-
/**
|
|
932
|
-
* Prompt for password with `str`, `mask` char and callback `fn(val)`.
|
|
933
|
-
*
|
|
934
|
-
* The mask string defaults to '', aka no output is
|
|
935
|
-
* written while typing, you may want to use "*" etc.
|
|
936
|
-
*
|
|
937
|
-
* Examples:
|
|
938
|
-
*
|
|
939
|
-
* program.password('Password: ', function(pass){
|
|
940
|
-
* console.log('got "%s"', pass);
|
|
941
|
-
* process.stdin.destroy();
|
|
942
|
-
* });
|
|
943
|
-
*
|
|
944
|
-
* program.password('Password: ', '*', function(pass){
|
|
945
|
-
* console.log('got "%s"', pass);
|
|
946
|
-
* process.stdin.destroy();
|
|
947
|
-
* });
|
|
948
|
-
*
|
|
949
|
-
* @param {String} str
|
|
950
|
-
* @param {String} mask
|
|
951
|
-
* @param {Function} fn
|
|
952
|
-
* @api public
|
|
953
|
-
*/
|
|
954
|
-
|
|
955
|
-
Command.prototype.password = function(str, mask, fn){
|
|
956
|
-
var self = this
|
|
957
|
-
, buf = '';
|
|
958
|
-
|
|
959
|
-
// default mask
|
|
960
|
-
if ('function' == typeof mask) {
|
|
961
|
-
fn = mask;
|
|
962
|
-
mask = '';
|
|
963
|
-
}
|
|
964
|
-
|
|
965
|
-
keypress(process.stdin);
|
|
966
|
-
|
|
967
|
-
function setRawMode(mode) {
|
|
968
|
-
if (process.stdin.setRawMode) {
|
|
969
|
-
process.stdin.setRawMode(mode);
|
|
970
|
-
} else {
|
|
971
|
-
tty.setRawMode(mode);
|
|
972
|
-
}
|
|
973
|
-
};
|
|
974
|
-
setRawMode(true);
|
|
975
|
-
process.stdout.write(str);
|
|
976
|
-
|
|
977
|
-
// keypress
|
|
978
|
-
process.stdin.on('keypress', function(c, key){
|
|
979
|
-
if (key && 'enter' == key.name) {
|
|
980
|
-
console.log();
|
|
981
|
-
process.stdin.pause();
|
|
982
|
-
process.stdin.removeAllListeners('keypress');
|
|
983
|
-
setRawMode(false);
|
|
984
|
-
if (!buf.trim().length) return self.password(str, mask, fn);
|
|
985
|
-
fn(buf);
|
|
986
|
-
return;
|
|
987
|
-
}
|
|
988
|
-
|
|
989
|
-
if (key && key.ctrl && 'c' == key.name) {
|
|
990
|
-
console.log('%s', buf);
|
|
991
|
-
process.exit();
|
|
992
|
-
}
|
|
993
|
-
|
|
994
|
-
process.stdout.write(mask);
|
|
995
|
-
buf += c;
|
|
996
|
-
}).resume();
|
|
997
|
-
};
|
|
998
|
-
|
|
999
|
-
/**
|
|
1000
|
-
* Confirmation prompt with `str` and callback `fn(bool)`
|
|
1001
|
-
*
|
|
1002
|
-
* Examples:
|
|
1003
|
-
*
|
|
1004
|
-
* program.confirm('continue? ', function(ok){
|
|
1005
|
-
* console.log(' got %j', ok);
|
|
1006
|
-
* process.stdin.destroy();
|
|
1007
|
-
* });
|
|
1008
|
-
*
|
|
1009
|
-
* @param {String} str
|
|
1010
|
-
* @param {Function} fn
|
|
1011
|
-
* @api public
|
|
1012
|
-
*/
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
Command.prototype.confirm = function(str, fn, verbose){
|
|
1016
|
-
var self = this;
|
|
1017
|
-
this.prompt(str, function(ok){
|
|
1018
|
-
if (!ok.trim()) {
|
|
1019
|
-
if (!verbose) str += '(yes or no) ';
|
|
1020
|
-
return self.confirm(str, fn, true);
|
|
1021
|
-
}
|
|
1022
|
-
fn(parseBool(ok));
|
|
1023
|
-
});
|
|
1024
|
-
};
|
|
1025
|
-
|
|
1026
|
-
/**
|
|
1027
|
-
* Choice prompt with `list` of items and callback `fn(index, item)`
|
|
1028
|
-
*
|
|
1029
|
-
* Examples:
|
|
1030
|
-
*
|
|
1031
|
-
* var list = ['tobi', 'loki', 'jane', 'manny', 'luna'];
|
|
1032
|
-
*
|
|
1033
|
-
* console.log('Choose the coolest pet:');
|
|
1034
|
-
* program.choose(list, function(i){
|
|
1035
|
-
* console.log('you chose %d "%s"', i, list[i]);
|
|
1036
|
-
* process.stdin.destroy();
|
|
1037
|
-
* });
|
|
1038
|
-
*
|
|
1039
|
-
* @param {Array} list
|
|
1040
|
-
* @param {Number|Function} index or fn
|
|
1041
|
-
* @param {Function} fn
|
|
1042
|
-
* @api public
|
|
1043
|
-
*/
|
|
1044
|
-
|
|
1045
|
-
Command.prototype.choose = function(list, index, fn){
|
|
1046
|
-
var self = this
|
|
1047
|
-
, hasDefault = 'number' == typeof index;
|
|
1048
|
-
|
|
1049
|
-
if (!hasDefault) {
|
|
1050
|
-
fn = index;
|
|
1051
|
-
index = null;
|
|
1052
|
-
}
|
|
1053
|
-
|
|
1054
|
-
list.forEach(function(item, i){
|
|
1055
|
-
if (hasDefault && i == index) {
|
|
1056
|
-
console.log('* %d) %s', i + 1, item);
|
|
1057
|
-
} else {
|
|
1058
|
-
console.log(' %d) %s', i + 1, item);
|
|
1059
|
-
}
|
|
1060
|
-
});
|
|
1061
|
-
|
|
1062
|
-
function again() {
|
|
1063
|
-
self.prompt(' : ', function(val){
|
|
1064
|
-
val = parseInt(val, 10) - 1;
|
|
1065
|
-
if (hasDefault && isNaN(val)) val = index;
|
|
1066
|
-
|
|
1067
|
-
if (null == list[val]) {
|
|
1068
|
-
again();
|
|
1069
|
-
} else {
|
|
1070
|
-
fn(val, list[val]);
|
|
1071
|
-
}
|
|
1072
|
-
});
|
|
1073
|
-
}
|
|
1074
|
-
|
|
1075
|
-
again();
|
|
1076
|
-
};
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
786
|
/**
|
|
1080
787
|
* Output help information for this command
|
|
1081
788
|
*
|
|
@@ -1112,18 +819,6 @@ function camelcase(flag) {
|
|
|
1112
819
|
});
|
|
1113
820
|
}
|
|
1114
821
|
|
|
1115
|
-
/**
|
|
1116
|
-
* Parse a boolean `str`.
|
|
1117
|
-
*
|
|
1118
|
-
* @param {String} str
|
|
1119
|
-
* @return {Boolean}
|
|
1120
|
-
* @api private
|
|
1121
|
-
*/
|
|
1122
|
-
|
|
1123
|
-
function parseBool(str) {
|
|
1124
|
-
return /^y|yes|ok|true$/i.test(str);
|
|
1125
|
-
}
|
|
1126
|
-
|
|
1127
822
|
/**
|
|
1128
823
|
* Pad `str` to `width`.
|
|
1129
824
|
*
|
package/package.json
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "commander"
|
|
3
|
-
, "version": "
|
|
3
|
+
, "version": "2.2.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,169 +0,0 @@
|
|
|
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
|
-
|
|
25
|
-
1.1.0 / 2012-11-16
|
|
26
|
-
==================
|
|
27
|
-
|
|
28
|
-
* add git-style executable subcommand support. Closes #94
|
|
29
|
-
|
|
30
|
-
1.0.5 / 2012-10-09
|
|
31
|
-
==================
|
|
32
|
-
|
|
33
|
-
* fix `--name` clobbering. Closes #92
|
|
34
|
-
* fix examples/help. Closes #89
|
|
35
|
-
|
|
36
|
-
1.0.4 / 2012-09-03
|
|
37
|
-
==================
|
|
38
|
-
|
|
39
|
-
* add `outputHelp()` method.
|
|
40
|
-
|
|
41
|
-
1.0.3 / 2012-08-30
|
|
42
|
-
==================
|
|
43
|
-
|
|
44
|
-
* remove invalid .version() defaulting
|
|
45
|
-
|
|
46
|
-
1.0.2 / 2012-08-24
|
|
47
|
-
==================
|
|
48
|
-
|
|
49
|
-
* add `--foo=bar` support [arv]
|
|
50
|
-
* fix password on node 0.8.8. Make backward compatible with 0.6 [focusaurus]
|
|
51
|
-
|
|
52
|
-
1.0.1 / 2012-08-03
|
|
53
|
-
==================
|
|
54
|
-
|
|
55
|
-
* fix issue #56
|
|
56
|
-
* fix tty.setRawMode(mode) was moved to tty.ReadStream#setRawMode() (i.e. process.stdin.setRawMode())
|
|
57
|
-
|
|
58
|
-
1.0.0 / 2012-07-05
|
|
59
|
-
==================
|
|
60
|
-
|
|
61
|
-
* add support for optional option descriptions
|
|
62
|
-
* add defaulting of `.version()` to package.json's version
|
|
63
|
-
|
|
64
|
-
0.6.1 / 2012-06-01
|
|
65
|
-
==================
|
|
66
|
-
|
|
67
|
-
* Added: append (yes or no) on confirmation
|
|
68
|
-
* Added: allow node.js v0.7.x
|
|
69
|
-
|
|
70
|
-
0.6.0 / 2012-04-10
|
|
71
|
-
==================
|
|
72
|
-
|
|
73
|
-
* Added `.prompt(obj, callback)` support. Closes #49
|
|
74
|
-
* Added default support to .choose(). Closes #41
|
|
75
|
-
* Fixed the choice example
|
|
76
|
-
|
|
77
|
-
0.5.1 / 2011-12-20
|
|
78
|
-
==================
|
|
79
|
-
|
|
80
|
-
* Fixed `password()` for recent nodes. Closes #36
|
|
81
|
-
|
|
82
|
-
0.5.0 / 2011-12-04
|
|
83
|
-
==================
|
|
84
|
-
|
|
85
|
-
* Added sub-command option support [itay]
|
|
86
|
-
|
|
87
|
-
0.4.3 / 2011-12-04
|
|
88
|
-
==================
|
|
89
|
-
|
|
90
|
-
* Fixed custom help ordering. Closes #32
|
|
91
|
-
|
|
92
|
-
0.4.2 / 2011-11-24
|
|
93
|
-
==================
|
|
94
|
-
|
|
95
|
-
* Added travis support
|
|
96
|
-
* Fixed: line-buffered input automatically trimmed. Closes #31
|
|
97
|
-
|
|
98
|
-
0.4.1 / 2011-11-18
|
|
99
|
-
==================
|
|
100
|
-
|
|
101
|
-
* Removed listening for "close" on --help
|
|
102
|
-
|
|
103
|
-
0.4.0 / 2011-11-15
|
|
104
|
-
==================
|
|
105
|
-
|
|
106
|
-
* Added support for `--`. Closes #24
|
|
107
|
-
|
|
108
|
-
0.3.3 / 2011-11-14
|
|
109
|
-
==================
|
|
110
|
-
|
|
111
|
-
* Fixed: wait for close event when writing help info [Jerry Hamlet]
|
|
112
|
-
|
|
113
|
-
0.3.2 / 2011-11-01
|
|
114
|
-
==================
|
|
115
|
-
|
|
116
|
-
* Fixed long flag definitions with values [felixge]
|
|
117
|
-
|
|
118
|
-
0.3.1 / 2011-10-31
|
|
119
|
-
==================
|
|
120
|
-
|
|
121
|
-
* Changed `--version` short flag to `-V` from `-v`
|
|
122
|
-
* Changed `.version()` so it's configurable [felixge]
|
|
123
|
-
|
|
124
|
-
0.3.0 / 2011-10-31
|
|
125
|
-
==================
|
|
126
|
-
|
|
127
|
-
* Added support for long flags only. Closes #18
|
|
128
|
-
|
|
129
|
-
0.2.1 / 2011-10-24
|
|
130
|
-
==================
|
|
131
|
-
|
|
132
|
-
* "node": ">= 0.4.x < 0.7.0". Closes #20
|
|
133
|
-
|
|
134
|
-
0.2.0 / 2011-09-26
|
|
135
|
-
==================
|
|
136
|
-
|
|
137
|
-
* Allow for defaults that are not just boolean. Default peassignment only occurs for --no-*, optional, and required arguments. [Jim Isaacs]
|
|
138
|
-
|
|
139
|
-
0.1.0 / 2011-08-24
|
|
140
|
-
==================
|
|
141
|
-
|
|
142
|
-
* Added support for custom `--help` output
|
|
143
|
-
|
|
144
|
-
0.0.5 / 2011-08-18
|
|
145
|
-
==================
|
|
146
|
-
|
|
147
|
-
* Changed: when the user enters nothing prompt for password again
|
|
148
|
-
* Fixed issue with passwords beginning with numbers [NuckChorris]
|
|
149
|
-
|
|
150
|
-
0.0.4 / 2011-08-15
|
|
151
|
-
==================
|
|
152
|
-
|
|
153
|
-
* Fixed `Commander#args`
|
|
154
|
-
|
|
155
|
-
0.0.3 / 2011-08-15
|
|
156
|
-
==================
|
|
157
|
-
|
|
158
|
-
* Added default option value support
|
|
159
|
-
|
|
160
|
-
0.0.2 / 2011-08-15
|
|
161
|
-
==================
|
|
162
|
-
|
|
163
|
-
* Added mask support to `Command#password(str[, mask], fn)`
|
|
164
|
-
* Added `Command#password(str, fn)`
|
|
165
|
-
|
|
166
|
-
0.0.1 / 2010-01-03
|
|
167
|
-
==================
|
|
168
|
-
|
|
169
|
-
* Initial release
|