yargs 3.7.1 → 3.9.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 +18 -0
- package/README.md +23 -7
- package/index.js +461 -456
- package/lib/completion.js +29 -29
- package/lib/parser.js +349 -354
- package/lib/usage.js +289 -381
- package/lib/validation.js +186 -187
- package/package.json +19 -20
package/lib/parser.js
CHANGED
|
@@ -1,406 +1,401 @@
|
|
|
1
1
|
// fancy-pants parsing of argv, originally forked
|
|
2
2
|
// from minimist: https://www.npmjs.com/package/minimist
|
|
3
3
|
var camelCase = require('camelcase'),
|
|
4
|
-
|
|
5
|
-
path = require('path');
|
|
4
|
+
path = require('path')
|
|
6
5
|
|
|
7
6
|
function increment (orig) {
|
|
8
|
-
|
|
7
|
+
return orig !== undefined ? orig + 1 : 0
|
|
9
8
|
}
|
|
10
9
|
|
|
11
10
|
module.exports = function (args, opts) {
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
if (!opts) opts = {}
|
|
12
|
+
var flags = { arrays: {}, bools: {}, strings: {}, counts: {}, normalize: {}, configs: {} }
|
|
14
13
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
14
|
+
;[].concat(opts['array']).filter(Boolean).forEach(function (key) {
|
|
15
|
+
flags.arrays[key] = true
|
|
16
|
+
})
|
|
18
17
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
18
|
+
;[].concat(opts['boolean']).filter(Boolean).forEach(function (key) {
|
|
19
|
+
flags.bools[key] = true
|
|
20
|
+
})
|
|
22
21
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
22
|
+
;[].concat(opts.string).filter(Boolean).forEach(function (key) {
|
|
23
|
+
flags.strings[key] = true
|
|
24
|
+
})
|
|
26
25
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
26
|
+
;[].concat(opts.count).filter(Boolean).forEach(function (key) {
|
|
27
|
+
flags.counts[key] = true
|
|
28
|
+
})
|
|
30
29
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
30
|
+
;[].concat(opts.normalize).filter(Boolean).forEach(function (key) {
|
|
31
|
+
flags.normalize[key] = true
|
|
32
|
+
})
|
|
34
33
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
34
|
+
;[].concat(opts.config).filter(Boolean).forEach(function (key) {
|
|
35
|
+
flags.configs[key] = true
|
|
36
|
+
})
|
|
38
37
|
|
|
39
|
-
|
|
40
|
-
|
|
38
|
+
var aliases = {},
|
|
39
|
+
newAliases = {}
|
|
41
40
|
|
|
42
|
-
|
|
43
|
-
|
|
41
|
+
extendAliases(opts.key)
|
|
42
|
+
extendAliases(opts.alias)
|
|
44
43
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
aliases[key] = aliases[key] || [];
|
|
50
|
-
}
|
|
51
|
-
(aliases[key] || []).forEach(function (alias) {
|
|
52
|
-
defaults[alias] = defaults[key];
|
|
53
|
-
});
|
|
54
|
-
});
|
|
55
|
-
|
|
56
|
-
var argv = { _ : [] };
|
|
57
|
-
Object.keys(flags.bools).forEach(function (key) {
|
|
58
|
-
setArg(key, !(key in defaults) ? false : defaults[key]);
|
|
59
|
-
});
|
|
60
|
-
|
|
61
|
-
var notFlags = [];
|
|
62
|
-
if (args.indexOf('--') !== -1) {
|
|
63
|
-
notFlags = args.slice(args.indexOf('--')+1);
|
|
64
|
-
args = args.slice(0, args.indexOf('--'));
|
|
44
|
+
var defaults = opts['default'] || {}
|
|
45
|
+
Object.keys(defaults).forEach(function (key) {
|
|
46
|
+
if (/-/.test(key) && !opts.alias[key]) {
|
|
47
|
+
aliases[key] = aliases[key] || []
|
|
65
48
|
}
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
49
|
+
(aliases[key] || []).forEach(function (alias) {
|
|
50
|
+
defaults[alias] = defaults[key]
|
|
51
|
+
})
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
var argv = { _: [] }
|
|
55
|
+
|
|
56
|
+
Object.keys(flags.bools).forEach(function (key) {
|
|
57
|
+
setArg(key, !(key in defaults) ? false : defaults[key])
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
var notFlags = []
|
|
61
|
+
if (args.indexOf('--') !== -1) {
|
|
62
|
+
notFlags = args.slice(args.indexOf('--') + 1)
|
|
63
|
+
args = args.slice(0, args.indexOf('--'))
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
for (var i = 0; i < args.length; i++) {
|
|
67
|
+
var arg = args[i],
|
|
68
|
+
broken,
|
|
69
|
+
key,
|
|
70
|
+
letters,
|
|
71
|
+
m,
|
|
72
|
+
next
|
|
73
|
+
|
|
74
|
+
// -- seperated by =
|
|
75
|
+
if (arg.match(/^--.+=/)) {
|
|
76
|
+
// Using [\s\S] instead of . because js doesn't support the
|
|
77
|
+
// 'dotall' regex modifier. See:
|
|
78
|
+
// http://stackoverflow.com/a/1068308/13216
|
|
79
|
+
m = arg.match(/^--([^=]+)=([\s\S]*)$/)
|
|
80
|
+
setArg(m[1], m[2])
|
|
81
|
+
} else if (arg.match(/^--no-.+/)) {
|
|
82
|
+
key = arg.match(/^--no-(.+)/)[1]
|
|
83
|
+
setArg(key, false)
|
|
84
|
+
|
|
85
|
+
// -- seperated by space.
|
|
86
|
+
} else if (arg.match(/^--.+/)) {
|
|
87
|
+
key = arg.match(/^--(.+)/)[1]
|
|
88
|
+
|
|
89
|
+
if (checkAllAliases(key, opts.narg)) {
|
|
90
|
+
i = eatNargs(i, key, args)
|
|
91
|
+
} else {
|
|
92
|
+
next = args[i + 1]
|
|
93
|
+
|
|
94
|
+
if (next !== undefined && !next.match(/^-/)
|
|
95
|
+
&& !checkAllAliases(key, flags.bools)
|
|
96
|
+
&& !checkAllAliases(key, flags.counts)) {
|
|
97
|
+
setArg(key, next)
|
|
98
|
+
i++
|
|
99
|
+
} else if (/^(true|false)$/.test(next)) {
|
|
100
|
+
setArg(key, next)
|
|
101
|
+
i++
|
|
102
|
+
} else {
|
|
103
|
+
setArg(key, defaultForType(guessType(key, flags)))
|
|
77
104
|
}
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// dot-notation flag seperated by '='.
|
|
108
|
+
} else if (arg.match(/^-.\..+=/)) {
|
|
109
|
+
m = arg.match(/^-([^=]+)=([\s\S]*)$/)
|
|
110
|
+
setArg(m[1], m[2])
|
|
111
|
+
|
|
112
|
+
// dot-notation flag seperated by space.
|
|
113
|
+
} else if (arg.match(/^-.\..+/)) {
|
|
114
|
+
next = args[i + 1]
|
|
115
|
+
key = arg.match(/^-(.\..+)/)[1]
|
|
116
|
+
|
|
117
|
+
if (next !== undefined && !next.match(/^-/)
|
|
118
|
+
&& !checkAllAliases(key, flags.bools)
|
|
119
|
+
&& !checkAllAliases(key, flags.counts)) {
|
|
120
|
+
setArg(key, next)
|
|
121
|
+
i++
|
|
122
|
+
} else {
|
|
123
|
+
setArg(key, defaultForType(guessType(key, flags)))
|
|
124
|
+
}
|
|
125
|
+
} else if (arg.match(/^-[^-]+/)) {
|
|
126
|
+
letters = arg.slice(1, -1).split('')
|
|
127
|
+
broken = false
|
|
128
|
+
|
|
129
|
+
for (var j = 0; j < letters.length; j++) {
|
|
130
|
+
next = arg.slice(j + 2)
|
|
131
|
+
|
|
132
|
+
if (letters[j + 1] && letters[j + 1] === '=') {
|
|
133
|
+
setArg(letters[j], arg.slice(j + 3))
|
|
134
|
+
broken = true
|
|
135
|
+
break
|
|
81
136
|
}
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
if (checkAllAliases(key, opts.narg)) {
|
|
87
|
-
i = eatNargs(i, key, args);
|
|
88
|
-
} else {
|
|
89
|
-
var next = args[i + 1];
|
|
90
|
-
|
|
91
|
-
if (next !== undefined && !next.match(/^-/)
|
|
92
|
-
&& !checkAllAliases(key, flags.bools)
|
|
93
|
-
&& !checkAllAliases(key, flags.counts)) {
|
|
94
|
-
setArg(key, next);
|
|
95
|
-
i++;
|
|
96
|
-
}
|
|
97
|
-
else if (/^(true|false)$/.test(next)) {
|
|
98
|
-
setArg(key, next);
|
|
99
|
-
i++;
|
|
100
|
-
}
|
|
101
|
-
else {
|
|
102
|
-
setArg(key, defaultForType(guessType(key, flags)));
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
// dot-notation flag seperated by '='.
|
|
107
|
-
else if (arg.match(/^-.\..+=/)) {
|
|
108
|
-
var m = arg.match(/^-([^=]+)=([\s\S]*)$/);
|
|
109
|
-
setArg(m[1], m[2]);
|
|
137
|
+
|
|
138
|
+
if (next === '-') {
|
|
139
|
+
setArg(letters[j], next)
|
|
140
|
+
continue
|
|
110
141
|
}
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
&& !checkAllAliases(key, flags.counts)) {
|
|
118
|
-
setArg(key, next);
|
|
119
|
-
i++;
|
|
120
|
-
}
|
|
121
|
-
else {
|
|
122
|
-
setArg(key, defaultForType(guessType(key, flags)));
|
|
123
|
-
}
|
|
142
|
+
|
|
143
|
+
if (/[A-Za-z]/.test(letters[j])
|
|
144
|
+
&& /-?\d+(\.\d*)?(e-?\d+)?$/.test(next)) {
|
|
145
|
+
setArg(letters[j], next)
|
|
146
|
+
broken = true
|
|
147
|
+
break
|
|
124
148
|
}
|
|
125
|
-
else if (arg.match(/^-[^-]+/)) {
|
|
126
|
-
var letters = arg.slice(1,-1).split('');
|
|
127
|
-
|
|
128
|
-
var broken = false;
|
|
129
|
-
for (var j = 0; j < letters.length; j++) {
|
|
130
|
-
var next = arg.slice(j+2);
|
|
131
|
-
|
|
132
|
-
if (letters[j+1] && letters[j+1] === '=') {
|
|
133
|
-
setArg(letters[j], arg.slice(j+3));
|
|
134
|
-
broken = true;
|
|
135
|
-
break;
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
if (next === '-') {
|
|
139
|
-
setArg(letters[j], next)
|
|
140
|
-
continue;
|
|
141
|
-
}
|
|
142
|
-
if (/[A-Za-z]/.test(letters[j])
|
|
143
|
-
&& /-?\d+(\.\d*)?(e-?\d+)?$/.test(next)) {
|
|
144
|
-
setArg(letters[j], next);
|
|
145
|
-
broken = true;
|
|
146
|
-
break;
|
|
147
|
-
}
|
|
148
|
-
if (letters[j+1] && letters[j+1].match(/\W/)) {
|
|
149
|
-
setArg(letters[j], arg.slice(j+2));
|
|
150
|
-
broken = true;
|
|
151
|
-
break;
|
|
152
|
-
}
|
|
153
|
-
else {
|
|
154
|
-
setArg(letters[j], defaultForType(guessType(letters[j], flags)));
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
149
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
if (args[i+1] && !/^(-|--)[^-]/.test(args[i+1])
|
|
165
|
-
&& !checkAllAliases(key, flags.bools)
|
|
166
|
-
&& !checkAllAliases(key, flags.counts)) {
|
|
167
|
-
setArg(key, args[i+1]);
|
|
168
|
-
i++;
|
|
169
|
-
}
|
|
170
|
-
else if (args[i+1] && /true|false/.test(args[i+1])) {
|
|
171
|
-
setArg(key, args[i+1]);
|
|
172
|
-
i++;
|
|
173
|
-
}
|
|
174
|
-
else {
|
|
175
|
-
setArg(key, defaultForType(guessType(key, flags)));
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
}
|
|
150
|
+
if (letters[j + 1] && letters[j + 1].match(/\W/)) {
|
|
151
|
+
setArg(letters[j], arg.slice(j + 2))
|
|
152
|
+
broken = true
|
|
153
|
+
break
|
|
154
|
+
} else {
|
|
155
|
+
setArg(letters[j], defaultForType(guessType(letters[j], flags)))
|
|
179
156
|
}
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
key = arg.slice(-1)[0]
|
|
160
|
+
|
|
161
|
+
if (!broken && key !== '-') {
|
|
162
|
+
if (checkAllAliases(key, opts.narg)) {
|
|
163
|
+
i = eatNargs(i, key, args)
|
|
164
|
+
} else {
|
|
165
|
+
if (args[i + 1] && !/^(-|--)[^-]/.test(args[i + 1])
|
|
166
|
+
&& !checkAllAliases(key, flags.bools)
|
|
167
|
+
&& !checkAllAliases(key, flags.counts)) {
|
|
168
|
+
setArg(key, args[i + 1])
|
|
169
|
+
i++
|
|
170
|
+
} else if (args[i + 1] && /true|false/.test(args[i + 1])) {
|
|
171
|
+
setArg(key, args[i + 1])
|
|
172
|
+
i++
|
|
173
|
+
} else {
|
|
174
|
+
setArg(key, defaultForType(guessType(key, flags)))
|
|
175
|
+
}
|
|
184
176
|
}
|
|
177
|
+
}
|
|
178
|
+
} else {
|
|
179
|
+
argv._.push(
|
|
180
|
+
flags.strings['_'] || !isNumber(arg) ? arg : Number(arg)
|
|
181
|
+
)
|
|
185
182
|
}
|
|
183
|
+
}
|
|
186
184
|
|
|
187
|
-
|
|
188
|
-
|
|
185
|
+
setConfig(argv)
|
|
186
|
+
applyDefaultsAndAliases(argv, aliases, defaults)
|
|
189
187
|
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
188
|
+
Object.keys(flags.counts).forEach(function (key) {
|
|
189
|
+
setArg(key, defaults[key])
|
|
190
|
+
})
|
|
193
191
|
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
192
|
+
notFlags.forEach(function (key) {
|
|
193
|
+
argv._.push(key)
|
|
194
|
+
})
|
|
197
195
|
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
196
|
+
// how many arguments should we consume, based
|
|
197
|
+
// on the nargs option?
|
|
198
|
+
function eatNargs (i, key, args) {
|
|
199
|
+
var toEat = checkAllAliases(key, opts.narg)
|
|
202
200
|
|
|
203
|
-
|
|
201
|
+
if (args.length - (i + 1) < toEat) throw Error('not enough arguments following: ' + key)
|
|
204
202
|
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
return (i + toEat);
|
|
203
|
+
for (var ii = i + 1; ii < (toEat + i + 1); ii++) {
|
|
204
|
+
setArg(key, args[ii])
|
|
210
205
|
}
|
|
211
206
|
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
if (checkAllAliases(key, flags.bools) || checkAllAliases(key, flags.counts)) {
|
|
215
|
-
if (typeof val === 'string') val = val === 'true';
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
if (/-/.test(key) && !(aliases[key] && aliases[key].length)) {
|
|
219
|
-
var c = camelCase(key);
|
|
220
|
-
aliases[key] = [c];
|
|
221
|
-
newAliases[c] = true;
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
var value = !checkAllAliases(key, flags.strings) && isNumber(val) ? Number(val) : val;
|
|
225
|
-
|
|
226
|
-
if (checkAllAliases(key, flags.counts)) {
|
|
227
|
-
value = increment;
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
var splitKey = key.split('.');
|
|
231
|
-
setKey(argv, splitKey, value);
|
|
232
|
-
|
|
233
|
-
(aliases[splitKey[0]] || []).forEach(function (x) {
|
|
234
|
-
x = x.split('.');
|
|
207
|
+
return (i + toEat)
|
|
208
|
+
}
|
|
235
209
|
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
a.shift(); // nuke the old key.
|
|
241
|
-
x = x.concat(a);
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
setKey(argv, x, value);
|
|
245
|
-
});
|
|
246
|
-
|
|
247
|
-
var keys = [key].concat(aliases[key] || []);
|
|
248
|
-
for (var i = 0, l = keys.length; i < l; i++) {
|
|
249
|
-
if (flags.normalize[keys[i]]) {
|
|
250
|
-
keys.forEach(function(key) {
|
|
251
|
-
argv.__defineSetter__(key, function(v) {
|
|
252
|
-
val = path.normalize(v);
|
|
253
|
-
});
|
|
254
|
-
|
|
255
|
-
argv.__defineGetter__(key, function () {
|
|
256
|
-
return typeof val === 'string' ?
|
|
257
|
-
path.normalize(val) : val;
|
|
258
|
-
});
|
|
259
|
-
});
|
|
260
|
-
break;
|
|
261
|
-
}
|
|
262
|
-
}
|
|
210
|
+
function setArg (key, val) {
|
|
211
|
+
// handle parsing boolean arguments --foo=true --bar false.
|
|
212
|
+
if (checkAllAliases(key, flags.bools) || checkAllAliases(key, flags.counts)) {
|
|
213
|
+
if (typeof val === 'string') val = val === 'true'
|
|
263
214
|
}
|
|
264
215
|
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
// expand defaults/aliases, in-case any happen to reference
|
|
271
|
-
// the config.json file.
|
|
272
|
-
applyDefaultsAndAliases(configLookup, aliases, defaults);
|
|
273
|
-
|
|
274
|
-
Object.keys(flags.configs).forEach(function(configKey) {
|
|
275
|
-
var configPath = argv[configKey] || configLookup[configKey];
|
|
276
|
-
if (configPath) {
|
|
277
|
-
try {
|
|
278
|
-
var config = require(path.resolve(process.cwd(), configPath));
|
|
279
|
-
Object.keys(config).forEach(function (key) {
|
|
280
|
-
// setting arguments via CLI takes precedence over
|
|
281
|
-
// values within the config file.
|
|
282
|
-
if (argv[key] === undefined) {
|
|
283
|
-
delete argv[key];
|
|
284
|
-
setArg(key, config[key]);
|
|
285
|
-
}
|
|
286
|
-
});
|
|
287
|
-
} catch (ex) {
|
|
288
|
-
throw Error('invalid json config file: ' + configPath);
|
|
289
|
-
}
|
|
290
|
-
}
|
|
291
|
-
});
|
|
216
|
+
if (/-/.test(key) && !(aliases[key] && aliases[key].length)) {
|
|
217
|
+
var c = camelCase(key)
|
|
218
|
+
aliases[key] = [c]
|
|
219
|
+
newAliases[c] = true
|
|
292
220
|
}
|
|
293
221
|
|
|
294
|
-
|
|
295
|
-
Object.keys(defaults).forEach(function (key) {
|
|
296
|
-
if (!hasKey(obj, key.split('.'))) {
|
|
297
|
-
setKey(obj, key.split('.'), defaults[key]);
|
|
222
|
+
var value = !checkAllAliases(key, flags.strings) && isNumber(val) ? Number(val) : val
|
|
298
223
|
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
});
|
|
302
|
-
}
|
|
303
|
-
});
|
|
224
|
+
if (checkAllAliases(key, flags.counts)) {
|
|
225
|
+
value = increment
|
|
304
226
|
}
|
|
305
227
|
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
228
|
+
var splitKey = key.split('.')
|
|
229
|
+
setKey(argv, splitKey, value)
|
|
230
|
+
|
|
231
|
+
;(aliases[splitKey[0]] || []).forEach(function (x) {
|
|
232
|
+
x = x.split('.')
|
|
233
|
+
|
|
234
|
+
// handle populating dot notation for both
|
|
235
|
+
// the key and its aliases.
|
|
236
|
+
if (splitKey.length > 1) {
|
|
237
|
+
var a = [].concat(splitKey)
|
|
238
|
+
a.shift() // nuke the old key.
|
|
239
|
+
x = x.concat(a)
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
setKey(argv, x, value)
|
|
243
|
+
})
|
|
244
|
+
|
|
245
|
+
var keys = [key].concat(aliases[key] || [])
|
|
246
|
+
for (var i = 0, l = keys.length; i < l; i++) {
|
|
247
|
+
if (flags.normalize[keys[i]]) {
|
|
248
|
+
keys.forEach(function (key) {
|
|
249
|
+
argv.__defineSetter__(key, function (v) {
|
|
250
|
+
val = path.normalize(v)
|
|
251
|
+
})
|
|
252
|
+
|
|
253
|
+
argv.__defineGetter__(key, function () {
|
|
254
|
+
return typeof val === 'string' ?
|
|
255
|
+
path.normalize(val) : val
|
|
256
|
+
})
|
|
257
|
+
})
|
|
258
|
+
break
|
|
259
|
+
}
|
|
314
260
|
}
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
// set args from config.json file, this should be
|
|
264
|
+
// applied last so that defaults can be applied.
|
|
265
|
+
function setConfig (argv) {
|
|
266
|
+
var configLookup = {}
|
|
267
|
+
|
|
268
|
+
// expand defaults/aliases, in-case any happen to reference
|
|
269
|
+
// the config.json file.
|
|
270
|
+
applyDefaultsAndAliases(configLookup, aliases, defaults)
|
|
271
|
+
|
|
272
|
+
Object.keys(flags.configs).forEach(function (configKey) {
|
|
273
|
+
var configPath = argv[configKey] || configLookup[configKey]
|
|
274
|
+
if (configPath) {
|
|
275
|
+
try {
|
|
276
|
+
var config = require(path.resolve(process.cwd(), configPath))
|
|
277
|
+
|
|
278
|
+
Object.keys(config).forEach(function (key) {
|
|
279
|
+
// setting arguments via CLI takes precedence over
|
|
280
|
+
// values within the config file.
|
|
281
|
+
if (argv[key] === undefined) {
|
|
282
|
+
delete argv[key]
|
|
283
|
+
setArg(key, config[key])
|
|
284
|
+
}
|
|
285
|
+
})
|
|
286
|
+
} catch (ex) {
|
|
287
|
+
throw Error('invalid json config file: ' + configPath)
|
|
338
288
|
}
|
|
339
|
-
|
|
289
|
+
}
|
|
290
|
+
})
|
|
291
|
+
}
|
|
340
292
|
|
|
341
|
-
|
|
342
|
-
function
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
aliases[key]
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
293
|
+
function applyDefaultsAndAliases (obj, aliases, defaults) {
|
|
294
|
+
Object.keys(defaults).forEach(function (key) {
|
|
295
|
+
if (!hasKey(obj, key.split('.'))) {
|
|
296
|
+
setKey(obj, key.split('.'), defaults[key])
|
|
297
|
+
|
|
298
|
+
;(aliases[key] || []).forEach(function (x) {
|
|
299
|
+
setKey(obj, x.split('.'), defaults[key])
|
|
300
|
+
})
|
|
301
|
+
}
|
|
302
|
+
})
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
function hasKey (obj, keys) {
|
|
306
|
+
var o = obj
|
|
307
|
+
keys.slice(0, -1).forEach(function (key) {
|
|
308
|
+
o = (o[key] || {})
|
|
309
|
+
})
|
|
310
|
+
|
|
311
|
+
var key = keys[keys.length - 1]
|
|
312
|
+
return key in o
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
function setKey (obj, keys, value) {
|
|
316
|
+
var o = obj
|
|
317
|
+
keys.slice(0, -1).forEach(function (key) {
|
|
318
|
+
if (o[key] === undefined) o[key] = {}
|
|
319
|
+
o = o[key]
|
|
320
|
+
})
|
|
321
|
+
|
|
322
|
+
var key = keys[keys.length - 1]
|
|
323
|
+
if (value === increment) {
|
|
324
|
+
o[key] = increment(o[key])
|
|
325
|
+
} else if (o[key] === undefined && checkAllAliases(key, flags.arrays)) {
|
|
326
|
+
o[key] = Array.isArray(value) ? value : [value]
|
|
327
|
+
} else if (o[key] === undefined || typeof o[key] === 'boolean') {
|
|
328
|
+
o[key] = value
|
|
329
|
+
} else if (Array.isArray(o[key])) {
|
|
330
|
+
o[key].push(value)
|
|
331
|
+
} else {
|
|
332
|
+
o[key] = [ o[key], value ]
|
|
359
333
|
}
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
// extend the aliases list with inferred aliases.
|
|
337
|
+
function extendAliases (obj) {
|
|
338
|
+
Object.keys(obj || {}).forEach(function (key) {
|
|
339
|
+
aliases[key] = [].concat(opts.alias[key] || [])
|
|
340
|
+
// For "--option-name", also set argv.optionName
|
|
341
|
+
aliases[key].concat(key).forEach(function (x) {
|
|
342
|
+
if (/-/.test(x)) {
|
|
343
|
+
var c = camelCase(x)
|
|
344
|
+
aliases[key].push(c)
|
|
345
|
+
newAliases[c] = true
|
|
346
|
+
}
|
|
347
|
+
})
|
|
348
|
+
aliases[key].forEach(function (x) {
|
|
349
|
+
aliases[x] = [key].concat(aliases[key].filter(function (y) {
|
|
350
|
+
return x !== y
|
|
351
|
+
}))
|
|
352
|
+
})
|
|
353
|
+
})
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
// check if a flag is set for any of a key's aliases.
|
|
357
|
+
function checkAllAliases (key, flag) {
|
|
358
|
+
var isSet = false,
|
|
359
|
+
toCheck = [].concat(aliases[key] || [], key)
|
|
360
|
+
|
|
361
|
+
toCheck.forEach(function (key) {
|
|
362
|
+
if (flag[key]) isSet = flag[key]
|
|
363
|
+
})
|
|
364
|
+
|
|
365
|
+
return isSet
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
// return a default value, given the type of a flag.,
|
|
369
|
+
// e.g., key of type 'string' will default to '', rather than 'true'.
|
|
370
|
+
function defaultForType (type) {
|
|
371
|
+
var def = {
|
|
372
|
+
boolean: true,
|
|
373
|
+
string: '',
|
|
374
|
+
array: []
|
|
383
375
|
}
|
|
384
376
|
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
var type = 'boolean';
|
|
377
|
+
return def[type]
|
|
378
|
+
}
|
|
388
379
|
|
|
389
|
-
|
|
390
|
-
|
|
380
|
+
// given a flag, enforce a default type.
|
|
381
|
+
function guessType (key, flags) {
|
|
382
|
+
var type = 'boolean'
|
|
391
383
|
|
|
392
|
-
|
|
393
|
-
|
|
384
|
+
if (flags.strings && flags.strings[key]) type = 'string'
|
|
385
|
+
else if (flags.arrays && flags.arrays[key]) type = 'array'
|
|
394
386
|
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
387
|
+
return type
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
function isNumber (x) {
|
|
391
|
+
if (typeof x === 'number') return true
|
|
392
|
+
if (/^0x[0-9a-f]+$/i.test(x)) return true
|
|
393
|
+
return /^[-+]?(?:\d+(?:\.\d*)?|\.\d+)(e[-+]?\d+)?$/.test(x)
|
|
394
|
+
}
|
|
400
395
|
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
}
|
|
396
|
+
return {
|
|
397
|
+
argv: argv,
|
|
398
|
+
aliases: aliases,
|
|
399
|
+
newAliases: newAliases
|
|
400
|
+
}
|
|
401
|
+
}
|