@trenskow/arguments-parser 0.3.120 → 0.3.122

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.
@@ -17,23 +17,73 @@ import {
17
17
 
18
18
  import caseit from '@trenskow/caseit';
19
19
 
20
- import buildIns from './build-ins/index.js';
21
-
22
20
  import zsh from './zsh.js';
23
21
 
24
22
  const supported = {
25
23
  zsh
26
24
  };
27
25
 
28
- const argumentsParser = (output) => {
26
+ const argumentsParser = (shell) => {
27
+
28
+ if (!shell) return;
29
+
30
+ shell = supported[shell];
31
+
32
+ if (!shell) {
33
+ process.stderr.write(`Unsupported shell: ${shell}\n`);
34
+ process.exit(1);
35
+ }
36
+
37
+ const normalize = (items) => items
38
+ .map((item) => {
39
+
40
+ if (typeof item === 'string') {
41
+ return {
42
+ type: 'option',
43
+ argument: item
44
+ };
45
+ }
46
+
47
+ return item;
48
+
49
+ });
50
+
51
+ const filter = (items, current) => {
52
+ return normalize(items)
53
+ .filter((item) => {
54
+ switch (item.type) {
55
+ case 'option':
56
+ // fall through
57
+ case 'command':
58
+ return item.argument !== current && item.argument.startsWith(current);
59
+ default:
60
+ return true;
61
+ }
62
+ });
63
+ };
64
+
65
+ const output = (items) => shell(
66
+ normalize(items)
67
+ .reduce((grouped, item) => {
68
+
69
+ grouped[item.type] = grouped[item.type] || [];
70
+
71
+ switch (item.type) {
72
+ case 'option':
73
+ // fall through
74
+ case 'command':
75
+ grouped[item.type].push(item);
76
+ break;
77
+ default:
78
+ }
29
79
 
30
- output = supported[output];
80
+ return grouped;
31
81
 
32
- if (!output) return undefined;
82
+ }, {}));
33
83
 
34
84
  const argumentsParser = (
35
85
  {
36
- args = process.argv.slice(output.argsOffset || 2),
86
+ args = process.argv.slice(shell.argsOffset || 2),
37
87
  argvLevel = 0,
38
88
  placeholder = '<>',
39
89
  command,
@@ -90,7 +140,8 @@ const argumentsParser = (output) => {
90
140
  return output(Object.keys(commands)
91
141
  .filter((command) => command.startsWith(tool))
92
142
  .map((command) => ({
93
- command: caseit(command, 'kebab'),
143
+ type: 'command',
144
+ argument: caseit(command, 'kebab'),
94
145
  description: commands[command].description
95
146
  })));
96
147
 
@@ -100,8 +151,7 @@ const argumentsParser = (output) => {
100
151
  autocomplete
101
152
  }, command) => {
102
153
 
103
- const available = (await autocomplete?.(args[0] || '') || [])
104
- .filter((item) => item !== args[0] && item.startsWith(args[0] || ''));
154
+ const available = filter(await autocomplete?.(args[0] || '') || []);
105
155
 
106
156
  if (available.length) {
107
157
  return output(available);
@@ -146,7 +196,9 @@ const argumentsParser = (output) => {
146
196
 
147
197
  const {
148
198
  variadic,
149
- autocomplete = buildIns.files
199
+ autocomplete = () => [{
200
+ type: 'files'
201
+ }]
150
202
  } = options.validationOptions;
151
203
 
152
204
  const allKeyPaths = keyPaths(options.schema)
@@ -172,17 +224,19 @@ const argumentsParser = (output) => {
172
224
  if (schemas[idx].enum) {
173
225
  return Object.keys(schemas[idx].enum)
174
226
  .filter((item) => caseit(key, 'kebab') !== item && item.startsWith(current))
175
- .map((item) => caseit(item, 'kebab'));
227
+ .map((item) => ({
228
+ type: 'option',
229
+ argument: caseit(item, 'kebab')
230
+ }));
176
231
  }
177
232
 
178
233
  if (schemas[idx].type === String && !schemas[idx].autocomplete) {
179
- return (await buildIns.files(
180
- current))
181
- .filter((item) => key !== item && item.startsWith(current));
234
+ return [{
235
+ type: 'files'
236
+ }];
182
237
  }
183
238
 
184
- return (await schemas[idx].autocomplete?.(current) || [])
185
- .filter((item) => key !== item && item.startsWith(current));
239
+ return filter(await schemas[idx].autocomplete?.(current) || []);
186
240
 
187
241
  } else {
188
242
 
@@ -193,8 +247,7 @@ const argumentsParser = (output) => {
193
247
  if (!current.startsWith('-')) {
194
248
  if (variadic === 'allow') {
195
249
  items = items.concat(
196
- (await autocomplete?.(current) || [])
197
- .filter((item) => current !== item && item.startsWith(current)));
250
+ filter(await autocomplete?.(current) || []));
198
251
  }
199
252
  }
200
253
 
@@ -203,9 +256,9 @@ const argumentsParser = (output) => {
203
256
  .filter((keyPath) => !spent.includes(keyPath))
204
257
  .filter((keyPath) => key !== keyPath && keyPath.startsWith(key) && keyPaths(options.schema).get(keyPath).short)
205
258
  .map((keyPath) => ({
206
- command: caseit(keyPaths(options.schema).get(keyPath).short, 'kebab'),
207
- description: keyPaths(options.schema).get(keyPath).description,
208
- prefix: '-'
259
+ type: 'option',
260
+ argument: `-${caseit(keyPaths(options.schema).get(keyPath).short, 'kebab')}`,
261
+ description: keyPaths(options.schema).get(keyPath).description
209
262
  })));
210
263
 
211
264
  }
@@ -215,9 +268,9 @@ const argumentsParser = (output) => {
215
268
  .filter((keyPath) => !spent.includes(keyPath))
216
269
  .filter((keyPath) => key !== keyPath && keyPath.startsWith(key))
217
270
  .map((keyPath) => ({
218
- command: caseit(keyPath, 'kebab'),
219
- description: keyPaths(options.schema).get(keyPath).description,
220
- prefix: '--'
271
+ type: 'option',
272
+ argument: `--${caseit(keyPath, 'kebab')}`,
273
+ description: keyPaths(options.schema).get(keyPath).description
221
274
  })));
222
275
 
223
276
  return items;
@@ -278,4 +331,3 @@ const argumentsParser = (output) => {
278
331
  };
279
332
 
280
333
  export default argumentsParser;
281
- export * as buildIns from './build-ins/index.js';
@@ -6,29 +6,45 @@
6
6
  // See license in LICENSE.
7
7
  //
8
8
 
9
- import caseit from '@trenskow/caseit';
10
-
11
9
  const zsh = (items) => {
12
10
 
13
- if (items.length === 0) {
11
+ const keys = Object.keys(items);
12
+
13
+ if (keys.length === 0) {
14
14
  process.exit(0);
15
15
  }
16
16
 
17
- process.stdout.write('_describe \'commands\' \'(\n');
17
+ keys
18
+ .forEach((key) => {
18
19
 
19
- items
20
- .forEach((command) => {
20
+ switch (key) {
21
+ case 'command':
22
+ // fall through
23
+ case 'option':
21
24
 
22
- if (typeof command === 'string') {
23
- process.stdout.write(` "${command}"\n`);
24
- return;
25
- }
25
+ process.stdout.write(`_describe '${key}s' '(\n`);
26
26
 
27
- process.stdout.write(` "${command.prefix || ''}${command.command}:${(command.description || '').replaceAll('`', '\\`')}"\n`);
27
+ items[key]
28
+ .forEach((item) => {
28
29
 
29
- });
30
+ const parts = [item.argument, item.description]
31
+ .filter((part) => part)
32
+ .map((part) => ['"', '\\', '$', '`']
33
+ .reduce((part, char) => part.replaceAll(char, `\\${char}`), part));
34
+
35
+ process.stdout.write(` "${parts.join(':')}"\n`);
30
36
 
31
- process.stdout.write(')\'\n');
37
+ });
38
+
39
+ process.stdout.write(')\'\n');
40
+
41
+ break;
42
+ case 'files':
43
+ process.stdout.write('_files\n');
44
+ return;
45
+ }
46
+
47
+ });
32
48
 
33
49
  process.exit(0);
34
50
 
package/lib/index.js CHANGED
@@ -484,4 +484,3 @@ const argumentsParser = (
484
484
  };
485
485
 
486
486
  export default argumentsParser;
487
- export { buildIns as autocompleteBuildIns } from './autocomplete/index.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@trenskow/arguments-parser",
3
- "version": "0.3.120",
3
+ "version": "0.3.122",
4
4
  "description": "Yet another arguments parser.",
5
5
  "main": "index.js",
6
6
  "type": "module",
@@ -1,70 +0,0 @@
1
- //
2
- // files.js
3
- // @trenskow/arguments-parser
4
- //
5
- // Created by Kristian Trenskow on 2026/08/02
6
- // See license in LICENSE.
7
- //
8
-
9
- import {
10
- join,
11
- resolve
12
- } from 'path';
13
-
14
- import {
15
- stat,
16
- readdir
17
- } from 'fs/promises';
18
-
19
- import parallel from '@trenskow/parallel';
20
-
21
- const safeStat = async (path) => {
22
- try {
23
- return await stat(path);
24
- } catch (_) {
25
- return undefined;
26
- }
27
- };
28
-
29
- export default async (current = '') => {
30
-
31
- if (current === '') {
32
- return await parallel(((await readdir(process.cwd()))
33
- .filter((file) => !file.startsWith('.')))
34
- .map(async (file) => `${file}${(await safeStat(resolve(process.cwd(), file)))?.isDirectory() ? '/' : ''}`));
35
- }
36
-
37
- const stat = await safeStat(
38
- resolve(
39
- process.cwd(),
40
- current));
41
-
42
- if (stat?.isDirectory()) {
43
-
44
- current = current.endsWith('/') ? current : `${current}/`;
45
-
46
- return (await parallel((await readdir(
47
- resolve(
48
- process.cwd(),
49
- current)))
50
- .map(async (file) => {
51
-
52
- if ((await safeStat(resolve(process.cwd(), current, file)))?.isDirectory()) {
53
- return `${file}/`;
54
- }
55
-
56
- return file;
57
-
58
- })))
59
- .filter((file) => !file.startsWith('.'))
60
- .map((file) => `${current}${file}`);
61
-
62
- } else if (stat) {
63
- return [];
64
- }
65
-
66
- return (await readdir(join(current, '../')))
67
- .filter((file) => !file.startsWith('.'))
68
- .map((file) => join(current, '../', file));
69
-
70
- };
@@ -1,15 +0,0 @@
1
- //
2
- // index.js
3
- // @trenskow/arguments-parser
4
- //
5
- // Created by Kristian Trenskow on 2026/08/02
6
- // See license in LICENSE.
7
- //
8
-
9
- import files from './files.js';
10
-
11
- export { files };
12
-
13
- export default {
14
- files
15
- };