@trenskow/arguments-parser 0.3.129 → 0.3.132

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 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
- ## Autocomplete
83
+ ## Autocompletion
84
84
 
85
- This supports Bash and ZSH autocomplete of the box.
85
+ The library supports Bash and ZSH autocompletion out of the box.
86
86
 
87
- > In both examples below replace `my_script` with the actual name of the script.
87
+ To generate the completion scripts to install for the current shell - use the command below...
88
88
 
89
- ### Bash
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
- #### ZSH
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
- _my_script
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 { plugins } from 'isvalid';
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
 
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
+
68
89
  export default autocomplete(process.env.AUTOCOMPLETE) || argumentsParser;
@@ -6,7 +6,7 @@
6
6
  // See license in LICENSE.
7
7
  //
8
8
 
9
- export default (items) => {
9
+ const bash = (items) => {
10
10
 
11
11
  const keys = Object.keys(items);
12
12
 
@@ -52,13 +52,23 @@ 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=bash AUTOCOMPLETE_CURRENT=$COMP_CWORD ${command} "\${COMP_WORDS[@]}")"
70
+ }
71
+
72
+ complete -F _${command} ${command}`;
73
+
74
+ export default bash;
@@ -25,13 +25,15 @@ const supported = {
25
25
  zsh
26
26
  };
27
27
 
28
+ const currentShell = basename(process.env.SHELL || '');
29
+
28
30
  const argumentsParser = (shell) => {
29
31
 
30
- if (!shell) return;
32
+ if (typeof shell === 'undefined') return;
31
33
 
32
- shell = supported[shell];
34
+ const writer = supported[shell || currentShell];
33
35
 
34
- if (!shell) {
36
+ if (!writer) {
35
37
  process.stderr.write(`Unsupported shell: ${shell}\n`);
36
38
  process.exit(1);
37
39
  }
@@ -64,7 +66,7 @@ const argumentsParser = (shell) => {
64
66
  });
65
67
  };
66
68
 
67
- const output = (items) => shell(
69
+ const output = (items) => writer(
68
70
  normalize(items)
69
71
  .reduce((grouped, item) => {
70
72
 
@@ -85,7 +87,7 @@ const argumentsParser = (shell) => {
85
87
 
86
88
  const argumentsParser = (
87
89
  {
88
- args = process.argv.slice(shell.argsOffset || 3),
90
+ args = process.argv.slice(3),
89
91
  argvLevel = 0,
90
92
  placeholder = '<>',
91
93
  command,
@@ -96,7 +98,8 @@ const argumentsParser = (shell) => {
96
98
  data: {},
97
99
  validationOptions: {}
98
100
  },
99
- parameters = {}
101
+ parameters = {},
102
+ autocompleteIndex = (process.env.AUTOCOMPLETE_INDEX || 2) - 2
100
103
  } = {}
101
104
  ) => {
102
105
 
@@ -114,7 +117,8 @@ const argumentsParser = (shell) => {
114
117
  placeholder,
115
118
  command: command,
116
119
  options,
117
- parameters
120
+ parameters,
121
+ autocompleteIndex: autocompleteIndex - 1
118
122
  }),
119
123
  parameters
120
124
  });
@@ -129,6 +133,18 @@ const argumentsParser = (shell) => {
129
133
 
130
134
  const tool = caseit(args[0] || '');
131
135
 
136
+ if (autocompleteIndex === 0) {
137
+
138
+ return output(Object.keys(commands)
139
+ .filter((command) => command.startsWith(tool))
140
+ .map((command) => ({
141
+ type: 'command',
142
+ argument: caseit(command, 'kebab'),
143
+ description: commands[command].description
144
+ })));
145
+
146
+ }
147
+
132
148
  if (commands[tool]) {
133
149
 
134
150
  onCommand?.(tool, args.slice(1));
@@ -139,13 +155,7 @@ const argumentsParser = (shell) => {
139
155
 
140
156
  }
141
157
 
142
- return output(Object.keys(commands)
143
- .filter((command) => command.startsWith(tool))
144
- .map((command) => ({
145
- type: 'command',
146
- argument: caseit(command, 'kebab'),
147
- description: commands[command].description
148
- })));
158
+ process.exit(0);
149
159
 
150
160
  },
151
161
  parameter: async ({
@@ -153,10 +163,10 @@ const argumentsParser = (shell) => {
153
163
  autocomplete
154
164
  }, command) => {
155
165
 
156
- const available = filter(await autocomplete?.(args[0] || '') || [], args[0]);
157
-
158
- if (available.length) {
159
- return output(available);
166
+ if (autocompleteIndex === 0) {
167
+ return output(
168
+ filter(
169
+ await autocomplete?.(args[0] || '') || [], args[0]));
160
170
  }
161
171
 
162
172
  parameters[identifier] = args[0];
@@ -203,6 +213,10 @@ const argumentsParser = (shell) => {
203
213
  }]
204
214
  } = options.validationOptions;
205
215
 
216
+ const variadicOnly = args
217
+ .slice(0, autocompleteIndex)
218
+ .some((arg) => arg === '--');
219
+
206
220
  const allKeyPaths = keyPaths(options.schema)
207
221
  .all()
208
222
  .filter((keyPath) => keyPath);
@@ -221,7 +235,7 @@ const argumentsParser = (shell) => {
221
235
 
222
236
  key = caseit(key);
223
237
 
224
- if (schemas[idx]) {
238
+ if (!variadicOnly && schemas[idx]) {
225
239
 
226
240
  if (schemas[idx].enum) {
227
241
  return Object.keys(schemas[idx].enum)
@@ -244,36 +258,46 @@ const argumentsParser = (shell) => {
244
258
 
245
259
  let items = [];
246
260
 
247
- if (!current.startsWith('--')) {
261
+ if (variadic === 'allow') {
262
+ items = items.concat(
263
+ filter(await autocomplete?.(current) || [], current));
264
+ }
265
+
266
+ if (!variadicOnly) {
267
+
268
+ if (!current.startsWith('--')) {
269
+
270
+ items = items.concat(
271
+ allKeyPaths
272
+ .filter((keyPath) => !spent.includes(keyPath))
273
+ .filter((keyPath) => key !== keyPath && keyPath.startsWith(key) && keyPaths(options.schema).get(keyPath).short)
274
+ .map((keyPath) => ({
275
+ type: 'option',
276
+ argument: `-${caseit(keyPaths(options.schema).get(keyPath).short, 'kebab')}`,
277
+ description: keyPaths(options.schema).get(keyPath).description
278
+ })));
248
279
 
249
- if (!current.startsWith('-')) {
250
- if (variadic === 'allow') {
251
- items = items.concat(
252
- filter(await autocomplete?.(current) || [], current));
253
- }
254
280
  }
255
281
 
282
+
256
283
  items = items.concat(
257
284
  allKeyPaths
258
285
  .filter((keyPath) => !spent.includes(keyPath))
259
- .filter((keyPath) => key !== keyPath && keyPath.startsWith(key) && keyPaths(options.schema).get(keyPath).short)
286
+ .filter((keyPath) => key !== keyPath && keyPath.startsWith(key))
260
287
  .map((keyPath) => ({
261
288
  type: 'option',
262
- argument: `-${caseit(keyPaths(options.schema).get(keyPath).short, 'kebab')}`,
289
+ argument: `--${caseit(keyPath, 'kebab')}`,
263
290
  description: keyPaths(options.schema).get(keyPath).description
264
291
  })));
265
292
 
266
293
  }
267
294
 
268
- items = items.concat(
269
- allKeyPaths
270
- .filter((keyPath) => !spent.includes(keyPath))
271
- .filter((keyPath) => key !== keyPath && keyPath.startsWith(key))
272
- .map((keyPath) => ({
273
- type: 'option',
274
- argument: `--${caseit(keyPath, 'kebab')}`,
275
- description: keyPaths(options.schema).get(keyPath).description
276
- })));
295
+ if (variadic === 'allow' && !variadicOnly && current === Array(current.length).fill('-').join('')) {
296
+ items = items.concat([{
297
+ type: 'option',
298
+ argument: '--'.slice(0, -current.length)
299
+ }]);
300
+ }
277
301
 
278
302
  return items;
279
303
 
@@ -286,13 +310,12 @@ const argumentsParser = (shell) => {
286
310
  await complete(-1));
287
311
  }
288
312
 
289
- for (idx = 0; idx < args.length; idx++) {
313
+ for (idx = 0; idx < autocompleteIndex || idx < args.length; idx++) {
290
314
 
291
315
  if (!schemas[idx]) {
292
316
 
293
- if (!args[idx].startsWith('-')) {
294
- return output(
295
- await complete(idx, args[idx]));
317
+ if (variadicOnly || !args[idx].startsWith('-')) {
318
+ continue;
296
319
  }
297
320
 
298
321
  const [keyPath, schema] = allKeyPaths
@@ -312,15 +335,8 @@ const argumentsParser = (shell) => {
312
335
 
313
336
  }
314
337
 
315
- const current = await complete(idx - 1, args[idx - 1]);
316
-
317
- if (current.length) {
318
- return output(current);
319
- }
320
-
321
338
  return output(
322
- await complete(idx));
323
-
339
+ await complete(autocompleteIndex));
324
340
 
325
341
  })().then(...resultArguments);
326
342
  }
@@ -334,4 +350,23 @@ const argumentsParser = (shell) => {
334
350
 
335
351
  };
336
352
 
353
+ argumentsParser.script = ({
354
+ shell = currentShell,
355
+ command
356
+ }) => {
357
+
358
+ const writer = supported[shell || currentShell];
359
+
360
+ if (!writer) {
361
+ process.stderr.write(`Unsupported shell: ${shell}\n`);
362
+ process.exit(1);
363
+ }
364
+
365
+ process.stdout.write(
366
+ writer.script({
367
+ command
368
+ }));
369
+
370
+ };
371
+
337
372
  export default argumentsParser;
@@ -6,7 +6,12 @@
6
6
  // See license in LICENSE.
7
7
  //
8
8
 
9
- export default (items) => {
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,15 @@ 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=zsh AUTOCOMPLETE_CURRENT=$CURRENT ${command} "\${words[@]}")"
64
+ }
65
+
66
+ _${command}`;
67
+
68
+ export default zsh;
package/lib/index.js CHANGED
@@ -6,7 +6,9 @@
6
6
  // See license in LICENSE.
7
7
  //
8
8
 
9
- import { basename } from 'path';
9
+ import {
10
+ basename
11
+ } from 'path';
10
12
 
11
13
  import caseit from '@trenskow/caseit';
12
14
  import { default as isvalid, merge, keyPaths } from 'isvalid';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@trenskow/arguments-parser",
3
- "version": "0.3.129",
3
+ "version": "0.3.132",
4
4
  "description": "Yet another arguments parser.",
5
5
  "main": "index.js",
6
6
  "type": "module",
@@ -25,7 +25,7 @@
25
25
  "homepage": "https://github.com/trenskow/arguments-parser#readme",
26
26
  "dependencies": {
27
27
  "@trenskow/caseit": "^1.4.30",
28
- "@trenskow/parallel": "^0.1.135",
28
+ "@trenskow/parallel": "^0.1.136",
29
29
  "@trenskow/print": "^0.1.74",
30
30
  "isvalid": "^5.0.21"
31
31
  },