@trenskow/arguments-parser 0.3.130 → 0.3.133
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -28
- package/index.js +23 -2
- package/lib/autocomplete/bash.js +15 -3
- package/lib/autocomplete/index.js +85 -49
- package/lib/autocomplete/zsh.js +20 -1
- package/lib/index.js +3 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -80,40 +80,20 @@ Options:
|
|
|
80
80
|
|
|
81
81
|
> The validation schema is described in package [isvalid](https://github.com/trenskow/isvalid).
|
|
82
82
|
|
|
83
|
-
##
|
|
83
|
+
## Autocompletion
|
|
84
84
|
|
|
85
|
-
|
|
85
|
+
The library supports Bash and ZSH autocompletion out of the box.
|
|
86
86
|
|
|
87
|
-
|
|
87
|
+
To generate the completion scripts to install for the current shell - use the command below...
|
|
88
88
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
The completion script for Bash should be installed as below.
|
|
92
|
-
|
|
93
|
-
````bash
|
|
94
|
-
_my_script() {
|
|
95
|
-
eval "$(AUTOCOMPLETE=bash my_script "${COMP_WORDS[@]}")"
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
complete -F _my_script my_script
|
|
89
|
+
````
|
|
90
|
+
./my_script _completion
|
|
99
91
|
````
|
|
100
92
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
The completion script for ZSH should be installed as below.
|
|
104
|
-
|
|
105
|
-
````zsh
|
|
106
|
-
#compdef my_script
|
|
107
|
-
|
|
108
|
-
_my_script() {
|
|
109
|
-
|
|
110
|
-
local -a completions
|
|
111
|
-
|
|
112
|
-
eval "$(AUTOCOMPLETE=zsh my_script ${words[@]})"
|
|
113
|
-
|
|
114
|
-
}
|
|
93
|
+
...or if you need to generate for another shell than the current one.
|
|
115
94
|
|
|
116
|
-
|
|
95
|
+
````
|
|
96
|
+
./my_script _completion [bash|zsh]
|
|
117
97
|
````
|
|
118
98
|
|
|
119
99
|
# License
|
package/index.js
CHANGED
|
@@ -6,7 +6,14 @@
|
|
|
6
6
|
// See license in LICENSE.
|
|
7
7
|
//
|
|
8
8
|
|
|
9
|
-
import {
|
|
9
|
+
import {
|
|
10
|
+
basename,
|
|
11
|
+
extname
|
|
12
|
+
} from 'path';
|
|
13
|
+
|
|
14
|
+
import {
|
|
15
|
+
plugins
|
|
16
|
+
} from 'isvalid';
|
|
10
17
|
|
|
11
18
|
import argumentsParser from './lib/index.js';
|
|
12
19
|
import autocomplete from './lib/autocomplete/index.js';
|
|
@@ -65,4 +72,18 @@ plugins.use('argumentsParser.autocomplete', () => ({
|
|
|
65
72
|
}
|
|
66
73
|
}));
|
|
67
74
|
|
|
68
|
-
|
|
75
|
+
if (process.argv[2] === '_completion') {
|
|
76
|
+
|
|
77
|
+
const path = process.env.COMPLETION_PATH || process.argv[1];
|
|
78
|
+
|
|
79
|
+
autocomplete.script({
|
|
80
|
+
shell: process.argv[3],
|
|
81
|
+
command: basename(path)
|
|
82
|
+
.slice(0, -extname(path).length)
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
process.exit(0);
|
|
86
|
+
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export default typeof process.env.AUTOCOMPLETE_INDEX !== 'undefined' ? autocomplete() : argumentsParser;
|
package/lib/autocomplete/bash.js
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
// See license in LICENSE.
|
|
7
7
|
//
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
const bash = (items) => {
|
|
10
10
|
|
|
11
11
|
const keys = Object.keys(items);
|
|
12
12
|
|
|
@@ -52,13 +52,25 @@ export default (items) => {
|
|
|
52
52
|
});
|
|
53
53
|
|
|
54
54
|
process.stdout.write(')\n');
|
|
55
|
-
|
|
55
|
+
|
|
56
56
|
}
|
|
57
57
|
|
|
58
58
|
if (files) {
|
|
59
|
-
process.stdout.write('COMPREPLY+=($(compgen -f -- "${COMP_WORDS[COMP_CWORD]}"))\n');
|
|
59
|
+
process.stdout.write('COMPREPLY+=($(compgen -f -- "${COMP_WORDS[COMP_CWORD]}"))\n');
|
|
60
60
|
}
|
|
61
61
|
|
|
62
62
|
process.exit(0);
|
|
63
63
|
|
|
64
64
|
};
|
|
65
|
+
|
|
66
|
+
bash.script = ({
|
|
67
|
+
command
|
|
68
|
+
}) => `_${command}() {
|
|
69
|
+
eval "$(AUTOCOMPLETE_INDEX=$COMP_CWORD ${command} "\${COMP_WORDS[@]}")"
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
complete -F _${command} ${command}`;
|
|
73
|
+
|
|
74
|
+
bash.autocompleteIndexOffset = 1;
|
|
75
|
+
|
|
76
|
+
export default bash;
|
|
@@ -25,14 +25,14 @@ const supported = {
|
|
|
25
25
|
zsh
|
|
26
26
|
};
|
|
27
27
|
|
|
28
|
-
const argumentsParser = (
|
|
28
|
+
const argumentsParser = () => {
|
|
29
29
|
|
|
30
|
-
|
|
30
|
+
const currentShell = basename(process.env.SHELL || '');
|
|
31
31
|
|
|
32
|
-
|
|
32
|
+
const writer = supported[currentShell];
|
|
33
33
|
|
|
34
|
-
if (!
|
|
35
|
-
process.stderr.write(`Unsupported shell: ${
|
|
34
|
+
if (!writer) {
|
|
35
|
+
process.stderr.write(`Unsupported shell: ${currentShell}\n`);
|
|
36
36
|
process.exit(1);
|
|
37
37
|
}
|
|
38
38
|
|
|
@@ -64,7 +64,7 @@ const argumentsParser = (shell) => {
|
|
|
64
64
|
});
|
|
65
65
|
};
|
|
66
66
|
|
|
67
|
-
const output = (items) =>
|
|
67
|
+
const output = (items) => writer(
|
|
68
68
|
normalize(items)
|
|
69
69
|
.reduce((grouped, item) => {
|
|
70
70
|
|
|
@@ -85,7 +85,7 @@ const argumentsParser = (shell) => {
|
|
|
85
85
|
|
|
86
86
|
const argumentsParser = (
|
|
87
87
|
{
|
|
88
|
-
args = process.argv.slice(
|
|
88
|
+
args = process.argv.slice(3),
|
|
89
89
|
argvLevel = 0,
|
|
90
90
|
placeholder = '<>',
|
|
91
91
|
command,
|
|
@@ -100,6 +100,10 @@ const argumentsParser = (shell) => {
|
|
|
100
100
|
} = {}
|
|
101
101
|
) => {
|
|
102
102
|
|
|
103
|
+
let autocompleteIndex = process.env.AUTOCOMPLETE_INDEX;
|
|
104
|
+
|
|
105
|
+
autocompleteIndex = parseInt(autocompleteIndex) - argvLevel - writer.autocompleteIndexOffset;
|
|
106
|
+
|
|
103
107
|
const base = `${process.argv.slice(1, argvLevel + 2).map(((arg) => basename(arg))).join(' ')}`;
|
|
104
108
|
|
|
105
109
|
const next = async (identifier, command) => {
|
|
@@ -114,7 +118,8 @@ const argumentsParser = (shell) => {
|
|
|
114
118
|
placeholder,
|
|
115
119
|
command: command,
|
|
116
120
|
options,
|
|
117
|
-
parameters
|
|
121
|
+
parameters,
|
|
122
|
+
autocompleteIndex: autocompleteIndex - 1
|
|
118
123
|
}),
|
|
119
124
|
parameters
|
|
120
125
|
});
|
|
@@ -129,6 +134,18 @@ const argumentsParser = (shell) => {
|
|
|
129
134
|
|
|
130
135
|
const tool = caseit(args[0] || '');
|
|
131
136
|
|
|
137
|
+
if (autocompleteIndex === 0) {
|
|
138
|
+
|
|
139
|
+
return output(Object.keys(commands)
|
|
140
|
+
.filter((command) => command.startsWith(tool))
|
|
141
|
+
.map((command) => ({
|
|
142
|
+
type: 'command',
|
|
143
|
+
argument: caseit(command, 'kebab'),
|
|
144
|
+
description: commands[command].description
|
|
145
|
+
})));
|
|
146
|
+
|
|
147
|
+
}
|
|
148
|
+
|
|
132
149
|
if (commands[tool]) {
|
|
133
150
|
|
|
134
151
|
onCommand?.(tool, args.slice(1));
|
|
@@ -139,13 +156,7 @@ const argumentsParser = (shell) => {
|
|
|
139
156
|
|
|
140
157
|
}
|
|
141
158
|
|
|
142
|
-
|
|
143
|
-
.filter((command) => command.startsWith(tool))
|
|
144
|
-
.map((command) => ({
|
|
145
|
-
type: 'command',
|
|
146
|
-
argument: caseit(command, 'kebab'),
|
|
147
|
-
description: commands[command].description
|
|
148
|
-
})));
|
|
159
|
+
process.exit(0);
|
|
149
160
|
|
|
150
161
|
},
|
|
151
162
|
parameter: async ({
|
|
@@ -153,10 +164,10 @@ const argumentsParser = (shell) => {
|
|
|
153
164
|
autocomplete
|
|
154
165
|
}, command) => {
|
|
155
166
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
167
|
+
if (autocompleteIndex === 0) {
|
|
168
|
+
return output(
|
|
169
|
+
filter(
|
|
170
|
+
await autocomplete?.(args[0] || '') || [], args[0]));
|
|
160
171
|
}
|
|
161
172
|
|
|
162
173
|
parameters[identifier] = args[0];
|
|
@@ -203,6 +214,10 @@ const argumentsParser = (shell) => {
|
|
|
203
214
|
}]
|
|
204
215
|
} = options.validationOptions;
|
|
205
216
|
|
|
217
|
+
const variadicOnly = args
|
|
218
|
+
.slice(0, autocompleteIndex)
|
|
219
|
+
.some((arg) => arg === '--');
|
|
220
|
+
|
|
206
221
|
const allKeyPaths = keyPaths(options.schema)
|
|
207
222
|
.all()
|
|
208
223
|
.filter((keyPath) => keyPath);
|
|
@@ -221,7 +236,7 @@ const argumentsParser = (shell) => {
|
|
|
221
236
|
|
|
222
237
|
key = caseit(key);
|
|
223
238
|
|
|
224
|
-
if (schemas[idx]) {
|
|
239
|
+
if (!variadicOnly && schemas[idx]) {
|
|
225
240
|
|
|
226
241
|
if (schemas[idx].enum) {
|
|
227
242
|
return Object.keys(schemas[idx].enum)
|
|
@@ -244,36 +259,46 @@ const argumentsParser = (shell) => {
|
|
|
244
259
|
|
|
245
260
|
let items = [];
|
|
246
261
|
|
|
247
|
-
if (
|
|
262
|
+
if (variadic === 'allow') {
|
|
263
|
+
items = items.concat(
|
|
264
|
+
filter(await autocomplete?.(current) || [], current));
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
if (!variadicOnly) {
|
|
268
|
+
|
|
269
|
+
if (!current.startsWith('--')) {
|
|
270
|
+
|
|
271
|
+
items = items.concat(
|
|
272
|
+
allKeyPaths
|
|
273
|
+
.filter((keyPath) => !spent.includes(keyPath))
|
|
274
|
+
.filter((keyPath) => key !== keyPath && keyPath.startsWith(key) && keyPaths(options.schema).get(keyPath).short)
|
|
275
|
+
.map((keyPath) => ({
|
|
276
|
+
type: 'option',
|
|
277
|
+
argument: `-${caseit(keyPaths(options.schema).get(keyPath).short, 'kebab')}`,
|
|
278
|
+
description: keyPaths(options.schema).get(keyPath).description
|
|
279
|
+
})));
|
|
248
280
|
|
|
249
|
-
if (!current.startsWith('-')) {
|
|
250
|
-
if (variadic === 'allow') {
|
|
251
|
-
items = items.concat(
|
|
252
|
-
filter(await autocomplete?.(current) || [], current));
|
|
253
|
-
}
|
|
254
281
|
}
|
|
255
282
|
|
|
283
|
+
|
|
256
284
|
items = items.concat(
|
|
257
285
|
allKeyPaths
|
|
258
286
|
.filter((keyPath) => !spent.includes(keyPath))
|
|
259
|
-
.filter((keyPath) => key !== keyPath && keyPath.startsWith(key)
|
|
287
|
+
.filter((keyPath) => key !== keyPath && keyPath.startsWith(key))
|
|
260
288
|
.map((keyPath) => ({
|
|
261
289
|
type: 'option',
|
|
262
|
-
argument:
|
|
290
|
+
argument: `--${caseit(keyPath, 'kebab')}`,
|
|
263
291
|
description: keyPaths(options.schema).get(keyPath).description
|
|
264
292
|
})));
|
|
265
293
|
|
|
266
294
|
}
|
|
267
295
|
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
.
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
argument: `--${caseit(keyPath, 'kebab')}`,
|
|
275
|
-
description: keyPaths(options.schema).get(keyPath).description
|
|
276
|
-
})));
|
|
296
|
+
if (variadic === 'allow' && !variadicOnly && current === Array(current.length).fill('-').join('')) {
|
|
297
|
+
items = items.concat([{
|
|
298
|
+
type: 'option',
|
|
299
|
+
argument: '--'.slice(0, -current.length)
|
|
300
|
+
}]);
|
|
301
|
+
}
|
|
277
302
|
|
|
278
303
|
return items;
|
|
279
304
|
|
|
@@ -286,13 +311,12 @@ const argumentsParser = (shell) => {
|
|
|
286
311
|
await complete(-1));
|
|
287
312
|
}
|
|
288
313
|
|
|
289
|
-
for (idx = 0; idx < args.length; idx++) {
|
|
314
|
+
for (idx = 0; idx < autocompleteIndex || idx < args.length; idx++) {
|
|
290
315
|
|
|
291
316
|
if (!schemas[idx]) {
|
|
292
317
|
|
|
293
|
-
if (!args[idx].startsWith('-')) {
|
|
294
|
-
|
|
295
|
-
await complete(idx, args[idx]));
|
|
318
|
+
if (variadicOnly || !args[idx].startsWith('-')) {
|
|
319
|
+
continue;
|
|
296
320
|
}
|
|
297
321
|
|
|
298
322
|
const [keyPath, schema] = allKeyPaths
|
|
@@ -312,15 +336,8 @@ const argumentsParser = (shell) => {
|
|
|
312
336
|
|
|
313
337
|
}
|
|
314
338
|
|
|
315
|
-
const current = await complete(idx - 1, args[idx - 1]);
|
|
316
|
-
|
|
317
|
-
if (current.length) {
|
|
318
|
-
return output(current);
|
|
319
|
-
}
|
|
320
|
-
|
|
321
339
|
return output(
|
|
322
|
-
await complete(
|
|
323
|
-
|
|
340
|
+
await complete(autocompleteIndex));
|
|
324
341
|
|
|
325
342
|
})().then(...resultArguments);
|
|
326
343
|
}
|
|
@@ -334,4 +351,23 @@ const argumentsParser = (shell) => {
|
|
|
334
351
|
|
|
335
352
|
};
|
|
336
353
|
|
|
354
|
+
argumentsParser.script = ({
|
|
355
|
+
shell = currentShell,
|
|
356
|
+
command
|
|
357
|
+
}) => {
|
|
358
|
+
|
|
359
|
+
const writer = supported[shell || currentShell];
|
|
360
|
+
|
|
361
|
+
if (!writer) {
|
|
362
|
+
process.stderr.write(`Unsupported shell: ${shell}\n`);
|
|
363
|
+
process.exit(1);
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
process.stdout.write(
|
|
367
|
+
writer.script({
|
|
368
|
+
command
|
|
369
|
+
}));
|
|
370
|
+
|
|
371
|
+
};
|
|
372
|
+
|
|
337
373
|
export default argumentsParser;
|
package/lib/autocomplete/zsh.js
CHANGED
|
@@ -6,7 +6,12 @@
|
|
|
6
6
|
// See license in LICENSE.
|
|
7
7
|
//
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
import {
|
|
10
|
+
basename,
|
|
11
|
+
extname
|
|
12
|
+
} from 'path';
|
|
13
|
+
|
|
14
|
+
const zsh = (items) => {
|
|
10
15
|
|
|
11
16
|
const keys = Object.keys(items);
|
|
12
17
|
|
|
@@ -49,3 +54,17 @@ export default (items) => {
|
|
|
49
54
|
process.exit(0);
|
|
50
55
|
|
|
51
56
|
};
|
|
57
|
+
|
|
58
|
+
zsh.script = ({
|
|
59
|
+
command
|
|
60
|
+
}) => `#compdef ${command}
|
|
61
|
+
|
|
62
|
+
_${command}() {
|
|
63
|
+
eval "$(AUTOCOMPLETE_INDEX=$CURRENT ${command} "\${words[@]}")"
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
_${command}`;
|
|
67
|
+
|
|
68
|
+
zsh.autocompleteIndexOffset = 2;
|
|
69
|
+
|
|
70
|
+
export default zsh;
|
package/lib/index.js
CHANGED