@optique/core 1.0.0-dev.1810 → 1.0.0-dev.1826
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 +1 -0
- package/dist/constructs.js +1 -0
- package/dist/facade.cjs +309 -160
- package/dist/facade.js +312 -163
- package/dist/modifiers.cjs +1 -0
- package/dist/modifiers.js +1 -0
- package/dist/parser.d.cts +10 -0
- package/dist/parser.d.ts +10 -0
- package/dist/primitives.cjs +10 -1
- package/dist/primitives.js +10 -1
- package/dist/validate.cjs +7 -39
- package/dist/validate.js +7 -39
- package/package.json +1 -1
package/dist/constructs.cjs
CHANGED
|
@@ -51,6 +51,7 @@ function mergeChildExec(parent, child) {
|
|
|
51
51
|
trace: child.trace ?? parent.trace,
|
|
52
52
|
dependencyRuntime: child.dependencyRuntime ?? parent.dependencyRuntime,
|
|
53
53
|
dependencyRegistry: child.dependencyRegistry ?? parent.dependencyRegistry,
|
|
54
|
+
commandPath: child.commandPath ?? parent.commandPath,
|
|
54
55
|
preCompletedByParser: child.preCompletedByParser ?? parent.preCompletedByParser,
|
|
55
56
|
excludedSourceFields: child.excludedSourceFields ?? parent.excludedSourceFields
|
|
56
57
|
};
|
package/dist/constructs.js
CHANGED
|
@@ -51,6 +51,7 @@ function mergeChildExec(parent, child) {
|
|
|
51
51
|
trace: child.trace ?? parent.trace,
|
|
52
52
|
dependencyRuntime: child.dependencyRuntime ?? parent.dependencyRuntime,
|
|
53
53
|
dependencyRegistry: child.dependencyRegistry ?? parent.dependencyRegistry,
|
|
54
|
+
commandPath: child.commandPath ?? parent.commandPath,
|
|
54
55
|
preCompletedByParser: child.preCompletedByParser ?? parent.preCompletedByParser,
|
|
55
56
|
excludedSourceFields: child.excludedSourceFields ?? parent.excludedSourceFields
|
|
56
57
|
};
|
package/dist/facade.cjs
CHANGED
|
@@ -95,11 +95,147 @@ function withPreparedParsedForContext(context, preparedParsed, run) {
|
|
|
95
95
|
function isBufferUnchanged(previous, current) {
|
|
96
96
|
return current.length > 0 && current.length === previous.length && current.every((item, i) => item === previous[i]);
|
|
97
97
|
}
|
|
98
|
+
function getFailureProgress(args, buffer, consumedInStep) {
|
|
99
|
+
return {
|
|
100
|
+
remainingArgs: buffer.slice(consumedInStep),
|
|
101
|
+
consumedCount: args.length - buffer.length + consumedInStep
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
function createParseExec(parser) {
|
|
105
|
+
return {
|
|
106
|
+
usage: parser.usage,
|
|
107
|
+
phase: "parse",
|
|
108
|
+
path: [],
|
|
109
|
+
commandPath: [],
|
|
110
|
+
trace: require_input_trace.createInputTrace()
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
function getCommandPath(exec) {
|
|
114
|
+
return exec?.commandPath ?? [];
|
|
115
|
+
}
|
|
116
|
+
function createCompleteExec(exec, context) {
|
|
117
|
+
const runtime = require_dependency_runtime.createDependencyRuntimeContext();
|
|
118
|
+
return {
|
|
119
|
+
...exec,
|
|
120
|
+
phase: "complete",
|
|
121
|
+
dependencyRuntime: runtime,
|
|
122
|
+
dependencyRegistry: runtime.registry,
|
|
123
|
+
commandPath: getCommandPath(context.exec) ?? exec.commandPath,
|
|
124
|
+
trace: context.exec?.trace ?? context.trace ?? exec.trace
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
function attemptParseSync(parser, args, mode = "complete") {
|
|
128
|
+
const shouldUnwrapAnnotatedValue = require_annotations.isInjectedAnnotationWrapper(parser.initialState);
|
|
129
|
+
const exec = createParseExec(parser);
|
|
130
|
+
let context = require_parser.createParserContext({
|
|
131
|
+
buffer: args,
|
|
132
|
+
state: parser.initialState,
|
|
133
|
+
optionsTerminated: false
|
|
134
|
+
}, exec);
|
|
135
|
+
do {
|
|
136
|
+
const result = parser.parse(context);
|
|
137
|
+
if (!result.success) {
|
|
138
|
+
const progress = getFailureProgress(args, context.buffer, result.consumed);
|
|
139
|
+
return {
|
|
140
|
+
kind: "failure",
|
|
141
|
+
error: result.error,
|
|
142
|
+
remainingArgs: progress.remainingArgs,
|
|
143
|
+
consumedCount: progress.consumedCount,
|
|
144
|
+
optionsTerminated: context.optionsTerminated,
|
|
145
|
+
commandPath: getCommandPath(context.exec)
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
const previousBuffer = context.buffer;
|
|
149
|
+
context = result.next;
|
|
150
|
+
if (isBufferUnchanged(previousBuffer, context.buffer)) {
|
|
151
|
+
const progress = getFailureProgress(args, previousBuffer, result.consumed.length);
|
|
152
|
+
return {
|
|
153
|
+
kind: "failure",
|
|
154
|
+
error: require_message.message`Unexpected option or argument: ${context.buffer[0]}.`,
|
|
155
|
+
remainingArgs: progress.remainingArgs,
|
|
156
|
+
consumedCount: progress.consumedCount,
|
|
157
|
+
optionsTerminated: context.optionsTerminated,
|
|
158
|
+
commandPath: getCommandPath(context.exec)
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
} while (context.buffer.length > 0);
|
|
162
|
+
if (mode === "parse-only") return {
|
|
163
|
+
kind: "success",
|
|
164
|
+
value: void 0
|
|
165
|
+
};
|
|
166
|
+
const endResult = parser.complete(context.state, createCompleteExec(exec, context));
|
|
167
|
+
if (!endResult.success) return {
|
|
168
|
+
kind: "failure",
|
|
169
|
+
error: endResult.error,
|
|
170
|
+
remainingArgs: [],
|
|
171
|
+
consumedCount: args.length,
|
|
172
|
+
optionsTerminated: context.optionsTerminated,
|
|
173
|
+
commandPath: getCommandPath(context.exec)
|
|
174
|
+
};
|
|
175
|
+
return {
|
|
176
|
+
kind: "success",
|
|
177
|
+
value: shouldUnwrapAnnotatedValue ? require_annotations.unwrapInjectedAnnotationWrapper(endResult.value) : endResult.value
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
async function attemptParseAsync(parser, args, mode = "complete") {
|
|
181
|
+
const shouldUnwrapAnnotatedValue = require_annotations.isInjectedAnnotationWrapper(parser.initialState);
|
|
182
|
+
const exec = createParseExec(parser);
|
|
183
|
+
let context = require_parser.createParserContext({
|
|
184
|
+
buffer: args,
|
|
185
|
+
state: parser.initialState,
|
|
186
|
+
optionsTerminated: false
|
|
187
|
+
}, exec);
|
|
188
|
+
do {
|
|
189
|
+
const result = await parser.parse(context);
|
|
190
|
+
if (!result.success) {
|
|
191
|
+
const progress = getFailureProgress(args, context.buffer, result.consumed);
|
|
192
|
+
return {
|
|
193
|
+
kind: "failure",
|
|
194
|
+
error: result.error,
|
|
195
|
+
remainingArgs: progress.remainingArgs,
|
|
196
|
+
consumedCount: progress.consumedCount,
|
|
197
|
+
optionsTerminated: context.optionsTerminated,
|
|
198
|
+
commandPath: getCommandPath(context.exec)
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
const previousBuffer = context.buffer;
|
|
202
|
+
context = result.next;
|
|
203
|
+
if (isBufferUnchanged(previousBuffer, context.buffer)) {
|
|
204
|
+
const progress = getFailureProgress(args, previousBuffer, result.consumed.length);
|
|
205
|
+
return {
|
|
206
|
+
kind: "failure",
|
|
207
|
+
error: require_message.message`Unexpected option or argument: ${context.buffer[0]}.`,
|
|
208
|
+
remainingArgs: progress.remainingArgs,
|
|
209
|
+
consumedCount: progress.consumedCount,
|
|
210
|
+
optionsTerminated: context.optionsTerminated,
|
|
211
|
+
commandPath: getCommandPath(context.exec)
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
} while (context.buffer.length > 0);
|
|
215
|
+
if (mode === "parse-only") return {
|
|
216
|
+
kind: "success",
|
|
217
|
+
value: void 0
|
|
218
|
+
};
|
|
219
|
+
const endResult = await parser.complete(context.state, createCompleteExec(exec, context));
|
|
220
|
+
if (!endResult.success) return {
|
|
221
|
+
kind: "failure",
|
|
222
|
+
error: endResult.error,
|
|
223
|
+
remainingArgs: [],
|
|
224
|
+
consumedCount: args.length,
|
|
225
|
+
optionsTerminated: context.optionsTerminated,
|
|
226
|
+
commandPath: getCommandPath(context.exec)
|
|
227
|
+
};
|
|
228
|
+
return {
|
|
229
|
+
kind: "success",
|
|
230
|
+
value: shouldUnwrapAnnotatedValue ? require_annotations.unwrapInjectedAnnotationWrapper(endResult.value) : endResult.value
|
|
231
|
+
};
|
|
232
|
+
}
|
|
98
233
|
function createPhase2SeedExec(parser, context) {
|
|
99
234
|
const exec = {
|
|
100
235
|
usage: parser.usage,
|
|
101
236
|
phase: "parse",
|
|
102
237
|
path: [],
|
|
238
|
+
commandPath: [],
|
|
103
239
|
trace: require_input_trace.createInputTrace()
|
|
104
240
|
};
|
|
105
241
|
const runtime = require_dependency_runtime.createDependencyRuntimeContext();
|
|
@@ -108,6 +244,7 @@ function createPhase2SeedExec(parser, context) {
|
|
|
108
244
|
phase: "complete",
|
|
109
245
|
dependencyRuntime: runtime,
|
|
110
246
|
dependencyRegistry: runtime.registry,
|
|
247
|
+
commandPath: getCommandPath(context.exec),
|
|
111
248
|
trace: context.exec?.trace ?? context.trace ?? exec.trace
|
|
112
249
|
};
|
|
113
250
|
}
|
|
@@ -116,6 +253,7 @@ function createPhase2SeedContext(parser, args) {
|
|
|
116
253
|
usage: parser.usage,
|
|
117
254
|
phase: "parse",
|
|
118
255
|
path: [],
|
|
256
|
+
commandPath: [],
|
|
119
257
|
trace: require_input_trace.createInputTrace()
|
|
120
258
|
};
|
|
121
259
|
return require_parser.createParserContext({
|
|
@@ -203,9 +341,6 @@ function createVersionParser(commandConfig, optionConfig) {
|
|
|
203
341
|
};
|
|
204
342
|
}
|
|
205
343
|
const metaResultBrand = Symbol("@optique/core/facade/meta");
|
|
206
|
-
function isMetaParseResult(value$1) {
|
|
207
|
-
return typeof value$1 === "object" && value$1 != null && metaResultBrand in value$1;
|
|
208
|
-
}
|
|
209
344
|
/**
|
|
210
345
|
* Creates completion parsers based on the sub-config.
|
|
211
346
|
*/
|
|
@@ -473,54 +608,115 @@ function combineWithHelpVersion(originalParser, helpParsers, versionParsers, com
|
|
|
473
608
|
}
|
|
474
609
|
return combined;
|
|
475
610
|
}
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
error: result.error
|
|
484
|
-
};
|
|
485
|
-
const value$1 = result.value;
|
|
486
|
-
if (isMetaParseResult(value$1)) {
|
|
487
|
-
const parsedValue = value$1;
|
|
488
|
-
const hasVersionOption = versionOptionNames.some((n) => args.includes(n));
|
|
489
|
-
const hasVersionCommand = args.length > 0 && versionCommandNames.includes(args[0]);
|
|
490
|
-
const hasCompletionCommand = args.length > 0 && completionCommandNames.includes(args[0]);
|
|
491
|
-
const hasHelpOption = hasCompletionCommand ? helpOptionNames.length > 0 && args.length >= 2 && helpOptionNames.includes(args[1]) : helpOptionNames.some((n) => args.includes(n));
|
|
492
|
-
const hasHelpCommand = args.length > 0 && helpCommandNames.includes(args[0]);
|
|
493
|
-
if (hasVersionCommand && hasHelpOption && parsedValue.helpFlag) return {
|
|
494
|
-
type: "help",
|
|
495
|
-
commands: [args[0]]
|
|
611
|
+
function classifyOptionMeta(scanArgs, fullArgs, helpOptionNames, versionOptionNames, completionOptionNames) {
|
|
612
|
+
let lastHelpVersion;
|
|
613
|
+
for (let i = 0; i < scanArgs.length; i++) {
|
|
614
|
+
const arg = scanArgs[i];
|
|
615
|
+
if (helpOptionNames.includes(arg)) lastHelpVersion = {
|
|
616
|
+
index: i,
|
|
617
|
+
kind: "help"
|
|
496
618
|
};
|
|
497
|
-
if (
|
|
498
|
-
|
|
499
|
-
|
|
619
|
+
else if (versionOptionNames.includes(arg)) lastHelpVersion = {
|
|
620
|
+
index: i,
|
|
621
|
+
kind: "version"
|
|
622
|
+
};
|
|
623
|
+
const equalsMatch = completionOptionNames.find((name) => arg.startsWith(name + "="));
|
|
624
|
+
if (equalsMatch != null) return {
|
|
625
|
+
lastHelpVersion,
|
|
626
|
+
completion: {
|
|
627
|
+
index: i,
|
|
628
|
+
shell: arg.slice(equalsMatch.length + 1),
|
|
629
|
+
args: fullArgs.slice(i + 1)
|
|
630
|
+
}
|
|
500
631
|
};
|
|
501
|
-
if (
|
|
502
|
-
|
|
503
|
-
if (Array.isArray(parsedValue.commands)) commandContext = parsedValue.commands;
|
|
504
|
-
else if (typeof parsedValue.commands === "object" && parsedValue.commands != null && "length" in parsedValue.commands) commandContext = parsedValue.commands;
|
|
632
|
+
if (completionOptionNames.includes(arg)) {
|
|
633
|
+
const shell = scanArgs[i + 1] ?? "";
|
|
505
634
|
return {
|
|
506
|
-
|
|
507
|
-
|
|
635
|
+
lastHelpVersion,
|
|
636
|
+
completion: {
|
|
637
|
+
index: i,
|
|
638
|
+
shell,
|
|
639
|
+
args: shell === "" ? [] : fullArgs.slice(i + 2)
|
|
640
|
+
}
|
|
508
641
|
};
|
|
509
642
|
}
|
|
510
|
-
|
|
511
|
-
|
|
643
|
+
}
|
|
644
|
+
return { lastHelpVersion };
|
|
645
|
+
}
|
|
646
|
+
function getHelpCommandContext(commandPath, args, helpIndex) {
|
|
647
|
+
const commands = [...commandPath];
|
|
648
|
+
for (let i = 0; i < helpIndex; i++) {
|
|
649
|
+
const arg = args[i];
|
|
650
|
+
if (!arg.startsWith("-")) commands.push(arg);
|
|
651
|
+
}
|
|
652
|
+
return commands;
|
|
653
|
+
}
|
|
654
|
+
function classifyParseFailure(failure, helpOptionNames, helpCommandNames, versionOptionNames, versionCommandNames, completionOptionNames, completionCommandNames) {
|
|
655
|
+
if (failure.remainingArgs.length < 1) return {
|
|
656
|
+
type: "error",
|
|
657
|
+
error: failure.error
|
|
658
|
+
};
|
|
659
|
+
const hasConsumedPrefix = failure.consumedCount > 0;
|
|
660
|
+
const firstArg = failure.remainingArgs[0];
|
|
661
|
+
if (!hasConsumedPrefix && completionCommandNames.includes(firstArg)) {
|
|
662
|
+
const secondArg = failure.remainingArgs[1];
|
|
663
|
+
if (helpOptionNames.includes(secondArg)) return {
|
|
664
|
+
type: "help",
|
|
665
|
+
commands: [firstArg]
|
|
666
|
+
};
|
|
667
|
+
return {
|
|
512
668
|
type: "completion",
|
|
513
|
-
|
|
514
|
-
|
|
669
|
+
source: "command",
|
|
670
|
+
shell: secondArg ?? "",
|
|
671
|
+
args: failure.remainingArgs.slice(2)
|
|
515
672
|
};
|
|
673
|
+
}
|
|
674
|
+
const optionArgs = failure.optionsTerminated ? [] : (() => {
|
|
675
|
+
const terminatorIndex = failure.remainingArgs.indexOf("--");
|
|
676
|
+
return terminatorIndex >= 0 ? failure.remainingArgs.slice(0, terminatorIndex) : failure.remainingArgs;
|
|
677
|
+
})();
|
|
678
|
+
const { lastHelpVersion, completion } = classifyOptionMeta(optionArgs, failure.remainingArgs, helpOptionNames, versionOptionNames, completionOptionNames);
|
|
679
|
+
if (!hasConsumedPrefix && versionCommandNames.includes(firstArg)) {
|
|
680
|
+
const secondArg = failure.remainingArgs[1];
|
|
681
|
+
if (helpOptionNames.includes(secondArg)) return {
|
|
682
|
+
type: "help",
|
|
683
|
+
commands: [firstArg]
|
|
684
|
+
};
|
|
685
|
+
const isCompletionImmediatelyAfter = completion?.index === 1;
|
|
686
|
+
if (secondArg == null || isCompletionImmediatelyAfter || lastHelpVersion?.index === 1 && lastHelpVersion.kind === "version") return { type: "version" };
|
|
516
687
|
return {
|
|
517
|
-
type: "
|
|
518
|
-
|
|
688
|
+
type: "error",
|
|
689
|
+
error: failure.error
|
|
519
690
|
};
|
|
520
691
|
}
|
|
692
|
+
let commandAction;
|
|
693
|
+
if (!hasConsumedPrefix && helpCommandNames.includes(firstArg)) commandAction = {
|
|
694
|
+
index: 0,
|
|
695
|
+
kind: "help"
|
|
696
|
+
};
|
|
697
|
+
const winner = lastHelpVersion == null ? commandAction : commandAction == null || lastHelpVersion.index >= commandAction.index ? lastHelpVersion : commandAction;
|
|
698
|
+
if (winner?.kind === "help") {
|
|
699
|
+
if (winner === commandAction) return {
|
|
700
|
+
type: "help",
|
|
701
|
+
commands: failure.remainingArgs.slice(1)
|
|
702
|
+
};
|
|
703
|
+
return {
|
|
704
|
+
type: "help",
|
|
705
|
+
commands: getHelpCommandContext(failure.commandPath, failure.remainingArgs, winner.index),
|
|
706
|
+
preferUserCommandDocs: failure.commandPath.length > 0
|
|
707
|
+
};
|
|
708
|
+
}
|
|
709
|
+
if (winner?.kind === "version") return { type: "version" };
|
|
710
|
+
if (completion != null) return {
|
|
711
|
+
type: "completion",
|
|
712
|
+
source: "option",
|
|
713
|
+
shell: completion.shell,
|
|
714
|
+
commandPath: failure.commandPath,
|
|
715
|
+
args: completion.args
|
|
716
|
+
};
|
|
521
717
|
return {
|
|
522
|
-
type: "
|
|
523
|
-
|
|
718
|
+
type: "error",
|
|
719
|
+
error: failure.error
|
|
524
720
|
};
|
|
525
721
|
}
|
|
526
722
|
/**
|
|
@@ -694,12 +890,7 @@ function runParser(parserOrProgram, programNameOrArgs, argsOrOptions, optionsPar
|
|
|
694
890
|
"completion command",
|
|
695
891
|
completionCommandNames
|
|
696
892
|
]);
|
|
697
|
-
require_validate.validateMetaNameCollisions(
|
|
698
|
-
leadingNames: parser.leadingNames,
|
|
699
|
-
allOptions: require_usage.extractOptionNames(parser.usage, true),
|
|
700
|
-
allCommands: require_usage.extractCommandNames(parser.usage, true),
|
|
701
|
-
allLiterals: require_usage.extractLiteralValues(parser.usage)
|
|
702
|
-
}, activeMetaEntries);
|
|
893
|
+
require_validate.validateMetaNameCollisions(activeMetaEntries);
|
|
703
894
|
const defaultShells = {
|
|
704
895
|
bash: require_completion.bash,
|
|
705
896
|
fish: require_completion.fish,
|
|
@@ -723,50 +914,6 @@ function runParser(parserOrProgram, programNameOrArgs, argsOrOptions, optionsPar
|
|
|
723
914
|
completionCommand: null,
|
|
724
915
|
completionOption: null
|
|
725
916
|
};
|
|
726
|
-
if (options.completion) {
|
|
727
|
-
const helpTerminatorIndex = args.indexOf("--");
|
|
728
|
-
const helpOptionArgs = helpTerminatorIndex >= 0 ? args.slice(0, helpTerminatorIndex) : args;
|
|
729
|
-
const hasHelpOption = helpOptionConfig ? completionCommandConfig && completionCommandNames.includes(args[0]) ? args.length >= 2 && helpOptionNames.includes(args[1]) : helpOptionNames.some((n) => helpOptionArgs.includes(n)) : false;
|
|
730
|
-
if (completionCommandConfig && args.length >= 1 && completionCommandNames.includes(args[0]) && !hasHelpOption) return handleCompletion(args.slice(1), programName, parser, completionParsers.completionCommand, stdout, stderr, onCompletionResult, onErrorResult, availableShells, colors, maxWidth, completionCommandNames[0], completionOptionNames[0], false, sectionOrder);
|
|
731
|
-
const hasMetaEntryBefore = (endIndex) => {
|
|
732
|
-
const argsBefore = args.slice(0, endIndex);
|
|
733
|
-
if (helpOptionConfig && helpOptionNames.some((n) => argsBefore.includes(n))) return true;
|
|
734
|
-
if (versionOptionConfig && versionOptionNames.some((n) => argsBefore.includes(n))) return true;
|
|
735
|
-
if (endIndex > 0) {
|
|
736
|
-
if (helpCommandConfig && helpCommandNames.includes(args[0])) return true;
|
|
737
|
-
if (versionCommandConfig && versionCommandNames.includes(args[0])) return true;
|
|
738
|
-
}
|
|
739
|
-
return false;
|
|
740
|
-
};
|
|
741
|
-
let completionOptionIndex = -1;
|
|
742
|
-
if (completionOptionConfig) {
|
|
743
|
-
const loopBound = helpTerminatorIndex >= 0 ? helpTerminatorIndex : args.length;
|
|
744
|
-
for (let i = 0; i < loopBound; i++) {
|
|
745
|
-
const arg = args[i];
|
|
746
|
-
const equalsMatch = completionOptionNames.find((n) => arg.startsWith(n + "="));
|
|
747
|
-
if (equalsMatch) {
|
|
748
|
-
if (hasMetaEntryBefore(i)) {
|
|
749
|
-
completionOptionIndex = i;
|
|
750
|
-
break;
|
|
751
|
-
}
|
|
752
|
-
const shell = arg.slice(equalsMatch.length + 1);
|
|
753
|
-
const completionArgs = args.slice(i + 1);
|
|
754
|
-
return handleCompletion([shell, ...completionArgs], programName, parser, completionParsers.completionOption, stdout, stderr, onCompletionResult, onErrorResult, availableShells, colors, maxWidth, completionCommandNames[0], completionOptionNames[0], true, sectionOrder);
|
|
755
|
-
}
|
|
756
|
-
const exactMatch = completionOptionNames.includes(arg);
|
|
757
|
-
if (exactMatch) {
|
|
758
|
-
if (hasMetaEntryBefore(i)) {
|
|
759
|
-
completionOptionIndex = i;
|
|
760
|
-
break;
|
|
761
|
-
}
|
|
762
|
-
const shell = i + 1 < args.length ? args[i + 1] : "";
|
|
763
|
-
const completionArgs = i + 1 < args.length ? args.slice(i + 2) : [];
|
|
764
|
-
return handleCompletion([shell, ...completionArgs], programName, parser, completionParsers.completionOption, stdout, stderr, onCompletionResult, onErrorResult, availableShells, colors, maxWidth, completionCommandNames[0], completionOptionNames[0], true, sectionOrder);
|
|
765
|
-
}
|
|
766
|
-
}
|
|
767
|
-
}
|
|
768
|
-
if (completionOptionIndex >= 0) args = args.slice(0, completionOptionIndex);
|
|
769
|
-
}
|
|
770
917
|
const augmentedParser = !options.help && !options.version && !options.completion ? parser : combineWithHelpVersion(parser, helpParsers, versionParsers, completionParsers, {
|
|
771
918
|
helpCommandGroup: helpCommandConfig?.group,
|
|
772
919
|
helpOptionGroup: helpOptionConfig?.group,
|
|
@@ -775,14 +922,17 @@ function runParser(parserOrProgram, programNameOrArgs, argsOrOptions, optionsPar
|
|
|
775
922
|
completionCommandGroup: completionCommandConfig?.group,
|
|
776
923
|
completionOptionGroup: completionOptionConfig?.group
|
|
777
924
|
}, helpOptionConfig ? [...helpOptionNames] : void 0, versionOptionConfig ? [...versionOptionNames] : void 0);
|
|
778
|
-
const handleResult = (
|
|
779
|
-
const classified = classifyResult(result, args, helpOptionConfig ? [...helpOptionNames] : [], helpCommandConfig ? [...helpCommandNames] : [], versionOptionConfig ? [...versionOptionNames] : [], versionCommandConfig ? [...versionCommandNames] : [], completionCommandConfig ? [...completionCommandNames] : []);
|
|
925
|
+
const handleResult = (classified) => {
|
|
780
926
|
switch (classified.type) {
|
|
781
927
|
case "success": return classified.value;
|
|
782
928
|
case "version":
|
|
783
929
|
stdout(versionValue);
|
|
784
930
|
return onVersion(0);
|
|
785
|
-
case "completion":
|
|
931
|
+
case "completion": return handleCompletion([
|
|
932
|
+
classified.shell,
|
|
933
|
+
...classified.commandPath ?? [],
|
|
934
|
+
...classified.args
|
|
935
|
+
], programName, parser, classified.source === "command" ? completionParsers.completionCommand : completionParsers.completionOption, stdout, stderr, onCompletionResult, onErrorResult, availableShells, colors, maxWidth, completionCommandNames[0], completionOptionNames[0], classified.source === "option", sectionOrder);
|
|
786
936
|
case "help": {
|
|
787
937
|
let helpGeneratorParser;
|
|
788
938
|
const helpAsCommand = helpCommandConfig != null;
|
|
@@ -792,9 +942,9 @@ function runParser(parserOrProgram, programNameOrArgs, argsOrOptions, optionsPar
|
|
|
792
942
|
const versionAsOption = versionOptionConfig != null;
|
|
793
943
|
const completionAsOption = completionOptionConfig != null;
|
|
794
944
|
const requestedCommand = classified.commands[0];
|
|
795
|
-
if (requestedCommand != null && completionCommandNames.includes(requestedCommand) && completionAsCommand && completionParsers.completionCommand) helpGeneratorParser = completionParsers.completionCommand;
|
|
796
|
-
else if (requestedCommand != null && helpCommandNames.includes(requestedCommand) && helpAsCommand && helpParsers.helpCommand) helpGeneratorParser = helpParsers.helpCommand;
|
|
797
|
-
else if (requestedCommand != null && versionCommandNames.includes(requestedCommand) && versionAsCommand && versionParsers.versionCommand) helpGeneratorParser = versionParsers.versionCommand;
|
|
945
|
+
if (requestedCommand != null && !classified.preferUserCommandDocs && completionCommandNames.includes(requestedCommand) && completionAsCommand && completionParsers.completionCommand) helpGeneratorParser = completionParsers.completionCommand;
|
|
946
|
+
else if (requestedCommand != null && !classified.preferUserCommandDocs && helpCommandNames.includes(requestedCommand) && helpAsCommand && helpParsers.helpCommand) helpGeneratorParser = helpParsers.helpCommand;
|
|
947
|
+
else if (requestedCommand != null && !classified.preferUserCommandDocs && versionCommandNames.includes(requestedCommand) && versionAsCommand && versionParsers.versionCommand) helpGeneratorParser = versionParsers.versionCommand;
|
|
798
948
|
else {
|
|
799
949
|
const commandParsers = [parser];
|
|
800
950
|
const groupedMeta = {};
|
|
@@ -886,8 +1036,8 @@ function runParser(parserOrProgram, programNameOrArgs, argsOrOptions, optionsPar
|
|
|
886
1036
|
while (validationResult === "continue") {
|
|
887
1037
|
const stepResult = helpGeneratorParser.parse(validationContext);
|
|
888
1038
|
if (stepResult instanceof Promise) {
|
|
889
|
-
const asyncValidate = async (result
|
|
890
|
-
let res = processStep(result
|
|
1039
|
+
const asyncValidate = async (result) => {
|
|
1040
|
+
let res = processStep(result);
|
|
891
1041
|
while (res === "continue") {
|
|
892
1042
|
const next = helpGeneratorParser.parse(validationContext);
|
|
893
1043
|
const resolved = next instanceof Promise ? await next : next;
|
|
@@ -953,13 +1103,21 @@ function runParser(parserOrProgram, programNameOrArgs, argsOrOptions, optionsPar
|
|
|
953
1103
|
};
|
|
954
1104
|
const parserMode = parser.$mode;
|
|
955
1105
|
return require_mode_dispatch.dispatchByMode(parserMode, () => {
|
|
956
|
-
const
|
|
957
|
-
const
|
|
1106
|
+
const attempted = attemptParseSync(parser, args);
|
|
1107
|
+
const classified = attempted.kind === "success" ? {
|
|
1108
|
+
type: "success",
|
|
1109
|
+
value: attempted.value
|
|
1110
|
+
} : classifyParseFailure(attempted, helpOptionConfig ? [...helpOptionNames] : [], helpCommandConfig ? [...helpCommandNames] : [], versionOptionConfig ? [...versionOptionNames] : [], versionCommandConfig ? [...versionCommandNames] : [], completionOptionConfig ? [...completionOptionNames] : [], completionCommandConfig ? [...completionCommandNames] : []);
|
|
1111
|
+
const handled = handleResult(classified);
|
|
958
1112
|
if (handled instanceof Promise) throw new RunParserError("Synchronous parser returned async result.");
|
|
959
1113
|
return handled;
|
|
960
1114
|
}, async () => {
|
|
961
|
-
const
|
|
962
|
-
const
|
|
1115
|
+
const attempted = await attemptParseAsync(parser, args);
|
|
1116
|
+
const classified = attempted.kind === "success" ? {
|
|
1117
|
+
type: "success",
|
|
1118
|
+
value: attempted.value
|
|
1119
|
+
} : classifyParseFailure(attempted, helpOptionConfig ? [...helpOptionNames] : [], helpCommandConfig ? [...helpCommandNames] : [], versionOptionConfig ? [...versionOptionNames] : [], versionCommandConfig ? [...versionCommandNames] : [], completionOptionConfig ? [...completionOptionNames] : [], completionCommandConfig ? [...completionCommandNames] : []);
|
|
1120
|
+
const handled = handleResult(classified);
|
|
963
1121
|
return handled instanceof Promise ? await handled : handled;
|
|
964
1122
|
});
|
|
965
1123
|
}
|
|
@@ -1020,49 +1178,38 @@ var RunParserError = class extends Error {
|
|
|
1020
1178
|
function indentLines(text$1, indent) {
|
|
1021
1179
|
return text$1.split("\n").join("\n" + " ".repeat(indent));
|
|
1022
1180
|
}
|
|
1181
|
+
function isMetaEarlyExit(classified) {
|
|
1182
|
+
return classified.type === "help" || classified.type === "version" || classified.type === "completion";
|
|
1183
|
+
}
|
|
1184
|
+
function classifyEarlyExitFailure(failure, options) {
|
|
1185
|
+
const norm = (c) => c === true ? {} : c;
|
|
1186
|
+
const helpOptionConfig = norm(options.help?.option);
|
|
1187
|
+
const helpCommandConfig = norm(options.help?.command);
|
|
1188
|
+
const versionOptionConfig = norm(options.version?.option);
|
|
1189
|
+
const versionCommandConfig = norm(options.version?.command);
|
|
1190
|
+
const completionOptionConfig = norm(options.completion?.option);
|
|
1191
|
+
const completionCommandConfig = norm(options.completion?.command);
|
|
1192
|
+
return classifyParseFailure(failure, helpOptionConfig ? [...helpOptionConfig.names ?? ["--help"]] : [], helpCommandConfig ? [...helpCommandConfig.names ?? ["help"]] : [], versionOptionConfig ? [...versionOptionConfig.names ?? ["--version"]] : [], versionCommandConfig ? [...versionCommandConfig.names ?? ["version"]] : [], completionOptionConfig ? [...completionOptionConfig.names ?? ["--completion"]] : [], completionCommandConfig ? [...completionCommandConfig.names ?? ["completion"]] : []);
|
|
1193
|
+
}
|
|
1194
|
+
function shouldProbeEarlyExit(options, needsTwoPhase) {
|
|
1195
|
+
return needsTwoPhase && (options.help != null || options.version != null || options.completion != null);
|
|
1196
|
+
}
|
|
1023
1197
|
/**
|
|
1024
|
-
* Checks if the arguments contain
|
|
1025
|
-
*
|
|
1026
|
-
*
|
|
1027
|
-
* This enables early exit optimization: when users request help, version,
|
|
1028
|
-
* or completion, we skip annotation collection and context processing
|
|
1029
|
-
* entirely, delegating directly to runParser().
|
|
1030
|
-
*
|
|
1031
|
-
* @param args Command-line arguments to check.
|
|
1032
|
-
* @param options Run options containing help/version/completion configuration.
|
|
1033
|
-
* @returns `true` if early exit should be performed, `false` otherwise.
|
|
1198
|
+
* Checks if the arguments contain parser-visible meta requests that can be
|
|
1199
|
+
* handled without collecting source-context annotations first.
|
|
1034
1200
|
*/
|
|
1035
|
-
function
|
|
1036
|
-
const
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
if (options.version) {
|
|
1048
|
-
const versionOptionConfig = norm(options.version.option);
|
|
1049
|
-
const versionCommandConfig = norm(options.version.command);
|
|
1050
|
-
const versionOptionNames = versionOptionConfig?.names ?? ["--version"];
|
|
1051
|
-
const versionCommandNames = versionCommandConfig?.names ?? ["version"];
|
|
1052
|
-
if (versionOptionConfig && versionOptionNames.some((n) => optionArgs.includes(n))) return true;
|
|
1053
|
-
if (versionCommandConfig && versionCommandNames.includes(args[0])) return true;
|
|
1054
|
-
}
|
|
1055
|
-
if (options.completion) {
|
|
1056
|
-
const completionCommandConfig = norm(options.completion.command);
|
|
1057
|
-
const completionOptionConfig = norm(options.completion.option);
|
|
1058
|
-
const completionCommandNames = completionCommandConfig?.names ?? ["completion"];
|
|
1059
|
-
const completionOptionNames = completionOptionConfig?.names ?? ["--completion"];
|
|
1060
|
-
if (completionCommandConfig && completionCommandNames.includes(args[0])) return true;
|
|
1061
|
-
if (completionOptionConfig) {
|
|
1062
|
-
for (const arg of optionArgs) for (const name of completionOptionNames) if (arg === name || arg.startsWith(name + "=")) return true;
|
|
1063
|
-
}
|
|
1064
|
-
}
|
|
1065
|
-
return false;
|
|
1201
|
+
function needsEarlyExitSync(parser, args, options) {
|
|
1202
|
+
const attempted = attemptParseSync(parser, args, "parse-only");
|
|
1203
|
+
if (attempted.kind === "success") return false;
|
|
1204
|
+
return isMetaEarlyExit(classifyEarlyExitFailure(attempted, options));
|
|
1205
|
+
}
|
|
1206
|
+
/**
|
|
1207
|
+
* Async variant of {@link needsEarlyExitSync}.
|
|
1208
|
+
*/
|
|
1209
|
+
async function needsEarlyExitAsync(parser, args, options) {
|
|
1210
|
+
const attempted = await attemptParseAsync(parser, args, "parse-only");
|
|
1211
|
+
if (attempted.kind === "success") return false;
|
|
1212
|
+
return isMetaEarlyExit(classifyEarlyExitFailure(attempted, options));
|
|
1066
1213
|
}
|
|
1067
1214
|
/**
|
|
1068
1215
|
* Merges multiple annotation objects, with earlier contexts having priority.
|
|
@@ -1250,23 +1397,25 @@ function disposeContextsSync(contexts) {
|
|
|
1250
1397
|
async function runWithBody(parser, programName, contexts, args, options) {
|
|
1251
1398
|
require_validate.validateContextIds(contexts);
|
|
1252
1399
|
validateContextPhases(contexts);
|
|
1253
|
-
if (needsEarlyExit(args, options)) {
|
|
1254
|
-
if (parser.$mode === "async") return runParser(parser, programName, args, options);
|
|
1255
|
-
return Promise.resolve(runParser(parser, programName, args, options));
|
|
1256
|
-
}
|
|
1257
1400
|
const ctxOptions = options.contextOptions;
|
|
1258
1401
|
const { annotations: phase1Annotations, needsTwoPhase, snapshots: phase1Snapshots } = await collectPhase1Annotations(contexts, ctxOptions);
|
|
1259
|
-
if (
|
|
1260
|
-
const
|
|
1261
|
-
if (
|
|
1262
|
-
|
|
1402
|
+
if (shouldProbeEarlyExit(options, needsTwoPhase)) {
|
|
1403
|
+
const earlyExitParser = injectAnnotationsIntoParser(parser, phase1Annotations);
|
|
1404
|
+
if (await needsEarlyExitAsync(earlyExitParser, args, options)) {
|
|
1405
|
+
if (parser.$mode === "async") return runParser(earlyExitParser, programName, args, options);
|
|
1406
|
+
return Promise.resolve(runParser(earlyExitParser, programName, args, options));
|
|
1407
|
+
}
|
|
1263
1408
|
}
|
|
1264
1409
|
const augmentedParser1 = injectAnnotationsIntoParser(parser, phase1Annotations);
|
|
1410
|
+
if (!needsTwoPhase) {
|
|
1411
|
+
if (parser.$mode === "async") return runParser(augmentedParser1, programName, args, options);
|
|
1412
|
+
return Promise.resolve(runParser(augmentedParser1, programName, args, options));
|
|
1413
|
+
}
|
|
1265
1414
|
const firstPassSeed = await require_mode_dispatch.dispatchByMode(parser.$mode, () => extractPhase2SeedSync(augmentedParser1, args), () => extractPhase2SeedAsync(augmentedParser1, args));
|
|
1266
1415
|
if (firstPassSeed == null) {
|
|
1267
|
-
const
|
|
1268
|
-
if (parser.$mode === "async") return runParser(
|
|
1269
|
-
return Promise.resolve(runParser(
|
|
1416
|
+
const fallbackParser = injectAnnotationsIntoParser(parser, phase1Annotations);
|
|
1417
|
+
if (parser.$mode === "async") return runParser(fallbackParser, programName, args, options);
|
|
1418
|
+
return Promise.resolve(runParser(fallbackParser, programName, args, options));
|
|
1270
1419
|
}
|
|
1271
1420
|
const { annotations: finalAnnotations } = await collectFinalAnnotations(contexts, phase1Snapshots, firstPassSeed.value, ctxOptions, firstPassSeed.deferred, firstPassSeed.deferredKeys);
|
|
1272
1421
|
const augmentedParser2 = injectAnnotationsIntoParser(parser, finalAnnotations);
|
|
@@ -1368,18 +1517,18 @@ async function runWith(parser, programName, contexts, options) {
|
|
|
1368
1517
|
function runWithSyncBody(parser, programName, contexts, args, options) {
|
|
1369
1518
|
require_validate.validateContextIds(contexts);
|
|
1370
1519
|
validateContextPhases(contexts);
|
|
1371
|
-
if (needsEarlyExit(args, options)) return runParser(parser, programName, args, options);
|
|
1372
1520
|
const ctxOptions = options.contextOptions;
|
|
1373
1521
|
const { annotations: phase1Annotations, needsTwoPhase, snapshots: phase1Snapshots } = collectPhase1AnnotationsSync(contexts, ctxOptions);
|
|
1374
|
-
if (
|
|
1375
|
-
const
|
|
1376
|
-
return runParser(
|
|
1522
|
+
if (shouldProbeEarlyExit(options, needsTwoPhase)) {
|
|
1523
|
+
const earlyExitParser = injectAnnotationsIntoParser(parser, phase1Annotations);
|
|
1524
|
+
if (needsEarlyExitSync(earlyExitParser, args, options)) return runParser(earlyExitParser, programName, args, options);
|
|
1377
1525
|
}
|
|
1378
1526
|
const augmentedParser1 = injectAnnotationsIntoParser(parser, phase1Annotations);
|
|
1527
|
+
if (!needsTwoPhase) return runParser(augmentedParser1, programName, args, options);
|
|
1379
1528
|
const firstPassSeed = extractPhase2SeedSync(augmentedParser1, args);
|
|
1380
1529
|
if (firstPassSeed == null) {
|
|
1381
|
-
const
|
|
1382
|
-
return runParser(
|
|
1530
|
+
const fallbackParser = injectAnnotationsIntoParser(parser, phase1Annotations);
|
|
1531
|
+
return runParser(fallbackParser, programName, args, options);
|
|
1383
1532
|
}
|
|
1384
1533
|
const { annotations: finalAnnotations } = collectFinalAnnotationsSync(contexts, phase1Snapshots, firstPassSeed.value, ctxOptions, firstPassSeed.deferred, firstPassSeed.deferredKeys);
|
|
1385
1534
|
const augmentedParser2 = injectAnnotationsIntoParser(parser, finalAnnotations);
|