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/index.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
'use strict'
|
|
1
2
|
// classic singleton yargs API, to use yargs
|
|
2
3
|
// without running as a singleton do:
|
|
3
4
|
// require('yargs/yargs')(process.argv.slice(2))
|
|
@@ -21,7 +22,7 @@ function Argv (processArgs, cwd) {
|
|
|
21
22
|
to get a parsed version of process.argv.
|
|
22
23
|
*/
|
|
23
24
|
function singletonify (inst) {
|
|
24
|
-
Object.keys(inst).forEach(
|
|
25
|
+
Object.keys(inst).forEach((key) => {
|
|
25
26
|
if (key === 'argv') {
|
|
26
27
|
Argv.__defineGetter__(key, inst.__lookupGetter__(key))
|
|
27
28
|
} else {
|
package/lib/apply-extends.js
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
|
-
var fs = require('fs')
|
|
2
|
-
var path = require('path')
|
|
3
|
-
var assign = require('./assign')
|
|
4
|
-
var YError = require('./yerror')
|
|
5
1
|
|
|
6
|
-
|
|
2
|
+
'use strict'
|
|
3
|
+
const fs = require('fs')
|
|
4
|
+
const path = require('path')
|
|
5
|
+
const YError = require('./yerror')
|
|
6
|
+
|
|
7
|
+
let previouslyVisitedConfigs = []
|
|
7
8
|
|
|
8
9
|
function checkForCircularExtends (path) {
|
|
9
10
|
if (previouslyVisitedConfigs.indexOf(path) > -1) {
|
|
10
|
-
throw new YError(
|
|
11
|
+
throw new YError(`Circular extended configurations: '${path}'.`)
|
|
11
12
|
}
|
|
12
13
|
}
|
|
13
14
|
|
|
@@ -16,12 +17,12 @@ function getPathToDefaultConfig (cwd, pathToExtend) {
|
|
|
16
17
|
}
|
|
17
18
|
|
|
18
19
|
function applyExtends (config, cwd) {
|
|
19
|
-
|
|
20
|
+
let defaultConfig = {}
|
|
20
21
|
|
|
21
22
|
if (config.hasOwnProperty('extends')) {
|
|
22
23
|
if (typeof config.extends !== 'string') return defaultConfig
|
|
23
|
-
|
|
24
|
-
|
|
24
|
+
const isPath = /\.json$/.test(config.extends)
|
|
25
|
+
let pathToDefault = null
|
|
25
26
|
if (!isPath) {
|
|
26
27
|
try {
|
|
27
28
|
pathToDefault = require.resolve(config.extends)
|
|
@@ -46,7 +47,7 @@ function applyExtends (config, cwd) {
|
|
|
46
47
|
|
|
47
48
|
previouslyVisitedConfigs = []
|
|
48
49
|
|
|
49
|
-
return assign(defaultConfig, config)
|
|
50
|
+
return Object.assign({}, defaultConfig, config)
|
|
50
51
|
}
|
|
51
52
|
|
|
52
53
|
module.exports = applyExtends
|
package/lib/argsert.js
CHANGED
|
@@ -1,20 +1,21 @@
|
|
|
1
|
+
'use strict'
|
|
1
2
|
const command = require('./command')()
|
|
2
3
|
const YError = require('./yerror')
|
|
3
4
|
|
|
4
5
|
const positionName = ['first', 'second', 'third', 'fourth', 'fifth', 'sixth']
|
|
5
6
|
|
|
6
|
-
module.exports = function (expected, callerArguments, length) {
|
|
7
|
+
module.exports = function argsert (expected, callerArguments, length) {
|
|
7
8
|
// TODO: should this eventually raise an exception.
|
|
8
9
|
try {
|
|
9
10
|
// preface the argument description with "cmd", so
|
|
10
11
|
// that we can run it through yargs' command parser.
|
|
11
|
-
|
|
12
|
-
|
|
12
|
+
let position = 0
|
|
13
|
+
let parsed = {demanded: [], optional: []}
|
|
13
14
|
if (typeof expected === 'object') {
|
|
14
15
|
length = callerArguments
|
|
15
16
|
callerArguments = expected
|
|
16
17
|
} else {
|
|
17
|
-
parsed = command.parseCommand(
|
|
18
|
+
parsed = command.parseCommand(`cmd ${expected}`)
|
|
18
19
|
}
|
|
19
20
|
const args = [].slice.call(callerArguments)
|
|
20
21
|
|
|
@@ -22,33 +23,27 @@ module.exports = function (expected, callerArguments, length) {
|
|
|
22
23
|
length = length || args.length
|
|
23
24
|
|
|
24
25
|
if (length < parsed.demanded.length) {
|
|
25
|
-
throw new YError(
|
|
26
|
-
' but received ' + args.length + '.')
|
|
26
|
+
throw new YError(`Not enough arguments provided. Expected ${parsed.demanded.length} but received ${args.length}.`)
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
const totalCommands = parsed.demanded.length + parsed.optional.length
|
|
30
30
|
if (length > totalCommands) {
|
|
31
|
-
throw new YError(
|
|
32
|
-
' but received ' + length + '.')
|
|
31
|
+
throw new YError(`Too many arguments provided. Expected max ${totalCommands} but received ${length}.`)
|
|
33
32
|
}
|
|
34
33
|
|
|
35
|
-
parsed.demanded.forEach(
|
|
34
|
+
parsed.demanded.forEach((demanded) => {
|
|
36
35
|
const arg = args.shift()
|
|
37
36
|
const observedType = guessType(arg)
|
|
38
|
-
const matchingTypes = demanded.cmd.filter(
|
|
39
|
-
return type === observedType || type === '*'
|
|
40
|
-
})
|
|
37
|
+
const matchingTypes = demanded.cmd.filter(type => type === observedType || type === '*')
|
|
41
38
|
if (matchingTypes.length === 0) argumentTypeError(observedType, demanded.cmd, position, false)
|
|
42
39
|
position += 1
|
|
43
40
|
})
|
|
44
41
|
|
|
45
|
-
parsed.optional.forEach(
|
|
42
|
+
parsed.optional.forEach((optional) => {
|
|
46
43
|
if (args.length === 0) return
|
|
47
44
|
const arg = args.shift()
|
|
48
45
|
const observedType = guessType(arg)
|
|
49
|
-
const matchingTypes = optional.cmd.filter(
|
|
50
|
-
return type === observedType || type === '*'
|
|
51
|
-
})
|
|
46
|
+
const matchingTypes = optional.cmd.filter(type => type === observedType || type === '*')
|
|
52
47
|
if (matchingTypes.length === 0) argumentTypeError(observedType, optional.cmd, position, true)
|
|
53
48
|
position += 1
|
|
54
49
|
})
|
|
@@ -67,6 +62,5 @@ function guessType (arg) {
|
|
|
67
62
|
}
|
|
68
63
|
|
|
69
64
|
function argumentTypeError (observedType, allowedTypes, position, optional) {
|
|
70
|
-
throw new YError(
|
|
71
|
-
' Expected ' + allowedTypes.join(' or ') + ' but received ' + observedType + '.')
|
|
65
|
+
throw new YError(`Invalid ${positionName[position] || 'manyith'} argument. Expected ${allowedTypes.join(' or ')} but received ${observedType}.`)
|
|
72
66
|
}
|
package/lib/command.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
'use strict'
|
|
1
2
|
const path = require('path')
|
|
2
3
|
const inspect = require('util').inspect
|
|
3
4
|
const camelCase = require('camelcase')
|
|
@@ -7,21 +8,21 @@ const DEFAULT_MARKER = '*'
|
|
|
7
8
|
// handles parsing positional arguments,
|
|
8
9
|
// and populating argv with said positional
|
|
9
10
|
// arguments.
|
|
10
|
-
module.exports = function (yargs, usage, validation) {
|
|
11
|
+
module.exports = function command (yargs, usage, validation) {
|
|
11
12
|
const self = {}
|
|
12
13
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
self.addHandler = function (cmd, description, builder, handler) {
|
|
17
|
-
|
|
18
|
-
handler = handler ||
|
|
14
|
+
let handlers = {}
|
|
15
|
+
let aliasMap = {}
|
|
16
|
+
let defaultCommand
|
|
17
|
+
self.addHandler = function addHandler (cmd, description, builder, handler) {
|
|
18
|
+
let aliases = []
|
|
19
|
+
handler = handler || (() => {})
|
|
19
20
|
|
|
20
21
|
if (Array.isArray(cmd)) {
|
|
21
22
|
aliases = cmd.slice(1)
|
|
22
23
|
cmd = cmd[0]
|
|
23
24
|
} else if (typeof cmd === 'object') {
|
|
24
|
-
|
|
25
|
+
let command = (Array.isArray(cmd.command) || typeof cmd.command === 'string') ? cmd.command : moduleName(cmd)
|
|
25
26
|
if (cmd.aliases) command = [].concat(command).concat(cmd.aliases)
|
|
26
27
|
self.addHandler(command, extractDesc(cmd), cmd.builder, cmd.handler)
|
|
27
28
|
return
|
|
@@ -34,16 +35,14 @@ module.exports = function (yargs, usage, validation) {
|
|
|
34
35
|
}
|
|
35
36
|
|
|
36
37
|
// parse positionals out of cmd string
|
|
37
|
-
|
|
38
|
+
const parsedCommand = self.parseCommand(cmd)
|
|
38
39
|
|
|
39
40
|
// remove positional args from aliases only
|
|
40
|
-
aliases = aliases.map(
|
|
41
|
-
return self.parseCommand(alias).cmd
|
|
42
|
-
})
|
|
41
|
+
aliases = aliases.map(alias => self.parseCommand(alias).cmd)
|
|
43
42
|
|
|
44
43
|
// check for default and filter out '*''
|
|
45
|
-
|
|
46
|
-
|
|
44
|
+
let isDefault = false
|
|
45
|
+
const parsedAliases = [parsedCommand.cmd].concat(aliases).filter((c) => {
|
|
47
46
|
if (c === DEFAULT_MARKER) {
|
|
48
47
|
isDefault = true
|
|
49
48
|
return false
|
|
@@ -55,7 +54,7 @@ module.exports = function (yargs, usage, validation) {
|
|
|
55
54
|
if (isDefault && parsedAliases.length === 0) {
|
|
56
55
|
defaultCommand = {
|
|
57
56
|
original: cmd.replace(DEFAULT_MARKER, '').trim(),
|
|
58
|
-
handler
|
|
57
|
+
handler,
|
|
59
58
|
builder: builder || {},
|
|
60
59
|
demanded: parsedCommand.demanded,
|
|
61
60
|
optional: parsedCommand.optional
|
|
@@ -71,7 +70,7 @@ module.exports = function (yargs, usage, validation) {
|
|
|
71
70
|
}
|
|
72
71
|
|
|
73
72
|
// populate aliasMap
|
|
74
|
-
aliases.forEach(
|
|
73
|
+
aliases.forEach((alias) => {
|
|
75
74
|
aliasMap[alias] = parsedCommand.cmd
|
|
76
75
|
})
|
|
77
76
|
|
|
@@ -81,7 +80,7 @@ module.exports = function (yargs, usage, validation) {
|
|
|
81
80
|
|
|
82
81
|
handlers[parsedCommand.cmd] = {
|
|
83
82
|
original: cmd,
|
|
84
|
-
handler
|
|
83
|
+
handler,
|
|
85
84
|
builder: builder || {},
|
|
86
85
|
demanded: parsedCommand.demanded,
|
|
87
86
|
optional: parsedCommand.optional
|
|
@@ -90,16 +89,16 @@ module.exports = function (yargs, usage, validation) {
|
|
|
90
89
|
if (isDefault) defaultCommand = handlers[parsedCommand.cmd]
|
|
91
90
|
}
|
|
92
91
|
|
|
93
|
-
self.addDirectory = function (dir, context, req, callerFile, opts) {
|
|
92
|
+
self.addDirectory = function addDirectory (dir, context, req, callerFile, opts) {
|
|
94
93
|
opts = opts || {}
|
|
95
94
|
// disable recursion to support nested directories of subcommands
|
|
96
95
|
if (typeof opts.recurse !== 'boolean') opts.recurse = false
|
|
97
96
|
// exclude 'json', 'coffee' from require-directory defaults
|
|
98
97
|
if (!Array.isArray(opts.extensions)) opts.extensions = ['js']
|
|
99
98
|
// allow consumer to define their own visitor function
|
|
100
|
-
const parentVisit = typeof opts.visit === 'function' ? opts.visit :
|
|
99
|
+
const parentVisit = typeof opts.visit === 'function' ? opts.visit : o => o
|
|
101
100
|
// call addHandler via visitor function
|
|
102
|
-
opts.visit = function (obj, joined, filename) {
|
|
101
|
+
opts.visit = function visit (obj, joined, filename) {
|
|
103
102
|
const visited = parentVisit(obj, joined, filename)
|
|
104
103
|
// allow consumer to skip modules with their own visitor
|
|
105
104
|
if (visited) {
|
|
@@ -119,7 +118,7 @@ module.exports = function (yargs, usage, validation) {
|
|
|
119
118
|
// if module was not require()d and no name given, throw error
|
|
120
119
|
function moduleName (obj) {
|
|
121
120
|
const mod = require('which-module')(obj)
|
|
122
|
-
if (!mod) throw new Error(
|
|
121
|
+
if (!mod) throw new Error(`No command name given for module: ${inspect(obj)}`)
|
|
123
122
|
return commandFromFilename(mod.filename)
|
|
124
123
|
}
|
|
125
124
|
|
|
@@ -129,64 +128,58 @@ module.exports = function (yargs, usage, validation) {
|
|
|
129
128
|
}
|
|
130
129
|
|
|
131
130
|
function extractDesc (obj) {
|
|
132
|
-
for (
|
|
131
|
+
for (let keys = ['describe', 'description', 'desc'], i = 0, l = keys.length, test; i < l; i++) {
|
|
133
132
|
test = obj[keys[i]]
|
|
134
133
|
if (typeof test === 'string' || typeof test === 'boolean') return test
|
|
135
134
|
}
|
|
136
135
|
return false
|
|
137
136
|
}
|
|
138
137
|
|
|
139
|
-
self.parseCommand = function (cmd) {
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
138
|
+
self.parseCommand = function parseCommand (cmd) {
|
|
139
|
+
const extraSpacesStrippedCommand = cmd.replace(/\s{2,}/g, ' ')
|
|
140
|
+
const splitCommand = extraSpacesStrippedCommand.split(/\s+(?![^[]*]|[^<]*>)/)
|
|
141
|
+
const bregex = /\.*[\][<>]/g
|
|
142
|
+
const parsedCommand = {
|
|
144
143
|
cmd: (splitCommand.shift()).replace(bregex, ''),
|
|
145
144
|
demanded: [],
|
|
146
145
|
optional: []
|
|
147
146
|
}
|
|
148
|
-
splitCommand.forEach(
|
|
149
|
-
|
|
147
|
+
splitCommand.forEach((cmd, i) => {
|
|
148
|
+
let variadic = false
|
|
150
149
|
cmd = cmd.replace(/\s/g, '')
|
|
151
150
|
if (/\.+[\]>]/.test(cmd) && i === splitCommand.length - 1) variadic = true
|
|
152
151
|
if (/^\[/.test(cmd)) {
|
|
153
152
|
parsedCommand.optional.push({
|
|
154
153
|
cmd: cmd.replace(bregex, '').split('|'),
|
|
155
|
-
variadic
|
|
154
|
+
variadic
|
|
156
155
|
})
|
|
157
156
|
} else {
|
|
158
157
|
parsedCommand.demanded.push({
|
|
159
158
|
cmd: cmd.replace(bregex, '').split('|'),
|
|
160
|
-
variadic
|
|
159
|
+
variadic
|
|
161
160
|
})
|
|
162
161
|
}
|
|
163
162
|
})
|
|
164
163
|
return parsedCommand
|
|
165
164
|
}
|
|
166
165
|
|
|
167
|
-
self.getCommands =
|
|
168
|
-
return Object.keys(handlers).concat(Object.keys(aliasMap))
|
|
169
|
-
}
|
|
166
|
+
self.getCommands = () => Object.keys(handlers).concat(Object.keys(aliasMap))
|
|
170
167
|
|
|
171
|
-
self.getCommandHandlers =
|
|
172
|
-
return handlers
|
|
173
|
-
}
|
|
168
|
+
self.getCommandHandlers = () => handlers
|
|
174
169
|
|
|
175
|
-
self.hasDefaultCommand =
|
|
176
|
-
return !!defaultCommand
|
|
177
|
-
}
|
|
170
|
+
self.hasDefaultCommand = () => !!defaultCommand
|
|
178
171
|
|
|
179
|
-
self.runCommand = function (command, yargs, parsed, commandIndex) {
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
172
|
+
self.runCommand = function runCommand (command, yargs, parsed, commandIndex) {
|
|
173
|
+
let aliases = parsed.aliases
|
|
174
|
+
const commandHandler = handlers[command] || handlers[aliasMap[command]] || defaultCommand
|
|
175
|
+
const currentContext = yargs.getContext()
|
|
176
|
+
let numFiles = currentContext.files.length
|
|
177
|
+
const parentCommands = currentContext.commands.slice()
|
|
185
178
|
|
|
186
179
|
// what does yargs look like after the buidler is run?
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
180
|
+
let innerArgv = parsed.argv
|
|
181
|
+
let innerYargs = null
|
|
182
|
+
let positionalMap = {}
|
|
190
183
|
|
|
191
184
|
if (command) currentContext.commands.push(command)
|
|
192
185
|
if (typeof commandHandler.builder === 'function') {
|
|
@@ -199,7 +192,7 @@ module.exports = function (yargs, usage, validation) {
|
|
|
199
192
|
// options object below.
|
|
200
193
|
if (yargs.parsed === false) {
|
|
201
194
|
if (typeof yargs.getUsageInstance().getUsage() === 'undefined') {
|
|
202
|
-
yargs.usage(
|
|
195
|
+
yargs.usage(`$0 ${parentCommands.length ? `${parentCommands.join(' ')} ` : ''}${commandHandler.original}`)
|
|
203
196
|
}
|
|
204
197
|
innerArgv = innerYargs ? innerYargs._parseArgs(null, null, true, commandIndex) : yargs._parseArgs(null, null, true, commandIndex)
|
|
205
198
|
} else {
|
|
@@ -212,8 +205,8 @@ module.exports = function (yargs, usage, validation) {
|
|
|
212
205
|
// as a short hand, an object can instead be provided, specifying
|
|
213
206
|
// the options that a command takes.
|
|
214
207
|
innerYargs = yargs.reset(parsed.aliases)
|
|
215
|
-
innerYargs.usage(
|
|
216
|
-
Object.keys(commandHandler.builder).forEach(
|
|
208
|
+
innerYargs.usage(`$0 ${parentCommands.length ? `${parentCommands.join(' ')} ` : ''}${commandHandler.original}`)
|
|
209
|
+
Object.keys(commandHandler.builder).forEach((key) => {
|
|
217
210
|
innerYargs.option(key, commandHandler.builder[key])
|
|
218
211
|
})
|
|
219
212
|
innerArgv = innerYargs._parseArgs(null, null, true, commandIndex)
|
|
@@ -244,19 +237,19 @@ module.exports = function (yargs, usage, validation) {
|
|
|
244
237
|
// onto argv.
|
|
245
238
|
function populatePositionals (commandHandler, argv, context, yargs) {
|
|
246
239
|
argv._ = argv._.slice(context.commands.length) // nuke the current commands
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
240
|
+
const demanded = commandHandler.demanded.slice(0)
|
|
241
|
+
const optional = commandHandler.optional.slice(0)
|
|
242
|
+
const positionalMap = {}
|
|
250
243
|
|
|
251
244
|
validation.positionalCount(demanded.length, argv._.length)
|
|
252
245
|
|
|
253
246
|
while (demanded.length) {
|
|
254
|
-
|
|
247
|
+
const demand = demanded.shift()
|
|
255
248
|
populatePositional(demand, argv, yargs, positionalMap)
|
|
256
249
|
}
|
|
257
250
|
|
|
258
251
|
while (optional.length) {
|
|
259
|
-
|
|
252
|
+
const maybe = optional.shift()
|
|
260
253
|
populatePositional(maybe, argv, yargs, positionalMap)
|
|
261
254
|
}
|
|
262
255
|
|
|
@@ -270,9 +263,9 @@ module.exports = function (yargs, usage, validation) {
|
|
|
270
263
|
// "positional" consists of the positional.cmd, an array representing
|
|
271
264
|
// the positional's name and aliases, and positional.variadic
|
|
272
265
|
// indicating whether or not it is a variadic array.
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
for (
|
|
266
|
+
let variadics = null
|
|
267
|
+
let value = null
|
|
268
|
+
for (let i = 0, cmd; (cmd = positional.cmd[i]) !== undefined; i++) {
|
|
276
269
|
if (positional.variadic) {
|
|
277
270
|
if (variadics) argv[cmd] = variadics.slice(0)
|
|
278
271
|
else argv[cmd] = variadics = argv._.splice(0)
|
|
@@ -289,7 +282,7 @@ module.exports = function (yargs, usage, validation) {
|
|
|
289
282
|
|
|
290
283
|
// TODO move positional arg logic to yargs-parser and remove this duplication
|
|
291
284
|
function postProcessPositional (yargs, argv, key) {
|
|
292
|
-
|
|
285
|
+
const coerce = yargs.getOptions().coerce[key]
|
|
293
286
|
if (typeof coerce === 'function') {
|
|
294
287
|
try {
|
|
295
288
|
argv[key] = coerce(argv[key])
|
|
@@ -307,7 +300,7 @@ module.exports = function (yargs, usage, validation) {
|
|
|
307
300
|
}
|
|
308
301
|
}
|
|
309
302
|
|
|
310
|
-
self.reset =
|
|
303
|
+
self.reset = () => {
|
|
311
304
|
handlers = {}
|
|
312
305
|
aliasMap = {}
|
|
313
306
|
defaultCommand = undefined
|
|
@@ -318,14 +311,14 @@ module.exports = function (yargs, usage, validation) {
|
|
|
318
311
|
// the state of commands such that
|
|
319
312
|
// we can apply .parse() multiple times
|
|
320
313
|
// with the same yargs instance.
|
|
321
|
-
|
|
322
|
-
self.freeze =
|
|
314
|
+
let frozen
|
|
315
|
+
self.freeze = () => {
|
|
323
316
|
frozen = {}
|
|
324
317
|
frozen.handlers = handlers
|
|
325
318
|
frozen.aliasMap = aliasMap
|
|
326
319
|
frozen.defaultCommand = defaultCommand
|
|
327
320
|
}
|
|
328
|
-
self.unfreeze =
|
|
321
|
+
self.unfreeze = () => {
|
|
329
322
|
handlers = frozen.handlers
|
|
330
323
|
aliasMap = frozen.aliasMap
|
|
331
324
|
defaultCommand = frozen.defaultCommand
|
package/lib/completion.js
CHANGED
|
@@ -1,16 +1,17 @@
|
|
|
1
|
+
'use strict'
|
|
1
2
|
const fs = require('fs')
|
|
2
3
|
const path = require('path')
|
|
3
4
|
|
|
4
5
|
// add bash completions to your
|
|
5
6
|
// yargs-powered applications.
|
|
6
|
-
module.exports = function (yargs, usage, command) {
|
|
7
|
+
module.exports = function completion (yargs, usage, command) {
|
|
7
8
|
const self = {
|
|
8
9
|
completionKey: 'get-yargs-completions'
|
|
9
10
|
}
|
|
10
11
|
|
|
11
12
|
// get a list of completion commands.
|
|
12
13
|
// 'args' is the array of strings from the line to be completed
|
|
13
|
-
self.getCompletion = function (args, done) {
|
|
14
|
+
self.getCompletion = function getCompletion (args, done) {
|
|
14
15
|
const completions = []
|
|
15
16
|
const current = args.length ? args[args.length - 1] : ''
|
|
16
17
|
const argv = yargs.parse(args, true)
|
|
@@ -20,14 +21,14 @@ module.exports = function (yargs, usage, command) {
|
|
|
20
21
|
// to completion().
|
|
21
22
|
if (completionFunction) {
|
|
22
23
|
if (completionFunction.length < 3) {
|
|
23
|
-
|
|
24
|
+
const result = completionFunction(current, argv)
|
|
24
25
|
|
|
25
26
|
// promise based completion function.
|
|
26
27
|
if (typeof result.then === 'function') {
|
|
27
|
-
return result.then(
|
|
28
|
-
process.nextTick(
|
|
29
|
-
}).catch(
|
|
30
|
-
process.nextTick(
|
|
28
|
+
return result.then((list) => {
|
|
29
|
+
process.nextTick(() => { done(list) })
|
|
30
|
+
}).catch((err) => {
|
|
31
|
+
process.nextTick(() => { throw err })
|
|
31
32
|
})
|
|
32
33
|
}
|
|
33
34
|
|
|
@@ -35,14 +36,14 @@ module.exports = function (yargs, usage, command) {
|
|
|
35
36
|
return done(result)
|
|
36
37
|
} else {
|
|
37
38
|
// asynchronous completion function
|
|
38
|
-
return completionFunction(current, argv,
|
|
39
|
+
return completionFunction(current, argv, (completions) => {
|
|
39
40
|
done(completions)
|
|
40
41
|
})
|
|
41
42
|
}
|
|
42
43
|
}
|
|
43
44
|
|
|
44
|
-
|
|
45
|
-
for (
|
|
45
|
+
const handlers = command.getCommandHandlers()
|
|
46
|
+
for (let i = 0, ii = args.length; i < ii; ++i) {
|
|
46
47
|
if (handlers[args[i]] && handlers[args[i]].builder) {
|
|
47
48
|
const builder = handlers[args[i]].builder
|
|
48
49
|
if (typeof builder === 'function') {
|
|
@@ -54,22 +55,21 @@ module.exports = function (yargs, usage, command) {
|
|
|
54
55
|
}
|
|
55
56
|
|
|
56
57
|
if (!current.match(/^-/)) {
|
|
57
|
-
usage.getCommands().forEach(
|
|
58
|
-
|
|
59
|
-
|
|
58
|
+
usage.getCommands().forEach((usageCommand) => {
|
|
59
|
+
const commandName = command.parseCommand(usageCommand[0]).cmd
|
|
60
|
+
if (args.indexOf(commandName) === -1) {
|
|
61
|
+
completions.push(commandName)
|
|
60
62
|
}
|
|
61
63
|
})
|
|
62
64
|
}
|
|
63
65
|
|
|
64
66
|
if (current.match(/^-/)) {
|
|
65
|
-
Object.keys(yargs.getOptions().key).forEach(
|
|
67
|
+
Object.keys(yargs.getOptions().key).forEach((key) => {
|
|
66
68
|
// If the key and its aliases aren't in 'args', add the key to 'completions'
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
return args.indexOf('--' + val) === -1
|
|
70
|
-
})
|
|
69
|
+
const keyAndAliases = [key].concat(aliases[key] || [])
|
|
70
|
+
const notInArgs = keyAndAliases.every(val => args.indexOf(`--${val}`) === -1)
|
|
71
71
|
if (notInArgs) {
|
|
72
|
-
completions.push(
|
|
72
|
+
completions.push(`--${key}`)
|
|
73
73
|
}
|
|
74
74
|
})
|
|
75
75
|
}
|
|
@@ -78,15 +78,15 @@ module.exports = function (yargs, usage, command) {
|
|
|
78
78
|
}
|
|
79
79
|
|
|
80
80
|
// generate the completion script to add to your .bashrc.
|
|
81
|
-
self.generateCompletionScript = function ($0) {
|
|
82
|
-
|
|
81
|
+
self.generateCompletionScript = function generateCompletionScript ($0) {
|
|
82
|
+
let script = fs.readFileSync(
|
|
83
83
|
path.resolve(__dirname, '../completion.sh.hbs'),
|
|
84
84
|
'utf-8'
|
|
85
85
|
)
|
|
86
|
-
|
|
86
|
+
const name = path.basename($0)
|
|
87
87
|
|
|
88
88
|
// add ./to applications not yet installed as bin.
|
|
89
|
-
if ($0.match(/\.js$/)) $0 =
|
|
89
|
+
if ($0.match(/\.js$/)) $0 = `./${$0}`
|
|
90
90
|
|
|
91
91
|
script = script.replace(/{{app_name}}/g, name)
|
|
92
92
|
return script.replace(/{{app_path}}/g, $0)
|
|
@@ -95,8 +95,8 @@ module.exports = function (yargs, usage, command) {
|
|
|
95
95
|
// register a function to perform your own custom
|
|
96
96
|
// completions., this function can be either
|
|
97
97
|
// synchrnous or asynchronous.
|
|
98
|
-
|
|
99
|
-
self.registerFunction =
|
|
98
|
+
let completionFunction = null
|
|
99
|
+
self.registerFunction = (fn) => {
|
|
100
100
|
completionFunction = fn
|
|
101
101
|
}
|
|
102
102
|
|
package/lib/levenshtein.js
CHANGED
|
@@ -10,22 +10,22 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
|
|
|
10
10
|
|
|
11
11
|
// levenshtein distance algorithm, pulled from Andrei Mackenzie's MIT licensed.
|
|
12
12
|
// gist, which can be found here: https://gist.github.com/andrei-m/982927
|
|
13
|
-
|
|
13
|
+
'use strict'
|
|
14
14
|
// Compute the edit distance between the two given strings
|
|
15
|
-
module.exports = function (a, b) {
|
|
15
|
+
module.exports = function levenshtein (a, b) {
|
|
16
16
|
if (a.length === 0) return b.length
|
|
17
17
|
if (b.length === 0) return a.length
|
|
18
18
|
|
|
19
|
-
|
|
19
|
+
const matrix = []
|
|
20
20
|
|
|
21
21
|
// increment along the first column of each row
|
|
22
|
-
|
|
22
|
+
let i
|
|
23
23
|
for (i = 0; i <= b.length; i++) {
|
|
24
24
|
matrix[i] = [i]
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
// increment each column in the first row
|
|
28
|
-
|
|
28
|
+
let j
|
|
29
29
|
for (j = 0; j <= a.length; j++) {
|
|
30
30
|
matrix[0][j] = j
|
|
31
31
|
}
|
package/lib/obj-filter.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
|
|
1
|
+
'use strict'
|
|
2
|
+
module.exports = function objFilter (original, filter) {
|
|
2
3
|
const obj = {}
|
|
3
|
-
filter = filter ||
|
|
4
|
-
Object.keys(original || {}).forEach(
|
|
4
|
+
filter = filter || ((k, v) => true)
|
|
5
|
+
Object.keys(original || {}).forEach((key) => {
|
|
5
6
|
if (filter(key, original[key])) {
|
|
6
7
|
obj[key] = original[key]
|
|
7
8
|
}
|