@optique/core 1.0.0-dev.921 → 1.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/dist/annotation-state.cjs +425 -0
- package/dist/annotation-state.d.cts +24 -0
- package/dist/annotation-state.d.ts +24 -0
- package/dist/annotation-state.js +414 -0
- package/dist/annotations.cjs +2 -248
- package/dist/annotations.d.cts +2 -137
- package/dist/annotations.d.ts +2 -137
- package/dist/annotations.js +2 -238
- package/dist/completion.cjs +611 -100
- package/dist/completion.d.cts +1 -1
- package/dist/completion.d.ts +1 -1
- package/dist/completion.js +611 -100
- package/dist/constructs.cjs +3338 -827
- package/dist/constructs.d.cts +48 -7
- package/dist/constructs.d.ts +48 -7
- package/dist/constructs.js +3338 -827
- package/dist/context.cjs +0 -23
- package/dist/context.d.cts +119 -53
- package/dist/context.d.ts +119 -53
- package/dist/context.js +0 -22
- package/dist/dependency-metadata.cjs +139 -0
- package/dist/dependency-metadata.d.cts +112 -0
- package/dist/dependency-metadata.d.ts +112 -0
- package/dist/dependency-metadata.js +138 -0
- package/dist/dependency-runtime.cjs +698 -0
- package/dist/dependency-runtime.d.cts +149 -0
- package/dist/dependency-runtime.d.ts +149 -0
- package/dist/dependency-runtime.js +687 -0
- package/dist/dependency.cjs +7 -928
- package/dist/dependency.d.cts +2 -794
- package/dist/dependency.d.ts +2 -794
- package/dist/dependency.js +2 -899
- package/dist/displaywidth.cjs +44 -0
- package/dist/displaywidth.js +43 -0
- package/dist/doc.cjs +285 -23
- package/dist/doc.d.cts +57 -2
- package/dist/doc.d.ts +57 -2
- package/dist/doc.js +283 -25
- package/dist/execution-context.cjs +56 -0
- package/dist/execution-context.js +53 -0
- package/dist/extension.cjs +87 -0
- package/dist/extension.d.cts +97 -0
- package/dist/extension.d.ts +97 -0
- package/dist/extension.js +76 -0
- package/dist/facade.cjs +718 -525
- package/dist/facade.d.cts +59 -15
- package/dist/facade.d.ts +59 -15
- package/dist/facade.js +718 -525
- package/dist/index.cjs +14 -29
- package/dist/index.d.cts +10 -10
- package/dist/index.d.ts +10 -10
- package/dist/index.js +7 -7
- package/dist/input-trace.cjs +56 -0
- package/dist/input-trace.d.cts +77 -0
- package/dist/input-trace.d.ts +77 -0
- package/dist/input-trace.js +55 -0
- package/dist/internal/annotations.cjs +316 -0
- package/dist/internal/annotations.d.cts +140 -0
- package/dist/internal/annotations.d.ts +140 -0
- package/dist/internal/annotations.js +306 -0
- package/dist/internal/dependency.cjs +984 -0
- package/dist/internal/dependency.d.cts +539 -0
- package/dist/internal/dependency.d.ts +539 -0
- package/dist/internal/dependency.js +964 -0
- package/dist/{mode-dispatch.cjs → internal/mode-dispatch.cjs} +1 -3
- package/dist/{mode-dispatch.d.cts → internal/mode-dispatch.d.cts} +3 -7
- package/dist/{mode-dispatch.d.ts → internal/mode-dispatch.d.ts} +3 -7
- package/dist/{mode-dispatch.js → internal/mode-dispatch.js} +1 -3
- package/dist/internal/parser.cjs +728 -0
- package/dist/internal/parser.d.cts +947 -0
- package/dist/internal/parser.d.ts +947 -0
- package/dist/internal/parser.js +711 -0
- package/dist/message.cjs +84 -26
- package/dist/message.d.cts +49 -9
- package/dist/message.d.ts +49 -9
- package/dist/message.js +84 -27
- package/dist/modifiers.cjs +1023 -240
- package/dist/modifiers.d.cts +42 -1
- package/dist/modifiers.d.ts +42 -1
- package/dist/modifiers.js +1023 -240
- package/dist/parser.cjs +11 -463
- package/dist/parser.d.cts +3 -537
- package/dist/parser.d.ts +3 -537
- package/dist/parser.js +2 -433
- package/dist/phase2-seed.cjs +59 -0
- package/dist/phase2-seed.js +56 -0
- package/dist/primitives.cjs +557 -208
- package/dist/primitives.d.cts +10 -14
- package/dist/primitives.d.ts +10 -14
- package/dist/primitives.js +557 -208
- package/dist/program.cjs +5 -1
- package/dist/program.d.cts +5 -3
- package/dist/program.d.ts +5 -3
- package/dist/program.js +6 -1
- package/dist/suggestion.cjs +22 -8
- package/dist/suggestion.js +22 -8
- package/dist/usage-internals.cjs +3 -2
- package/dist/usage-internals.js +4 -2
- package/dist/usage.cjs +195 -40
- package/dist/usage.d.cts +92 -11
- package/dist/usage.d.ts +92 -11
- package/dist/usage.js +194 -41
- package/dist/validate.cjs +170 -0
- package/dist/validate.js +164 -0
- package/dist/valueparser.cjs +1270 -187
- package/dist/valueparser.d.cts +320 -14
- package/dist/valueparser.d.ts +320 -14
- package/dist/valueparser.js +1269 -188
- package/package.json +9 -9
package/dist/parser.js
CHANGED
|
@@ -1,434 +1,3 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { message } from "./message.js";
|
|
3
|
-
import { dispatchByMode } from "./mode-dispatch.js";
|
|
4
|
-
import { normalizeUsage } from "./usage.js";
|
|
5
|
-
import { DuplicateOptionError, concat, conditional, group, longestMatch, merge, object, or, tuple } from "./constructs.js";
|
|
6
|
-
import { WithDefaultError, map, multiple, nonEmpty, optional, withDefault } from "./modifiers.js";
|
|
7
|
-
import { argument, command, constant, fail, flag, option, passThrough } from "./primitives.js";
|
|
1
|
+
import { createParserContext, getDocPage, getDocPageAsync, getDocPageSync, parse, parseAsync, parseSync, suggest, suggestAsync, suggestSync } from "./internal/parser.js";
|
|
8
2
|
|
|
9
|
-
|
|
10
|
-
function injectAnnotationsIntoState(state, options) {
|
|
11
|
-
const annotations = options?.annotations;
|
|
12
|
-
if (annotations == null) return state;
|
|
13
|
-
return injectAnnotations(state, annotations);
|
|
14
|
-
}
|
|
15
|
-
/**
|
|
16
|
-
* Parses an array of command-line arguments using the provided combined parser.
|
|
17
|
-
* This function processes the input arguments, applying the parser to each
|
|
18
|
-
* argument until all arguments are consumed or an error occurs.
|
|
19
|
-
*
|
|
20
|
-
* This function only accepts synchronous parsers. For asynchronous parsers,
|
|
21
|
-
* use {@link parseAsync}.
|
|
22
|
-
*
|
|
23
|
-
* @template T The type of the value produced by the parser.
|
|
24
|
-
* @param parser The combined {@link Parser} to use for parsing the input
|
|
25
|
-
* arguments. Must be a synchronous parser.
|
|
26
|
-
* @param args The array of command-line arguments to parse. Usually this is
|
|
27
|
-
* `process.argv.slice(2)` in Node.js or `Deno.args` in Deno.
|
|
28
|
-
* @param options Optional {@link ParseOptions} for customizing parsing behavior.
|
|
29
|
-
* @returns A {@link Result} object indicating whether the parsing was
|
|
30
|
-
* successful or not. If successful, it contains the parsed value of
|
|
31
|
-
* type `T`. If not, it contains an error message describing the
|
|
32
|
-
* failure.
|
|
33
|
-
* @since 0.9.0 Renamed from the original `parse` function which now delegates
|
|
34
|
-
* to this for sync parsers.
|
|
35
|
-
* @since 0.10.0 Added optional `options` parameter for annotations support.
|
|
36
|
-
*/
|
|
37
|
-
function parseSync(parser, args, options) {
|
|
38
|
-
const initialState = injectAnnotationsIntoState(parser.initialState, options);
|
|
39
|
-
const shouldUnwrapAnnotatedValue = options?.annotations != null || isInjectedAnnotationWrapper(parser.initialState);
|
|
40
|
-
let context = {
|
|
41
|
-
buffer: args,
|
|
42
|
-
optionsTerminated: false,
|
|
43
|
-
state: initialState,
|
|
44
|
-
usage: parser.usage
|
|
45
|
-
};
|
|
46
|
-
do {
|
|
47
|
-
const result = parser.parse(context);
|
|
48
|
-
if (!result.success) return {
|
|
49
|
-
success: false,
|
|
50
|
-
error: result.error
|
|
51
|
-
};
|
|
52
|
-
const previousBuffer = context.buffer;
|
|
53
|
-
context = result.next;
|
|
54
|
-
if (context.buffer.length > 0 && context.buffer.length === previousBuffer.length && context.buffer.every((item, i) => item === previousBuffer[i])) return {
|
|
55
|
-
success: false,
|
|
56
|
-
error: message`Unexpected option or argument: ${context.buffer[0]}.`
|
|
57
|
-
};
|
|
58
|
-
} while (context.buffer.length > 0);
|
|
59
|
-
const endResult = parser.complete(context.state);
|
|
60
|
-
return endResult.success ? {
|
|
61
|
-
success: true,
|
|
62
|
-
value: shouldUnwrapAnnotatedValue ? unwrapInjectedAnnotationWrapper(endResult.value) : endResult.value
|
|
63
|
-
} : {
|
|
64
|
-
success: false,
|
|
65
|
-
error: endResult.error
|
|
66
|
-
};
|
|
67
|
-
}
|
|
68
|
-
/**
|
|
69
|
-
* Parses an array of command-line arguments using the provided combined parser.
|
|
70
|
-
* This function processes the input arguments, applying the parser to each
|
|
71
|
-
* argument until all arguments are consumed or an error occurs.
|
|
72
|
-
*
|
|
73
|
-
* This function accepts any parser (sync or async) and always returns a Promise.
|
|
74
|
-
* For synchronous parsing with sync parsers, use {@link parseSync} instead.
|
|
75
|
-
*
|
|
76
|
-
* @template T The type of the value produced by the parser.
|
|
77
|
-
* @param parser The combined {@link Parser} to use for parsing the input
|
|
78
|
-
* arguments.
|
|
79
|
-
* @param args The array of command-line arguments to parse. Usually this is
|
|
80
|
-
* `process.argv.slice(2)` in Node.js or `Deno.args` in Deno.
|
|
81
|
-
* @param options Optional {@link ParseOptions} for customizing parsing behavior.
|
|
82
|
-
* @returns A Promise that resolves to a {@link Result} object indicating
|
|
83
|
-
* whether the parsing was successful or not.
|
|
84
|
-
* @since 0.9.0
|
|
85
|
-
* @since 0.10.0 Added optional `options` parameter for annotations support.
|
|
86
|
-
*/
|
|
87
|
-
async function parseAsync(parser, args, options) {
|
|
88
|
-
const initialState = injectAnnotationsIntoState(parser.initialState, options);
|
|
89
|
-
const shouldUnwrapAnnotatedValue = options?.annotations != null || isInjectedAnnotationWrapper(parser.initialState);
|
|
90
|
-
let context = {
|
|
91
|
-
buffer: args,
|
|
92
|
-
optionsTerminated: false,
|
|
93
|
-
state: initialState,
|
|
94
|
-
usage: parser.usage
|
|
95
|
-
};
|
|
96
|
-
do {
|
|
97
|
-
const result = await parser.parse(context);
|
|
98
|
-
if (!result.success) return {
|
|
99
|
-
success: false,
|
|
100
|
-
error: result.error
|
|
101
|
-
};
|
|
102
|
-
const previousBuffer = context.buffer;
|
|
103
|
-
context = result.next;
|
|
104
|
-
if (context.buffer.length > 0 && context.buffer.length === previousBuffer.length && context.buffer.every((item, i) => item === previousBuffer[i])) return {
|
|
105
|
-
success: false,
|
|
106
|
-
error: message`Unexpected option or argument: ${context.buffer[0]}.`
|
|
107
|
-
};
|
|
108
|
-
} while (context.buffer.length > 0);
|
|
109
|
-
const endResult = await parser.complete(context.state);
|
|
110
|
-
return endResult.success ? {
|
|
111
|
-
success: true,
|
|
112
|
-
value: shouldUnwrapAnnotatedValue ? unwrapInjectedAnnotationWrapper(endResult.value) : endResult.value
|
|
113
|
-
} : {
|
|
114
|
-
success: false,
|
|
115
|
-
error: endResult.error
|
|
116
|
-
};
|
|
117
|
-
}
|
|
118
|
-
/**
|
|
119
|
-
* Parses an array of command-line arguments using the provided combined parser.
|
|
120
|
-
* This function processes the input arguments, applying the parser to each
|
|
121
|
-
* argument until all arguments are consumed or an error occurs.
|
|
122
|
-
*
|
|
123
|
-
* The return type depends on the parser's mode:
|
|
124
|
-
* - Sync parsers return `Result<T>` directly.
|
|
125
|
-
* - Async parsers return `Promise<Result<T>>`.
|
|
126
|
-
*
|
|
127
|
-
* For explicit control, use {@link parseSync} or {@link parseAsync}.
|
|
128
|
-
*
|
|
129
|
-
* @template M The execution mode of the parser.
|
|
130
|
-
* @template T The type of the value produced by the parser.
|
|
131
|
-
* @param parser The combined {@link Parser} to use for parsing the input
|
|
132
|
-
* arguments.
|
|
133
|
-
* @param args The array of command-line arguments to parse. Usually this is
|
|
134
|
-
* `process.argv.slice(2)` in Node.js or `Deno.args` in Deno.
|
|
135
|
-
* @param options Optional {@link ParseOptions} for customizing parsing behavior.
|
|
136
|
-
* @returns A {@link Result} object (for sync) or Promise thereof (for async)
|
|
137
|
-
* indicating whether the parsing was successful or not.
|
|
138
|
-
* @since 0.10.0 Added optional `options` parameter for annotations support.
|
|
139
|
-
*/
|
|
140
|
-
function parse(parser, args, options) {
|
|
141
|
-
return dispatchByMode(parser.$mode, () => parseSync(parser, args, options), () => parseAsync(parser, args, options));
|
|
142
|
-
}
|
|
143
|
-
/**
|
|
144
|
-
* Generates command-line suggestions based on current parsing state.
|
|
145
|
-
* This function processes the input arguments up to the last argument,
|
|
146
|
-
* then calls the parser's suggest method with the remaining prefix.
|
|
147
|
-
*
|
|
148
|
-
* This function only accepts synchronous parsers. For asynchronous parsers,
|
|
149
|
-
* use {@link suggestAsync}.
|
|
150
|
-
*
|
|
151
|
-
* @template T The type of the value produced by the parser.
|
|
152
|
-
* @param parser The {@link Parser} to use for generating suggestions.
|
|
153
|
-
* Must be a synchronous parser.
|
|
154
|
-
* @param args The array of command-line arguments including the partial
|
|
155
|
-
* argument to complete. The last element is treated as
|
|
156
|
-
* the prefix for suggestions.
|
|
157
|
-
* @param options Optional {@link ParseOptions} for customizing parsing behavior.
|
|
158
|
-
* @returns An array of {@link Suggestion} objects containing completion
|
|
159
|
-
* candidates.
|
|
160
|
-
* @example
|
|
161
|
-
* ```typescript
|
|
162
|
-
* const parser = object({
|
|
163
|
-
* verbose: option("-v", "--verbose"),
|
|
164
|
-
* format: option("-f", "--format", choice(["json", "yaml"]))
|
|
165
|
-
* });
|
|
166
|
-
*
|
|
167
|
-
* // Get suggestions for options starting with "--"
|
|
168
|
-
* const suggestions = suggestSync(parser, ["--"]);
|
|
169
|
-
* // Returns: [{ text: "--verbose" }, { text: "--format" }]
|
|
170
|
-
*
|
|
171
|
-
* // Get suggestions after parsing some arguments
|
|
172
|
-
* const suggestions2 = suggestSync(parser, ["-v", "--format="]);
|
|
173
|
-
* // Returns: [{ text: "--format=json" }, { text: "--format=yaml" }]
|
|
174
|
-
* ```
|
|
175
|
-
* @since 0.6.0
|
|
176
|
-
* @since 0.9.0 Renamed from the original `suggest` function.
|
|
177
|
-
* @since 0.10.0 Added optional `options` parameter for annotations support.
|
|
178
|
-
*/
|
|
179
|
-
function suggestSync(parser, args, options) {
|
|
180
|
-
const allButLast = args.slice(0, -1);
|
|
181
|
-
const prefix = args[args.length - 1];
|
|
182
|
-
const initialState = injectAnnotationsIntoState(parser.initialState, options);
|
|
183
|
-
let context = {
|
|
184
|
-
buffer: allButLast,
|
|
185
|
-
optionsTerminated: false,
|
|
186
|
-
state: initialState,
|
|
187
|
-
usage: parser.usage
|
|
188
|
-
};
|
|
189
|
-
while (context.buffer.length > 0) {
|
|
190
|
-
const result = parser.parse(context);
|
|
191
|
-
if (!result.success) return Array.from(parser.suggest(context, prefix));
|
|
192
|
-
const previousBuffer = context.buffer;
|
|
193
|
-
context = result.next;
|
|
194
|
-
if (context.buffer.length > 0 && context.buffer.length === previousBuffer.length && context.buffer.every((item, i) => item === previousBuffer[i])) return [];
|
|
195
|
-
}
|
|
196
|
-
return Array.from(parser.suggest(context, prefix));
|
|
197
|
-
}
|
|
198
|
-
/**
|
|
199
|
-
* Generates command-line suggestions based on current parsing state.
|
|
200
|
-
* This function processes the input arguments up to the last argument,
|
|
201
|
-
* then calls the parser's suggest method with the remaining prefix.
|
|
202
|
-
*
|
|
203
|
-
* This function accepts any parser (sync or async) and always returns a Promise.
|
|
204
|
-
* For synchronous suggestion generation with sync parsers, use
|
|
205
|
-
* {@link suggestSync} instead.
|
|
206
|
-
*
|
|
207
|
-
* @template T The type of the value produced by the parser.
|
|
208
|
-
* @param parser The {@link Parser} to use for generating suggestions.
|
|
209
|
-
* @param args The array of command-line arguments including the partial
|
|
210
|
-
* argument to complete. The last element is treated as
|
|
211
|
-
* the prefix for suggestions.
|
|
212
|
-
* @param options Optional {@link ParseOptions} for customizing parsing behavior.
|
|
213
|
-
* @returns A Promise that resolves to an array of {@link Suggestion} objects
|
|
214
|
-
* containing completion candidates.
|
|
215
|
-
* @since 0.9.0
|
|
216
|
-
* @since 0.10.0 Added optional `options` parameter for annotations support.
|
|
217
|
-
*/
|
|
218
|
-
async function suggestAsync(parser, args, options) {
|
|
219
|
-
const allButLast = args.slice(0, -1);
|
|
220
|
-
const prefix = args[args.length - 1];
|
|
221
|
-
const initialState = injectAnnotationsIntoState(parser.initialState, options);
|
|
222
|
-
let context = {
|
|
223
|
-
buffer: allButLast,
|
|
224
|
-
optionsTerminated: false,
|
|
225
|
-
state: initialState,
|
|
226
|
-
usage: parser.usage
|
|
227
|
-
};
|
|
228
|
-
while (context.buffer.length > 0) {
|
|
229
|
-
const result = await parser.parse(context);
|
|
230
|
-
if (!result.success) {
|
|
231
|
-
const suggestions$1 = [];
|
|
232
|
-
for await (const suggestion of parser.suggest(context, prefix)) suggestions$1.push(suggestion);
|
|
233
|
-
return suggestions$1;
|
|
234
|
-
}
|
|
235
|
-
const previousBuffer = context.buffer;
|
|
236
|
-
context = result.next;
|
|
237
|
-
if (context.buffer.length > 0 && context.buffer.length === previousBuffer.length && context.buffer.every((item, i) => item === previousBuffer[i])) return [];
|
|
238
|
-
}
|
|
239
|
-
const suggestions = [];
|
|
240
|
-
for await (const suggestion of parser.suggest(context, prefix)) suggestions.push(suggestion);
|
|
241
|
-
return suggestions;
|
|
242
|
-
}
|
|
243
|
-
/**
|
|
244
|
-
* Generates command-line suggestions based on current parsing state.
|
|
245
|
-
* This function processes the input arguments up to the last argument,
|
|
246
|
-
* then calls the parser's suggest method with the remaining prefix.
|
|
247
|
-
*
|
|
248
|
-
* The return type depends on the parser's mode:
|
|
249
|
-
* - Sync parsers return `readonly Suggestion[]` directly.
|
|
250
|
-
* - Async parsers return `Promise<readonly Suggestion[]>`.
|
|
251
|
-
*
|
|
252
|
-
* For explicit control, use {@link suggestSync} or {@link suggestAsync}.
|
|
253
|
-
*
|
|
254
|
-
* @template M The execution mode of the parser.
|
|
255
|
-
* @template T The type of the value produced by the parser.
|
|
256
|
-
* @param parser The {@link Parser} to use for generating suggestions.
|
|
257
|
-
* @param args The array of command-line arguments including the partial
|
|
258
|
-
* argument to complete. The last element is treated as
|
|
259
|
-
* the prefix for suggestions.
|
|
260
|
-
* @param options Optional {@link ParseOptions} for customizing parsing behavior.
|
|
261
|
-
* @returns An array of {@link Suggestion} objects (for sync) or Promise thereof
|
|
262
|
-
* (for async) containing completion candidates.
|
|
263
|
-
* @since 0.6.0
|
|
264
|
-
* @since 0.10.0 Added optional `options` parameter for annotations support.
|
|
265
|
-
*/
|
|
266
|
-
function suggest(parser, args, options) {
|
|
267
|
-
return dispatchByMode(parser.$mode, () => suggestSync(parser, args, options), () => suggestAsync(parser, args, options));
|
|
268
|
-
}
|
|
269
|
-
/**
|
|
270
|
-
* Recursively searches for a command within nested exclusive usage terms.
|
|
271
|
-
* When the command is found, returns the expanded usage terms for that command.
|
|
272
|
-
*
|
|
273
|
-
* @param term The usage term to search in
|
|
274
|
-
* @param commandName The command name to find
|
|
275
|
-
* @returns The expanded usage terms if found, null otherwise
|
|
276
|
-
*/
|
|
277
|
-
function findCommandInExclusive(term, commandName) {
|
|
278
|
-
if (term.type !== "exclusive") return null;
|
|
279
|
-
for (const termGroup of term.terms) {
|
|
280
|
-
const firstTerm = termGroup[0];
|
|
281
|
-
if (firstTerm?.type === "command" && firstTerm.name === commandName) return termGroup;
|
|
282
|
-
if (firstTerm?.type === "exclusive") {
|
|
283
|
-
const found = findCommandInExclusive(firstTerm, commandName);
|
|
284
|
-
if (found) return [...found, ...termGroup.slice(1)];
|
|
285
|
-
}
|
|
286
|
-
}
|
|
287
|
-
return null;
|
|
288
|
-
}
|
|
289
|
-
/**
|
|
290
|
-
* Generates a documentation page for a synchronous parser.
|
|
291
|
-
*
|
|
292
|
-
* This is the sync-specific version of {@link getDocPage}. It only accepts
|
|
293
|
-
* sync parsers and returns the documentation page directly (not wrapped
|
|
294
|
-
* in a Promise).
|
|
295
|
-
*
|
|
296
|
-
* @param parser The sync parser to generate documentation for.
|
|
297
|
-
* @param args Optional array of command-line arguments for context.
|
|
298
|
-
* @param options Optional {@link ParseOptions} for customizing parsing behavior.
|
|
299
|
-
* @returns A {@link DocPage} or `undefined`.
|
|
300
|
-
* @since 0.9.0
|
|
301
|
-
* @since 0.10.0 Added optional `options` parameter for annotations support.
|
|
302
|
-
*/
|
|
303
|
-
function getDocPageSync(parser, args = [], options) {
|
|
304
|
-
return getDocPageSyncImpl(parser, args, options);
|
|
305
|
-
}
|
|
306
|
-
/**
|
|
307
|
-
* Generates a documentation page for any parser, returning a Promise.
|
|
308
|
-
*
|
|
309
|
-
* This function accepts parsers of any mode (sync or async) and always
|
|
310
|
-
* returns a Promise. Use this when working with parsers that may contain
|
|
311
|
-
* async value parsers.
|
|
312
|
-
*
|
|
313
|
-
* @param parser The parser to generate documentation for.
|
|
314
|
-
* @param args Optional array of command-line arguments for context.
|
|
315
|
-
* @param options Optional {@link ParseOptions} for customizing parsing behavior.
|
|
316
|
-
* @returns A Promise of {@link DocPage} or `undefined`.
|
|
317
|
-
* @since 0.9.0
|
|
318
|
-
* @since 0.10.0 Added optional `options` parameter for annotations support.
|
|
319
|
-
*/
|
|
320
|
-
function getDocPageAsync(parser, args = [], options) {
|
|
321
|
-
if (parser.$mode === "sync") return Promise.resolve(getDocPageSyncImpl(parser, args, options));
|
|
322
|
-
return getDocPageAsyncImpl(parser, args, options);
|
|
323
|
-
}
|
|
324
|
-
function getDocPage(parser, args = [], options) {
|
|
325
|
-
if (parser.$mode === "sync") return getDocPageSyncImpl(parser, args, options);
|
|
326
|
-
return getDocPageAsyncImpl(parser, args, options);
|
|
327
|
-
}
|
|
328
|
-
/**
|
|
329
|
-
* Internal sync implementation of getDocPage.
|
|
330
|
-
*/
|
|
331
|
-
function getDocPageSyncImpl(parser, args, options) {
|
|
332
|
-
const initialState = injectAnnotationsIntoState(parser.initialState, options);
|
|
333
|
-
let context = {
|
|
334
|
-
buffer: args,
|
|
335
|
-
optionsTerminated: false,
|
|
336
|
-
state: initialState,
|
|
337
|
-
usage: parser.usage
|
|
338
|
-
};
|
|
339
|
-
while (context.buffer.length > 0) {
|
|
340
|
-
const result = parser.parse(context);
|
|
341
|
-
if (!result.success) break;
|
|
342
|
-
context = result.next;
|
|
343
|
-
}
|
|
344
|
-
return buildDocPage(parser, context, args);
|
|
345
|
-
}
|
|
346
|
-
/**
|
|
347
|
-
* Internal async implementation of getDocPage.
|
|
348
|
-
*/
|
|
349
|
-
async function getDocPageAsyncImpl(parser, args, options) {
|
|
350
|
-
const initialState = injectAnnotationsIntoState(parser.initialState, options);
|
|
351
|
-
let context = {
|
|
352
|
-
buffer: args,
|
|
353
|
-
optionsTerminated: false,
|
|
354
|
-
state: initialState,
|
|
355
|
-
usage: parser.usage
|
|
356
|
-
};
|
|
357
|
-
while (context.buffer.length > 0) {
|
|
358
|
-
const result = await parser.parse(context);
|
|
359
|
-
if (!result.success) break;
|
|
360
|
-
context = result.next;
|
|
361
|
-
}
|
|
362
|
-
return buildDocPage(parser, context, args);
|
|
363
|
-
}
|
|
364
|
-
/**
|
|
365
|
-
* Builds a DocPage from the parser and context.
|
|
366
|
-
* Shared by both sync and async implementations.
|
|
367
|
-
*/
|
|
368
|
-
function buildDocPage(parser, context, args) {
|
|
369
|
-
const { brief, description, fragments, footer } = parser.getDocFragments({
|
|
370
|
-
kind: "available",
|
|
371
|
-
state: context.state
|
|
372
|
-
}, void 0);
|
|
373
|
-
const buildingSections = [];
|
|
374
|
-
let untitledSection = null;
|
|
375
|
-
const titledSectionMap = /* @__PURE__ */ new Map();
|
|
376
|
-
for (const fragment of fragments) if (fragment.type === "entry") {
|
|
377
|
-
if (untitledSection == null) {
|
|
378
|
-
untitledSection = { entries: [] };
|
|
379
|
-
buildingSections.push(untitledSection);
|
|
380
|
-
}
|
|
381
|
-
untitledSection.entries.push(fragment);
|
|
382
|
-
} else if (fragment.type === "section") if (fragment.title == null) {
|
|
383
|
-
if (untitledSection == null) {
|
|
384
|
-
untitledSection = { entries: [] };
|
|
385
|
-
buildingSections.push(untitledSection);
|
|
386
|
-
}
|
|
387
|
-
untitledSection.entries.push(...fragment.entries);
|
|
388
|
-
} else {
|
|
389
|
-
let section = titledSectionMap.get(fragment.title);
|
|
390
|
-
if (section == null) {
|
|
391
|
-
section = {
|
|
392
|
-
title: fragment.title,
|
|
393
|
-
entries: []
|
|
394
|
-
};
|
|
395
|
-
titledSectionMap.set(fragment.title, section);
|
|
396
|
-
buildingSections.push(section);
|
|
397
|
-
}
|
|
398
|
-
section.entries.push(...fragment.entries);
|
|
399
|
-
}
|
|
400
|
-
const sections = buildingSections;
|
|
401
|
-
const usage = [...normalizeUsage(parser.usage)];
|
|
402
|
-
const maybeApplyCommandUsageLine = (term, arg, isLastArg, usageIndex) => {
|
|
403
|
-
if (term?.type !== "command" || term.name !== arg || !isLastArg || term.usageLine == null) return;
|
|
404
|
-
const defaultUsageLine = usage.slice(usageIndex + 1);
|
|
405
|
-
const customUsageLine = typeof term.usageLine === "function" ? term.usageLine(defaultUsageLine) : term.usageLine;
|
|
406
|
-
const normalizedCustomUsageLine = normalizeUsage(customUsageLine);
|
|
407
|
-
usage.splice(usageIndex + 1, usage.length - (usageIndex + 1), ...normalizedCustomUsageLine);
|
|
408
|
-
};
|
|
409
|
-
let i = 0;
|
|
410
|
-
for (let argIndex = 0; argIndex < args.length; argIndex++) {
|
|
411
|
-
const arg = args[argIndex];
|
|
412
|
-
if (i >= usage.length) break;
|
|
413
|
-
let term = usage[i];
|
|
414
|
-
if (term.type === "exclusive") {
|
|
415
|
-
const found = findCommandInExclusive(term, arg);
|
|
416
|
-
if (found) {
|
|
417
|
-
usage.splice(i, 1, ...found);
|
|
418
|
-
term = usage[i];
|
|
419
|
-
}
|
|
420
|
-
}
|
|
421
|
-
maybeApplyCommandUsageLine(term, arg, argIndex === args.length - 1, i);
|
|
422
|
-
i++;
|
|
423
|
-
}
|
|
424
|
-
return {
|
|
425
|
-
usage,
|
|
426
|
-
sections,
|
|
427
|
-
...brief != null && { brief },
|
|
428
|
-
...description != null && { description },
|
|
429
|
-
...footer != null && { footer }
|
|
430
|
-
};
|
|
431
|
-
}
|
|
432
|
-
|
|
433
|
-
//#endregion
|
|
434
|
-
export { DuplicateOptionError, WithDefaultError, argument, command, concat, conditional, constant, fail, flag, getDocPage, getDocPageAsync, getDocPageSync, group, longestMatch, map, merge, multiple, nonEmpty, object, option, optional, or, parse, parseAsync, parseSync, passThrough, suggest, suggestAsync, suggestSync, tuple, withDefault };
|
|
3
|
+
export { createParserContext, getDocPage, getDocPageAsync, getDocPageSync, parse, parseAsync, parseSync, suggest, suggestAsync, suggestSync };
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
const require_annotations = require('./internal/annotations.cjs');
|
|
2
|
+
const require_mode_dispatch = require('./internal/mode-dispatch.cjs');
|
|
3
|
+
|
|
4
|
+
//#region src/phase2-seed.ts
|
|
5
|
+
/**
|
|
6
|
+
* Internal parser hook key for phase-two seed extraction.
|
|
7
|
+
*
|
|
8
|
+
* @internal
|
|
9
|
+
*/
|
|
10
|
+
const extractPhase2SeedKey = Symbol("@optique/core/extractPhase2Seed");
|
|
11
|
+
/**
|
|
12
|
+
* Converts a successful complete() result into a phase-two seed.
|
|
13
|
+
*
|
|
14
|
+
* @internal
|
|
15
|
+
*/
|
|
16
|
+
function phase2SeedFromValueResult(result) {
|
|
17
|
+
return {
|
|
18
|
+
value: require_annotations.unwrapInjectedAnnotationWrapper(result.value),
|
|
19
|
+
...result.deferred ? { deferred: true } : {},
|
|
20
|
+
...result.deferredKeys != null ? { deferredKeys: result.deferredKeys } : {}
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Invokes a parser's internal phase-two seed hook when present.
|
|
25
|
+
*
|
|
26
|
+
* @internal
|
|
27
|
+
*/
|
|
28
|
+
function extractPhase2Seed(parser, state, exec) {
|
|
29
|
+
return require_mode_dispatch.dispatchByMode(parser.mode, () => {
|
|
30
|
+
const extractor = parser[extractPhase2SeedKey];
|
|
31
|
+
return extractor == null ? null : extractor(state, exec);
|
|
32
|
+
}, async () => {
|
|
33
|
+
const extractor = parser[extractPhase2SeedKey];
|
|
34
|
+
return extractor == null ? null : await extractor(state, exec);
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Attempts to complete a parser and falls back to the internal phase-two
|
|
39
|
+
* seed hook when completion returns an unsuccessful result.
|
|
40
|
+
*
|
|
41
|
+
* @internal
|
|
42
|
+
*/
|
|
43
|
+
function completeOrExtractPhase2Seed(parser, state, exec) {
|
|
44
|
+
return require_mode_dispatch.dispatchByMode(parser.mode, () => {
|
|
45
|
+
const result = parser.complete(state, exec);
|
|
46
|
+
if (result.success) return phase2SeedFromValueResult(result);
|
|
47
|
+
return extractPhase2Seed(parser, state, exec);
|
|
48
|
+
}, async () => {
|
|
49
|
+
const result = await parser.complete(state, exec);
|
|
50
|
+
if (result.success) return phase2SeedFromValueResult(result);
|
|
51
|
+
return await extractPhase2Seed(parser, state, exec);
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
//#endregion
|
|
56
|
+
exports.completeOrExtractPhase2Seed = completeOrExtractPhase2Seed;
|
|
57
|
+
exports.extractPhase2Seed = extractPhase2Seed;
|
|
58
|
+
exports.extractPhase2SeedKey = extractPhase2SeedKey;
|
|
59
|
+
exports.phase2SeedFromValueResult = phase2SeedFromValueResult;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { unwrapInjectedAnnotationWrapper } from "./internal/annotations.js";
|
|
2
|
+
import { dispatchByMode } from "./internal/mode-dispatch.js";
|
|
3
|
+
|
|
4
|
+
//#region src/phase2-seed.ts
|
|
5
|
+
/**
|
|
6
|
+
* Internal parser hook key for phase-two seed extraction.
|
|
7
|
+
*
|
|
8
|
+
* @internal
|
|
9
|
+
*/
|
|
10
|
+
const extractPhase2SeedKey = Symbol("@optique/core/extractPhase2Seed");
|
|
11
|
+
/**
|
|
12
|
+
* Converts a successful complete() result into a phase-two seed.
|
|
13
|
+
*
|
|
14
|
+
* @internal
|
|
15
|
+
*/
|
|
16
|
+
function phase2SeedFromValueResult(result) {
|
|
17
|
+
return {
|
|
18
|
+
value: unwrapInjectedAnnotationWrapper(result.value),
|
|
19
|
+
...result.deferred ? { deferred: true } : {},
|
|
20
|
+
...result.deferredKeys != null ? { deferredKeys: result.deferredKeys } : {}
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Invokes a parser's internal phase-two seed hook when present.
|
|
25
|
+
*
|
|
26
|
+
* @internal
|
|
27
|
+
*/
|
|
28
|
+
function extractPhase2Seed(parser, state, exec) {
|
|
29
|
+
return dispatchByMode(parser.mode, () => {
|
|
30
|
+
const extractor = parser[extractPhase2SeedKey];
|
|
31
|
+
return extractor == null ? null : extractor(state, exec);
|
|
32
|
+
}, async () => {
|
|
33
|
+
const extractor = parser[extractPhase2SeedKey];
|
|
34
|
+
return extractor == null ? null : await extractor(state, exec);
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Attempts to complete a parser and falls back to the internal phase-two
|
|
39
|
+
* seed hook when completion returns an unsuccessful result.
|
|
40
|
+
*
|
|
41
|
+
* @internal
|
|
42
|
+
*/
|
|
43
|
+
function completeOrExtractPhase2Seed(parser, state, exec) {
|
|
44
|
+
return dispatchByMode(parser.mode, () => {
|
|
45
|
+
const result = parser.complete(state, exec);
|
|
46
|
+
if (result.success) return phase2SeedFromValueResult(result);
|
|
47
|
+
return extractPhase2Seed(parser, state, exec);
|
|
48
|
+
}, async () => {
|
|
49
|
+
const result = await parser.complete(state, exec);
|
|
50
|
+
if (result.success) return phase2SeedFromValueResult(result);
|
|
51
|
+
return await extractPhase2Seed(parser, state, exec);
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
//#endregion
|
|
56
|
+
export { completeOrExtractPhase2Seed, extractPhase2Seed, extractPhase2SeedKey, phase2SeedFromValueResult };
|