yargs 1.2.6 → 1.3.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.
package/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
  yargs
2
2
  ========
3
3
 
4
- Yargs be a node.js library fer hearties tryin' ter parse optstrings against their will where even the boo box be not enough to coerce them. This here module is fer scallywags lookin' ter plunder all the sunken -shipz of their --treasures thru program usage but be tired of optstrings disincling to acquiesce to yer requests.
4
+ Yargs be a node.js library fer hearties tryin' ter parse optstrings.
5
5
 
6
6
  With yargs, ye be havin' a map that leads straight to yer treasure! Treasure of course, being a simple option hash.
7
7
 
@@ -11,12 +11,12 @@ With yargs, ye be havin' a map that leads straight to yer treasure! Treasure of
11
11
 
12
12
  > ~~NOTE: Yargs is a fork of [optimist](https://github.com/substack/node-optimist) by [substack (James Halliday)](https://github.com/substack). It is obvious that substack is stretched pretty thin maintaining over 300 modules on npm at the time of this writing. So rather than complain in the project issue tracker I thought I'd just pick up the torch and maintain a proper fork. Currently the project is totally backward compatible with optimist but this may change in the future (if it does I will update this notice to inform you of this). For now though, enjoy optimist with about 5 months worth of fixes and updates rolled in, most of them pulled from optimist's own [stale pull requests](https://github.com/substack/node-optimist/pulls).~~
13
13
 
14
- > UPDATE: Yargs is now the official successor to optimist. Please feel free to submit issues and pull requests. While I personally don't have the time to pour over all the issues and fix all of them on a regular basis, I'm more than happy to look over pull requests, test them, and merge them in. If you'd like to contribute and don't know where to start, have a look at [the issue list](https://github.com/chevex/yargs/issues) :)
14
+ > UPDATE: Yargs is now the official successor to optimist. Please feel free to submit issues and pull requests. While I personally don't have the time to pore over all the issues and fix all of them on a regular basis, I'm more than happy to look over pull requests, test them, and merge them in. If you'd like to contribute and don't know where to start, have a look at [the issue list](https://github.com/chevex/yargs/issues) :)
15
15
 
16
16
  examples
17
17
  ========
18
18
 
19
- With yargs, the options be just a hash! No optstrings be attached.
19
+ With yargs, the options be just a hash!
20
20
  -------------------------------------------------------------------
21
21
 
22
22
  xup.js:
@@ -43,7 +43,7 @@ else {
43
43
 
44
44
  ![Joe was one optimistic pirate.](http://i.imgur.com/4WFGVJ9.png)
45
45
 
46
- But don' walk the plank jus' yet! Ther' be more! Ye can do short options:
46
+ But don't walk the plank just yet! There be more! You can do short options:
47
47
  -------------------------------------------------
48
48
 
49
49
  short.js:
@@ -59,7 +59,7 @@ console.log('(%d,%d)', argv.x, argv.y);
59
59
  $ ./short.js -x 10 -y 21
60
60
  (10,21)
61
61
 
62
- And gold doubooleans, both long an' short (an' grouped!):
62
+ And booleans, both long, short, and even grouped:
63
63
  ----------------------------------
64
64
 
65
65
  bool.js:
@@ -110,7 +110,7 @@ console.log(argv._);
110
110
  (0.54,1.12)
111
111
  [ 'me hearties', 'yo', 'ho' ]
112
112
 
113
- Yargs even counts yer gold doubooleans!
113
+ Yargs even counts your booleans!
114
114
  ----------------------------------------------------------------------
115
115
 
116
116
  count.js
@@ -151,7 +151,7 @@ DEBUG("Extra chatty mode");
151
151
  Showing semi-important stuff too
152
152
  Extra chatty mode
153
153
 
154
- Tell yer friends how ter use yer options and make demands from yer enemies.
154
+ Tell users how to use yer options and make demands.
155
155
  -------------------------------------------------
156
156
 
157
157
  divide.js:
@@ -238,7 +238,7 @@ console.log(argv.x + argv.y);
238
238
  $ ./default_hash.js -y 7
239
239
  17
240
240
 
241
- And if ye really want ter get all descriptive about it...
241
+ And if you really want to get all descriptive about it...
242
242
  ---------------------------------------------------------
243
243
 
244
244
  boolean_single.js
@@ -278,7 +278,7 @@ console.dir(argv._);
278
278
  [ true, false, true ]
279
279
  [ 'one', 'two', 'three' ]
280
280
 
281
- Yargs is here ter help ye...
281
+ Yargs is here to help you...
282
282
  ---------------------------
283
283
 
284
284
  Ye can describe parameters fer help messages and set aliases. Yargs figures
@@ -372,8 +372,12 @@ Set `argv[key]` to `value` if no option was specified on `process.argv`.
372
372
 
373
373
  Optionally `.default()` can take an object that maps keys to default values.
374
374
 
375
- .demand(key, [msg])
376
- ------------
375
+ .demand(key, [msg | boolean])
376
+ -----------------------------
377
+ .require(key, [msg | boolean])
378
+ ------------------------------
379
+ .required(key, [msg | boolean])
380
+ -------------------------------
377
381
 
378
382
  If `key` is a string, show the usage information and exit if `key` wasn't
379
383
  specified in `process.argv`.
@@ -383,9 +387,12 @@ up in `argv._`.
383
387
 
384
388
  If `key` is an Array, demand each element.
385
389
 
386
- If `msg` is supplied, it will be printed when the argument is missing,
390
+ If a `msg` string is given, it will be printed when the argument is missing,
387
391
  instead of the standard error message. This is especially helpful for the non-option arguments in `argv._`.
388
392
 
393
+ If a `boolean` value is given, it controls whether the option is demanded;
394
+ this is useful when using `.options()` to specify command line parameters.
395
+
389
396
  .requiresArg(key)
390
397
  -----------------
391
398
 
@@ -496,10 +503,14 @@ Format usage output to wrap at `columns` many columns.
496
503
  Any command-line argument given that is not demanded, or does not have a
497
504
  corresponding description, will be reported as an error.
498
505
 
499
- .help()
500
- -------
506
+ .help([option, [description]])
507
+ ------------------------------
508
+
509
+ Add an option (e.g., `--help`) that displays the usage string and exits the
510
+ process. If present, the `description` parameter customises the description of
511
+ the help option in the usage string.
501
512
 
502
- Return the generated usage string.
513
+ If invoked without parameters, `.help` returns the generated usage string.
503
514
 
504
515
  Example:
505
516
 
@@ -511,6 +522,43 @@ console.log(yargs.help());
511
522
 
512
523
  Later on, ```argv``` can be retrived with ```yargs.argv```
513
524
 
525
+ .version(version, option, [description])
526
+ ----------------------------------------
527
+
528
+ Add an option (e.g., `--version`) that displays the version number (given by the
529
+ `version` parameter) and exits the process. If present, the `description`
530
+ parameter customises the description of the version option in the usage string.
531
+
532
+ .showHelpOnFail(enable, [message])
533
+ ----------------------------------
534
+
535
+ By default, yargs outputs a usage string if any error is detected. Use the
536
+ `.showHelpOnFail` method to customize this behaviour. if `enable` is `false`,
537
+ the usage string is not output. If the `message` parameter is present, this
538
+ message is output after the error message.
539
+
540
+ line_count.js
541
+
542
+ ````javascript
543
+ #!/usr/bin/env node
544
+ var argv = require('yargs')
545
+ .usage('Count the lines in a file.\nUsage: $0')
546
+ .demand('f')
547
+ .alias('f', 'file')
548
+ .describe('f', 'Load a file')
549
+ .showHelpOnFail(false, "Specify --help for available options")
550
+ .argv;
551
+
552
+ // etc.
553
+ ````
554
+
555
+ ***
556
+
557
+ $ node line_count.js --file
558
+ Missing argument value: f
559
+
560
+ Specify --help for available options
561
+
514
562
  .showHelp(fn=console.error)
515
563
  ---------------------------
516
564
 
@@ -0,0 +1,27 @@
1
+ var yargs = require('../index');
2
+
3
+ var argv = yargs
4
+ .usage('This is my awesome program\n\nUsage: $0 [options]')
5
+ .help('help').alias('help', 'h')
6
+ .version('1.0.1', 'version').alias('version', 'V')
7
+ .options({
8
+ input: {
9
+ alias: 'i',
10
+ description: "<filename> Input file name",
11
+ requiresArg: true,
12
+ required: true
13
+ },
14
+ output: {
15
+ alias: 'o',
16
+ description: "<filename> output file name",
17
+ requiresArg: true,
18
+ required: true
19
+ }
20
+ })
21
+ .argv;
22
+
23
+ console.log('Inspecting options');
24
+ console.dir(argv);
25
+
26
+ console.log("input:", argv.input);
27
+ console.log("output:", argv.output);
@@ -4,12 +4,12 @@ var argv = yargs.usage('This is my awesome program', {
4
4
  'about': {
5
5
  description: 'Provide some details about the author of this program',
6
6
  required: true,
7
- short: 'a',
7
+ alias: 'a',
8
8
  },
9
9
  'info': {
10
10
  description: 'Provide some information about the node.js agains!!!!!!',
11
11
  boolean: true,
12
- short: 'i'
12
+ alias: 'i'
13
13
  }
14
14
  }).argv;
15
15
 
package/index.js CHANGED
@@ -110,7 +110,7 @@ function Argv (processArgs, cwd) {
110
110
  };
111
111
 
112
112
  var demanded = {};
113
- self.demand = function (keys, msg) {
113
+ self.demand = self.required = self.require = function (keys, msg) {
114
114
  if (typeof keys == 'number') {
115
115
  if (!demanded._) demanded._ = { count: 0, msg: null };
116
116
  demanded._.count += keys;
@@ -122,7 +122,12 @@ function Argv (processArgs, cwd) {
122
122
  });
123
123
  }
124
124
  else {
125
- demanded[keys] = { msg: msg };
125
+ if (typeof msg === 'string') {
126
+ demanded[keys] = { msg: msg };
127
+ }
128
+ else if (msg === true || typeof msg === 'undefined') {
129
+ demanded[keys] = { msg: null };
130
+ }
126
131
  }
127
132
 
128
133
  return self;
@@ -171,8 +176,16 @@ function Argv (processArgs, cwd) {
171
176
  f(msg);
172
177
  });
173
178
  } else {
174
- self.showHelp();
179
+ if (showHelpOnFail) {
180
+ self.showHelp();
181
+ }
175
182
  if (msg) console.error(msg);
183
+ if (failMessage) {
184
+ if (msg) {
185
+ console.error("");
186
+ }
187
+ console.error(failMessage);
188
+ }
176
189
  process.exit(1);
177
190
  }
178
191
  }
@@ -210,7 +223,12 @@ function Argv (processArgs, cwd) {
210
223
  }
211
224
  else {
212
225
  if (opt.alias) self.alias(key, opt.alias);
213
- if (opt.demand) self.demand(key, opt.demand);
226
+
227
+ var demand = opt.demand || opt.required || opt.require;
228
+ if (demand) {
229
+ self.demand(key, demand);
230
+ }
231
+
214
232
  if (typeof opt.default !== 'undefined') {
215
233
  self.default(key, opt.default);
216
234
  }
@@ -226,7 +244,7 @@ function Argv (processArgs, cwd) {
226
244
  if (opt.count || opt.type === 'count') {
227
245
  self.count(key);
228
246
  }
229
-
247
+
230
248
  var desc = opt.describe || opt.description || opt.desc;
231
249
  if (desc) {
232
250
  self.describe(key, desc);
@@ -236,10 +254,10 @@ function Argv (processArgs, cwd) {
236
254
  self.requiresArg(key);
237
255
  }
238
256
  }
239
-
257
+
240
258
  return self;
241
259
  };
242
-
260
+
243
261
  var wrap = null;
244
262
  self.wrap = function (cols) {
245
263
  wrap = cols;
@@ -257,8 +275,44 @@ function Argv (processArgs, cwd) {
257
275
  fn(self.help());
258
276
  return self;
259
277
  };
260
-
278
+
279
+ var version = null;
280
+ var versionOpt = null;
281
+ self.version = function (ver, opt, msg) {
282
+ version = ver;
283
+ versionOpt = opt;
284
+ self.describe(opt, msg || 'Show version number');
285
+ return self;
286
+ };
287
+
288
+ var helpOpt = null;
289
+ self.addHelpOpt = function (opt, msg) {
290
+ helpOpt = opt;
291
+ self.describe(opt, msg || 'Show help');
292
+ return self;
293
+ };
294
+
295
+ var failMessage = null;
296
+ var showHelpOnFail = true;
297
+ self.showHelpOnFail = function (enabled, message) {
298
+ if (typeof enabled === 'string') {
299
+ enabled = true;
300
+ message = enabled;
301
+ }
302
+ else if (typeof enabled === 'undefined') {
303
+ enabled = true;
304
+ }
305
+ failMessage = message;
306
+ showHelpOnFail = enabled;
307
+ return self;
308
+ };
309
+
310
+
261
311
  self.help = function () {
312
+ if (arguments.length > 0) {
313
+ return self.addHelpOpt.apply(self, arguments);
314
+ }
315
+
262
316
  var keys = Object.keys(
263
317
  Object.keys(descriptions)
264
318
  .concat(Object.keys(demanded))
@@ -297,9 +351,12 @@ function Argv (processArgs, cwd) {
297
351
  help.unshift(usage.replace(/\$0/g, self.$0), '');
298
352
  }
299
353
 
354
+ var aliasKeys = (Object.keys(options.alias) || [])
355
+ .concat(Object.keys(self.parsed.newAliases) || []);
356
+
300
357
  keys = keys.filter(function(key) {
301
- return Object.keys(options.alias).every(function(alias) {
302
- return -1 == options.alias[alias].indexOf(key);
358
+ return !self.parsed.newAliases[key] && aliasKeys.every(function(alias) {
359
+ return -1 == (options.alias[alias] || []).indexOf(key);
303
360
  });
304
361
  });
305
362
  var switches = keys.reduce(function (acc, key) {
@@ -397,6 +454,19 @@ function Argv (processArgs, cwd) {
397
454
 
398
455
  argv.$0 = self.$0;
399
456
 
457
+ self.parsed = parsed;
458
+
459
+ Object.keys(argv).forEach(function(key) {
460
+ if (key === helpOpt) {
461
+ self.showHelp(console.log);
462
+ process.exit(0);
463
+ }
464
+ else if (key === versionOpt) {
465
+ process.stdout.write(version);
466
+ process.exit(0);
467
+ }
468
+ });
469
+
400
470
  if (demanded._ && argv._.length < demanded._.count) {
401
471
  if (demanded._.msg) {
402
472
  fail(demanded._.msg);
@@ -454,8 +524,8 @@ function Argv (processArgs, cwd) {
454
524
 
455
525
  var aliases = {};
456
526
 
457
- Object.keys(options.alias).forEach(function (key) {
458
- options.alias[key].forEach(function (alias) {
527
+ Object.keys(parsed.aliases).forEach(function (key) {
528
+ parsed.aliases[key].forEach(function (alias) {
459
529
  aliases[alias] = key;
460
530
  });
461
531
  });
package/lib/minimist.js CHANGED
@@ -32,13 +32,17 @@ module.exports = function (args, opts) {
32
32
  }).join('');
33
33
  }
34
34
 
35
- var aliases = {};
35
+ var aliases = {},
36
+ newAliases = {};
37
+
36
38
  Object.keys(opts.alias || {}).forEach(function (key) {
37
39
  aliases[key] = [].concat(opts.alias[key]);
38
40
  // For "--option-name", also set argv.optionName
39
41
  aliases[key].concat(key).forEach(function (x) {
40
42
  if (/-/.test(x)) {
41
- aliases[key].push(toCamelCase(x));
43
+ var c = toCamelCase(x);
44
+ aliases[key].push(c);
45
+ newAliases[c] = true;
42
46
  }
43
47
  });
44
48
  aliases[key].forEach(function (x) {
@@ -52,7 +56,13 @@ module.exports = function (args, opts) {
52
56
 
53
57
  Object.keys(defaults || {}).forEach(function (key) {
54
58
  if (/-/.test(key) && !opts.alias[key]) {
55
- aliases[key] = (aliases[key] || []).concat(toCamelCase(key));
59
+ var c = toCamelCase(key);
60
+ aliases[key] = aliases[key] || [];
61
+ // don't allow the same key to be added multiple times.
62
+ if (aliases[key].indexOf(c) === -1) {
63
+ aliases[key] = (aliases[key] || []).concat(c);
64
+ newAliases[c] = true;
65
+ }
56
66
  }
57
67
  (aliases[key] || []).forEach(function (alias) {
58
68
  defaults[alias] = defaults[key];
@@ -65,7 +75,6 @@ module.exports = function (args, opts) {
65
75
  });
66
76
 
67
77
  var notFlags = [];
68
-
69
78
  if (args.indexOf('--') !== -1) {
70
79
  notFlags = args.slice(args.indexOf('--')+1);
71
80
  args = args.slice(0, args.indexOf('--'));
@@ -73,7 +82,9 @@ module.exports = function (args, opts) {
73
82
 
74
83
  function setArg (key, val) {
75
84
  if (/-/.test(key) && !(aliases[key] && aliases[key].length)) {
76
- aliases[key] = [toCamelCase(key)];
85
+ var c = toCamelCase(key);
86
+ aliases[key] = [c];
87
+ newAliases[c] = true;
77
88
  }
78
89
 
79
90
  var value = !flags.strings[key] && isNumber(val) ? Number(val) : val;
@@ -228,7 +239,8 @@ module.exports = function (args, opts) {
228
239
 
229
240
  return {
230
241
  argv: argv,
231
- aliases: aliases
242
+ aliases: aliases,
243
+ newAliases: newAliases
232
244
  };
233
245
  };
234
246
 
package/package.json CHANGED
@@ -1,11 +1,9 @@
1
1
  {
2
2
  "name": "yargs",
3
- "version": "1.2.6",
3
+ "version": "1.3.3",
4
4
  "description": "Light-weight option parsing with an argv hash. No optstrings attached.",
5
5
  "main": "./index.js",
6
- "dependencies": {
7
- "minimist": "^0.1.0"
8
- },
6
+ "dependencies": {},
9
7
  "devDependencies": {
10
8
  "hashish": "*",
11
9
  "mocha": "*",
@@ -32,6 +30,22 @@
32
30
  "email": "Alex.Ford@CodeTunnel.com",
33
31
  "url": "http://CodeTunnel.com"
34
32
  },
33
+ "contributors": [
34
+ {
35
+ "name": "Chris Needham",
36
+ "email": "chris@chrisneedham.com",
37
+ "url": "http://chrisneedham.com"
38
+ },
39
+ {
40
+ "name": "James Nylen",
41
+ "email": "jnylen@gmail.com",
42
+ "url": "https://github.com/nylen"
43
+ },
44
+ {
45
+ "name": "Benjamin Horsleben",
46
+ "url": "https://github.com/fizker"
47
+ }
48
+ ],
35
49
  "license": "MIT/X11",
36
50
  "engine": {
37
51
  "node": ">=0.4"
package/test/parse.js CHANGED
@@ -15,7 +15,7 @@ describe('parse', function () {
15
15
  parse.should.have.property('bool', true);
16
16
  parse.should.have.property('_').with.length(0);
17
17
  });
18
-
18
+
19
19
  it('should place bare options in the _ array', function () {
20
20
  var parse = yargs.parse(['foo', 'bar', 'baz']);
21
21
  parse.should.have.property('_').and.deep.equal(['foo','bar','baz']);
@@ -38,7 +38,7 @@ describe('parse', function () {
38
38
  parse.should.have.property('s', 'meow');
39
39
  parse.should.have.property('_').with.length(0);
40
40
  });
41
-
41
+
42
42
  it('should set the value of a single short option to the next supplied value', function () {
43
43
  var parse = yargs.parse(['-h', 'localhost']);
44
44
  parse.should.have.property('h', 'localhost');
@@ -85,7 +85,7 @@ describe('parse', function () {
85
85
  parse.should.have.property('h', 'localhost');
86
86
  parse.should.have.property('_').and.deep.equal(['script.js']);
87
87
  });
88
-
88
+
89
89
  it('should still set values appropriately if a mix of short and long options are specified', function () {
90
90
  var parse = yargs.parse(['-h', 'localhost', '--port', '555']);
91
91
  parse.should.have.property('h', 'localhost');
@@ -98,13 +98,13 @@ describe('parse', function () {
98
98
  parse.should.have.property('moo', false);
99
99
  parse.should.have.property('_').with.length(0);
100
100
  });
101
-
101
+
102
102
  it('should group values into an array if the same option is specified multiple times', function () {
103
103
  var parse = yargs.parse(['-v', 'a', '-v', 'b', '-v', 'c' ]);
104
104
  parse.should.have.property('v').and.deep.equal(['a','b','c']);
105
105
  parse.should.have.property('_').with.length(0);
106
106
  });
107
-
107
+
108
108
  it('should still set values appropriately if we supply a comprehensive list of various types of options', function () {
109
109
  var parse = yargs.parse([
110
110
  '--name=meowmers', 'bare', '-cats', 'woo',
@@ -352,4 +352,38 @@ describe('parse', function () {
352
352
  parsed.should.have.property('other', 'false');
353
353
  });
354
354
 
355
+ // regression, see https://github.com/chevex/yargs/issues/63
356
+ it('should not add the same key to argv multiple times, when creating camel-case aliases', function() {
357
+ var yargs = require('../')(['--health-check=banana', '--second-key', 'apple', '-t=blarg'])
358
+ .options('h', {
359
+ alias: 'health-check',
360
+ description: 'health check',
361
+ default: 'apple'
362
+ })
363
+ .options('second-key', {
364
+ alias: 's',
365
+ description: 'second key',
366
+ default: 'banana'
367
+ })
368
+ .options('third-key', {
369
+ alias: 't',
370
+ description: 'third key',
371
+ default: 'third'
372
+ })
373
+
374
+ // before this fix, yargs failed parsing
375
+ // one but not all forms of an arg.
376
+ yargs.argv.secondKey.should.eql('apple');
377
+ yargs.argv.s.should.eql('apple');
378
+ yargs.argv['second-key'].should.eql('apple');
379
+
380
+ yargs.argv.healthCheck.should.eql('banana');
381
+ yargs.argv.h.should.eql('banana');
382
+ yargs.argv['health-check'].should.eql('banana');
383
+
384
+ yargs.argv.thirdKey.should.eql('blarg');
385
+ yargs.argv.t.should.eql('blarg');
386
+ yargs.argv['third-key'].should.eql('blarg');
387
+ });
388
+
355
389
  });
@@ -3,14 +3,18 @@ var should = require('chai').should(),
3
3
 
4
4
  describe('parse', function () {
5
5
 
6
- describe('dashes and camelCase', function () {
6
+ function runTests (yargs, strict) {
7
7
 
8
- it('should provide options with dashes as camelCase properties', function () {
9
- var result = yargs()
10
- .parse([ '--some-option' ]);
8
+ if (!strict) {
9
+ // Skip this test in strict mode because this option is not specified
10
+ it('should provide options with dashes as camelCase properties', function () {
11
+ var result = yargs()
12
+ .parse([ '--some-option' ]);
11
13
 
12
- result.should.have.property('someOption').that.is.a('boolean').and.is.true;
13
- });
14
+ result.should.have.property('some-option').that.is.a('boolean').and.is.true;
15
+ result.should.have.property('someOption' ).that.is.a('boolean').and.is.true;
16
+ });
17
+ }
14
18
 
15
19
  it('should provide count options with dashes as camelCase properties', function () {
16
20
  var result = yargs()
@@ -20,7 +24,8 @@ describe('parse', function () {
20
24
  })
21
25
  .parse([ '--some-option', '--some-option', '--some-option' ]);
22
26
 
23
- result.should.have.property('someOption', 3);
27
+ result.should.have.property('some-option', 3);
28
+ result.should.have.property('someOption' , 3);
24
29
  });
25
30
 
26
31
  it('should provide options with dashes and aliases as camelCase properties', function () {
@@ -31,7 +36,8 @@ describe('parse', function () {
31
36
  })
32
37
  .parse([ '--some-option' ]);
33
38
 
34
- result.should.have.property('someOption').that.is.a('boolean').and.is.true;
39
+ result.should.have.property('some-option').that.is.a('boolean').and.is.true;
40
+ result.should.have.property('someOption' ).that.is.a('boolean').and.is.true;
35
41
  });
36
42
 
37
43
  it('should provide defaults of options with dashes as camelCase properties', function() {
@@ -42,7 +48,8 @@ describe('parse', function () {
42
48
  })
43
49
  .parse([ ]);
44
50
 
45
- result.should.have.property('someOption', 'asdf');
51
+ result.should.have.property('some-option', 'asdf');
52
+ result.should.have.property('someOption' , 'asdf');
46
53
  });
47
54
 
48
55
  it('should provide aliases of options with dashes as camelCase properties', function() {
@@ -55,6 +62,8 @@ describe('parse', function () {
55
62
  .parse([ ]);
56
63
 
57
64
  result.should.have.property('o', 'asdf');
65
+ result.should.have.property('some-option', 'asdf');
66
+ result.should.have.property('someOption' , 'asdf');
58
67
  });
59
68
 
60
69
  it('should provide aliases of options with dashes as camelCase properties', function() {
@@ -66,7 +75,9 @@ describe('parse', function () {
66
75
  })
67
76
  .parse([ ]);
68
77
 
69
- result.should.have.property('someOption', 'asdf');
78
+ result.should.have.property('o', 'asdf');
79
+ result.should.have.property('some-option', 'asdf');
80
+ result.should.have.property('someOption' , 'asdf');
70
81
  });
71
82
 
72
83
  it('should provide aliases with dashes as camelCase properties', function() {
@@ -77,7 +88,41 @@ describe('parse', function () {
77
88
  })
78
89
  .parse([ '--some-option', 'val' ]);
79
90
 
80
- result.should.have.property('someOption').that.is.a('string').and.equals('val');
91
+ result.should.have.property('o' ).that.is.a('string').and.equals('val');
92
+ result.should.have.property('some-option').that.is.a('string').and.equals('val');
93
+ result.should.have.property('someOption' ).that.is.a('string').and.equals('val');
94
+ });
95
+
96
+ }
97
+
98
+ describe('dashes and camelCase', function () {
99
+ runTests(function() {
100
+ return yargs();
101
+ });
102
+ });
103
+
104
+ describe('dashes and camelCase (strict)', function () {
105
+ runTests(function() {
106
+ // Special handling for failure messages, because normally a
107
+ // failure calls process.exit(1);
108
+ return yargs().strict().fail(function(msg) {
109
+ throw new Error(msg);
110
+ });
111
+ }, true);
112
+
113
+ // See https://github.com/chevex/yargs/issues/31
114
+
115
+ it('should not fail when options with defaults are missing', function () {
116
+ var result = yargs()
117
+ .fail(function(msg) {
118
+ throw new Error(msg);
119
+ })
120
+ .option('some-option', {
121
+ describe : 'some option',
122
+ default : 80
123
+ })
124
+ .strict()
125
+ .parse([ ]);
81
126
  });
82
127
  });
83
128
 
package/test/usage.js CHANGED
@@ -4,62 +4,89 @@ var should = require('chai').should(),
4
4
 
5
5
  describe('usage', function () {
6
6
 
7
- it ('should show an error along with the missing arguments on demand fail', function () {
8
- var r = checkUsage(function () {
9
- return yargs('-x 10 -z 20'.split(' '))
10
- .usage('Usage: $0 -x NUM -y NUM')
11
- .demand(['x','y'])
12
- .argv;
7
+ describe('demand options', function () {
8
+ describe('using .demand()', function () {
9
+ it ('should show an error along with the missing arguments on demand fail', function () {
10
+ var r = checkUsage(function () {
11
+ return yargs('-x 10 -z 20'.split(' '))
12
+ .usage('Usage: $0 -x NUM -y NUM')
13
+ .demand(['x','y'])
14
+ .argv;
15
+ });
16
+ r.result.should.have.property('x', 10);
17
+ r.result.should.have.property('z', 20);
18
+ r.result.should.have.property('_').with.length(0);
19
+ r.errors.join('\n').split(/\n+/).should.deep.equal([
20
+ 'Usage: ./usage -x NUM -y NUM',
21
+ 'Options:',
22
+ ' -x [required]',
23
+ ' -y [required]',
24
+ 'Missing required arguments: y'
25
+ ]);
26
+ r.logs.should.have.length(0);
27
+ r.exit.should.be.ok;
28
+ });
29
+
30
+ describe('using .require()', function() {
31
+ it ('should show an error along with the missing arguments on demand fail', function () {
32
+ var r = checkUsage(function () {
33
+ return yargs('-x 10 -z 20'.split(' '))
34
+ .usage('Usage: $0 -x NUM -y NUM')
35
+ .require(['x','y'])
36
+ .argv;
37
+ });
38
+ r.result.should.have.property('x', 10);
39
+ r.result.should.have.property('z', 20);
40
+ r.result.should.have.property('_').with.length(0);
41
+ r.errors.join('\n').split(/\n+/).should.deep.equal([
42
+ 'Usage: ./usage -x NUM -y NUM',
43
+ 'Options:',
44
+ ' -x [required]',
45
+ ' -y [required]',
46
+ 'Missing required arguments: y'
47
+ ]);
48
+ r.logs.should.have.length(0);
49
+ r.exit.should.be.ok;
50
+ });
51
+ });
13
52
  });
14
- r.result.should.have.property('x', 10);
15
- r.result.should.have.property('z', 20);
16
- r.result.should.have.property('_').with.length(0);
17
- r.errors.join('\n').split(/\n+/).should.deep.equal([
18
- 'Usage: ./usage -x NUM -y NUM',
19
- 'Options:',
20
- ' -x [required]',
21
- ' -y [required]',
22
- 'Missing required arguments: y'
23
- ]);
24
- r.logs.should.have.length(0);
25
- r.exit.should.be.ok;
26
- });
27
53
 
28
- it('should show an error along with a custom message on demand fail', function () {
29
- var r = checkUsage(function () {
30
- return yargs('-z 20'.split(' '))
31
- .usage('Usage: $0 -x NUM -y NUM')
32
- .demand(['x','y'], 'x and y are both required to multiply all the things')
33
- .argv;
54
+ it('should show an error along with a custom message on demand fail', function () {
55
+ var r = checkUsage(function () {
56
+ return yargs('-z 20'.split(' '))
57
+ .usage('Usage: $0 -x NUM -y NUM')
58
+ .demand(['x','y'], 'x and y are both required to multiply all the things')
59
+ .argv;
60
+ });
61
+ r.result.should.have.property('z', 20);
62
+ r.result.should.have.property('_').with.length(0);
63
+ r.errors.join('\n').split(/\n+/).should.deep.equal([
64
+ 'Usage: ./usage -x NUM -y NUM',
65
+ 'Options:',
66
+ ' -x [required]',
67
+ ' -y [required]',
68
+ 'Missing required arguments: x, y',
69
+ 'x and y are both required to multiply all the things'
70
+ ]);
71
+ r.logs.should.have.length(0);
72
+ r.exit.should.be.ok;
34
73
  });
35
- r.result.should.have.property('z', 20);
36
- r.result.should.have.property('_').with.length(0);
37
- r.errors.join('\n').split(/\n+/).should.deep.equal([
38
- 'Usage: ./usage -x NUM -y NUM',
39
- 'Options:',
40
- ' -x [required]',
41
- ' -y [required]',
42
- 'Missing required arguments: x, y',
43
- 'x and y are both required to multiply all the things'
44
- ]);
45
- r.logs.should.have.length(0);
46
- r.exit.should.be.ok;
47
- });
48
74
 
49
- it('should return valid values when demand passes', function () {
50
- var r = checkUsage(function () {
51
- return yargs('-x 10 -y 20'.split(' '))
52
- .usage('Usage: $0 -x NUM -y NUM')
53
- .demand(['x','y'])
54
- .argv;
75
+ it('should return valid values when demand passes', function () {
76
+ var r = checkUsage(function () {
77
+ return yargs('-x 10 -y 20'.split(' '))
78
+ .usage('Usage: $0 -x NUM -y NUM')
79
+ .demand(['x','y'])
80
+ .argv;
81
+ });
82
+ r.should.have.property('result');
83
+ r.result.should.have.property('x', 10);
84
+ r.result.should.have.property('y', 20)
85
+ r.result.should.have.property('_').with.length(0);
86
+ r.should.have.property('errors').with.length(0);
87
+ r.should.have.property('logs').with.length(0);
88
+ r.should.have.property('exit', false);
55
89
  });
56
- r.should.have.property('result');
57
- r.result.should.have.property('x', 10);
58
- r.result.should.have.property('y', 20)
59
- r.result.should.have.property('_').with.length(0);
60
- r.should.have.property('errors').with.length(0);
61
- r.should.have.property('logs').with.length(0);
62
- r.should.have.property('exit', false);
63
90
  });
64
91
 
65
92
  it('should return valid values when check passes', function () {
@@ -532,6 +559,171 @@ describe('usage', function () {
532
559
  ]);
533
560
  });
534
561
 
562
+ describe('demand option with boolean flag', function () {
563
+ describe('with demand option', function () {
564
+ it('should report missing required arguments', function () {
565
+ var r = checkUsage(function () {
566
+ return yargs('-y 10 -z 20'.split(' '))
567
+ .usage('Usage: $0 -x NUM [-y NUM]')
568
+ .options({
569
+ 'x': { description: 'an option', demand: true },
570
+ 'y': { description: 'another option', demand: false }
571
+ })
572
+ .argv;
573
+ });
574
+ r.result.should.have.property('y', 10);
575
+ r.result.should.have.property('z', 20);
576
+ r.result.should.have.property('_').with.length(0);
577
+ r.errors.join('\n').split(/\n/).should.deep.equal([
578
+ 'Usage: ./usage -x NUM [-y NUM]',
579
+ '',
580
+ 'Options:',
581
+ ' -x an option [required]',
582
+ ' -y another option',
583
+ '',
584
+ 'Missing required arguments: x'
585
+ ]);
586
+ r.logs.should.have.length(0);
587
+ r.exit.should.be.ok;
588
+ });
589
+ });
590
+
591
+ describe('with required option', function () {
592
+ it('should report missing required arguments', function () {
593
+ var r = checkUsage(function () {
594
+ return yargs('-y 10 -z 20'.split(' '))
595
+ .usage('Usage: $0 -x NUM [-y NUM]')
596
+ .options({
597
+ 'x': { description: 'an option', required: true },
598
+ 'y': { description: 'another option', required: false }
599
+ })
600
+ .argv;
601
+ });
602
+ r.result.should.have.property('y', 10);
603
+ r.result.should.have.property('z', 20);
604
+ r.result.should.have.property('_').with.length(0);
605
+ r.errors.join('\n').split(/\n/).should.deep.equal([
606
+ 'Usage: ./usage -x NUM [-y NUM]',
607
+ '',
608
+ 'Options:',
609
+ ' -x an option [required]',
610
+ ' -y another option',
611
+ '',
612
+ 'Missing required arguments: x'
613
+ ]);
614
+ r.logs.should.have.length(0);
615
+ r.exit.should.be.ok;
616
+ });
617
+ });
618
+
619
+ it('should not report missing required arguments when given an alias', function () {
620
+ var r = checkUsage(function () {
621
+ return yargs('-w 10'.split(' '))
622
+ .usage('Usage: $0 --width NUM [--height NUM]')
623
+ .options({
624
+ 'width': { description: 'Width', alias: 'w', demand: true },
625
+ 'height': { description: 'Height', alias: 'h', demand: false }
626
+ })
627
+ .argv;
628
+ });
629
+ r.result.should.have.property('w', 10);
630
+ r.result.should.have.property('_').with.length(0);
631
+ r.should.have.property('errors').with.length(0);
632
+ r.logs.should.have.length(0);
633
+ });
634
+ });
635
+
636
+ describe('help option', function () {
637
+ it('should display usage', function () {
638
+ var r = checkUsage(function () {
639
+ return yargs(['--help'])
640
+ .demand(['y'])
641
+ .help('help')
642
+ .argv;
643
+ });
644
+ r.should.have.property('result');
645
+ r.result.should.have.property('_').with.length(0);
646
+ r.should.have.property('errors');
647
+ r.should.have.property('logs').with.length(1);
648
+ r.should.have.property('exit').and.be.ok;
649
+ r.logs.join('\n').split(/\n+/).should.deep.equal([
650
+ 'Options:',
651
+ ' --help Show help',
652
+ ' -y [required]',
653
+ ''
654
+ ]);
655
+ });
656
+
657
+ it('should not show both dashed and camelCase aliases', function () {
658
+ var r = checkUsage(function () {
659
+ return yargs(['--help'])
660
+ .usage('Usage: $0 options')
661
+ .help('help')
662
+ .describe('some-opt', 'Some option')
663
+ .default('some-opt', 2)
664
+ .argv;
665
+ });
666
+ r.should.have.property('result');
667
+ r.result.should.have.property('_').with.length(0);
668
+ r.should.have.property('exit').and.be.ok;
669
+ r.should.have.property('errors').with.length(0);
670
+ r.should.have.property('logs');
671
+ r.logs.join('\n').split(/\n+/).should.deep.equal([
672
+ 'Usage: ./usage options',
673
+ 'Options:',
674
+ ' --help Show help ',
675
+ ' --some-opt Some option [default: 2]',
676
+ ''
677
+ ]);
678
+ });
679
+ });
680
+
681
+ describe('version option', function () {
682
+ it('should display version', function () {
683
+ var r = checkUsage(function () {
684
+ return yargs(['--version'])
685
+ .version('1.0.1', 'version', 'Show version number')
686
+ .argv;
687
+ });
688
+ r.should.have.property('result');
689
+ r.result.should.have.property('_').with.length(0);
690
+ r.should.have.property('errors');
691
+ r.should.have.property('logs').with.length(1);
692
+ r.should.have.property('exit').and.be.ok;
693
+ r.logs.join('\n').split(/\n+/).should.deep.equal([
694
+ '1.0.1'
695
+ ]);
696
+ });
697
+ });
698
+
699
+ describe('showHelpOnFail', function () {
700
+ it('should display user supplied message', function () {
701
+ var opts = {
702
+ foo: { desc: 'foo option', alias: 'f' },
703
+ bar: { desc: 'bar option', alias: 'b' }
704
+ };
705
+
706
+ var r = checkUsage(function () {
707
+ return yargs(['--foo'])
708
+ .usage('Usage: $0 [options]')
709
+ .options(opts)
710
+ .demand(['foo', 'bar'])
711
+ .showHelpOnFail(false, "Specify --help for available options")
712
+ .argv;
713
+ });
714
+ r.should.have.property('result');
715
+ r.result.should.have.property('_').with.length(0);
716
+ r.should.have.property('errors');
717
+ r.should.have.property('logs').with.length(0);
718
+ r.should.have.property('exit').and.be.ok;
719
+ r.errors.join('\n').split(/\n/).should.deep.equal([
720
+ 'Missing required arguments: bar',
721
+ '',
722
+ 'Specify --help for available options'
723
+ ]);
724
+ });
725
+ });
726
+
535
727
  it('should succeed when rebase', function () {
536
728
  yargs.rebase('/home/chevex', '/home/chevex/foo/bar/baz').should.equal('./foo/bar/baz');
537
729
  yargs.rebase('/home/chevex/foo/bar/baz', '/home/chevex').should.equal('../../..');
@@ -545,10 +737,12 @@ describe('usage', function () {
545
737
  process._exit = process.exit;
546
738
  process._env = process.env;
547
739
  process._argv = process.argv;
740
+ process.stdout._write = process.stdout.write;
548
741
 
549
742
  process.exit = function () { exit = true };
550
743
  process.env = Hash.merge(process.env, { _ : 'node' });
551
744
  process.argv = [ './usage' ];
745
+ process.stdout.write = function (msg) { logs.push(msg) };
552
746
 
553
747
  var errors = [];
554
748
  var logs = [];
@@ -563,6 +757,7 @@ describe('usage', function () {
563
757
  process.exit = process._exit;
564
758
  process.env = process._env;
565
759
  process.argv = process._argv;
760
+ process.stdout.write = process.stdout._write;
566
761
 
567
762
  console.error = console._error;
568
763
  console.log = console._log;