yargs 8.0.0 → 9.0.1
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 +48 -2
- package/README.md +56 -1999
- package/index.js +2 -1
- package/lib/apply-extends.js +11 -10
- package/lib/argsert.js +12 -18
- package/lib/command.js +58 -65
- package/lib/completion.js +25 -25
- package/lib/levenshtein.js +5 -5
- package/lib/obj-filter.js +4 -3
- package/lib/usage.js +105 -125
- package/lib/validation.js +124 -115
- package/lib/yerror.js +1 -0
- package/package.json +9 -16
- package/yargs.js +172 -189
- package/lib/assign.js +0 -15
package/lib/validation.js
CHANGED
|
@@ -1,16 +1,18 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
const argsert = require('./argsert')
|
|
1
3
|
const objFilter = require('./obj-filter')
|
|
2
4
|
const specialKeys = ['$0', '--', '_']
|
|
3
5
|
|
|
4
6
|
// validation-type-stuff, missing params,
|
|
5
7
|
// bad implications, custom checks.
|
|
6
|
-
module.exports = function (yargs, usage, y18n) {
|
|
8
|
+
module.exports = function validation (yargs, usage, y18n) {
|
|
7
9
|
const __ = y18n.__
|
|
8
10
|
const __n = y18n.__n
|
|
9
11
|
const self = {}
|
|
10
12
|
|
|
11
13
|
// validate appropriate # of non-option
|
|
12
14
|
// arguments were provided, i.e., '_'.
|
|
13
|
-
self.nonOptionCount = function (argv) {
|
|
15
|
+
self.nonOptionCount = function nonOptionCount (argv) {
|
|
14
16
|
const demandedCommands = yargs.getDemandedCommands()
|
|
15
17
|
// don't count currently executing commands
|
|
16
18
|
const _s = argv._.length - yargs.getContext().commands.length
|
|
@@ -44,7 +46,7 @@ module.exports = function (yargs, usage, y18n) {
|
|
|
44
46
|
|
|
45
47
|
// validate the appropriate # of <required>
|
|
46
48
|
// positional arguments were provided:
|
|
47
|
-
self.positionalCount = function (required, observed) {
|
|
49
|
+
self.positionalCount = function positionalCount (required, observed) {
|
|
48
50
|
if (observed < required) {
|
|
49
51
|
usage.fail(
|
|
50
52
|
__('Not enough non-option arguments: got %s, need at least %s', observed, required)
|
|
@@ -54,14 +56,14 @@ module.exports = function (yargs, usage, y18n) {
|
|
|
54
56
|
|
|
55
57
|
// make sure that any args that require an
|
|
56
58
|
// value (--foo=bar), have a value.
|
|
57
|
-
self.missingArgumentValue = function (argv) {
|
|
59
|
+
self.missingArgumentValue = function missingArgumentValue (argv) {
|
|
58
60
|
const defaultValues = [true, false, '']
|
|
59
61
|
const options = yargs.getOptions()
|
|
60
62
|
|
|
61
63
|
if (options.requiresArg.length > 0) {
|
|
62
64
|
const missingRequiredArgs = []
|
|
63
65
|
|
|
64
|
-
options.requiresArg.forEach(
|
|
66
|
+
options.requiresArg.forEach((key) => {
|
|
65
67
|
const value = argv[key]
|
|
66
68
|
|
|
67
69
|
// if a value is explicitly requested,
|
|
@@ -85,11 +87,11 @@ module.exports = function (yargs, usage, y18n) {
|
|
|
85
87
|
}
|
|
86
88
|
|
|
87
89
|
// make sure all the required arguments are present.
|
|
88
|
-
self.requiredArguments = function (argv) {
|
|
90
|
+
self.requiredArguments = function requiredArguments (argv) {
|
|
89
91
|
const demandedOptions = yargs.getDemandedOptions()
|
|
90
|
-
|
|
92
|
+
let missing = null
|
|
91
93
|
|
|
92
|
-
Object.keys(demandedOptions).forEach(
|
|
94
|
+
Object.keys(demandedOptions).forEach((key) => {
|
|
93
95
|
if (!argv.hasOwnProperty(key) || typeof argv[key] === 'undefined') {
|
|
94
96
|
missing = missing || {}
|
|
95
97
|
missing[key] = demandedOptions[key]
|
|
@@ -98,14 +100,14 @@ module.exports = function (yargs, usage, y18n) {
|
|
|
98
100
|
|
|
99
101
|
if (missing) {
|
|
100
102
|
const customMsgs = []
|
|
101
|
-
Object.keys(missing).forEach(
|
|
103
|
+
Object.keys(missing).forEach((key) => {
|
|
102
104
|
const msg = missing[key]
|
|
103
105
|
if (msg && customMsgs.indexOf(msg) < 0) {
|
|
104
106
|
customMsgs.push(msg)
|
|
105
107
|
}
|
|
106
108
|
})
|
|
107
109
|
|
|
108
|
-
const customMsg = customMsgs.length ?
|
|
110
|
+
const customMsg = customMsgs.length ? `\n${customMsgs.join('\n')}` : ''
|
|
109
111
|
|
|
110
112
|
usage.fail(__n(
|
|
111
113
|
'Missing required argument: %s',
|
|
@@ -117,33 +119,23 @@ module.exports = function (yargs, usage, y18n) {
|
|
|
117
119
|
}
|
|
118
120
|
|
|
119
121
|
// check for unknown arguments (strict-mode).
|
|
120
|
-
self.unknownArguments = function (argv, aliases, positionalMap) {
|
|
121
|
-
const aliasLookup = {}
|
|
122
|
-
const descriptions = usage.getDescriptions()
|
|
123
|
-
const demandedOptions = yargs.getDemandedOptions()
|
|
122
|
+
self.unknownArguments = function unknownArguments (argv, aliases, positionalMap) {
|
|
124
123
|
const commandKeys = yargs.getCommandInstance().getCommands()
|
|
125
124
|
const unknown = []
|
|
126
125
|
const currentContext = yargs.getContext()
|
|
127
126
|
|
|
128
|
-
Object.keys(
|
|
129
|
-
aliases[key].forEach(function (alias) {
|
|
130
|
-
aliasLookup[alias] = key
|
|
131
|
-
})
|
|
132
|
-
})
|
|
133
|
-
|
|
134
|
-
Object.keys(argv).forEach(function (key) {
|
|
127
|
+
Object.keys(argv).forEach((key) => {
|
|
135
128
|
if (specialKeys.indexOf(key) === -1 &&
|
|
136
|
-
!descriptions.hasOwnProperty(key) &&
|
|
137
|
-
!demandedOptions.hasOwnProperty(key) &&
|
|
138
129
|
!positionalMap.hasOwnProperty(key) &&
|
|
139
130
|
!yargs._getParseContext().hasOwnProperty(key) &&
|
|
140
|
-
!
|
|
131
|
+
!aliases.hasOwnProperty(key)
|
|
132
|
+
) {
|
|
141
133
|
unknown.push(key)
|
|
142
134
|
}
|
|
143
135
|
})
|
|
144
136
|
|
|
145
137
|
if (commandKeys.length > 0) {
|
|
146
|
-
argv._.slice(currentContext.commands.length).forEach(
|
|
138
|
+
argv._.slice(currentContext.commands.length).forEach((key) => {
|
|
147
139
|
if (commandKeys.indexOf(key) === -1) {
|
|
148
140
|
unknown.push(key)
|
|
149
141
|
}
|
|
@@ -161,18 +153,19 @@ module.exports = function (yargs, usage, y18n) {
|
|
|
161
153
|
}
|
|
162
154
|
|
|
163
155
|
// validate arguments limited to enumerated choices
|
|
164
|
-
self.limitedChoices = function (argv) {
|
|
156
|
+
self.limitedChoices = function limitedChoices (argv) {
|
|
165
157
|
const options = yargs.getOptions()
|
|
166
158
|
const invalid = {}
|
|
167
159
|
|
|
168
160
|
if (!Object.keys(options.choices).length) return
|
|
169
161
|
|
|
170
|
-
Object.keys(argv).forEach(
|
|
162
|
+
Object.keys(argv).forEach((key) => {
|
|
171
163
|
if (specialKeys.indexOf(key) === -1 &&
|
|
172
164
|
options.choices.hasOwnProperty(key)) {
|
|
173
|
-
[].concat(argv[key]).forEach(
|
|
165
|
+
[].concat(argv[key]).forEach((value) => {
|
|
174
166
|
// TODO case-insensitive configurability
|
|
175
|
-
if (options.choices[key].indexOf(value) === -1
|
|
167
|
+
if (options.choices[key].indexOf(value) === -1 &&
|
|
168
|
+
value !== undefined) {
|
|
176
169
|
invalid[key] = (invalid[key] || []).concat(value)
|
|
177
170
|
}
|
|
178
171
|
})
|
|
@@ -183,31 +176,31 @@ module.exports = function (yargs, usage, y18n) {
|
|
|
183
176
|
|
|
184
177
|
if (!invalidKeys.length) return
|
|
185
178
|
|
|
186
|
-
|
|
187
|
-
invalidKeys.forEach(
|
|
188
|
-
msg +=
|
|
179
|
+
let msg = __('Invalid values:')
|
|
180
|
+
invalidKeys.forEach((key) => {
|
|
181
|
+
msg += `\n ${__(
|
|
189
182
|
'Argument: %s, Given: %s, Choices: %s',
|
|
190
183
|
key,
|
|
191
184
|
usage.stringifiedValues(invalid[key]),
|
|
192
185
|
usage.stringifiedValues(options.choices[key])
|
|
193
|
-
)
|
|
186
|
+
)}`
|
|
194
187
|
})
|
|
195
188
|
usage.fail(msg)
|
|
196
189
|
}
|
|
197
190
|
|
|
198
191
|
// custom checks, added using the `check` option on yargs.
|
|
199
|
-
|
|
200
|
-
self.check = function (f, global) {
|
|
192
|
+
let checks = []
|
|
193
|
+
self.check = function check (f, global) {
|
|
201
194
|
checks.push({
|
|
202
195
|
func: f,
|
|
203
|
-
global
|
|
196
|
+
global
|
|
204
197
|
})
|
|
205
198
|
}
|
|
206
199
|
|
|
207
|
-
self.customChecks = function (argv, aliases) {
|
|
208
|
-
for (
|
|
209
|
-
|
|
210
|
-
|
|
200
|
+
self.customChecks = function customChecks (argv, aliases) {
|
|
201
|
+
for (let i = 0, f; (f = checks[i]) !== undefined; i++) {
|
|
202
|
+
const func = f.func
|
|
203
|
+
let result = null
|
|
211
204
|
try {
|
|
212
205
|
result = func(argv, aliases)
|
|
213
206
|
} catch (err) {
|
|
@@ -224,107 +217,129 @@ module.exports = function (yargs, usage, y18n) {
|
|
|
224
217
|
}
|
|
225
218
|
|
|
226
219
|
// check implications, argument foo implies => argument bar.
|
|
227
|
-
|
|
228
|
-
self.implies = function (key, value) {
|
|
220
|
+
let implied = {}
|
|
221
|
+
self.implies = function implies (key, value) {
|
|
222
|
+
argsert('<string|object> [array|number|string]', [key, value], arguments.length)
|
|
223
|
+
|
|
229
224
|
if (typeof key === 'object') {
|
|
230
|
-
Object.keys(key).forEach(
|
|
225
|
+
Object.keys(key).forEach((k) => {
|
|
231
226
|
self.implies(k, key[k])
|
|
232
227
|
})
|
|
233
228
|
} else {
|
|
234
229
|
yargs.global(key)
|
|
235
|
-
implied[key]
|
|
230
|
+
if (!implied[key]) {
|
|
231
|
+
implied[key] = []
|
|
232
|
+
}
|
|
233
|
+
if (Array.isArray(value)) {
|
|
234
|
+
value.forEach((i) => self.implies(key, i))
|
|
235
|
+
} else {
|
|
236
|
+
implied[key].push(value)
|
|
237
|
+
}
|
|
236
238
|
}
|
|
237
239
|
}
|
|
238
|
-
self.getImplied = function () {
|
|
240
|
+
self.getImplied = function getImplied () {
|
|
239
241
|
return implied
|
|
240
242
|
}
|
|
241
243
|
|
|
242
|
-
self.implications = function (argv) {
|
|
244
|
+
self.implications = function implications (argv) {
|
|
243
245
|
const implyFail = []
|
|
244
246
|
|
|
245
|
-
Object.keys(implied).forEach(
|
|
246
|
-
var num
|
|
247
|
+
Object.keys(implied).forEach((key) => {
|
|
247
248
|
const origKey = key
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
249
|
+
;(implied[key] || []).forEach((value) => {
|
|
250
|
+
let num
|
|
251
|
+
let key = origKey
|
|
252
|
+
const origValue = value
|
|
253
|
+
|
|
254
|
+
// convert string '1' to number 1
|
|
255
|
+
num = Number(key)
|
|
256
|
+
key = isNaN(num) ? key : num
|
|
257
|
+
|
|
258
|
+
if (typeof key === 'number') {
|
|
259
|
+
// check length of argv._
|
|
260
|
+
key = argv._.length >= key
|
|
261
|
+
} else if (key.match(/^--no-.+/)) {
|
|
262
|
+
// check if key doesn't exist
|
|
263
|
+
key = key.match(/^--no-(.+)/)[1]
|
|
264
|
+
key = !argv[key]
|
|
265
|
+
} else {
|
|
266
|
+
// check if key exists
|
|
267
|
+
key = argv[key]
|
|
268
|
+
}
|
|
268
269
|
|
|
269
|
-
|
|
270
|
-
value =
|
|
271
|
-
} else if (value.match(/^--no-.+/)) {
|
|
272
|
-
value = value.match(/^--no-(.+)/)[1]
|
|
273
|
-
value = !argv[value]
|
|
274
|
-
} else {
|
|
275
|
-
value = argv[value]
|
|
276
|
-
}
|
|
270
|
+
num = Number(value)
|
|
271
|
+
value = isNaN(num) ? value : num
|
|
277
272
|
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
273
|
+
if (typeof value === 'number') {
|
|
274
|
+
value = argv._.length >= value
|
|
275
|
+
} else if (value.match(/^--no-.+/)) {
|
|
276
|
+
value = value.match(/^--no-(.+)/)[1]
|
|
277
|
+
value = !argv[value]
|
|
278
|
+
} else {
|
|
279
|
+
value = argv[value]
|
|
280
|
+
}
|
|
281
|
+
if (key && !value) {
|
|
282
|
+
implyFail.push(` ${origKey} -> ${origValue}`)
|
|
283
|
+
}
|
|
284
|
+
})
|
|
281
285
|
})
|
|
282
286
|
|
|
283
287
|
if (implyFail.length) {
|
|
284
|
-
|
|
288
|
+
let msg = `${__('Implications failed:')}\n`
|
|
285
289
|
|
|
286
|
-
implyFail.forEach(
|
|
287
|
-
msg += (
|
|
290
|
+
implyFail.forEach((value) => {
|
|
291
|
+
msg += (value)
|
|
288
292
|
})
|
|
289
293
|
|
|
290
294
|
usage.fail(msg)
|
|
291
295
|
}
|
|
292
296
|
}
|
|
293
297
|
|
|
294
|
-
|
|
295
|
-
self.conflicts = function (key, value) {
|
|
298
|
+
let conflicting = {}
|
|
299
|
+
self.conflicts = function conflicts (key, value) {
|
|
300
|
+
argsert('<string|object> [array|string]', [key, value], arguments.length)
|
|
301
|
+
|
|
296
302
|
if (typeof key === 'object') {
|
|
297
|
-
Object.keys(key).forEach(
|
|
303
|
+
Object.keys(key).forEach((k) => {
|
|
298
304
|
self.conflicts(k, key[k])
|
|
299
305
|
})
|
|
300
306
|
} else {
|
|
301
307
|
yargs.global(key)
|
|
302
|
-
conflicting[key]
|
|
308
|
+
if (!conflicting[key]) {
|
|
309
|
+
conflicting[key] = []
|
|
310
|
+
}
|
|
311
|
+
if (Array.isArray(value)) {
|
|
312
|
+
value.forEach((i) => self.conflicts(key, i))
|
|
313
|
+
} else {
|
|
314
|
+
conflicting[key].push(value)
|
|
315
|
+
}
|
|
303
316
|
}
|
|
304
317
|
}
|
|
305
|
-
self.getConflicting =
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
318
|
+
self.getConflicting = () => conflicting
|
|
319
|
+
|
|
320
|
+
self.conflicting = function conflictingFn (argv) {
|
|
321
|
+
Object.keys(argv).forEach((key) => {
|
|
322
|
+
if (conflicting[key]) {
|
|
323
|
+
conflicting[key].forEach((value) => {
|
|
324
|
+
// we default keys to 'undefined' that have been configured, we should not
|
|
325
|
+
// apply conflicting check unless they are a value other than 'undefined'.
|
|
326
|
+
if (value && argv[key] !== undefined && argv[value] !== undefined) {
|
|
327
|
+
usage.fail(__(`Arguments ${key} and ${value} are mutually exclusive`))
|
|
328
|
+
}
|
|
329
|
+
})
|
|
315
330
|
}
|
|
316
331
|
})
|
|
317
332
|
}
|
|
318
333
|
|
|
319
|
-
self.recommendCommands = function (cmd, potentialCommands) {
|
|
334
|
+
self.recommendCommands = function recommendCommands (cmd, potentialCommands) {
|
|
320
335
|
const distance = require('./levenshtein')
|
|
321
336
|
const threshold = 3 // if it takes more than three edits, let's move on.
|
|
322
|
-
potentialCommands = potentialCommands.sort(
|
|
337
|
+
potentialCommands = potentialCommands.sort((a, b) => b.length - a.length)
|
|
323
338
|
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
for (
|
|
327
|
-
|
|
339
|
+
let recommended = null
|
|
340
|
+
let bestDistance = Infinity
|
|
341
|
+
for (let i = 0, candidate; (candidate = potentialCommands[i]) !== undefined; i++) {
|
|
342
|
+
const d = distance(cmd, candidate)
|
|
328
343
|
if (d <= threshold && d < bestDistance) {
|
|
329
344
|
bestDistance = d
|
|
330
345
|
recommended = candidate
|
|
@@ -333,27 +348,21 @@ module.exports = function (yargs, usage, y18n) {
|
|
|
333
348
|
if (recommended) usage.fail(__('Did you mean %s?', recommended))
|
|
334
349
|
}
|
|
335
350
|
|
|
336
|
-
self.reset = function (localLookup) {
|
|
337
|
-
implied = objFilter(implied,
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
conflicting = objFilter(conflicting, function (k, v) {
|
|
341
|
-
return !localLookup[k]
|
|
342
|
-
})
|
|
343
|
-
checks = checks.filter(function (c) {
|
|
344
|
-
return c.global
|
|
345
|
-
})
|
|
351
|
+
self.reset = function reset (localLookup) {
|
|
352
|
+
implied = objFilter(implied, (k, v) => !localLookup[k])
|
|
353
|
+
conflicting = objFilter(conflicting, (k, v) => !localLookup[k])
|
|
354
|
+
checks = checks.filter(c => c.global)
|
|
346
355
|
return self
|
|
347
356
|
}
|
|
348
357
|
|
|
349
|
-
|
|
350
|
-
self.freeze = function () {
|
|
358
|
+
let frozen
|
|
359
|
+
self.freeze = function freeze () {
|
|
351
360
|
frozen = {}
|
|
352
361
|
frozen.implied = implied
|
|
353
362
|
frozen.checks = checks
|
|
354
363
|
frozen.conflicting = conflicting
|
|
355
364
|
}
|
|
356
|
-
self.unfreeze = function () {
|
|
365
|
+
self.unfreeze = function unfreeze () {
|
|
357
366
|
implied = frozen.implied
|
|
358
367
|
checks = frozen.checks
|
|
359
368
|
conflicting = frozen.conflicting
|
package/lib/yerror.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "yargs",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "9.0.1",
|
|
4
4
|
"description": "yargs the modern, pirate-themed, successor to optimist.",
|
|
5
5
|
"main": "./index.js",
|
|
6
6
|
"files": [
|
|
@@ -12,19 +12,19 @@
|
|
|
12
12
|
"LICENSE"
|
|
13
13
|
],
|
|
14
14
|
"dependencies": {
|
|
15
|
-
"camelcase": "^
|
|
15
|
+
"camelcase": "^4.1.0",
|
|
16
16
|
"cliui": "^3.2.0",
|
|
17
17
|
"decamelize": "^1.1.1",
|
|
18
18
|
"get-caller-file": "^1.0.1",
|
|
19
|
-
"os-locale": "^
|
|
20
|
-
"read-pkg-up": "^
|
|
19
|
+
"os-locale": "^2.0.0",
|
|
20
|
+
"read-pkg-up": "^2.0.0",
|
|
21
21
|
"require-directory": "^2.1.1",
|
|
22
22
|
"require-main-filename": "^1.0.1",
|
|
23
23
|
"set-blocking": "^2.0.0",
|
|
24
|
-
"string-width": "^
|
|
25
|
-
"which-module": "^
|
|
24
|
+
"string-width": "^2.0.0",
|
|
25
|
+
"which-module": "^2.0.0",
|
|
26
26
|
"y18n": "^3.2.1",
|
|
27
|
-
"yargs-parser": "^
|
|
27
|
+
"yargs-parser": "^7.0.0"
|
|
28
28
|
},
|
|
29
29
|
"devDependencies": {
|
|
30
30
|
"chai": "^3.4.1",
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
"nyc": "^10.3.0",
|
|
39
39
|
"rimraf": "^2.5.0",
|
|
40
40
|
"standard": "^8.6.0",
|
|
41
|
-
"standard-version": "^
|
|
41
|
+
"standard-version": "^4.2.0",
|
|
42
42
|
"which": "^1.2.9",
|
|
43
43
|
"yargs-test-extends": "^1.0.1"
|
|
44
44
|
},
|
|
@@ -69,13 +69,6 @@
|
|
|
69
69
|
],
|
|
70
70
|
"license": "MIT",
|
|
71
71
|
"engine": {
|
|
72
|
-
"node": ">=
|
|
73
|
-
},
|
|
74
|
-
"greenkeeper": {
|
|
75
|
-
"ignore": [
|
|
76
|
-
"string-width",
|
|
77
|
-
"read-pkg-up",
|
|
78
|
-
"camelcase"
|
|
79
|
-
]
|
|
72
|
+
"node": ">=4"
|
|
80
73
|
}
|
|
81
74
|
}
|