@optique/core 0.9.0-dev.201 → 0.9.0-dev.202
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/dist/constructs.cjs +1337 -589
- package/dist/constructs.d.cts +182 -62
- package/dist/constructs.d.ts +182 -62
- package/dist/constructs.js +1337 -589
- package/dist/facade.cjs +128 -138
- package/dist/facade.d.cts +4 -2
- package/dist/facade.d.ts +4 -2
- package/dist/facade.js +129 -139
- package/dist/index.cjs +4 -0
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/dist/modifiers.cjs +228 -79
- package/dist/modifiers.d.cts +11 -6
- package/dist/modifiers.d.ts +11 -6
- package/dist/modifiers.js +228 -79
- package/dist/parser.cjs +158 -5
- package/dist/parser.d.cts +164 -12
- package/dist/parser.d.ts +164 -12
- package/dist/parser.js +155 -6
- package/dist/primitives.cjs +242 -97
- package/dist/primitives.d.cts +14 -10
- package/dist/primitives.d.ts +14 -10
- package/dist/primitives.js +242 -97
- package/dist/valueparser.cjs +10 -1
- package/dist/valueparser.d.cts +29 -16
- package/dist/valueparser.d.ts +29 -16
- package/dist/valueparser.js +10 -1
- package/package.json +1 -1
package/dist/modifiers.js
CHANGED
|
@@ -9,12 +9,31 @@ import { formatMessage, message, text } from "./message.js";
|
|
|
9
9
|
* - Returning success with undefined state when inner parser fails without consuming
|
|
10
10
|
* @internal
|
|
11
11
|
*/
|
|
12
|
-
function
|
|
12
|
+
function parseOptionalStyleSync(context, parser) {
|
|
13
13
|
const innerState = typeof context.state === "undefined" ? parser.initialState : context.state[0];
|
|
14
14
|
const result = parser.parse({
|
|
15
15
|
...context,
|
|
16
16
|
state: innerState
|
|
17
17
|
});
|
|
18
|
+
return processOptionalStyleResult(result, innerState, context);
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Internal async helper for optional-style parsing logic.
|
|
22
|
+
* @internal
|
|
23
|
+
*/
|
|
24
|
+
async function parseOptionalStyleAsync(context, parser) {
|
|
25
|
+
const innerState = typeof context.state === "undefined" ? parser.initialState : context.state[0];
|
|
26
|
+
const result = await parser.parse({
|
|
27
|
+
...context,
|
|
28
|
+
state: innerState
|
|
29
|
+
});
|
|
30
|
+
return processOptionalStyleResult(result, innerState, context);
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Internal helper to process optional-style parse results.
|
|
34
|
+
* @internal
|
|
35
|
+
*/
|
|
36
|
+
function processOptionalStyleResult(result, innerState, context) {
|
|
18
37
|
if (result.success) {
|
|
19
38
|
if (result.next.state !== innerState || result.consumed.length === 0) return {
|
|
20
39
|
success: true,
|
|
@@ -45,6 +64,7 @@ function parseOptionalStyle(context, parser) {
|
|
|
45
64
|
* without consuming input if the wrapped parser fails to match.
|
|
46
65
|
* If the wrapped parser succeeds, this returns its value.
|
|
47
66
|
* If the wrapped parser fails, this returns `undefined` without consuming input.
|
|
67
|
+
* @template M The execution mode of the parser.
|
|
48
68
|
* @template TValue The type of the value returned by the wrapped parser.
|
|
49
69
|
* @template TState The type of the state used by the wrapped parser.
|
|
50
70
|
* @param parser The {@link Parser} to make optional.
|
|
@@ -52,7 +72,25 @@ function parseOptionalStyle(context, parser) {
|
|
|
52
72
|
* or `undefined` if the wrapped parser fails to match.
|
|
53
73
|
*/
|
|
54
74
|
function optional(parser) {
|
|
75
|
+
const syncParser = parser;
|
|
76
|
+
const isAsync = parser.$mode === "async";
|
|
77
|
+
function* suggestSync(context, prefix) {
|
|
78
|
+
const innerState = typeof context.state === "undefined" ? syncParser.initialState : context.state[0];
|
|
79
|
+
yield* syncParser.suggest({
|
|
80
|
+
...context,
|
|
81
|
+
state: innerState
|
|
82
|
+
}, prefix);
|
|
83
|
+
}
|
|
84
|
+
async function* suggestAsync(context, prefix) {
|
|
85
|
+
const innerState = typeof context.state === "undefined" ? syncParser.initialState : context.state[0];
|
|
86
|
+
const suggestions = parser.suggest({
|
|
87
|
+
...context,
|
|
88
|
+
state: innerState
|
|
89
|
+
}, prefix);
|
|
90
|
+
for await (const s of suggestions) yield s;
|
|
91
|
+
}
|
|
55
92
|
return {
|
|
93
|
+
$mode: parser.$mode,
|
|
56
94
|
$valueType: [],
|
|
57
95
|
$stateType: [],
|
|
58
96
|
priority: parser.priority,
|
|
@@ -62,28 +100,27 @@ function optional(parser) {
|
|
|
62
100
|
}],
|
|
63
101
|
initialState: void 0,
|
|
64
102
|
parse(context) {
|
|
65
|
-
return
|
|
103
|
+
if (isAsync) return parseOptionalStyleAsync(context, parser);
|
|
104
|
+
return parseOptionalStyleSync(context, syncParser);
|
|
66
105
|
},
|
|
67
106
|
complete(state) {
|
|
68
107
|
if (typeof state === "undefined") return {
|
|
69
108
|
success: true,
|
|
70
109
|
value: void 0
|
|
71
110
|
};
|
|
72
|
-
return
|
|
111
|
+
if (!isAsync) return syncParser.complete(state[0]);
|
|
112
|
+
return (async () => await parser.complete(state[0]))();
|
|
73
113
|
},
|
|
74
114
|
suggest(context, prefix) {
|
|
75
|
-
|
|
76
|
-
return
|
|
77
|
-
...context,
|
|
78
|
-
state: innerState
|
|
79
|
-
}, prefix);
|
|
115
|
+
if (isAsync) return suggestAsync(context, prefix);
|
|
116
|
+
return suggestSync(context, prefix);
|
|
80
117
|
},
|
|
81
118
|
getDocFragments(state, defaultValue) {
|
|
82
119
|
const innerState = state.kind === "unavailable" ? { kind: "unavailable" } : state.state === void 0 ? { kind: "unavailable" } : {
|
|
83
120
|
kind: "available",
|
|
84
121
|
state: state.state[0]
|
|
85
122
|
};
|
|
86
|
-
return
|
|
123
|
+
return syncParser.getDocFragments(innerState, defaultValue);
|
|
87
124
|
}
|
|
88
125
|
};
|
|
89
126
|
}
|
|
@@ -122,7 +159,25 @@ var WithDefaultError = class extends Error {
|
|
|
122
159
|
}
|
|
123
160
|
};
|
|
124
161
|
function withDefault(parser, defaultValue, options) {
|
|
162
|
+
const syncParser = parser;
|
|
163
|
+
const isAsync = parser.$mode === "async";
|
|
164
|
+
function* suggestSync(context, prefix) {
|
|
165
|
+
const innerState = typeof context.state === "undefined" ? syncParser.initialState : context.state[0];
|
|
166
|
+
yield* syncParser.suggest({
|
|
167
|
+
...context,
|
|
168
|
+
state: innerState
|
|
169
|
+
}, prefix);
|
|
170
|
+
}
|
|
171
|
+
async function* suggestAsync(context, prefix) {
|
|
172
|
+
const innerState = typeof context.state === "undefined" ? syncParser.initialState : context.state[0];
|
|
173
|
+
const suggestions = parser.suggest({
|
|
174
|
+
...context,
|
|
175
|
+
state: innerState
|
|
176
|
+
}, prefix);
|
|
177
|
+
for await (const s of suggestions) yield s;
|
|
178
|
+
}
|
|
125
179
|
return {
|
|
180
|
+
$mode: parser.$mode,
|
|
126
181
|
$valueType: [],
|
|
127
182
|
$stateType: [],
|
|
128
183
|
priority: parser.priority,
|
|
@@ -132,7 +187,8 @@ function withDefault(parser, defaultValue, options) {
|
|
|
132
187
|
}],
|
|
133
188
|
initialState: void 0,
|
|
134
189
|
parse(context) {
|
|
135
|
-
return
|
|
190
|
+
if (isAsync) return parseOptionalStyleAsync(context, parser);
|
|
191
|
+
return parseOptionalStyleSync(context, syncParser);
|
|
136
192
|
},
|
|
137
193
|
complete(state) {
|
|
138
194
|
if (typeof state === "undefined") try {
|
|
@@ -147,14 +203,12 @@ function withDefault(parser, defaultValue, options) {
|
|
|
147
203
|
error: error instanceof WithDefaultError ? error.errorMessage : message`${text(String(error))}`
|
|
148
204
|
};
|
|
149
205
|
}
|
|
150
|
-
return
|
|
206
|
+
if (!isAsync) return syncParser.complete(state[0]);
|
|
207
|
+
return (async () => await parser.complete(state[0]))();
|
|
151
208
|
},
|
|
152
209
|
suggest(context, prefix) {
|
|
153
|
-
|
|
154
|
-
return
|
|
155
|
-
...context,
|
|
156
|
-
state: innerState
|
|
157
|
-
}, prefix);
|
|
210
|
+
if (isAsync) return suggestAsync(context, prefix);
|
|
211
|
+
return suggestSync(context, prefix);
|
|
158
212
|
},
|
|
159
213
|
getDocFragments(state, upperDefaultValue) {
|
|
160
214
|
const innerState = state.kind === "unavailable" ? { kind: "unavailable" } : state.state === void 0 ? { kind: "unavailable" } : {
|
|
@@ -162,7 +216,7 @@ function withDefault(parser, defaultValue, options) {
|
|
|
162
216
|
state: state.state[0]
|
|
163
217
|
};
|
|
164
218
|
const actualDefaultValue = upperDefaultValue != null ? upperDefaultValue : typeof defaultValue === "function" ? defaultValue() : defaultValue;
|
|
165
|
-
const fragments =
|
|
219
|
+
const fragments = syncParser.getDocFragments(innerState, actualDefaultValue);
|
|
166
220
|
if (options?.message) {
|
|
167
221
|
const modifiedFragments = fragments.fragments.map((fragment) => {
|
|
168
222
|
if (fragment.type === "entry") return {
|
|
@@ -191,6 +245,7 @@ function withDefault(parser, defaultValue, options) {
|
|
|
191
245
|
* - Computing derived values from parsed input
|
|
192
246
|
* - Creating reusable transformations that can be applied to any parser
|
|
193
247
|
*
|
|
248
|
+
* @template M The execution mode of the parser.
|
|
194
249
|
* @template T The type of the value produced by the original parser.
|
|
195
250
|
* @template U The type of the value produced by the mapping function.
|
|
196
251
|
* @template TState The type of the state used by the original parser.
|
|
@@ -214,33 +269,68 @@ function withDefault(parser, defaultValue, options) {
|
|
|
214
269
|
* ```
|
|
215
270
|
*/
|
|
216
271
|
function map(parser, transform) {
|
|
217
|
-
|
|
272
|
+
const syncParser = parser;
|
|
273
|
+
const isAsync = parser.$mode === "async";
|
|
274
|
+
function* suggestSync(context, prefix) {
|
|
275
|
+
yield* syncParser.suggest(context, prefix);
|
|
276
|
+
}
|
|
277
|
+
async function* suggestAsync(context, prefix) {
|
|
278
|
+
const suggestions = parser.suggest(context, prefix);
|
|
279
|
+
for await (const s of suggestions) yield s;
|
|
280
|
+
}
|
|
281
|
+
const result = {
|
|
282
|
+
$mode: "sync",
|
|
218
283
|
$valueType: [],
|
|
219
284
|
$stateType: parser.$stateType,
|
|
220
285
|
priority: parser.priority,
|
|
221
286
|
usage: parser.usage,
|
|
222
287
|
initialState: parser.initialState,
|
|
223
|
-
parse
|
|
288
|
+
parse(context) {
|
|
289
|
+
if (isAsync) return parser.parse(context);
|
|
290
|
+
return syncParser.parse(context);
|
|
291
|
+
},
|
|
224
292
|
complete(state) {
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
success
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
293
|
+
if (!isAsync) {
|
|
294
|
+
const innerResult = syncParser.complete(state);
|
|
295
|
+
if (innerResult.success) return {
|
|
296
|
+
success: true,
|
|
297
|
+
value: transform(innerResult.value)
|
|
298
|
+
};
|
|
299
|
+
return {
|
|
300
|
+
success: false,
|
|
301
|
+
error: innerResult.error
|
|
302
|
+
};
|
|
303
|
+
}
|
|
304
|
+
return (async () => {
|
|
305
|
+
const innerResult = await parser.complete(state);
|
|
306
|
+
if (innerResult.success) return {
|
|
307
|
+
success: true,
|
|
308
|
+
value: transform(innerResult.value)
|
|
309
|
+
};
|
|
310
|
+
return {
|
|
311
|
+
success: false,
|
|
312
|
+
error: innerResult.error
|
|
313
|
+
};
|
|
314
|
+
})();
|
|
231
315
|
},
|
|
232
316
|
suggest(context, prefix) {
|
|
233
|
-
return
|
|
317
|
+
if (isAsync) return suggestAsync(context, prefix);
|
|
318
|
+
return suggestSync(context, prefix);
|
|
234
319
|
},
|
|
235
320
|
getDocFragments(state, _defaultValue) {
|
|
236
|
-
return
|
|
321
|
+
return syncParser.getDocFragments(state, void 0);
|
|
237
322
|
}
|
|
238
323
|
};
|
|
324
|
+
return {
|
|
325
|
+
...result,
|
|
326
|
+
$mode: parser.$mode
|
|
327
|
+
};
|
|
239
328
|
}
|
|
240
329
|
/**
|
|
241
330
|
* Creates a parser that allows multiple occurrences of a given parser.
|
|
242
331
|
* This parser can be used to parse multiple values of the same type,
|
|
243
332
|
* such as multiple command-line arguments or options.
|
|
333
|
+
* @template M The execution mode of the parser.
|
|
244
334
|
* @template TValue The type of the value that the parser produces.
|
|
245
335
|
* @template TState The type of the state used by the parser.
|
|
246
336
|
* @param parser The {@link Parser} to apply multiple times.
|
|
@@ -252,8 +342,59 @@ function map(parser, transform) {
|
|
|
252
342
|
* of type {@link TState}.
|
|
253
343
|
*/
|
|
254
344
|
function multiple(parser, options = {}) {
|
|
345
|
+
const syncParser = parser;
|
|
346
|
+
const isAsync = parser.$mode === "async";
|
|
255
347
|
const { min = 0, max = Infinity } = options;
|
|
256
|
-
|
|
348
|
+
const parseSync = (context) => {
|
|
349
|
+
let added = context.state.length < 1;
|
|
350
|
+
let result = syncParser.parse({
|
|
351
|
+
...context,
|
|
352
|
+
state: context.state.at(-1) ?? syncParser.initialState
|
|
353
|
+
});
|
|
354
|
+
if (!result.success) if (!added) {
|
|
355
|
+
result = syncParser.parse({
|
|
356
|
+
...context,
|
|
357
|
+
state: syncParser.initialState
|
|
358
|
+
});
|
|
359
|
+
if (!result.success) return result;
|
|
360
|
+
added = true;
|
|
361
|
+
} else return result;
|
|
362
|
+
return {
|
|
363
|
+
success: true,
|
|
364
|
+
next: {
|
|
365
|
+
...result.next,
|
|
366
|
+
state: [...added ? context.state : context.state.slice(0, -1), result.next.state]
|
|
367
|
+
},
|
|
368
|
+
consumed: result.consumed
|
|
369
|
+
};
|
|
370
|
+
};
|
|
371
|
+
const parseAsync = async (context) => {
|
|
372
|
+
let added = context.state.length < 1;
|
|
373
|
+
let resultOrPromise = parser.parse({
|
|
374
|
+
...context,
|
|
375
|
+
state: context.state.at(-1) ?? parser.initialState
|
|
376
|
+
});
|
|
377
|
+
let result = await resultOrPromise;
|
|
378
|
+
if (!result.success) if (!added) {
|
|
379
|
+
resultOrPromise = parser.parse({
|
|
380
|
+
...context,
|
|
381
|
+
state: parser.initialState
|
|
382
|
+
});
|
|
383
|
+
result = await resultOrPromise;
|
|
384
|
+
if (!result.success) return result;
|
|
385
|
+
added = true;
|
|
386
|
+
} else return result;
|
|
387
|
+
return {
|
|
388
|
+
success: true,
|
|
389
|
+
next: {
|
|
390
|
+
...result.next,
|
|
391
|
+
state: [...added ? context.state : context.state.slice(0, -1), result.next.state]
|
|
392
|
+
},
|
|
393
|
+
consumed: result.consumed
|
|
394
|
+
};
|
|
395
|
+
};
|
|
396
|
+
const resultParser = {
|
|
397
|
+
$mode: parser.$mode,
|
|
257
398
|
$valueType: [],
|
|
258
399
|
$stateType: [],
|
|
259
400
|
priority: parser.priority,
|
|
@@ -264,71 +405,79 @@ function multiple(parser, options = {}) {
|
|
|
264
405
|
}],
|
|
265
406
|
initialState: [],
|
|
266
407
|
parse(context) {
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
...context,
|
|
270
|
-
state: context.state.at(-1) ?? parser.initialState
|
|
271
|
-
});
|
|
272
|
-
if (!result.success) if (!added) {
|
|
273
|
-
result = parser.parse({
|
|
274
|
-
...context,
|
|
275
|
-
state: parser.initialState
|
|
276
|
-
});
|
|
277
|
-
if (!result.success) return result;
|
|
278
|
-
added = true;
|
|
279
|
-
} else return result;
|
|
280
|
-
return {
|
|
281
|
-
success: true,
|
|
282
|
-
next: {
|
|
283
|
-
...result.next,
|
|
284
|
-
state: [...added ? context.state : context.state.slice(0, -1), result.next.state]
|
|
285
|
-
},
|
|
286
|
-
consumed: result.consumed
|
|
287
|
-
};
|
|
408
|
+
if (isAsync) return parseAsync(context);
|
|
409
|
+
return parseSync(context);
|
|
288
410
|
},
|
|
289
411
|
complete(state) {
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
const
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
return {
|
|
302
|
-
success: false,
|
|
303
|
-
error: customMessage ? typeof customMessage === "function" ? customMessage(min, result.length) : customMessage : message`Expected at least ${text(min.toLocaleString("en"))} values, but got only ${text(result.length.toLocaleString("en"))}.`
|
|
304
|
-
};
|
|
305
|
-
} else if (result.length > max) {
|
|
306
|
-
const customMessage = options.errors?.tooMany;
|
|
307
|
-
return {
|
|
308
|
-
success: false,
|
|
309
|
-
error: customMessage ? typeof customMessage === "function" ? customMessage(max, result.length) : customMessage : message`Expected at most ${text(max.toLocaleString("en"))} values, but got ${text(result.length.toLocaleString("en"))}.`
|
|
310
|
-
};
|
|
412
|
+
if (!isAsync) {
|
|
413
|
+
const result = [];
|
|
414
|
+
for (const s of state) {
|
|
415
|
+
const valueResult = syncParser.complete(s);
|
|
416
|
+
if (valueResult.success) result.push(valueResult.value);
|
|
417
|
+
else return {
|
|
418
|
+
success: false,
|
|
419
|
+
error: valueResult.error
|
|
420
|
+
};
|
|
421
|
+
}
|
|
422
|
+
return validateMultipleResult(result);
|
|
311
423
|
}
|
|
312
|
-
return {
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
424
|
+
return (async () => {
|
|
425
|
+
const result = [];
|
|
426
|
+
for (const s of state) {
|
|
427
|
+
const valueResult = await parser.complete(s);
|
|
428
|
+
if (valueResult.success) result.push(valueResult.value);
|
|
429
|
+
else return {
|
|
430
|
+
success: false,
|
|
431
|
+
error: valueResult.error
|
|
432
|
+
};
|
|
433
|
+
}
|
|
434
|
+
return validateMultipleResult(result);
|
|
435
|
+
})();
|
|
316
436
|
},
|
|
317
437
|
suggest(context, prefix) {
|
|
318
438
|
const innerState = context.state.length > 0 ? context.state.at(-1) : parser.initialState;
|
|
319
|
-
return
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
439
|
+
if (isAsync) return async function* () {
|
|
440
|
+
const suggestions = parser.suggest({
|
|
441
|
+
...context,
|
|
442
|
+
state: innerState
|
|
443
|
+
}, prefix);
|
|
444
|
+
for await (const s of suggestions) yield s;
|
|
445
|
+
}();
|
|
446
|
+
return function* () {
|
|
447
|
+
yield* syncParser.suggest({
|
|
448
|
+
...context,
|
|
449
|
+
state: innerState
|
|
450
|
+
}, prefix);
|
|
451
|
+
}();
|
|
323
452
|
},
|
|
324
453
|
getDocFragments(state, defaultValue) {
|
|
325
454
|
const innerState = state.kind === "unavailable" ? { kind: "unavailable" } : state.state.length > 0 ? {
|
|
326
455
|
kind: "available",
|
|
327
456
|
state: state.state.at(-1)
|
|
328
457
|
} : { kind: "unavailable" };
|
|
329
|
-
return
|
|
458
|
+
return syncParser.getDocFragments(innerState, defaultValue != null && defaultValue.length > 0 ? defaultValue[0] : void 0);
|
|
330
459
|
}
|
|
331
460
|
};
|
|
461
|
+
function validateMultipleResult(result) {
|
|
462
|
+
if (result.length < min) {
|
|
463
|
+
const customMessage = options.errors?.tooFew;
|
|
464
|
+
return {
|
|
465
|
+
success: false,
|
|
466
|
+
error: customMessage ? typeof customMessage === "function" ? customMessage(min, result.length) : customMessage : message`Expected at least ${text(min.toLocaleString("en"))} values, but got only ${text(result.length.toLocaleString("en"))}.`
|
|
467
|
+
};
|
|
468
|
+
} else if (result.length > max) {
|
|
469
|
+
const customMessage = options.errors?.tooMany;
|
|
470
|
+
return {
|
|
471
|
+
success: false,
|
|
472
|
+
error: customMessage ? typeof customMessage === "function" ? customMessage(max, result.length) : customMessage : message`Expected at most ${text(max.toLocaleString("en"))} values, but got ${text(result.length.toLocaleString("en"))}.`
|
|
473
|
+
};
|
|
474
|
+
}
|
|
475
|
+
return {
|
|
476
|
+
success: true,
|
|
477
|
+
value: result
|
|
478
|
+
};
|
|
479
|
+
}
|
|
480
|
+
return resultParser;
|
|
332
481
|
}
|
|
333
482
|
|
|
334
483
|
//#endregion
|
package/dist/parser.cjs
CHANGED
|
@@ -9,17 +9,23 @@ const require_primitives = require('./primitives.cjs');
|
|
|
9
9
|
* Parses an array of command-line arguments using the provided combined parser.
|
|
10
10
|
* This function processes the input arguments, applying the parser to each
|
|
11
11
|
* argument until all arguments are consumed or an error occurs.
|
|
12
|
+
*
|
|
13
|
+
* This function only accepts synchronous parsers. For asynchronous parsers,
|
|
14
|
+
* use {@link parseAsync}.
|
|
15
|
+
*
|
|
12
16
|
* @template T The type of the value produced by the parser.
|
|
13
17
|
* @param parser The combined {@link Parser} to use for parsing the input
|
|
14
|
-
* arguments.
|
|
18
|
+
* arguments. Must be a synchronous parser.
|
|
15
19
|
* @param args The array of command-line arguments to parse. Usually this is
|
|
16
20
|
* `process.argv.slice(2)` in Node.js or `Deno.args` in Deno.
|
|
17
21
|
* @returns A {@link Result} object indicating whether the parsing was
|
|
18
22
|
* successful or not. If successful, it contains the parsed value of
|
|
19
23
|
* type `T`. If not, it contains an error message describing the
|
|
20
24
|
* failure.
|
|
25
|
+
* @since 0.9.0 Renamed from the original `parse` function which now delegates
|
|
26
|
+
* to this for sync parsers.
|
|
21
27
|
*/
|
|
22
|
-
function
|
|
28
|
+
function parseSync(parser, args) {
|
|
23
29
|
let context = {
|
|
24
30
|
buffer: args,
|
|
25
31
|
optionsTerminated: false,
|
|
@@ -49,11 +55,86 @@ function parse(parser, args) {
|
|
|
49
55
|
};
|
|
50
56
|
}
|
|
51
57
|
/**
|
|
58
|
+
* Parses an array of command-line arguments using the provided combined parser.
|
|
59
|
+
* This function processes the input arguments, applying the parser to each
|
|
60
|
+
* argument until all arguments are consumed or an error occurs.
|
|
61
|
+
*
|
|
62
|
+
* This function accepts any parser (sync or async) and always returns a Promise.
|
|
63
|
+
* For synchronous parsing with sync parsers, use {@link parseSync} instead.
|
|
64
|
+
*
|
|
65
|
+
* @template T The type of the value produced by the parser.
|
|
66
|
+
* @param parser The combined {@link Parser} to use for parsing the input
|
|
67
|
+
* arguments.
|
|
68
|
+
* @param args The array of command-line arguments to parse. Usually this is
|
|
69
|
+
* `process.argv.slice(2)` in Node.js or `Deno.args` in Deno.
|
|
70
|
+
* @returns A Promise that resolves to a {@link Result} object indicating
|
|
71
|
+
* whether the parsing was successful or not.
|
|
72
|
+
* @since 0.9.0
|
|
73
|
+
*/
|
|
74
|
+
async function parseAsync(parser, args) {
|
|
75
|
+
let context = {
|
|
76
|
+
buffer: args,
|
|
77
|
+
optionsTerminated: false,
|
|
78
|
+
state: parser.initialState,
|
|
79
|
+
usage: parser.usage
|
|
80
|
+
};
|
|
81
|
+
do {
|
|
82
|
+
const result = await parser.parse(context);
|
|
83
|
+
if (!result.success) return {
|
|
84
|
+
success: false,
|
|
85
|
+
error: result.error
|
|
86
|
+
};
|
|
87
|
+
const previousBuffer = context.buffer;
|
|
88
|
+
context = result.next;
|
|
89
|
+
if (context.buffer.length > 0 && context.buffer.length === previousBuffer.length && context.buffer.every((item, i) => item === previousBuffer[i])) return {
|
|
90
|
+
success: false,
|
|
91
|
+
error: require_message.message`Unexpected option or argument: ${context.buffer[0]}.`
|
|
92
|
+
};
|
|
93
|
+
} while (context.buffer.length > 0);
|
|
94
|
+
const endResult = await parser.complete(context.state);
|
|
95
|
+
return endResult.success ? {
|
|
96
|
+
success: true,
|
|
97
|
+
value: endResult.value
|
|
98
|
+
} : {
|
|
99
|
+
success: false,
|
|
100
|
+
error: endResult.error
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Parses an array of command-line arguments using the provided combined parser.
|
|
105
|
+
* This function processes the input arguments, applying the parser to each
|
|
106
|
+
* argument until all arguments are consumed or an error occurs.
|
|
107
|
+
*
|
|
108
|
+
* The return type depends on the parser's mode:
|
|
109
|
+
* - Sync parsers return `Result<T>` directly.
|
|
110
|
+
* - Async parsers return `Promise<Result<T>>`.
|
|
111
|
+
*
|
|
112
|
+
* For explicit control, use {@link parseSync} or {@link parseAsync}.
|
|
113
|
+
*
|
|
114
|
+
* @template M The execution mode of the parser.
|
|
115
|
+
* @template T The type of the value produced by the parser.
|
|
116
|
+
* @param parser The combined {@link Parser} to use for parsing the input
|
|
117
|
+
* arguments.
|
|
118
|
+
* @param args The array of command-line arguments to parse. Usually this is
|
|
119
|
+
* `process.argv.slice(2)` in Node.js or `Deno.args` in Deno.
|
|
120
|
+
* @returns A {@link Result} object (for sync) or Promise thereof (for async)
|
|
121
|
+
* indicating whether the parsing was successful or not.
|
|
122
|
+
*/
|
|
123
|
+
function parse(parser, args) {
|
|
124
|
+
if (parser.$mode === "async") return parseAsync(parser, args);
|
|
125
|
+
return parseSync(parser, args);
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
52
128
|
* Generates command-line suggestions based on current parsing state.
|
|
53
129
|
* This function processes the input arguments up to the last argument,
|
|
54
130
|
* then calls the parser's suggest method with the remaining prefix.
|
|
131
|
+
*
|
|
132
|
+
* This function only accepts synchronous parsers. For asynchronous parsers,
|
|
133
|
+
* use {@link suggestAsync}.
|
|
134
|
+
*
|
|
55
135
|
* @template T The type of the value produced by the parser.
|
|
56
136
|
* @param parser The {@link Parser} to use for generating suggestions.
|
|
137
|
+
* Must be a synchronous parser.
|
|
57
138
|
* @param args The array of command-line arguments including the partial
|
|
58
139
|
* argument to complete. The last element is treated as
|
|
59
140
|
* the prefix for suggestions.
|
|
@@ -67,16 +148,17 @@ function parse(parser, args) {
|
|
|
67
148
|
* });
|
|
68
149
|
*
|
|
69
150
|
* // Get suggestions for options starting with "--"
|
|
70
|
-
* const suggestions =
|
|
151
|
+
* const suggestions = suggestSync(parser, ["--"]);
|
|
71
152
|
* // Returns: [{ text: "--verbose" }, { text: "--format" }]
|
|
72
153
|
*
|
|
73
154
|
* // Get suggestions after parsing some arguments
|
|
74
|
-
* const suggestions2 =
|
|
155
|
+
* const suggestions2 = suggestSync(parser, ["-v", "--format="]);
|
|
75
156
|
* // Returns: [{ text: "--format=json" }, { text: "--format=yaml" }]
|
|
76
157
|
* ```
|
|
77
158
|
* @since 0.6.0
|
|
159
|
+
* @since 0.9.0 Renamed from the original `suggest` function.
|
|
78
160
|
*/
|
|
79
|
-
function
|
|
161
|
+
function suggestSync(parser, args) {
|
|
80
162
|
const allButLast = args.slice(0, -1);
|
|
81
163
|
const prefix = args[args.length - 1];
|
|
82
164
|
let context = {
|
|
@@ -95,6 +177,73 @@ function suggest(parser, args) {
|
|
|
95
177
|
return Array.from(parser.suggest(context, prefix));
|
|
96
178
|
}
|
|
97
179
|
/**
|
|
180
|
+
* Generates command-line suggestions based on current parsing state.
|
|
181
|
+
* This function processes the input arguments up to the last argument,
|
|
182
|
+
* then calls the parser's suggest method with the remaining prefix.
|
|
183
|
+
*
|
|
184
|
+
* This function accepts any parser (sync or async) and always returns a Promise.
|
|
185
|
+
* For synchronous suggestion generation with sync parsers, use
|
|
186
|
+
* {@link suggestSync} instead.
|
|
187
|
+
*
|
|
188
|
+
* @template T The type of the value produced by the parser.
|
|
189
|
+
* @param parser The {@link Parser} to use for generating suggestions.
|
|
190
|
+
* @param args The array of command-line arguments including the partial
|
|
191
|
+
* argument to complete. The last element is treated as
|
|
192
|
+
* the prefix for suggestions.
|
|
193
|
+
* @returns A Promise that resolves to an array of {@link Suggestion} objects
|
|
194
|
+
* containing completion candidates.
|
|
195
|
+
* @since 0.9.0
|
|
196
|
+
*/
|
|
197
|
+
async function suggestAsync(parser, args) {
|
|
198
|
+
const allButLast = args.slice(0, -1);
|
|
199
|
+
const prefix = args[args.length - 1];
|
|
200
|
+
let context = {
|
|
201
|
+
buffer: allButLast,
|
|
202
|
+
optionsTerminated: false,
|
|
203
|
+
state: parser.initialState,
|
|
204
|
+
usage: parser.usage
|
|
205
|
+
};
|
|
206
|
+
while (context.buffer.length > 0) {
|
|
207
|
+
const result = await parser.parse(context);
|
|
208
|
+
if (!result.success) {
|
|
209
|
+
const suggestions$1 = [];
|
|
210
|
+
for await (const suggestion of parser.suggest(context, prefix)) suggestions$1.push(suggestion);
|
|
211
|
+
return suggestions$1;
|
|
212
|
+
}
|
|
213
|
+
const previousBuffer = context.buffer;
|
|
214
|
+
context = result.next;
|
|
215
|
+
if (context.buffer.length > 0 && context.buffer.length === previousBuffer.length && context.buffer.every((item, i) => item === previousBuffer[i])) return [];
|
|
216
|
+
}
|
|
217
|
+
const suggestions = [];
|
|
218
|
+
for await (const suggestion of parser.suggest(context, prefix)) suggestions.push(suggestion);
|
|
219
|
+
return suggestions;
|
|
220
|
+
}
|
|
221
|
+
/**
|
|
222
|
+
* Generates command-line suggestions based on current parsing state.
|
|
223
|
+
* This function processes the input arguments up to the last argument,
|
|
224
|
+
* then calls the parser's suggest method with the remaining prefix.
|
|
225
|
+
*
|
|
226
|
+
* The return type depends on the parser's mode:
|
|
227
|
+
* - Sync parsers return `readonly Suggestion[]` directly.
|
|
228
|
+
* - Async parsers return `Promise<readonly Suggestion[]>`.
|
|
229
|
+
*
|
|
230
|
+
* For explicit control, use {@link suggestSync} or {@link suggestAsync}.
|
|
231
|
+
*
|
|
232
|
+
* @template M The execution mode of the parser.
|
|
233
|
+
* @template T The type of the value produced by the parser.
|
|
234
|
+
* @param parser The {@link Parser} to use for generating suggestions.
|
|
235
|
+
* @param args The array of command-line arguments including the partial
|
|
236
|
+
* argument to complete. The last element is treated as
|
|
237
|
+
* the prefix for suggestions.
|
|
238
|
+
* @returns An array of {@link Suggestion} objects (for sync) or Promise thereof
|
|
239
|
+
* (for async) containing completion candidates.
|
|
240
|
+
* @since 0.6.0
|
|
241
|
+
*/
|
|
242
|
+
function suggest(parser, args) {
|
|
243
|
+
if (parser.$mode === "async") return suggestAsync(parser, args);
|
|
244
|
+
return suggestSync(parser, args);
|
|
245
|
+
}
|
|
246
|
+
/**
|
|
98
247
|
* Recursively searches for a command within nested exclusive usage terms.
|
|
99
248
|
* When the command is found, returns the expanded usage terms for that command.
|
|
100
249
|
*
|
|
@@ -212,7 +361,11 @@ exports.option = require_primitives.option;
|
|
|
212
361
|
exports.optional = require_modifiers.optional;
|
|
213
362
|
exports.or = require_constructs.or;
|
|
214
363
|
exports.parse = parse;
|
|
364
|
+
exports.parseAsync = parseAsync;
|
|
365
|
+
exports.parseSync = parseSync;
|
|
215
366
|
exports.passThrough = require_primitives.passThrough;
|
|
216
367
|
exports.suggest = suggest;
|
|
368
|
+
exports.suggestAsync = suggestAsync;
|
|
369
|
+
exports.suggestSync = suggestSync;
|
|
217
370
|
exports.tuple = require_constructs.tuple;
|
|
218
371
|
exports.withDefault = require_modifiers.withDefault;
|