spacedocs 0.0.2 → 0.0.3

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 (41) hide show
  1. data/README.md +6 -2
  2. data/{source → lib}/class.html.haml +1 -4
  3. data/{source → lib}/index.html.haml +2 -2
  4. data/{dox → lib/node_modules/dox}/History.md +0 -0
  5. data/{dox → lib/node_modules/dox}/Makefile +0 -0
  6. data/{dox → lib/node_modules/dox}/Readme.md +0 -0
  7. data/{dox → lib/node_modules/dox}/bin/dox +0 -0
  8. data/{dox → lib/node_modules/dox}/index.js +0 -0
  9. data/{dox → lib/node_modules/dox}/lib/dox.js +1 -10
  10. data/{dox → lib/node_modules/dox}/lib/utils.js +0 -0
  11. data/lib/node_modules/dox/node_modules/commander/History.md +99 -0
  12. data/lib/node_modules/dox/node_modules/commander/Makefile +7 -0
  13. data/lib/node_modules/dox/node_modules/commander/Readme.md +263 -0
  14. data/lib/node_modules/dox/node_modules/commander/index.js +2 -0
  15. data/lib/node_modules/dox/node_modules/commander/lib/commander.js +992 -0
  16. data/lib/node_modules/dox/node_modules/commander/package.json +38 -0
  17. data/lib/node_modules/dox/node_modules/github-flavored-markdown/README.md +17 -0
  18. data/lib/node_modules/dox/node_modules/github-flavored-markdown/_config.yml +3 -0
  19. data/lib/node_modules/dox/node_modules/github-flavored-markdown/_layouts/default.html +77 -0
  20. data/lib/node_modules/dox/node_modules/github-flavored-markdown/code.rb +67 -0
  21. data/lib/node_modules/dox/node_modules/github-flavored-markdown/images/gfm.png +0 -0
  22. data/lib/node_modules/dox/node_modules/github-flavored-markdown/index.md +78 -0
  23. data/lib/node_modules/dox/node_modules/github-flavored-markdown/package.json +27 -0
  24. data/lib/node_modules/dox/node_modules/github-flavored-markdown/preview.md +27 -0
  25. data/lib/node_modules/dox/node_modules/github-flavored-markdown/sample_content.html +169 -0
  26. data/lib/node_modules/dox/node_modules/github-flavored-markdown/scripts/preview.js +18 -0
  27. data/lib/node_modules/dox/node_modules/github-flavored-markdown/scripts/showdown.js +1414 -0
  28. data/lib/node_modules/dox/node_modules/github-flavored-markdown/stylesheets/screen.css +20 -0
  29. data/lib/node_modules/dox/package.json +43 -0
  30. data/lib/spacedocs.rb +42 -53
  31. data/lib/{assets/stylesheets/spacedocs/docs.css.sass → spacedocs.sass} +0 -0
  32. data/lib/spacedocs/version.rb +1 -1
  33. metadata +116 -25
  34. data/dox/package.json +0 -16
  35. data/dox/test/dox.test.js +0 -287
  36. data/dox/test/fixtures/a.js +0 -12
  37. data/dox/test/fixtures/b.js +0 -26
  38. data/dox/test/fixtures/c.js +0 -266
  39. data/dox/test/fixtures/d.js +0 -15
  40. data/dox/test/fixtures/titles.js +0 -14
  41. data/lib/spacedocs/engine.rb +0 -6
@@ -0,0 +1,2 @@
1
+
2
+ module.exports = require('./lib/commander');
@@ -0,0 +1,992 @@
1
+
2
+ /*!
3
+ * commander
4
+ * Copyright(c) 2011 TJ Holowaychuk <tj@vision-media.ca>
5
+ * MIT Licensed
6
+ */
7
+
8
+ /**
9
+ * Module dependencies.
10
+ */
11
+
12
+ var EventEmitter = require('events').EventEmitter
13
+ , path = require('path')
14
+ , tty = require('tty')
15
+ , basename = path.basename;
16
+
17
+ /**
18
+ * Expose the root command.
19
+ */
20
+
21
+ exports = module.exports = new Command;
22
+
23
+ /**
24
+ * Expose `Command`.
25
+ */
26
+
27
+ exports.Command = Command;
28
+
29
+ /**
30
+ * Expose `Option`.
31
+ */
32
+
33
+ exports.Option = Option;
34
+
35
+ /**
36
+ * Initialize a new `Option` with the given `flags` and `description`.
37
+ *
38
+ * @param {String} flags
39
+ * @param {String} description
40
+ * @api public
41
+ */
42
+
43
+ function Option(flags, description) {
44
+ this.flags = flags;
45
+ this.required = ~flags.indexOf('<');
46
+ this.optional = ~flags.indexOf('[');
47
+ this.bool = !~flags.indexOf('-no-');
48
+ flags = flags.split(/[ ,|]+/);
49
+ if (flags.length > 1 && !/^[[<]/.test(flags[1])) this.short = flags.shift();
50
+ this.long = flags.shift();
51
+ this.description = description;
52
+ }
53
+
54
+ /**
55
+ * Return option name.
56
+ *
57
+ * @return {String}
58
+ * @api private
59
+ */
60
+
61
+ Option.prototype.name = function(){
62
+ return this.long
63
+ .replace('--', '')
64
+ .replace('no-', '');
65
+ };
66
+
67
+ /**
68
+ * Check if `arg` matches the short or long flag.
69
+ *
70
+ * @param {String} arg
71
+ * @return {Boolean}
72
+ * @api private
73
+ */
74
+
75
+ Option.prototype.is = function(arg){
76
+ return arg == this.short
77
+ || arg == this.long;
78
+ };
79
+
80
+ /**
81
+ * Initialize a new `Command`.
82
+ *
83
+ * @param {String} name
84
+ * @api public
85
+ */
86
+
87
+ function Command(name) {
88
+ this.commands = [];
89
+ this.options = [];
90
+ this.args = [];
91
+ this.name = name;
92
+ }
93
+
94
+ /**
95
+ * Inherit from `EventEmitter.prototype`.
96
+ */
97
+
98
+ Command.prototype.__proto__ = EventEmitter.prototype;
99
+
100
+ /**
101
+ * Add command `name`.
102
+ *
103
+ * The `.action()` callback is invoked when the
104
+ * command `name` is specified via __ARGV__,
105
+ * and the remaining arguments are applied to the
106
+ * function for access.
107
+ *
108
+ * When the `name` is "*" an un-matched command
109
+ * will be passed as the first arg, followed by
110
+ * the rest of __ARGV__ remaining.
111
+ *
112
+ * Examples:
113
+ *
114
+ * program
115
+ * .version('0.0.1')
116
+ * .option('-C, --chdir <path>', 'change the working directory')
117
+ * .option('-c, --config <path>', 'set config path. defaults to ./deploy.conf')
118
+ * .option('-T, --no-tests', 'ignore test hook')
119
+ *
120
+ * program
121
+ * .command('setup')
122
+ * .description('run remote setup commands')
123
+ * .action(function(){
124
+ * console.log('setup');
125
+ * });
126
+ *
127
+ * program
128
+ * .command('exec <cmd>')
129
+ * .description('run the given remote command')
130
+ * .action(function(cmd){
131
+ * console.log('exec "%s"', cmd);
132
+ * });
133
+ *
134
+ * program
135
+ * .command('*')
136
+ * .description('deploy the given env')
137
+ * .action(function(env){
138
+ * console.log('deploying "%s"', env);
139
+ * });
140
+ *
141
+ * program.parse(process.argv);
142
+ *
143
+ * @param {String} name
144
+ * @return {Command} the new command
145
+ * @api public
146
+ */
147
+
148
+ Command.prototype.command = function(name){
149
+ var args = name.split(/ +/);
150
+ var cmd = new Command(args.shift());
151
+ this.commands.push(cmd);
152
+ cmd.parseExpectedArgs(args);
153
+ cmd.parent = this;
154
+ return cmd;
155
+ };
156
+
157
+ /**
158
+ * Parse expected `args`.
159
+ *
160
+ * For example `["[type]"]` becomes `[{ required: false, name: 'type' }]`.
161
+ *
162
+ * @param {Array} args
163
+ * @return {Command} for chaining
164
+ * @api public
165
+ */
166
+
167
+ Command.prototype.parseExpectedArgs = function(args){
168
+ if (!args.length) return;
169
+ var self = this;
170
+ args.forEach(function(arg){
171
+ switch (arg[0]) {
172
+ case '<':
173
+ self.args.push({ required: true, name: arg.slice(1, -1) });
174
+ break;
175
+ case '[':
176
+ self.args.push({ required: false, name: arg.slice(1, -1) });
177
+ break;
178
+ }
179
+ });
180
+ return this;
181
+ };
182
+
183
+ /**
184
+ * Register callback `fn` for the command.
185
+ *
186
+ * Examples:
187
+ *
188
+ * program
189
+ * .command('help')
190
+ * .description('display verbose help')
191
+ * .action(function(){
192
+ * // output help here
193
+ * });
194
+ *
195
+ * @param {Function} fn
196
+ * @return {Command} for chaining
197
+ * @api public
198
+ */
199
+
200
+ Command.prototype.action = function(fn){
201
+ var self = this;
202
+ this.parent.on(this.name, function(args, unknown){
203
+ // Parse any so-far unknown options
204
+ unknown = unknown || [];
205
+ var parsed = self.parseOptions(unknown);
206
+
207
+ // Output help if necessary
208
+ outputHelpIfNecessary(self, parsed.unknown);
209
+
210
+ // If there are still any unknown options, then we simply
211
+ // die, unless someone asked for help, in which case we give it
212
+ // to them, and then we die.
213
+ if (parsed.unknown.length > 0) {
214
+ self.unknownOption(parsed.unknown[0]);
215
+ }
216
+
217
+ self.args.forEach(function(arg, i){
218
+ if (arg.required && null == args[i]) {
219
+ self.missingArgument(arg.name);
220
+ }
221
+ });
222
+
223
+ // Always append ourselves to the end of the arguments,
224
+ // to make sure we match the number of arguments the user
225
+ // expects
226
+ if (self.args.length) {
227
+ args[self.args.length] = self;
228
+ } else {
229
+ args.push(self);
230
+ }
231
+
232
+ fn.apply(this, args);
233
+ });
234
+ return this;
235
+ };
236
+
237
+ /**
238
+ * Define option with `flags`, `description` and optional
239
+ * coercion `fn`.
240
+ *
241
+ * The `flags` string should contain both the short and long flags,
242
+ * separated by comma, a pipe or space. The following are all valid
243
+ * all will output this way when `--help` is used.
244
+ *
245
+ * "-p, --pepper"
246
+ * "-p|--pepper"
247
+ * "-p --pepper"
248
+ *
249
+ * Examples:
250
+ *
251
+ * // simple boolean defaulting to false
252
+ * program.option('-p, --pepper', 'add pepper');
253
+ *
254
+ * --pepper
255
+ * program.pepper
256
+ * // => Boolean
257
+ *
258
+ * // simple boolean defaulting to false
259
+ * program.option('-C, --no-cheese', 'remove cheese');
260
+ *
261
+ * program.cheese
262
+ * // => true
263
+ *
264
+ * --no-cheese
265
+ * program.cheese
266
+ * // => true
267
+ *
268
+ * // required argument
269
+ * program.option('-C, --chdir <path>', 'change the working directory');
270
+ *
271
+ * --chdir /tmp
272
+ * program.chdir
273
+ * // => "/tmp"
274
+ *
275
+ * // optional argument
276
+ * program.option('-c, --cheese [type]', 'add cheese [marble]');
277
+ *
278
+ * @param {String} flags
279
+ * @param {String} description
280
+ * @param {Function|Mixed} fn or default
281
+ * @param {Mixed} defaultValue
282
+ * @return {Command} for chaining
283
+ * @api public
284
+ */
285
+
286
+ Command.prototype.option = function(flags, description, fn, defaultValue){
287
+ var self = this
288
+ , option = new Option(flags, description)
289
+ , oname = option.name()
290
+ , name = camelcase(oname);
291
+
292
+ // default as 3rd arg
293
+ if ('function' != typeof fn) defaultValue = fn, fn = null;
294
+
295
+ // preassign default value only for --no-*, [optional], or <required>
296
+ if (false == option.bool || option.optional || option.required) {
297
+ // when --no-* we make sure default is true
298
+ if (false == option.bool) defaultValue = true;
299
+ // preassign only if we have a default
300
+ if (undefined !== defaultValue) self[name] = defaultValue;
301
+ }
302
+
303
+ // register the option
304
+ this.options.push(option);
305
+
306
+ // when it's passed assign the value
307
+ // and conditionally invoke the callback
308
+ this.on(oname, function(val){
309
+ // coercion
310
+ if (null != val && fn) val = fn(val);
311
+
312
+ // unassigned or bool
313
+ if ('boolean' == typeof self[name] || 'undefined' == typeof self[name]) {
314
+ // if no value, bool true, and we have a default, then use it!
315
+ if (null == val) {
316
+ self[name] = option.bool
317
+ ? defaultValue || true
318
+ : false;
319
+ } else {
320
+ self[name] = val;
321
+ }
322
+ } else if (null !== val) {
323
+ // reassign
324
+ self[name] = val;
325
+ }
326
+ });
327
+
328
+ return this;
329
+ };
330
+
331
+ /**
332
+ * Parse `argv`, settings options and invoking commands when defined.
333
+ *
334
+ * @param {Array} argv
335
+ * @return {Command} for chaining
336
+ * @api public
337
+ */
338
+
339
+ Command.prototype.parse = function(argv){
340
+ // store raw args
341
+ this.rawArgs = argv;
342
+
343
+ // guess name
344
+ if (!this.name) this.name = basename(argv[1]);
345
+
346
+ // process argv
347
+ var parsed = this.parseOptions(this.normalize(argv.slice(2)));
348
+ this.args = parsed.args;
349
+ return this.parseArgs(this.args, parsed.unknown);
350
+ };
351
+
352
+ /**
353
+ * Normalize `args`, splitting joined short flags. For example
354
+ * the arg "-abc" is equivalent to "-a -b -c".
355
+ *
356
+ * @param {Array} args
357
+ * @return {Array}
358
+ * @api private
359
+ */
360
+
361
+ Command.prototype.normalize = function(args){
362
+ var ret = []
363
+ , arg;
364
+
365
+ for (var i = 0, len = args.length; i < len; ++i) {
366
+ arg = args[i];
367
+ if (arg.length > 1 && '-' == arg[0] && '-' != arg[1]) {
368
+ arg.slice(1).split('').forEach(function(c){
369
+ ret.push('-' + c);
370
+ });
371
+ } else {
372
+ ret.push(arg);
373
+ }
374
+ }
375
+
376
+ return ret;
377
+ };
378
+
379
+ /**
380
+ * Parse command `args`.
381
+ *
382
+ * When listener(s) are available those
383
+ * callbacks are invoked, otherwise the "*"
384
+ * event is emitted and those actions are invoked.
385
+ *
386
+ * @param {Array} args
387
+ * @return {Command} for chaining
388
+ * @api private
389
+ */
390
+
391
+ Command.prototype.parseArgs = function(args, unknown){
392
+ var cmds = this.commands
393
+ , len = cmds.length
394
+ , name;
395
+
396
+ if (args.length) {
397
+ name = args[0];
398
+ if (this.listeners(name).length) {
399
+ this.emit(args.shift(), args, unknown);
400
+ } else {
401
+ this.emit('*', args);
402
+ }
403
+ } else {
404
+ outputHelpIfNecessary(this, unknown);
405
+
406
+ // If there were no args and we have unknown options,
407
+ // then they are extraneous and we need to error.
408
+ if (unknown.length > 0) {
409
+ this.unknownOption(unknown[0]);
410
+ }
411
+ }
412
+
413
+ return this;
414
+ };
415
+
416
+ /**
417
+ * Return an option matching `arg` if any.
418
+ *
419
+ * @param {String} arg
420
+ * @return {Option}
421
+ * @api private
422
+ */
423
+
424
+ Command.prototype.optionFor = function(arg){
425
+ for (var i = 0, len = this.options.length; i < len; ++i) {
426
+ if (this.options[i].is(arg)) {
427
+ return this.options[i];
428
+ }
429
+ }
430
+ };
431
+
432
+ /**
433
+ * Parse options from `argv` returning `argv`
434
+ * void of these options.
435
+ *
436
+ * @param {Array} argv
437
+ * @return {Array}
438
+ * @api public
439
+ */
440
+
441
+ Command.prototype.parseOptions = function(argv){
442
+ var args = []
443
+ , len = argv.length
444
+ , literal
445
+ , option
446
+ , arg;
447
+
448
+ var unknownOptions = [];
449
+
450
+ // parse options
451
+ for (var i = 0; i < len; ++i) {
452
+ arg = argv[i];
453
+
454
+ // literal args after --
455
+ if ('--' == arg) {
456
+ literal = true;
457
+ continue;
458
+ }
459
+
460
+ if (literal) {
461
+ args.push(arg);
462
+ continue;
463
+ }
464
+
465
+ // find matching Option
466
+ option = this.optionFor(arg);
467
+
468
+ // option is defined
469
+ if (option) {
470
+ // requires arg
471
+ if (option.required) {
472
+ arg = argv[++i];
473
+ if (null == arg) return this.optionMissingArgument(option);
474
+ if ('-' == arg[0]) return this.optionMissingArgument(option, arg);
475
+ this.emit(option.name(), arg);
476
+ // optional arg
477
+ } else if (option.optional) {
478
+ arg = argv[i+1];
479
+ if (null == arg || '-' == arg[0]) {
480
+ arg = null;
481
+ } else {
482
+ ++i;
483
+ }
484
+ this.emit(option.name(), arg);
485
+ // bool
486
+ } else {
487
+ this.emit(option.name());
488
+ }
489
+ continue;
490
+ }
491
+
492
+ // looks like an option
493
+ if (arg.length > 1 && '-' == arg[0]) {
494
+ unknownOptions.push(arg);
495
+
496
+ // If the next argument looks like it might be
497
+ // an argument for this option, we pass it on.
498
+ // If it isn't, then it'll simply be ignored
499
+ if (argv[i+1] && '-' != argv[i+1][0]) {
500
+ unknownOptions.push(argv[++i]);
501
+ }
502
+ continue;
503
+ }
504
+
505
+ // arg
506
+ args.push(arg);
507
+ }
508
+
509
+ return { args: args, unknown: unknownOptions };
510
+ };
511
+
512
+ /**
513
+ * Argument `name` is missing.
514
+ *
515
+ * @param {String} name
516
+ * @api private
517
+ */
518
+
519
+ Command.prototype.missingArgument = function(name){
520
+ console.error();
521
+ console.error(" error: missing required argument `%s'", name);
522
+ console.error();
523
+ process.exit(1);
524
+ };
525
+
526
+ /**
527
+ * `Option` is missing an argument, but received `flag` or nothing.
528
+ *
529
+ * @param {String} option
530
+ * @param {String} flag
531
+ * @api private
532
+ */
533
+
534
+ Command.prototype.optionMissingArgument = function(option, flag){
535
+ console.error();
536
+ if (flag) {
537
+ console.error(" error: option `%s' argument missing, got `%s'", option.flags, flag);
538
+ } else {
539
+ console.error(" error: option `%s' argument missing", option.flags);
540
+ }
541
+ console.error();
542
+ process.exit(1);
543
+ };
544
+
545
+ /**
546
+ * Unknown option `flag`.
547
+ *
548
+ * @param {String} flag
549
+ * @api private
550
+ */
551
+
552
+ Command.prototype.unknownOption = function(flag){
553
+ console.error();
554
+ console.error(" error: unknown option `%s'", flag);
555
+ console.error();
556
+ process.exit(1);
557
+ };
558
+
559
+ /**
560
+ * Set the program version to `str`.
561
+ *
562
+ * This method auto-registers the "-V, --version" flag
563
+ * which will print the version number when passed.
564
+ *
565
+ * @param {String} str
566
+ * @param {String} flags
567
+ * @return {Command} for chaining
568
+ * @api public
569
+ */
570
+
571
+ Command.prototype.version = function(str, flags){
572
+ if (0 == arguments.length) return this._version;
573
+ this._version = str;
574
+ flags = flags || '-V, --version';
575
+ this.option(flags, 'output the version number');
576
+ this.on('version', function(){
577
+ console.log(str);
578
+ process.exit(0);
579
+ });
580
+ return this;
581
+ };
582
+
583
+ /**
584
+ * Set the description `str`.
585
+ *
586
+ * @param {String} str
587
+ * @return {String|Command}
588
+ * @api public
589
+ */
590
+
591
+ Command.prototype.description = function(str){
592
+ if (0 == arguments.length) return this._description;
593
+ this._description = str;
594
+ return this;
595
+ };
596
+
597
+ /**
598
+ * Set / get the command usage `str`.
599
+ *
600
+ * @param {String} str
601
+ * @return {String|Command}
602
+ * @api public
603
+ */
604
+
605
+ Command.prototype.usage = function(str){
606
+ var args = this.args.map(function(arg){
607
+ return arg.required
608
+ ? '<' + arg.name + '>'
609
+ : '[' + arg.name + ']';
610
+ });
611
+
612
+ var usage = '[options'
613
+ + (this.commands.length ? '] [command' : '')
614
+ + ']'
615
+ + (this.args.length ? ' ' + args : '');
616
+ if (0 == arguments.length) return this._usage || usage;
617
+ this._usage = str;
618
+
619
+ return this;
620
+ };
621
+
622
+ /**
623
+ * Return the largest option length.
624
+ *
625
+ * @return {Number}
626
+ * @api private
627
+ */
628
+
629
+ Command.prototype.largestOptionLength = function(){
630
+ return this.options.reduce(function(max, option){
631
+ return Math.max(max, option.flags.length);
632
+ }, 0);
633
+ };
634
+
635
+ /**
636
+ * Return help for options.
637
+ *
638
+ * @return {String}
639
+ * @api private
640
+ */
641
+
642
+ Command.prototype.optionHelp = function(){
643
+ var width = this.largestOptionLength();
644
+
645
+ // Prepend the help information
646
+ return [pad('-h, --help', width) + ' ' + 'output usage information']
647
+ .concat(this.options.map(function(option){
648
+ return pad(option.flags, width)
649
+ + ' ' + option.description;
650
+ }))
651
+ .join('\n');
652
+ };
653
+
654
+ /**
655
+ * Return command help documentation.
656
+ *
657
+ * @return {String}
658
+ * @api private
659
+ */
660
+
661
+ Command.prototype.commandHelp = function(){
662
+ if (!this.commands.length) return '';
663
+ return [
664
+ ''
665
+ , ' Commands:'
666
+ , ''
667
+ , this.commands.map(function(cmd){
668
+ var args = cmd.args.map(function(arg){
669
+ return arg.required
670
+ ? '<' + arg.name + '>'
671
+ : '[' + arg.name + ']';
672
+ }).join(' ');
673
+
674
+ return cmd.name
675
+ + (cmd.options.length
676
+ ? ' [options]'
677
+ : '') + ' ' + args
678
+ + (cmd.description()
679
+ ? '\n' + cmd.description()
680
+ : '');
681
+ }).join('\n\n').replace(/^/gm, ' ')
682
+ , ''
683
+ ].join('\n');
684
+ };
685
+
686
+ /**
687
+ * Return program help documentation.
688
+ *
689
+ * @return {String}
690
+ * @api private
691
+ */
692
+
693
+ Command.prototype.helpInformation = function(){
694
+ return [
695
+ ''
696
+ , ' Usage: ' + this.name + ' ' + this.usage()
697
+ , '' + this.commandHelp()
698
+ , ' Options:'
699
+ , ''
700
+ , '' + this.optionHelp().replace(/^/gm, ' ')
701
+ , ''
702
+ , ''
703
+ ].join('\n');
704
+ };
705
+
706
+ /**
707
+ * Prompt for a `Number`.
708
+ *
709
+ * @param {String} str
710
+ * @param {Function} fn
711
+ * @api private
712
+ */
713
+
714
+ Command.prototype.promptForNumber = function(str, fn){
715
+ var self = this;
716
+ this.promptSingleLine(str, function parseNumber(val){
717
+ val = Number(val);
718
+ if (isNaN(val)) return self.promptSingleLine(str + '(must be a number) ', parseNumber);
719
+ fn(val);
720
+ });
721
+ };
722
+
723
+ /**
724
+ * Prompt for a `Date`.
725
+ *
726
+ * @param {String} str
727
+ * @param {Function} fn
728
+ * @api private
729
+ */
730
+
731
+ Command.prototype.promptForDate = function(str, fn){
732
+ var self = this;
733
+ this.promptSingleLine(str, function parseDate(val){
734
+ val = new Date(val);
735
+ if (isNaN(val.getTime())) return self.promptSingleLine(str + '(must be a date) ', parseDate);
736
+ fn(val);
737
+ });
738
+ };
739
+
740
+ /**
741
+ * Single-line prompt.
742
+ *
743
+ * @param {String} str
744
+ * @param {Function} fn
745
+ * @api private
746
+ */
747
+
748
+ Command.prototype.promptSingleLine = function(str, fn){
749
+ if ('function' == typeof arguments[2]) {
750
+ return this['promptFor' + (fn.name || fn)](str, arguments[2]);
751
+ }
752
+
753
+ process.stdout.write(str);
754
+ process.stdin.setEncoding('utf8');
755
+ process.stdin.once('data', function(val){
756
+ fn(val.trim());
757
+ }).resume();
758
+ };
759
+
760
+ /**
761
+ * Multi-line prompt.
762
+ *
763
+ * @param {String} str
764
+ * @param {Function} fn
765
+ * @api private
766
+ */
767
+
768
+ Command.prototype.promptMultiLine = function(str, fn){
769
+ var buf = [];
770
+ console.log(str);
771
+ process.stdin.setEncoding('utf8');
772
+ process.stdin.on('data', function(val){
773
+ if ('\n' == val || '\r\n' == val) {
774
+ process.stdin.removeAllListeners('data');
775
+ fn(buf.join('\n'));
776
+ } else {
777
+ buf.push(val.trimRight());
778
+ }
779
+ }).resume();
780
+ };
781
+
782
+ /**
783
+ * Prompt `str` and callback `fn(val)`
784
+ *
785
+ * Commander supports single-line and multi-line prompts.
786
+ * To issue a single-line prompt simply add white-space
787
+ * to the end of `str`, something like "name: ", whereas
788
+ * for a multi-line prompt omit this "description:".
789
+ *
790
+ *
791
+ * Examples:
792
+ *
793
+ * program.prompt('Username: ', function(name){
794
+ * console.log('hi %s', name);
795
+ * });
796
+ *
797
+ * program.prompt('Description:', function(desc){
798
+ * console.log('description was "%s"', desc.trim());
799
+ * });
800
+ *
801
+ * @param {String} str
802
+ * @param {Function} fn
803
+ * @api public
804
+ */
805
+
806
+ Command.prototype.prompt = function(str, fn){
807
+ if (/ $/.test(str)) return this.promptSingleLine.apply(this, arguments);
808
+ this.promptMultiLine(str, fn);
809
+ };
810
+
811
+ /**
812
+ * Prompt for password with `str`, `mask` char and callback `fn(val)`.
813
+ *
814
+ * The mask string defaults to '', aka no output is
815
+ * written while typing, you may want to use "*" etc.
816
+ *
817
+ * Examples:
818
+ *
819
+ * program.password('Password: ', function(pass){
820
+ * console.log('got "%s"', pass);
821
+ * process.stdin.destroy();
822
+ * });
823
+ *
824
+ * program.password('Password: ', '*', function(pass){
825
+ * console.log('got "%s"', pass);
826
+ * process.stdin.destroy();
827
+ * });
828
+ *
829
+ * @param {String} str
830
+ * @param {String} mask
831
+ * @param {Function} fn
832
+ * @api public
833
+ */
834
+
835
+ Command.prototype.password = function(str, mask, fn){
836
+ var self = this
837
+ , buf = '';
838
+
839
+ // default mask
840
+ if ('function' == typeof mask) {
841
+ fn = mask;
842
+ mask = '';
843
+ }
844
+
845
+ process.stdin.resume();
846
+ tty.setRawMode(true);
847
+ process.stdout.write(str);
848
+
849
+ // keypress
850
+ process.stdin.on('keypress', function(c, key){
851
+ if (key && 'enter' == key.name) {
852
+ console.log();
853
+ process.stdin.removeAllListeners('keypress');
854
+ tty.setRawMode(false);
855
+ if (!buf.trim().length) return self.password(str, mask, fn);
856
+ fn(buf);
857
+ return;
858
+ }
859
+
860
+ if (key && key.ctrl && 'c' == key.name) {
861
+ console.log('%s', buf);
862
+ process.exit();
863
+ }
864
+
865
+ process.stdout.write(mask);
866
+ buf += c;
867
+ }).resume();
868
+ };
869
+
870
+ /**
871
+ * Confirmation prompt with `str` and callback `fn(bool)`
872
+ *
873
+ * Examples:
874
+ *
875
+ * program.confirm('continue? ', function(ok){
876
+ * console.log(' got %j', ok);
877
+ * process.stdin.destroy();
878
+ * });
879
+ *
880
+ * @param {String} str
881
+ * @param {Function} fn
882
+ * @api public
883
+ */
884
+
885
+
886
+ Command.prototype.confirm = function(str, fn){
887
+ var self = this;
888
+ this.prompt(str, function(ok){
889
+ if (!ok.trim()) {
890
+ return self.confirm(str, fn);
891
+ }
892
+ fn(parseBool(ok));
893
+ });
894
+ };
895
+
896
+ /**
897
+ * Choice prompt with `list` of items and callback `fn(index, item)`
898
+ *
899
+ * Examples:
900
+ *
901
+ * var list = ['tobi', 'loki', 'jane', 'manny', 'luna'];
902
+ *
903
+ * console.log('Choose the coolest pet:');
904
+ * program.choose(list, function(i){
905
+ * console.log('you chose %d "%s"', i, list[i]);
906
+ * process.stdin.destroy();
907
+ * });
908
+ *
909
+ * @param {Array} list
910
+ * @param {Function} fn
911
+ * @api public
912
+ */
913
+
914
+ Command.prototype.choose = function(list, fn){
915
+ var self = this;
916
+
917
+ list.forEach(function(item, i){
918
+ console.log(' %d) %s', i + 1, item);
919
+ });
920
+
921
+ function again() {
922
+ self.prompt(' : ', function(val){
923
+ val = parseInt(val, 10) - 1;
924
+ if (null == list[val]) {
925
+ again();
926
+ } else {
927
+ fn(val, list[val]);
928
+ }
929
+ });
930
+ }
931
+
932
+ again();
933
+ };
934
+
935
+ /**
936
+ * Camel-case the given `flag`
937
+ *
938
+ * @param {String} flag
939
+ * @return {String}
940
+ * @api private
941
+ */
942
+
943
+ function camelcase(flag) {
944
+ return flag.split('-').reduce(function(str, word){
945
+ return str + word[0].toUpperCase() + word.slice(1);
946
+ });
947
+ }
948
+
949
+ /**
950
+ * Parse a boolean `str`.
951
+ *
952
+ * @param {String} str
953
+ * @return {Boolean}
954
+ * @api private
955
+ */
956
+
957
+ function parseBool(str) {
958
+ return /^y|yes|ok|true$/i.test(str);
959
+ }
960
+
961
+ /**
962
+ * Pad `str` to `width`.
963
+ *
964
+ * @param {String} str
965
+ * @param {Number} width
966
+ * @return {String}
967
+ * @api private
968
+ */
969
+
970
+ function pad(str, width) {
971
+ var len = Math.max(0, width - str.length);
972
+ return str + Array(len + 1).join(' ');
973
+ }
974
+
975
+ /**
976
+ * Output help information if necessary
977
+ *
978
+ * @param {Command} command to output help for
979
+ * @param {Array} array of options to search for -h or --help
980
+ * @api private
981
+ */
982
+
983
+ function outputHelpIfNecessary(cmd, options) {
984
+ options = options || [];
985
+ for (var i = 0; i < options.length; i++) {
986
+ if (options[i] == '--help' || options[i] == '-h') {
987
+ process.stdout.write(cmd.helpInformation());
988
+ cmd.emit('--help');
989
+ process.exit(0);
990
+ }
991
+ }
992
+ }