yargs 6.3.0 → 6.6.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/CHANGELOG.md CHANGED
@@ -2,6 +2,62 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
4
4
 
5
+ <a name="6.6.0"></a>
6
+ # [6.6.0](https://github.com/yargs/yargs/compare/v6.5.0...v6.6.0) (2016-12-29)
7
+
8
+
9
+ ### Bug Fixes
10
+
11
+ * [object Object] was accidentally being populated on options object ([#736](https://github.com/yargs/yargs/issues/736)) ([f755e27](https://github.com/yargs/yargs/commit/f755e27))
12
+ * do not use cwd when resolving package.json for yargs parsing config ([#726](https://github.com/yargs/yargs/issues/726)) ([9bdaab7](https://github.com/yargs/yargs/commit/9bdaab7))
13
+
14
+
15
+ ### Features
16
+
17
+ * implement conflicts() for defining mutually exclusive arguments; thanks [@madcampos](https://github.com/madcampos)! ([#741](https://github.com/yargs/yargs/issues/741)) ([5883779](https://github.com/yargs/yargs/commit/5883779))
18
+ * split demand() into demandCommand()/demandOption() ([#740](https://github.com/yargs/yargs/issues/740)) ([66573c8](https://github.com/yargs/yargs/commit/66573c8))
19
+ * support for positional argument aliases ([#727](https://github.com/yargs/yargs/issues/727)) ([27e1a57](https://github.com/yargs/yargs/commit/27e1a57))
20
+
21
+
22
+
23
+ <a name="6.5.0"></a>
24
+ # [6.5.0](https://github.com/yargs/yargs/compare/v6.4.0...v6.5.0) (2016-12-01)
25
+
26
+
27
+ ### Bug Fixes
28
+
29
+ * still freeze/unfreeze if parse() is called in isolation ([#717](https://github.com/yargs/yargs/issues/717)) ([30a9492](https://github.com/yargs/yargs/commit/30a9492))
30
+
31
+
32
+ ### Features
33
+
34
+ * pull in yargs-parser introducing additional settings ([#688](https://github.com/yargs/yargs/issues/688)), and fixing [#716](https://github.com/yargs/yargs/issues/716) ([#722](https://github.com/yargs/yargs/issues/722)) ([702995a](https://github.com/yargs/yargs/commit/702995a))
35
+
36
+
37
+
38
+ <a name="6.4.0"></a>
39
+ # [6.4.0](https://github.com/yargs/yargs/compare/v6.3.0...v6.4.0) (2016-11-13)
40
+
41
+
42
+ ### Bug Fixes
43
+
44
+ * **locales:** correct some Russian translations ([#691](https://github.com/yargs/yargs/issues/691)) ([a980671](https://github.com/yargs/yargs/commit/a980671))
45
+
46
+
47
+ ### Features
48
+
49
+ * **locales:** Added Belarusian translation ([#690](https://github.com/yargs/yargs/issues/690)) ([68dac1f](https://github.com/yargs/yargs/commit/68dac1f))
50
+ * **locales:** Create nl.json ([#687](https://github.com/yargs/yargs/issues/687)) ([46ce1bb](https://github.com/yargs/yargs/commit/46ce1bb))
51
+ * update to yargs-parser that addresses [#598](https://github.com/yargs/yargs/issues/598), [#617](https://github.com/yargs/yargs/issues/617) ([#700](https://github.com/yargs/yargs/issues/700)) ([54cb31d](https://github.com/yargs/yargs/commit/54cb31d))
52
+ * yargs is now passed as the third-argument to fail handler ([#613](https://github.com/yargs/yargs/issues/613)) ([21b74f9](https://github.com/yargs/yargs/commit/21b74f9))
53
+
54
+
55
+ ### Performance Improvements
56
+
57
+ * normalizing package data is an expensive operation ([#705](https://github.com/yargs/yargs/issues/705)) ([49cf533](https://github.com/yargs/yargs/commit/49cf533))
58
+
59
+
60
+
5
61
  <a name="6.3.0"></a>
6
62
  # [6.3.0](https://github.com/yargs/yargs/compare/v6.2.0...v6.3.0) (2016-10-19)
7
63
 
package/README.md CHANGED
@@ -42,7 +42,7 @@ if (argv.ships > 3 && argv.distance < 53.5) {
42
42
  $ ./plunder.js --ships 12 --distance 98.7
43
43
  Retreat from the xupptumblers!
44
44
 
45
- ![Joe was one optimistic pirate.](http://i.imgur.com/4WFGVJ9.png)
45
+ ![Joe was one optimistic pirate.](https://i.imgur.com/4WFGVJ9.png)
46
46
 
47
47
  But don't walk the plank just yet! There be more! You can do short options:
48
48
  -------------------------------------------------
@@ -160,7 +160,7 @@ area.js:
160
160
  #!/usr/bin/env node
161
161
  var argv = require('yargs')
162
162
  .usage('Usage: $0 -w [num] -h [num]')
163
- .demand(['w','h'])
163
+ .demandOption(['w','h'])
164
164
  .argv;
165
165
 
166
166
  console.log("The area is:", argv.w * argv.h);
@@ -188,7 +188,7 @@ demand_count.js:
188
188
  ````javascript
189
189
  #!/usr/bin/env node
190
190
  var argv = require('yargs')
191
- .demand(2)
191
+ .demandCommand(2)
192
192
  .argv;
193
193
  console.dir(argv);
194
194
  ````
@@ -298,7 +298,7 @@ var argv = require('yargs')
298
298
  .alias('f', 'file')
299
299
  .nargs('f', 1)
300
300
  .describe('f', 'Load a file')
301
- .demand(1, ['f'])
301
+ .demandOption(['f'])
302
302
  .help('h')
303
303
  .alias('h', 'help')
304
304
  .epilog('copyright 2015')
@@ -609,6 +609,21 @@ yargs.command('get <source> [proxy]', 'make a get HTTP request')
609
609
  .argv
610
610
  ```
611
611
 
612
+ #### Positional Argument Aliases
613
+
614
+ Aliases can be provided for positional arguments using the `|` character.
615
+ As an example, suppose our application allows either a username _or_
616
+ an email as the first argument:
617
+
618
+ ```js
619
+ yargs.command('get <username|email> [password]', 'fetch a user by username or email.')
620
+ .help()
621
+ .argv
622
+ ```
623
+
624
+ In this way, both `argv.username` and `argv.email` would be populated with the
625
+ same value when the command is executed.
626
+
612
627
  #### Variadic Positional Arguments
613
628
 
614
629
  The last positional argument can optionally accept an array of
@@ -663,7 +678,7 @@ require('yargs')
663
678
  console.log(`setting ${argv.key} to ${argv.value}`)
664
679
  }
665
680
  })
666
- .demand(1)
681
+ .demandCommand(1)
667
682
  .help()
668
683
  .wrap(72)
669
684
  .argv
@@ -809,7 +824,7 @@ cli.js:
809
824
  #!/usr/bin/env node
810
825
  require('yargs')
811
826
  .commandDir('cmds')
812
- .demand(1)
827
+ .demandCommand(1)
813
828
  .help()
814
829
  .argv
815
830
  ```
@@ -970,6 +985,13 @@ $ node test.js
970
985
  '$0': 'test.js' }
971
986
  ```
972
987
 
988
+ <a name="conflicts"></a>.conflicts(x, y)
989
+ ----------------------------------------------
990
+
991
+ Given the key `x` is set, the key `y` must not be set.
992
+
993
+ Optionally `.conflicts()` can accept an object specifying multiple conflicting keys.
994
+
973
995
  <a name="count"></a>.count(key)
974
996
  ------------
975
997
 
@@ -1005,45 +1027,127 @@ displaying the value in the usage instructions:
1005
1027
  .default('timeout', 60000, '(one-minute)')
1006
1028
  ```
1007
1029
 
1008
- <a name="demand"></a>.demand(key, [msg | boolean])
1030
+ <a name="demand"></a>.demand(count, [max], [msg]) [DEPRECATED]
1031
+ --------------------
1032
+
1033
+ `demand()` has been deprecated, please instead see [`demandOption()`](#demandOption) and
1034
+ [`demandCommand()`](#demandCommand).
1035
+
1036
+ <a name="demandOption"></a>.demandOption(key, [msg | boolean])
1009
1037
  ------------------------------
1010
- .demand(count, [max], [msg])
1038
+ .demandOption(key, msg)
1011
1039
  ------------------------------
1012
1040
 
1013
1041
  If `key` is a string, show the usage information and exit if `key` wasn't
1014
1042
  specified in `process.argv`.
1015
1043
 
1016
- If `key` is a number, demand at least as many non-option arguments, which show
1017
- up in `argv._`. A second number can also optionally be provided, which indicates
1018
- the maximum number of non-option arguments.
1019
-
1020
1044
  If `key` is an array, demand each element.
1021
1045
 
1022
- If a `msg` string is given, it will be printed when the argument is missing,
1023
- instead of the standard error message. This is especially helpful for the non-option arguments in `argv._`.
1046
+ If a `msg` string is given, it will be printed when the argument is missing, instead of the standard error message.
1047
+
1048
+ ```javascript
1049
+ // demand an array of keys to be provided
1050
+ require('yargs')
1051
+ .option('run', {
1052
+ alias: 'r',
1053
+ describe: 'run your program'
1054
+ })
1055
+ .option('path', {
1056
+ alias: 'p',
1057
+ describe: 'provide a path to file'
1058
+ })
1059
+ .option('spec', {
1060
+ alias: 's',
1061
+ describe: 'program specifications'
1062
+ })
1063
+ .demandOption(['run', 'path'], 'Please provide both run and path arguments to work with this tool')
1064
+ .help()
1065
+ .argv
1066
+ ```
1067
+ which will provide the following output:
1068
+ ```bash
1069
+ Options:
1070
+ --run, -r run your program [required]
1071
+ --path, -p provide a path to file [required]
1072
+ --spec, -s program specifications
1073
+ --help Show help [boolean]
1074
+
1075
+ Missing required arguments: run, path
1076
+ Please provide both run and path arguments to work with this tool
1077
+ ```
1024
1078
 
1025
1079
  If a `boolean` value is given, it controls whether the option is demanded;
1026
1080
  this is useful when using `.options()` to specify command line parameters.
1027
1081
 
1028
- A combination of `.demand(1)` and `.strict()` will allow you to require a user to pass at least one command:
1029
-
1030
- ```js
1031
- var argv = require('yargs')
1032
- .command('install', 'tis a mighty fine package to install')
1033
- .demand(1)
1034
- .strict()
1082
+ ```javascript
1083
+ // demand individual options within the option constructor
1084
+ require('yargs')
1085
+ .options({
1086
+ 'run': {
1087
+ alias: 'r',
1088
+ describe: 'run your program',
1089
+ demand: true
1090
+ },
1091
+ 'path': {
1092
+ alias: 'p',
1093
+ describe: 'provide a path to file',
1094
+ demand: true
1095
+ },
1096
+ 'spec': {
1097
+ alias: 's',
1098
+ describe: 'program specifications'
1099
+ }
1100
+ })
1101
+ .help()
1035
1102
  .argv
1036
1103
  ```
1104
+ which will provide the following output:
1105
+ ```bash
1106
+ Options:
1107
+ --run, -r run your program [required]
1108
+ --path, -p provide a path to file [required]
1109
+ --spec, -s program specifications
1110
+ --help Show help [boolean]
1037
1111
 
1038
- Similarly, you can require a command and arguments at the same time:
1112
+ Missing required arguments: run, path
1113
+ ```
1039
1114
 
1040
- ```js
1041
- var argv = require('yargs')
1042
- .command('install', 'tis a mighty fine package to install')
1043
- .demand(1, ['w', 'm'])
1044
- .strict()
1115
+ <a name="demandCommand"></a>.demandCommand(min, [minMsg])
1116
+ ------------------------------
1117
+ .demandCommand(min, [max], [minMsg], [maxMsg])
1118
+ ------------------------------
1119
+
1120
+ Demand in context of commands. You can demand a minimum and a maximum number a user can have within your program, as well as provide corresponding error messages if either of the demands is not met.
1121
+ ```javascript
1122
+ require('yargs')
1123
+ .command({
1124
+ command: 'configure <key> [value]',
1125
+ aliases: ['config', 'cfg'],
1126
+ desc: 'Set a config variable',
1127
+ builder: (yargs) => yargs.default('value', 'true'),
1128
+ handler: (argv) => {
1129
+ console.log(`setting ${argv.key} to ${argv.value}`)
1130
+ }
1131
+ })
1132
+ // provide a minimum demand and a minimum demand message
1133
+ .demandCommand(1, 'You need at least one command before moving on')
1134
+ .help()
1045
1135
  .argv
1046
1136
  ```
1137
+ which will provide the following output:
1138
+ ```bash
1139
+ Commands:
1140
+ configure <key> [value] Set a config variable [aliases: config, cfg]
1141
+
1142
+ Options:
1143
+ --help Show help [boolean]
1144
+
1145
+ You need at least one command before moving on
1146
+ ```
1147
+
1148
+ _Note: in `minMsg` and `maxMsg`, every occurrence of `$0` will be replaced
1149
+ with the observed value, and every instance of `$1` will be replaced with the
1150
+ expected value._
1047
1151
 
1048
1152
  <a name="describe"></a>.describe(key, desc)
1049
1153
  --------------------
@@ -1150,15 +1254,17 @@ yargs have been validated.
1150
1254
 
1151
1255
  Method to execute when a failure occurs, rather than printing the failure message.
1152
1256
 
1153
- `fn` is called with the failure message that would have been printed and the
1154
- `Error` instance originally thrown, if any.
1257
+ `fn` is called with the failure message that would have been printed, the
1258
+ `Error` instance originally thrown and yargs state when the failure
1259
+ occured.
1155
1260
 
1156
1261
  ```js
1157
1262
  var argv = require('yargs')
1158
- .fail(function (msg, err) {
1263
+ .fail(function (msg, err, yargs) {
1159
1264
  if (err) throw err // preserve stack
1160
1265
  console.error('You broke it!')
1161
1266
  console.error(msg)
1267
+ console.error('You should be doing', yargs.help())
1162
1268
  process.exit(1)
1163
1269
  })
1164
1270
  .argv
@@ -1416,7 +1522,7 @@ var argv = require('yargs')
1416
1522
 
1417
1523
  This method can be used to make yargs aware of options that _could_
1418
1524
  exist. You can also pass an `opt` object which can hold further
1419
- customization, like `.alias()`, `.demand()` etc. for that option.
1525
+ customization, like `.alias()`, `.demandOption()` etc. for that option.
1420
1526
 
1421
1527
  For example:
1422
1528
 
@@ -1438,7 +1544,7 @@ is the same as
1438
1544
  ````javascript
1439
1545
  var argv = require('yargs')
1440
1546
  .alias('f', 'file')
1441
- .demand('f')
1547
+ .demandOption('f')
1442
1548
  .default('f', '/etc/passwd')
1443
1549
  .describe('f', 'x marks the spot')
1444
1550
  .string('f')
@@ -1475,7 +1581,7 @@ Valid `opt` keys include:
1475
1581
  - `count`: boolean, interpret option as a count of boolean flags, see [`count()`](#count)
1476
1582
  - `default`: value, set a default value for the option, see [`default()`](#default)
1477
1583
  - `defaultDescription`: string, use this description for the default value in help content, see [`default()`](#default)
1478
- - `demand`/`require`/`required`: boolean or string, demand the option be given, with optional error message, see [`demand()`](#demand)
1584
+ - `demandOption`: boolean or string, demand the option be given, with optional error message, see [`demandOption()`](#demandOption)
1479
1585
  - `desc`/`describe`/`description`: string, the option description for help content, see [`describe()`](#describe)
1480
1586
  - `global`: boolean, indicate that this key should not be [reset](#reset) when a command is invoked, see [`global()`](#global)
1481
1587
  - `group`: string, when displaying usage instructions place the option under an alternative group heading, see [`group()`](#group)
@@ -1577,7 +1683,7 @@ var yargs = require('yargs')
1577
1683
  .usage('$0 command')
1578
1684
  .command('hello', 'hello command')
1579
1685
  .command('world', 'world command')
1580
- .demand(1, 'must provide a valid command'),
1686
+ .demandCommand(1, 'must provide a valid command'),
1581
1687
  argv = yargs.argv,
1582
1688
  command = argv._[0];
1583
1689
 
@@ -1644,7 +1750,7 @@ line_count.js:
1644
1750
  #!/usr/bin/env node
1645
1751
  var argv = require('yargs')
1646
1752
  .usage('Count the lines in a file.\nUsage: $0 -f <file>')
1647
- .demand('f')
1753
+ .demandOption('f')
1648
1754
  .alias('f', 'file')
1649
1755
  .describe('f', 'Load a file')
1650
1756
  .string('f')
package/lib/command.js CHANGED
@@ -96,7 +96,7 @@ module.exports = function (yargs, usage, validation) {
96
96
 
97
97
  function parseCommand (cmd) {
98
98
  var extraSpacesStrippedCommand = cmd.replace(/\s{2,}/g, ' ')
99
- var splitCommand = extraSpacesStrippedCommand.split(/\s/)
99
+ var splitCommand = extraSpacesStrippedCommand.split(/\s+(?![^[]*]|[^<]*>)/)
100
100
  var bregex = /\.*[\][<>]/g
101
101
  var parsedCommand = {
102
102
  cmd: (splitCommand.shift()).replace(bregex, ''),
@@ -105,15 +105,16 @@ module.exports = function (yargs, usage, validation) {
105
105
  }
106
106
  splitCommand.forEach(function (cmd, i) {
107
107
  var variadic = false
108
+ cmd = cmd.replace(/\s/g, '')
108
109
  if (/\.+[\]>]/.test(cmd) && i === splitCommand.length - 1) variadic = true
109
110
  if (/^\[/.test(cmd)) {
110
111
  parsedCommand.optional.push({
111
- cmd: cmd.replace(bregex, ''),
112
+ cmd: cmd.replace(bregex, '').split('|'),
112
113
  variadic: variadic
113
114
  })
114
115
  } else {
115
116
  parsedCommand.demanded.push({
116
- cmd: cmd.replace(bregex, ''),
117
+ cmd: cmd.replace(bregex, '').split('|'),
117
118
  variadic: variadic
118
119
  })
119
120
  }
@@ -163,7 +164,7 @@ module.exports = function (yargs, usage, validation) {
163
164
  })
164
165
  innerArgv = innerArgv.argv
165
166
  }
166
- if (!yargs._hasOutput()) populatePositional(commandHandler, innerArgv, currentContext, yargs)
167
+ if (!yargs._hasOutput()) populatePositionals(commandHandler, innerArgv, currentContext, yargs)
167
168
 
168
169
  if (commandHandler.handler && !yargs._hasOutput()) {
169
170
  commandHandler.handler(innerArgv)
@@ -174,7 +175,9 @@ module.exports = function (yargs, usage, validation) {
174
175
  return innerArgv
175
176
  }
176
177
 
177
- function populatePositional (commandHandler, argv, context, yargs) {
178
+ // transcribe all positional arguments "command <foo> <bar> [apple]"
179
+ // onto argv.
180
+ function populatePositionals (commandHandler, argv, context, yargs) {
178
181
  argv._ = argv._.slice(context.commands.length) // nuke the current commands
179
182
  var demanded = commandHandler.demanded.slice(0)
180
183
  var optional = commandHandler.optional.slice(0)
@@ -183,27 +186,39 @@ module.exports = function (yargs, usage, validation) {
183
186
 
184
187
  while (demanded.length) {
185
188
  var demand = demanded.shift()
186
- if (demand.variadic) argv[demand.cmd] = []
187
- if (!argv._.length) break
188
- if (demand.variadic) argv[demand.cmd] = argv._.splice(0)
189
- else argv[demand.cmd] = argv._.shift()
190
- postProcessPositional(yargs, argv, demand.cmd)
191
- addCamelCaseExpansions(argv, demand.cmd)
189
+ populatePositional(demand, argv, yargs)
192
190
  }
193
191
 
194
192
  while (optional.length) {
195
193
  var maybe = optional.shift()
196
- if (maybe.variadic) argv[maybe.cmd] = []
197
- if (!argv._.length) break
198
- if (maybe.variadic) argv[maybe.cmd] = argv._.splice(0)
199
- else argv[maybe.cmd] = argv._.shift()
200
- postProcessPositional(yargs, argv, maybe.cmd)
201
- addCamelCaseExpansions(argv, maybe.cmd)
194
+ populatePositional(maybe, argv, yargs)
202
195
  }
203
196
 
204
197
  argv._ = context.commands.concat(argv._)
205
198
  }
206
199
 
200
+ // populate a single positional argument and its
201
+ // aliases onto argv.
202
+ function populatePositional (positional, argv, yargs) {
203
+ // "positional" consists of the positional.cmd, an array representing
204
+ // the positional's name and aliases, and positional.variadic
205
+ // indicating whether or not it is a variadic array.
206
+ var variadics = null
207
+ var value = null
208
+ for (var i = 0, cmd; (cmd = positional.cmd[i]) !== undefined; i++) {
209
+ if (positional.variadic) {
210
+ if (variadics) argv[cmd] = variadics.slice(0)
211
+ else argv[cmd] = variadics = argv._.splice(0)
212
+ } else {
213
+ if (!value && !argv._.length) continue
214
+ if (value) argv[cmd] = value
215
+ else argv[cmd] = value = argv._.shift()
216
+ }
217
+ postProcessPositional(yargs, argv, cmd)
218
+ addCamelCaseExpansions(argv, cmd)
219
+ }
220
+ }
221
+
207
222
  // TODO move positional arg logic to yargs-parser and remove this duplication
208
223
  function postProcessPositional (yargs, argv, key) {
209
224
  var coerce = yargs.getOptions().coerce[key]
package/lib/usage.js CHANGED
@@ -34,7 +34,7 @@ module.exports = function (yargs, y18n) {
34
34
 
35
35
  if (fails.length) {
36
36
  for (var i = fails.length - 1; i >= 0; --i) {
37
- fails[i](msg, err)
37
+ fails[i](msg, err, self)
38
38
  }
39
39
  } else {
40
40
  if (yargs.getExitProcess()) setBlocking(true)
@@ -110,12 +110,11 @@ module.exports = function (yargs, y18n) {
110
110
  }
111
111
 
112
112
  function getWrap () {
113
- // lazily call windowWidth() because it's very expensive,
114
- // and only needs to be called if the user wants to show usage/help
115
113
  if (!wrapSet) {
116
114
  wrap = windowWidth()
117
115
  wrapSet = true
118
116
  }
117
+
119
118
  return wrap
120
119
  }
121
120
 
@@ -128,18 +127,22 @@ module.exports = function (yargs, y18n) {
128
127
  self.help = function () {
129
128
  normalizeAliases()
130
129
 
131
- var demanded = yargs.getDemanded()
130
+ // handle old demanded API
131
+ var demandedOptions = yargs.getDemandedOptions()
132
+ var demandedCommands = yargs.getDemandedCommands()
132
133
  var groups = yargs.getGroups()
133
134
  var options = yargs.getOptions()
134
135
  var keys = Object.keys(
135
136
  Object.keys(descriptions)
136
- .concat(Object.keys(demanded))
137
+ .concat(Object.keys(demandedOptions))
138
+ .concat(Object.keys(demandedCommands))
137
139
  .concat(Object.keys(options.default))
138
140
  .reduce(function (acc, key) {
139
141
  if (key !== '_') acc[key] = true
140
142
  return acc
141
143
  }, {})
142
144
  )
145
+
143
146
  var theWrap = getWrap()
144
147
  var ui = require('cliui')({
145
148
  width: theWrap,
@@ -231,7 +234,7 @@ module.exports = function (yargs, y18n) {
231
234
 
232
235
  var extra = [
233
236
  type,
234
- demanded[key] ? '[' + __('required') + ']' : null,
237
+ demandedOptions[key] ? '[' + __('required') + ']' : null,
235
238
  options.choices && options.choices[key] ? '[' + __('choices:') + ' ' +
236
239
  self.stringifiedValues(options.choices[key]) + ']' : null,
237
240
  defaultString(options.default[key], options.defaultDescription[key])
@@ -303,7 +306,8 @@ module.exports = function (yargs, y18n) {
303
306
  // make sure any options set for aliases,
304
307
  // are copied to the keys being aliased.
305
308
  function normalizeAliases () {
306
- var demanded = yargs.getDemanded()
309
+ // handle old demanded API
310
+ var demandedOptions = yargs.getDemandedOptions()
307
311
  var options = yargs.getOptions()
308
312
 
309
313
  ;(Object.keys(options.alias) || []).forEach(function (key) {
@@ -311,7 +315,7 @@ module.exports = function (yargs, y18n) {
311
315
  // copy descriptions.
312
316
  if (descriptions[alias]) self.describe(key, descriptions[alias])
313
317
  // copy demanded.
314
- if (demanded[alias]) yargs.demand(key, demanded[alias].msg)
318
+ if (demandedOptions[alias]) yargs.demandOption(key, demandedOptions[alias].msg)
315
319
  // type messages.
316
320
  if (~options.boolean.indexOf(alias)) yargs.boolean(key)
317
321
  if (~options.count.indexOf(alias)) yargs.count(key)
@@ -397,8 +401,12 @@ module.exports = function (yargs, y18n) {
397
401
 
398
402
  // guess the width of the console window, max-width 80.
399
403
  function windowWidth () {
400
- const wsize = require('window-size')
401
- return wsize.width ? Math.min(80, wsize.width) : null
404
+ var maxWidth = 80
405
+ if (typeof process === 'object' && process.stdout && process.stdout.columns) {
406
+ return Math.min(maxWidth, process.stdout.columns)
407
+ } else {
408
+ return maxWidth
409
+ }
402
410
  }
403
411
 
404
412
  // logic for displaying application version.
package/lib/validation.js CHANGED
@@ -10,21 +10,33 @@ module.exports = function (yargs, usage, y18n) {
10
10
  // validate appropriate # of non-option
11
11
  // arguments were provided, i.e., '_'.
12
12
  self.nonOptionCount = function (argv) {
13
- const demanded = yargs.getDemanded()
13
+ const demandedCommands = yargs.getDemandedCommands()
14
14
  // don't count currently executing commands
15
15
  const _s = argv._.length - yargs.getContext().commands.length
16
16
 
17
- if (demanded._ && (_s < demanded._.count || _s > demanded._.max)) {
18
- if (demanded._.msg !== undefined) {
19
- usage.fail(demanded._.msg)
20
- } else if (_s < demanded._.count) {
21
- usage.fail(
22
- __('Not enough non-option arguments: got %s, need at least %s', _s, demanded._.count)
23
- )
24
- } else {
25
- usage.fail(
26
- __('Too many non-option arguments: got %s, maximum of %s', _s, demanded._.max)
27
- )
17
+ if (demandedCommands._ && (_s < demandedCommands._.min || _s > demandedCommands._.max)) {
18
+ if (_s < demandedCommands._.min) {
19
+ if (demandedCommands._.minMsg !== undefined) {
20
+ usage.fail(
21
+ // replace $0 with observed, $1 with expected.
22
+ demandedCommands._.minMsg ? demandedCommands._.minMsg.replace(/\$0/g, _s).replace(/\$1/, demandedCommands._.min) : null
23
+ )
24
+ } else {
25
+ usage.fail(
26
+ __('Not enough non-option arguments: got %s, need at least %s', _s, demandedCommands._.min)
27
+ )
28
+ }
29
+ } else if (_s > demandedCommands._.max) {
30
+ if (demandedCommands._.maxMsg !== undefined) {
31
+ usage.fail(
32
+ // replace $0 with observed, $1 with expected.
33
+ demandedCommands._.maxMsg ? demandedCommands._.maxMsg.replace(/\$0/g, _s).replace(/\$1/, demandedCommands._.max) : null
34
+ )
35
+ } else {
36
+ usage.fail(
37
+ __('Too many non-option arguments: got %s, maximum of %s', _s, demandedCommands._.max)
38
+ )
39
+ }
28
40
  }
29
41
  }
30
42
  }
@@ -73,13 +85,13 @@ module.exports = function (yargs, usage, y18n) {
73
85
 
74
86
  // make sure all the required arguments are present.
75
87
  self.requiredArguments = function (argv) {
76
- const demanded = yargs.getDemanded()
88
+ const demandedOptions = yargs.getDemandedOptions()
77
89
  var missing = null
78
90
 
79
- Object.keys(demanded).forEach(function (key) {
91
+ Object.keys(demandedOptions).forEach(function (key) {
80
92
  if (!argv.hasOwnProperty(key)) {
81
93
  missing = missing || {}
82
- missing[key] = demanded[key]
94
+ missing[key] = demandedOptions[key]
83
95
  }
84
96
  })
85
97
 
@@ -107,7 +119,7 @@ module.exports = function (yargs, usage, y18n) {
107
119
  self.unknownArguments = function (argv, aliases) {
108
120
  const aliasLookup = {}
109
121
  const descriptions = usage.getDescriptions()
110
- const demanded = yargs.getDemanded()
122
+ const demandedOptions = yargs.getDemandedOptions()
111
123
  const commandKeys = yargs.getCommandInstance().getCommands()
112
124
  const unknown = []
113
125
  const currentContext = yargs.getContext()
@@ -121,7 +133,7 @@ module.exports = function (yargs, usage, y18n) {
121
133
  Object.keys(argv).forEach(function (key) {
122
134
  if (key !== '$0' && key !== '_' &&
123
135
  !descriptions.hasOwnProperty(key) &&
124
- !demanded.hasOwnProperty(key) &&
136
+ !demandedOptions.hasOwnProperty(key) &&
125
137
  !aliasLookup.hasOwnProperty(key)) {
126
138
  unknown.push(key)
127
139
  }
@@ -223,12 +235,6 @@ module.exports = function (yargs, usage, y18n) {
223
235
  const implyFail = []
224
236
 
225
237
  Object.keys(implied).forEach(function (key) {
226
- var booleanNegation
227
- if (yargs.getOptions().configuration['boolean-negation'] === false) {
228
- booleanNegation = false
229
- } else {
230
- booleanNegation = true
231
- }
232
238
  var num
233
239
  const origKey = key
234
240
  var value = implied[key]
@@ -240,7 +246,7 @@ module.exports = function (yargs, usage, y18n) {
240
246
  if (typeof key === 'number') {
241
247
  // check length of argv._
242
248
  key = argv._.length >= key
243
- } else if (key.match(/^--no-.+/) && booleanNegation) {
249
+ } else if (key.match(/^--no-.+/)) {
244
250
  // check if key doesn't exist
245
251
  key = key.match(/^--no-(.+)/)[1]
246
252
  key = !argv[key]
@@ -254,7 +260,7 @@ module.exports = function (yargs, usage, y18n) {
254
260
 
255
261
  if (typeof value === 'number') {
256
262
  value = argv._.length >= value
257
- } else if (value.match(/^--no-.+/) && booleanNegation) {
263
+ } else if (value.match(/^--no-.+/)) {
258
264
  value = value.match(/^--no-(.+)/)[1]
259
265
  value = !argv[value]
260
266
  } else {
@@ -277,6 +283,30 @@ module.exports = function (yargs, usage, y18n) {
277
283
  }
278
284
  }
279
285
 
286
+ var conflicting = {}
287
+ self.conflicts = function (key, value) {
288
+ if (typeof key === 'object') {
289
+ Object.keys(key).forEach(function (k) {
290
+ self.conflicts(k, key[k])
291
+ })
292
+ } else {
293
+ conflicting[key] = value
294
+ }
295
+ }
296
+ self.getConflicting = function () {
297
+ return conflicting
298
+ }
299
+
300
+ self.conflicting = function (argv) {
301
+ var args = Object.getOwnPropertyNames(argv)
302
+
303
+ args.forEach(function (arg) {
304
+ if (conflicting[arg] && args.indexOf(conflicting[arg]) !== -1) {
305
+ usage.fail(__('Arguments %s and %s are mutually exclusive', arg, conflicting[arg]))
306
+ }
307
+ })
308
+ }
309
+
280
310
  self.recommendCommands = function (cmd, potentialCommands) {
281
311
  const distance = require('./levenshtein')
282
312
  const threshold = 3 // if it takes more than three edits, let's move on.
@@ -299,6 +329,7 @@ module.exports = function (yargs, usage, y18n) {
299
329
  return globalLookup[k]
300
330
  })
301
331
  checks = []
332
+ conflicting = {}
302
333
  return self
303
334
  }
304
335
 
@@ -307,10 +338,12 @@ module.exports = function (yargs, usage, y18n) {
307
338
  frozen = {}
308
339
  frozen.implied = implied
309
340
  frozen.checks = checks
341
+ frozen.conflicting = conflicting
310
342
  }
311
343
  self.unfreeze = function () {
312
344
  implied = frozen.implied
313
345
  checks = frozen.checks
346
+ conflicting = frozen.conflicting
314
347
  frozen = undefined
315
348
  }
316
349
 
@@ -0,0 +1,39 @@
1
+ {
2
+ "Commands:": "Каманды:",
3
+ "Options:": "Опцыі:",
4
+ "Examples:": "Прыклады:",
5
+ "boolean": "булевы тып",
6
+ "count": "падлік",
7
+ "string": "радковы тып",
8
+ "number": "лік",
9
+ "array": "масіў",
10
+ "required": "неабходна",
11
+ "default:": "па змаўчанні:",
12
+ "choices:": "магчымасці:",
13
+ "aliases:": "аліасы:",
14
+ "generated-value": "згенераванае значэнне",
15
+ "Not enough non-option arguments: got %s, need at least %s": "Недастаткова неапцыйных аргументаў: ёсць %s, трэба як мінімум %s",
16
+ "Too many non-option arguments: got %s, maximum of %s": "Занадта шмат неапцыйных аргументаў: ёсць %s, максімум дапушчальна %s",
17
+ "Missing argument value: %s": {
18
+ "one": "Не хапае значэння аргументу: %s",
19
+ "other": "Не хапае значэнняў аргументаў: %s"
20
+ },
21
+ "Missing required argument: %s": {
22
+ "one": "Не хапае неабходнага аргументу: %s",
23
+ "other": "Не хапае неабходных аргументаў: %s"
24
+ },
25
+ "Unknown argument: %s": {
26
+ "one": "Невядомы аргумент: %s",
27
+ "other": "Невядомыя аргументы: %s"
28
+ },
29
+ "Invalid values:": "Несапраўдныя значэння:",
30
+ "Argument: %s, Given: %s, Choices: %s": "Аргумент: %s, Дадзенае значэнне: %s, Магчымасці: %s",
31
+ "Argument check failed: %s": "Праверка аргументаў не ўдалася: %s",
32
+ "Implications failed:": "Дадзены аргумент патрабуе наступны дадатковы аргумент:",
33
+ "Not enough arguments following: %s": "Недастаткова наступных аргументаў: %s",
34
+ "Invalid JSON config file: %s": "Несапраўдны файл канфігурацыі JSON: %s",
35
+ "Path to JSON config file": "Шлях да файла канфігурацыі JSON",
36
+ "Show help": "Паказаць дапамогу",
37
+ "Show version number": "Паказаць нумар версіі",
38
+ "Did you mean %s?": "Вы мелі на ўвазе %s?"
39
+ }
package/locales/en.json CHANGED
@@ -35,5 +35,6 @@
35
35
  "Path to JSON config file": "Path to JSON config file",
36
36
  "Show help": "Show help",
37
37
  "Show version number": "Show version number",
38
- "Did you mean %s?": "Did you mean %s?"
38
+ "Did you mean %s?": "Did you mean %s?",
39
+ "Arguments %s and %s are mutually exclusive" : "Arguments %s and %s are mutually exclusive"
39
40
  }
@@ -0,0 +1,39 @@
1
+ {
2
+ "Commands:": "Opdrachten:",
3
+ "Options:": "Opties:",
4
+ "Examples:": "Voorbeelden:",
5
+ "boolean": "boolean",
6
+ "count": "aantal",
7
+ "string": "text",
8
+ "number": "nummer",
9
+ "array": "lijst",
10
+ "required": "verplicht",
11
+ "default:": "standaard:",
12
+ "choices:": "keuzes:",
13
+ "aliases:": "aliassen:",
14
+ "generated-value": "gegenereerde waarde",
15
+ "Not enough non-option arguments: got %s, need at least %s": "Niet genoeg non-optie argumenten. Gekregen: %s, minstens nodig: %s",
16
+ "Too many non-option arguments: got %s, maximum of %s": "Te veel non-optie argumenten. Gekregen: %s, maximum: %s",
17
+ "Missing argument value: %s": {
18
+ "one": "Missing argument value: %s",
19
+ "other": "Missing argument values: %s"
20
+ },
21
+ "Missing required argument: %s": {
22
+ "one": "Missend verplichte argument: %s",
23
+ "other": "Missende verplichte argumenten: %s"
24
+ },
25
+ "Unknown argument: %s": {
26
+ "one": "Onbekend argument: %s",
27
+ "other": "Onbekende argumenten: %s"
28
+ },
29
+ "Invalid values:": "Ongeldige waardes:",
30
+ "Argument: %s, Given: %s, Choices: %s": "Argument: %s, Gegeven: %s, Keuzes: %s",
31
+ "Argument check failed: %s": "Argument check mislukt: %s",
32
+ "Implications failed:": "Implicaties mislukt:",
33
+ "Not enough arguments following: %s": "Niet genoeg argumenten na: %s",
34
+ "Invalid JSON config file: %s": "Ongeldig JSON configuratiebestand: %s",
35
+ "Path to JSON config file": "Pad naar JSON configuratiebestand",
36
+ "Show help": "Toon help",
37
+ "Show version number": "Toon versie nummer",
38
+ "Did you mean %s?": "Bedoelde u misschien %s?"
39
+ }
package/locales/pt.json CHANGED
@@ -33,5 +33,6 @@
33
33
  "Invalid JSON config file: %s": "Arquivo de configuração em JSON esta inválido: %s",
34
34
  "Path to JSON config file": "Caminho para o arquivo de configuração em JSON",
35
35
  "Show help": "Mostra ajuda",
36
- "Show version number": "Mostra número de versão"
36
+ "Show version number": "Mostra número de versão",
37
+ "Arguments %s and %s are mutually exclusive" : "Argumentos %s e %s são mutualmente exclusivos"
37
38
  }
@@ -35,5 +35,6 @@
35
35
  "Path to JSON config file": "Caminho para o arquivo JSON de configuração",
36
36
  "Show help": "Exibe ajuda",
37
37
  "Show version number": "Exibe a versão",
38
- "Did you mean %s?": "Você quis dizer %s?"
38
+ "Did you mean %s?": "Você quis dizer %s?",
39
+ "Arguments %s and %s are mutually exclusive" : "Argumentos %s e %s são mutualmente exclusivos"
39
40
  }
package/locales/ru.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "Commands:": "Комманды:",
2
+ "Commands:": "Команды:",
3
3
  "Options:": "Опции:",
4
4
  "Examples:": "Примеры:",
5
5
  "boolean": "булевый тип",
@@ -12,7 +12,7 @@
12
12
  "choices:": "возможности:",
13
13
  "aliases:": "алиасы:",
14
14
  "generated-value": "генерированное значение",
15
- "Not enough non-option arguments: got %s, need at least %s": "Не достаточно неопционных аргументов: есть %s, нужно как минимум %s",
15
+ "Not enough non-option arguments: got %s, need at least %s": "Недостаточно неопционных аргументов: есть %s, нужно как минимум %s",
16
16
  "Too many non-option arguments: got %s, maximum of %s": "Слишком много неопционных аргументов: есть %s, максимум допустимо %s",
17
17
  "Missing argument value: %s": {
18
18
  "one": "Не хватает значения аргумента: %s",
@@ -30,7 +30,7 @@
30
30
  "Argument: %s, Given: %s, Choices: %s": "Аргумент: %s, Данное значение: %s, Возможности: %s",
31
31
  "Argument check failed: %s": "Проверка аргументов не удалась: %s",
32
32
  "Implications failed:": "Данный аргумент требует следующий дополнительный аргумент:",
33
- "Not enough arguments following: %s": "Not enough arguments following: %s",
33
+ "Not enough arguments following: %s": "Недостаточно следующих аргументов: %s",
34
34
  "Invalid JSON config file: %s": "Недействительный файл конфигурации JSON: %s",
35
35
  "Path to JSON config file": "Путь к файлу конфигурации JSON",
36
36
  "Show help": "Показать помощь",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "yargs",
3
- "version": "6.3.0",
3
+ "version": "6.6.0",
4
4
  "description": "yargs the modern, pirate-themed, successor to optimist.",
5
5
  "main": "./index.js",
6
6
  "files": [
@@ -23,22 +23,21 @@
23
23
  "set-blocking": "^2.0.0",
24
24
  "string-width": "^1.0.2",
25
25
  "which-module": "^1.0.0",
26
- "window-size": "^0.2.0",
27
26
  "y18n": "^3.2.1",
28
- "yargs-parser": "^4.0.2"
27
+ "yargs-parser": "^4.2.0"
29
28
  },
30
29
  "devDependencies": {
31
30
  "chai": "^3.4.1",
32
31
  "chalk": "^1.1.3",
33
32
  "coveralls": "^2.11.11",
34
33
  "cpr": "^2.0.0",
35
- "cross-spawn": "^4.0.0",
34
+ "cross-spawn": "^5.0.1",
36
35
  "es6-promise": "^4.0.2",
37
36
  "hashish": "0.0.4",
38
37
  "mocha": "^3.0.1",
39
- "nyc": "^8.3.2",
38
+ "nyc": "^10.0.0",
40
39
  "rimraf": "^2.5.0",
41
- "standard": "^8.2.0",
40
+ "standard": "^8.6.0",
42
41
  "standard-version": "^3.0.0",
43
42
  "which": "^1.2.9"
44
43
  },
@@ -74,7 +73,8 @@
74
73
  "greenkeeper": {
75
74
  "ignore": [
76
75
  "string-width",
77
- "read-pkg-up"
76
+ "read-pkg-up",
77
+ "camelcase"
78
78
  ]
79
79
  }
80
80
  }
package/yargs.js CHANGED
@@ -98,7 +98,7 @@ function Yargs (processArgs, cwd, parentRequire) {
98
98
 
99
99
  var objectOptions = [
100
100
  'narg', 'key', 'alias', 'default', 'defaultDescription',
101
- 'config', 'choices', 'demanded', 'coerce'
101
+ 'config', 'choices', 'demandedOptions', 'demandedCommands', 'coerce'
102
102
  ]
103
103
 
104
104
  arrayOptions.forEach(function (k) {
@@ -301,14 +301,15 @@ function Yargs (processArgs, cwd, parentRequire) {
301
301
  return self
302
302
  }
303
303
 
304
+ // deprecated: the demand API is too overloaded, and is being
305
+ // deprecated in favor of .demandCommand() .demandOption().
304
306
  self.demand = self.required = self.require = function (keys, max, msg) {
305
307
  // you can optionally provide a 'max' key,
306
308
  // which will raise an exception if too many '_'
307
309
  // options are provided.
308
-
309
310
  if (Array.isArray(max)) {
310
311
  max.forEach(function (key) {
311
- self.demand(key, msg)
312
+ self.demandOption(key, msg)
312
313
  })
313
314
  max = Infinity
314
315
  } else if (typeof max !== 'number') {
@@ -317,26 +318,61 @@ function Yargs (processArgs, cwd, parentRequire) {
317
318
  }
318
319
 
319
320
  if (typeof keys === 'number') {
320
- if (!options.demanded._) options.demanded._ = { count: 0, msg: null, max: max }
321
- options.demanded._.count = keys
322
- options.demanded._.msg = msg
321
+ self.demandCommand(keys, max, msg)
323
322
  } else if (Array.isArray(keys)) {
324
323
  keys.forEach(function (key) {
325
- self.demand(key, msg)
324
+ self.demandOption(key, msg)
326
325
  })
327
326
  } else {
328
327
  if (typeof msg === 'string') {
329
- options.demanded[keys] = { msg: msg }
328
+ self.demandOption(keys, msg)
330
329
  } else if (msg === true || typeof msg === 'undefined') {
331
- options.demanded[keys] = { msg: undefined }
330
+ self.demandOption(keys)
332
331
  }
333
332
  }
334
333
 
335
334
  return self
336
335
  }
337
336
 
338
- self.getDemanded = function () {
339
- return options.demanded
337
+ self.demandOption = function (key, msg) {
338
+ if (Array.isArray(key)) {
339
+ key.forEach(function (key) {
340
+ self.demandOption(key, msg)
341
+ })
342
+ } else {
343
+ if (typeof msg === 'string') {
344
+ options.demandedOptions[key] = { msg: msg }
345
+ // allow edge-case of options: {a: {demand: true}, b: {demand: false}}
346
+ } else if (msg === true || typeof msg === 'undefined') {
347
+ options.demandedOptions[key] = { msg: undefined }
348
+ }
349
+ }
350
+
351
+ return self
352
+ }
353
+
354
+ self.demandCommand = function (min, max, minMsg, maxMsg) {
355
+ if (typeof max !== 'number') {
356
+ minMsg = max
357
+ max = Infinity
358
+ }
359
+
360
+ options.demandedCommands._ = {
361
+ min: min,
362
+ max: max,
363
+ minMsg: minMsg,
364
+ maxMsg: maxMsg
365
+ }
366
+
367
+ return self
368
+ }
369
+
370
+ self.getDemandedOptions = function () {
371
+ return options.demandedOptions
372
+ }
373
+
374
+ self.getDemandedCommands = function () {
375
+ return options.demandedCommands
340
376
  }
341
377
 
342
378
  self.requiresArg = function (requiresArgs) {
@@ -354,6 +390,11 @@ function Yargs (processArgs, cwd, parentRequire) {
354
390
  return self
355
391
  }
356
392
 
393
+ self.conflicts = function (key1, key2) {
394
+ validation.conflicts(key1, key2)
395
+ return self
396
+ }
397
+
357
398
  self.usage = function (msg, opts) {
358
399
  if (!opts && typeof msg === 'object') {
359
400
  opts = msg
@@ -383,7 +424,13 @@ function Yargs (processArgs, cwd, parentRequire) {
383
424
  }
384
425
 
385
426
  self.describe = function (key, desc) {
386
- options.key[key] = true
427
+ if (typeof key === 'object') {
428
+ Object.keys(key).forEach(function (k) {
429
+ options.key[k] = true
430
+ })
431
+ } else {
432
+ options.key[key] = true
433
+ }
387
434
  usage.describe(key, desc)
388
435
  return self
389
436
  }
@@ -416,7 +463,8 @@ function Yargs (processArgs, cwd, parentRequire) {
416
463
  var obj = {}
417
464
  try {
418
465
  obj = readPkgUp.sync({
419
- cwd: path || require('require-main-filename')(parentRequire || require)
466
+ cwd: path || require('require-main-filename')(parentRequire || require),
467
+ normalize: false
420
468
  })
421
469
  } catch (noop) {}
422
470
 
@@ -445,16 +493,12 @@ function Yargs (processArgs, cwd, parentRequire) {
445
493
  // skipping validation, etc.
446
494
  if (!shortCircuit) processArgs = args
447
495
 
448
- if (parseFn) {
449
- freeze()
450
- exitProcess = false
451
- }
496
+ freeze()
497
+ if (parseFn) exitProcess = false
452
498
 
453
499
  var parsed = parseArgs(args, shortCircuit)
454
- if (parseFn) {
455
- parseFn(exitError, parsed, output)
456
- unfreeze()
457
- }
500
+ if (parseFn) parseFn(exitError, parsed, output)
501
+ unfreeze()
458
502
 
459
503
  return parsed
460
504
  }
@@ -483,6 +527,10 @@ function Yargs (processArgs, cwd, parentRequire) {
483
527
  self.demand(key, demand)
484
528
  }
485
529
 
530
+ if ('demandOption' in opt) {
531
+ self.demandOption(key, opt.demandOption)
532
+ }
533
+
486
534
  if ('config' in opt) {
487
535
  self.config(key, opt.configParser)
488
536
  }
@@ -801,7 +849,7 @@ function Yargs (processArgs, cwd, parentRequire) {
801
849
  }
802
850
 
803
851
  self.terminalWidth = function () {
804
- return require('window-size').width
852
+ return process.stdout.columns
805
853
  }
806
854
 
807
855
  Object.defineProperty(self, 'argv', {
@@ -821,7 +869,7 @@ function Yargs (processArgs, cwd, parentRequire) {
821
869
 
822
870
  function parseArgs (args, shortCircuit) {
823
871
  options.__ = y18n.__
824
- options.configuration = pkgUp(cwd)['yargs'] || {}
872
+ options.configuration = pkgUp()['yargs'] || {}
825
873
  const parsed = Parser.detailed(args, options)
826
874
  var argv = parsed.argv
827
875
  if (parseContext) argv = assign(parseContext, argv)
@@ -949,6 +997,7 @@ function Yargs (processArgs, cwd, parentRequire) {
949
997
  validation.customChecks(argv, aliases)
950
998
  validation.limitedChoices(argv)
951
999
  validation.implications(argv)
1000
+ validation.conflicting(argv)
952
1001
  }
953
1002
  }
954
1003