@optique/core 1.1.0-dev.1998 → 1.1.0-dev.2053
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 +20 -1
- package/dist/constructs.js +20 -1
- package/dist/dependency-runtime.cjs +34 -22
- package/dist/dependency-runtime.js +34 -22
- package/dist/facade.cjs +269 -157
- package/dist/facade.js +272 -160
- package/dist/index.cjs +1 -0
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/dist/primitives.cjs +221 -5
- package/dist/primitives.d.cts +105 -1
- package/dist/primitives.d.ts +105 -1
- package/dist/primitives.js +221 -6
- package/dist/valueparser.cjs +19 -64
- package/dist/valueparser.js +19 -64
- package/package.json +1 -1
package/dist/facade.cjs
CHANGED
|
@@ -384,162 +384,42 @@ function createCompletionParser(programName, availableShells, commandConfig, opt
|
|
|
384
384
|
completionOption
|
|
385
385
|
};
|
|
386
386
|
}
|
|
387
|
-
function
|
|
387
|
+
function createMetaOptionDocParser(source) {
|
|
388
|
+
return {
|
|
389
|
+
mode: "sync",
|
|
390
|
+
$valueType: [],
|
|
391
|
+
$stateType: [],
|
|
392
|
+
priority: 200,
|
|
393
|
+
usage: source.usage,
|
|
394
|
+
leadingNames: source.leadingNames,
|
|
395
|
+
acceptingAnyToken: false,
|
|
396
|
+
initialState: null,
|
|
397
|
+
parse: () => ({
|
|
398
|
+
success: false,
|
|
399
|
+
error: require_message.message`Documentation-only meta option.`,
|
|
400
|
+
consumed: 0
|
|
401
|
+
}),
|
|
402
|
+
complete: (state) => ({
|
|
403
|
+
success: true,
|
|
404
|
+
value: state
|
|
405
|
+
}),
|
|
406
|
+
suggest: function* () {},
|
|
407
|
+
getDocFragments: (_state, defaultValue) => source.getDocFragments({
|
|
408
|
+
kind: "available",
|
|
409
|
+
state: source.initialState
|
|
410
|
+
}, defaultValue)
|
|
411
|
+
};
|
|
412
|
+
}
|
|
413
|
+
function combineWithHelpVersion(originalParser, helpParsers, versionParsers, completionParsers, groups) {
|
|
388
414
|
const parsers = [];
|
|
389
|
-
const effectiveHelpOptionNames = helpOptionNames ?? ["--help"];
|
|
390
|
-
const effectiveVersionOptionNames = versionOptionNames ?? ["--version"];
|
|
391
415
|
if (helpParsers.helpOption) {
|
|
392
|
-
const
|
|
393
|
-
|
|
394
|
-
$valueType: [],
|
|
395
|
-
$stateType: [],
|
|
396
|
-
priority: 200,
|
|
397
|
-
usage: helpParsers.helpOption.usage,
|
|
398
|
-
leadingNames: helpParsers.helpOption.leadingNames,
|
|
399
|
-
acceptingAnyToken: false,
|
|
400
|
-
initialState: null,
|
|
401
|
-
parse(context) {
|
|
402
|
-
const { buffer, optionsTerminated } = context;
|
|
403
|
-
if (optionsTerminated) return {
|
|
404
|
-
success: false,
|
|
405
|
-
error: require_message.message`Options terminated.`,
|
|
406
|
-
consumed: 0
|
|
407
|
-
};
|
|
408
|
-
let helpFound = false;
|
|
409
|
-
let helpIndex = -1;
|
|
410
|
-
let versionIndex = -1;
|
|
411
|
-
for (let i = 0; i < buffer.length; i++) {
|
|
412
|
-
if (buffer[i] === "--") break;
|
|
413
|
-
if (effectiveHelpOptionNames.includes(buffer[i])) {
|
|
414
|
-
helpFound = true;
|
|
415
|
-
helpIndex = i;
|
|
416
|
-
}
|
|
417
|
-
if (effectiveVersionOptionNames.includes(buffer[i])) versionIndex = i;
|
|
418
|
-
}
|
|
419
|
-
if (helpFound && versionIndex > helpIndex) return {
|
|
420
|
-
success: false,
|
|
421
|
-
error: require_message.message`Version option wins.`,
|
|
422
|
-
consumed: 0
|
|
423
|
-
};
|
|
424
|
-
if (helpFound) {
|
|
425
|
-
const commands = [];
|
|
426
|
-
for (let i = 0; i < helpIndex; i++) {
|
|
427
|
-
const arg = buffer[i];
|
|
428
|
-
if (!arg.startsWith("-")) commands.push(arg);
|
|
429
|
-
}
|
|
430
|
-
return {
|
|
431
|
-
success: true,
|
|
432
|
-
next: {
|
|
433
|
-
...context,
|
|
434
|
-
buffer: [],
|
|
435
|
-
state: {
|
|
436
|
-
[metaResultBrand]: true,
|
|
437
|
-
help: true,
|
|
438
|
-
version: false,
|
|
439
|
-
completion: false,
|
|
440
|
-
commands,
|
|
441
|
-
helpFlag: true
|
|
442
|
-
}
|
|
443
|
-
},
|
|
444
|
-
consumed: buffer.slice(0)
|
|
445
|
-
};
|
|
446
|
-
}
|
|
447
|
-
return {
|
|
448
|
-
success: false,
|
|
449
|
-
error: require_message.message`Flag ${require_message.optionName(effectiveHelpOptionNames[0])} not found.`,
|
|
450
|
-
consumed: 0
|
|
451
|
-
};
|
|
452
|
-
},
|
|
453
|
-
complete(state) {
|
|
454
|
-
return {
|
|
455
|
-
success: true,
|
|
456
|
-
value: state
|
|
457
|
-
};
|
|
458
|
-
},
|
|
459
|
-
*suggest(_context, prefix) {
|
|
460
|
-
for (const name of effectiveHelpOptionNames) if (name.startsWith(prefix)) yield {
|
|
461
|
-
kind: "literal",
|
|
462
|
-
text: name
|
|
463
|
-
};
|
|
464
|
-
},
|
|
465
|
-
getDocFragments(state) {
|
|
466
|
-
return helpParsers.helpOption?.getDocFragments(state) ?? { fragments: [] };
|
|
467
|
-
}
|
|
468
|
-
};
|
|
469
|
-
const wrappedHelp = groups?.helpOptionGroup ? require_constructs.group(groups.helpOptionGroup, lenientHelpParser) : lenientHelpParser;
|
|
416
|
+
const helpOptionDocParser = createMetaOptionDocParser(helpParsers.helpOption);
|
|
417
|
+
const wrappedHelp = groups?.helpOptionGroup ? require_constructs.group(groups.helpOptionGroup, helpOptionDocParser) : helpOptionDocParser;
|
|
470
418
|
parsers.push(wrappedHelp);
|
|
471
419
|
}
|
|
472
420
|
if (versionParsers.versionOption) {
|
|
473
|
-
const
|
|
474
|
-
|
|
475
|
-
$valueType: [],
|
|
476
|
-
$stateType: [],
|
|
477
|
-
priority: 200,
|
|
478
|
-
usage: versionParsers.versionOption.usage,
|
|
479
|
-
leadingNames: versionParsers.versionOption.leadingNames,
|
|
480
|
-
acceptingAnyToken: false,
|
|
481
|
-
initialState: null,
|
|
482
|
-
parse(context) {
|
|
483
|
-
const { buffer, optionsTerminated } = context;
|
|
484
|
-
if (optionsTerminated) return {
|
|
485
|
-
success: false,
|
|
486
|
-
error: require_message.message`Options terminated.`,
|
|
487
|
-
consumed: 0
|
|
488
|
-
};
|
|
489
|
-
let versionFound = false;
|
|
490
|
-
let versionIndex = -1;
|
|
491
|
-
let helpIndex = -1;
|
|
492
|
-
for (let i = 0; i < buffer.length; i++) {
|
|
493
|
-
if (buffer[i] === "--") break;
|
|
494
|
-
if (effectiveVersionOptionNames.includes(buffer[i])) {
|
|
495
|
-
versionFound = true;
|
|
496
|
-
versionIndex = i;
|
|
497
|
-
}
|
|
498
|
-
if (effectiveHelpOptionNames.includes(buffer[i])) helpIndex = i;
|
|
499
|
-
}
|
|
500
|
-
if (versionFound && helpIndex > versionIndex) return {
|
|
501
|
-
success: false,
|
|
502
|
-
error: require_message.message`Help option wins.`,
|
|
503
|
-
consumed: 0
|
|
504
|
-
};
|
|
505
|
-
if (versionFound) return {
|
|
506
|
-
success: true,
|
|
507
|
-
next: {
|
|
508
|
-
...context,
|
|
509
|
-
buffer: [],
|
|
510
|
-
state: {
|
|
511
|
-
[metaResultBrand]: true,
|
|
512
|
-
help: false,
|
|
513
|
-
version: true,
|
|
514
|
-
completion: false,
|
|
515
|
-
versionFlag: true
|
|
516
|
-
}
|
|
517
|
-
},
|
|
518
|
-
consumed: buffer.slice(0)
|
|
519
|
-
};
|
|
520
|
-
return {
|
|
521
|
-
success: false,
|
|
522
|
-
error: require_message.message`Flag ${require_message.optionName(effectiveVersionOptionNames[0])} not found.`,
|
|
523
|
-
consumed: 0
|
|
524
|
-
};
|
|
525
|
-
},
|
|
526
|
-
complete(state) {
|
|
527
|
-
return {
|
|
528
|
-
success: true,
|
|
529
|
-
value: state
|
|
530
|
-
};
|
|
531
|
-
},
|
|
532
|
-
*suggest(_context, prefix) {
|
|
533
|
-
for (const name of effectiveVersionOptionNames) if (name.startsWith(prefix)) yield {
|
|
534
|
-
kind: "literal",
|
|
535
|
-
text: name
|
|
536
|
-
};
|
|
537
|
-
},
|
|
538
|
-
getDocFragments(state) {
|
|
539
|
-
return versionParsers.versionOption?.getDocFragments(state) ?? { fragments: [] };
|
|
540
|
-
}
|
|
541
|
-
};
|
|
542
|
-
const wrappedVersion = groups?.versionOptionGroup ? require_constructs.group(groups.versionOptionGroup, lenientVersionParser) : lenientVersionParser;
|
|
421
|
+
const versionOptionDocParser = createMetaOptionDocParser(versionParsers.versionOption);
|
|
422
|
+
const wrappedVersion = groups?.versionOptionGroup ? require_constructs.group(groups.versionOptionGroup, versionOptionDocParser) : versionOptionDocParser;
|
|
543
423
|
parsers.push(wrappedVersion);
|
|
544
424
|
}
|
|
545
425
|
if (versionParsers.versionCommand) {
|
|
@@ -717,7 +597,7 @@ function classifyParseFailure(failure, helpOptionNames, helpCommandNames, versio
|
|
|
717
597
|
* Handles shell completion requests.
|
|
718
598
|
* @since 0.6.0
|
|
719
599
|
*/
|
|
720
|
-
function handleCompletion(completionArgs, programName, parser, completionParser, stdout, stderr, onCompletion, onError, availableShells, colors, maxWidth, completionCommandDisplayName, completionOptionDisplayName, isOptionMode, sectionOrder) {
|
|
600
|
+
function handleCompletion(completionArgs, programName, parser, completionParser, stdout, stderr, onCompletion, onError, availableShells, colors, maxWidth, completionCommandDisplayName, completionOptionDisplayName, isOptionMode, sectionOrder, rootOptionSuggestions = []) {
|
|
721
601
|
const shellName = completionArgs[0] || "";
|
|
722
602
|
const args = completionArgs.slice(1);
|
|
723
603
|
const callOnError = (code) => onError(code);
|
|
@@ -768,17 +648,248 @@ function handleCompletion(completionArgs, programName, parser, completionParser,
|
|
|
768
648
|
}
|
|
769
649
|
return require_mode_dispatch.dispatchByMode(parser.mode, () => {
|
|
770
650
|
const syncParser = parser;
|
|
771
|
-
const
|
|
651
|
+
const completionSuggestions = getSyncCompletionSuggestions(syncParser, args, rootOptionSuggestions);
|
|
652
|
+
const suggestions = withRootOptionSuggestions(completionSuggestions.suggestions, args, rootOptionSuggestions, completionSuggestions.argumentContext);
|
|
772
653
|
for (const chunk of shell.encodeSuggestions(suggestions)) stdout(chunk);
|
|
773
654
|
const result = callOnCompletion(0);
|
|
774
655
|
if (result instanceof Promise) throw new RunParserError("Synchronous parser returned async result.");
|
|
775
656
|
return result;
|
|
776
657
|
}, async () => {
|
|
777
|
-
const
|
|
778
|
-
|
|
658
|
+
const asyncParser = parser;
|
|
659
|
+
const completionSuggestions = await getAsyncCompletionSuggestions(asyncParser, args, rootOptionSuggestions);
|
|
660
|
+
for (const chunk of shell.encodeSuggestions(withRootOptionSuggestions(completionSuggestions.suggestions, args, rootOptionSuggestions, completionSuggestions.argumentContext))) stdout(chunk);
|
|
779
661
|
return callOnCompletion(0);
|
|
780
662
|
});
|
|
781
663
|
}
|
|
664
|
+
function withRootOptionSuggestions(suggestions, args, extraSuggestions, argumentContext) {
|
|
665
|
+
if (extraSuggestions.length === 0) return suggestions;
|
|
666
|
+
const prefix = args.at(-1) ?? "";
|
|
667
|
+
if (argumentContext.optionsTerminated) return suggestions;
|
|
668
|
+
if (argumentContext.completingOptionValue) return suggestions;
|
|
669
|
+
if (argumentContext.completedRootOption) return suggestions;
|
|
670
|
+
if (!(prefix === "" || prefix.startsWith("--") || prefix.startsWith("-") || prefix.startsWith("/") || prefix.startsWith("+"))) return suggestions;
|
|
671
|
+
const seen = new Set(suggestions.flatMap((suggestion) => suggestion.kind === "literal" ? [suggestion.text] : []));
|
|
672
|
+
const combined = [...suggestions];
|
|
673
|
+
for (const suggestion of extraSuggestions) {
|
|
674
|
+
if (prefix === "-" && suggestion.text.startsWith("--")) continue;
|
|
675
|
+
if (prefix !== "" && !suggestion.text.startsWith(prefix)) continue;
|
|
676
|
+
if (seen.has(suggestion.text)) continue;
|
|
677
|
+
combined.push(suggestion);
|
|
678
|
+
seen.add(suggestion.text);
|
|
679
|
+
}
|
|
680
|
+
return combined;
|
|
681
|
+
}
|
|
682
|
+
function getSyncCompletionSuggestions(parser, args, rootOptionSuggestions) {
|
|
683
|
+
const prefix = args.at(-1) ?? "";
|
|
684
|
+
let context = createCompletionArgumentParserContext(parser, args.slice(0, -1));
|
|
685
|
+
while (context.buffer.length > 0) {
|
|
686
|
+
const result = parser.parse(context);
|
|
687
|
+
if (result instanceof Promise) throw new RunParserError("Synchronous parser returned async result.");
|
|
688
|
+
if (!result.success) {
|
|
689
|
+
const argumentContext = getFailedCompletionArgumentContext(result, context, parser, rootOptionSuggestions);
|
|
690
|
+
return {
|
|
691
|
+
suggestions: Array.from(parser.suggest(withCompletionSuggestRuntime(parser, context), prefix)),
|
|
692
|
+
argumentContext
|
|
693
|
+
};
|
|
694
|
+
}
|
|
695
|
+
const previousBuffer = context.buffer;
|
|
696
|
+
context = result.next;
|
|
697
|
+
if (isCompletionBufferUnchanged(previousBuffer, context.buffer)) return {
|
|
698
|
+
suggestions: [],
|
|
699
|
+
argumentContext: getCompletedCompletionArgumentContext(context)
|
|
700
|
+
};
|
|
701
|
+
}
|
|
702
|
+
return {
|
|
703
|
+
suggestions: Array.from(parser.suggest(withCompletionSuggestRuntime(parser, context), prefix)),
|
|
704
|
+
argumentContext: getCompletedCompletionArgumentContext(context)
|
|
705
|
+
};
|
|
706
|
+
}
|
|
707
|
+
async function getAsyncCompletionSuggestions(parser, args, rootOptionSuggestions) {
|
|
708
|
+
const prefix = args.at(-1) ?? "";
|
|
709
|
+
let context = createCompletionArgumentParserContext(parser, args.slice(0, -1));
|
|
710
|
+
while (context.buffer.length > 0) {
|
|
711
|
+
const result = await parser.parse(context);
|
|
712
|
+
if (!result.success) {
|
|
713
|
+
const argumentContext = getFailedCompletionArgumentContext(result, context, parser, rootOptionSuggestions);
|
|
714
|
+
const suggestions$1 = [];
|
|
715
|
+
const suggestContext$1 = await withCompletionSuggestRuntimeAsync(parser, context);
|
|
716
|
+
for await (const suggestion of parser.suggest(suggestContext$1, prefix)) suggestions$1.push(suggestion);
|
|
717
|
+
return {
|
|
718
|
+
suggestions: suggestions$1,
|
|
719
|
+
argumentContext
|
|
720
|
+
};
|
|
721
|
+
}
|
|
722
|
+
const previousBuffer = context.buffer;
|
|
723
|
+
context = result.next;
|
|
724
|
+
if (isCompletionBufferUnchanged(previousBuffer, context.buffer)) return {
|
|
725
|
+
suggestions: [],
|
|
726
|
+
argumentContext: getCompletedCompletionArgumentContext(context)
|
|
727
|
+
};
|
|
728
|
+
}
|
|
729
|
+
const suggestions = [];
|
|
730
|
+
const suggestContext = await withCompletionSuggestRuntimeAsync(parser, context);
|
|
731
|
+
for await (const suggestion of parser.suggest(suggestContext, prefix)) suggestions.push(suggestion);
|
|
732
|
+
return {
|
|
733
|
+
suggestions,
|
|
734
|
+
argumentContext: getCompletedCompletionArgumentContext(context)
|
|
735
|
+
};
|
|
736
|
+
}
|
|
737
|
+
function getCompletedCompletionArgumentContext(context) {
|
|
738
|
+
return {
|
|
739
|
+
completingOptionValue: false,
|
|
740
|
+
completedRootOption: false,
|
|
741
|
+
optionsTerminated: context.optionsTerminated
|
|
742
|
+
};
|
|
743
|
+
}
|
|
744
|
+
function withCompletionSuggestRuntime(parser, context) {
|
|
745
|
+
const runtime = require_dependency_runtime.createDependencyRuntimeContext();
|
|
746
|
+
const nodes = getCompletionSuggestRuntimeNodes(parser, context.state, context.exec?.path ?? []);
|
|
747
|
+
if (nodes.length > 0) require_dependency_runtime.collectExplicitSourceValues(nodes, runtime);
|
|
748
|
+
return addCompletionSuggestRuntime(context, runtime);
|
|
749
|
+
}
|
|
750
|
+
async function withCompletionSuggestRuntimeAsync(parser, context) {
|
|
751
|
+
const runtime = require_dependency_runtime.createDependencyRuntimeContext();
|
|
752
|
+
const nodes = getCompletionSuggestRuntimeNodes(parser, context.state, context.exec?.path ?? []);
|
|
753
|
+
if (nodes.length > 0) await require_dependency_runtime.collectExplicitSourceValuesAsync(nodes, runtime);
|
|
754
|
+
return addCompletionSuggestRuntime(context, runtime);
|
|
755
|
+
}
|
|
756
|
+
function addCompletionSuggestRuntime(context, runtime) {
|
|
757
|
+
return {
|
|
758
|
+
...context,
|
|
759
|
+
dependencyRegistry: runtime.registry,
|
|
760
|
+
exec: context.exec ? {
|
|
761
|
+
...context.exec,
|
|
762
|
+
dependencyRuntime: runtime,
|
|
763
|
+
dependencyRegistry: runtime.registry
|
|
764
|
+
} : void 0
|
|
765
|
+
};
|
|
766
|
+
}
|
|
767
|
+
function getCompletionSuggestRuntimeNodes(parser, state, path) {
|
|
768
|
+
if (typeof parser.getSuggestRuntimeNodes === "function") return parser.getSuggestRuntimeNodes(state, path);
|
|
769
|
+
if (parser.dependencyMetadata?.source == null) return [];
|
|
770
|
+
return [{
|
|
771
|
+
path,
|
|
772
|
+
parser,
|
|
773
|
+
state
|
|
774
|
+
}];
|
|
775
|
+
}
|
|
776
|
+
function createCompletionArgumentParserContext(parser, args) {
|
|
777
|
+
return require_parser.createParserContext({
|
|
778
|
+
buffer: args,
|
|
779
|
+
state: parser.initialState,
|
|
780
|
+
optionsTerminated: false
|
|
781
|
+
}, {
|
|
782
|
+
usage: parser.usage,
|
|
783
|
+
phase: "suggest",
|
|
784
|
+
path: [],
|
|
785
|
+
trace: require_input_trace.createInputTrace()
|
|
786
|
+
});
|
|
787
|
+
}
|
|
788
|
+
function getFailedCompletionArgumentContext(result, context, parser, rootOptionSuggestions) {
|
|
789
|
+
const activeValueOptionNames = collectActiveValueOptionNames(parser.usage, context.exec?.commandPath ?? [], result.consumed > 0, parser.leadingNames);
|
|
790
|
+
const token = context.buffer[0];
|
|
791
|
+
return {
|
|
792
|
+
completingOptionValue: (result.consumed === 0 || result.consumed === 1) && activeValueOptionNames.has(token),
|
|
793
|
+
completedRootOption: result.consumed === 0 && isRootOptionToken(token, rootOptionSuggestions),
|
|
794
|
+
optionsTerminated: context.optionsTerminated
|
|
795
|
+
};
|
|
796
|
+
}
|
|
797
|
+
function isCompletionBufferUnchanged(before, after) {
|
|
798
|
+
return before.length === after.length && before.every((arg, index) => arg === after[index]);
|
|
799
|
+
}
|
|
800
|
+
function collectActiveValueOptionNames(usage, commandPath, includeDirectAfterCommandOptions, rootLeadingNames) {
|
|
801
|
+
const optionNames = {
|
|
802
|
+
value: /* @__PURE__ */ new Set(),
|
|
803
|
+
flag: /* @__PURE__ */ new Set()
|
|
804
|
+
};
|
|
805
|
+
if (commandPath.length === 0) {
|
|
806
|
+
collectRootOptionNames(usage, optionNames, rootLeadingNames);
|
|
807
|
+
return optionNames.value;
|
|
808
|
+
} else collectActiveOptionNames(usage, commandPath, optionNames, false, includeDirectAfterCommandOptions);
|
|
809
|
+
const names = new Set(optionNames.value);
|
|
810
|
+
for (const name of optionNames.flag) names.delete(name);
|
|
811
|
+
return names;
|
|
812
|
+
}
|
|
813
|
+
function collectRootOptionNames(usage, names, rootLeadingNames) {
|
|
814
|
+
for (const term of usage) collectRootOptionNamesFromTerm(term, names, rootLeadingNames);
|
|
815
|
+
}
|
|
816
|
+
function collectRootOptionNamesFromTerm(term, names, rootLeadingNames) {
|
|
817
|
+
switch (term.type) {
|
|
818
|
+
case "option":
|
|
819
|
+
for (const name of term.names) {
|
|
820
|
+
if (!rootLeadingNames.has(name)) continue;
|
|
821
|
+
if (term.metavar != null) names.value.add(name);
|
|
822
|
+
else names.flag.add(name);
|
|
823
|
+
}
|
|
824
|
+
return;
|
|
825
|
+
case "optional":
|
|
826
|
+
case "multiple":
|
|
827
|
+
collectRootOptionNames(term.terms, names, rootLeadingNames);
|
|
828
|
+
return;
|
|
829
|
+
case "exclusive":
|
|
830
|
+
for (const branch of term.terms) collectRootOptionNames(branch, names, rootLeadingNames);
|
|
831
|
+
return;
|
|
832
|
+
case "argument":
|
|
833
|
+
case "command":
|
|
834
|
+
case "literal":
|
|
835
|
+
case "passthrough":
|
|
836
|
+
case "ellipsis": return;
|
|
837
|
+
}
|
|
838
|
+
}
|
|
839
|
+
function collectActiveOptionNames(usage, commandPath, names, fromExclusive, includeDirectAfterCommandOptions) {
|
|
840
|
+
if (commandPath.length === 0) {
|
|
841
|
+
collectOptionNamesAtCurrentCommandDepth(usage, names, false);
|
|
842
|
+
return;
|
|
843
|
+
}
|
|
844
|
+
const [commandName, ...rest] = commandPath;
|
|
845
|
+
for (let i = 0; i < usage.length; i++) {
|
|
846
|
+
const term = usage[i];
|
|
847
|
+
if (term.type === "command" && term.name === commandName) {
|
|
848
|
+
const remainingUsage = usage.slice(i + 1);
|
|
849
|
+
if (rest.length === 0) collectOptionNamesAtCurrentCommandDepth(remainingUsage, names, !fromExclusive && includeDirectAfterCommandOptions);
|
|
850
|
+
else collectActiveOptionNames(remainingUsage, rest, names, fromExclusive, includeDirectAfterCommandOptions);
|
|
851
|
+
} else if (term.type === "exclusive") for (const branch of term.terms) collectActiveOptionNames(branch, commandPath, names, true, includeDirectAfterCommandOptions);
|
|
852
|
+
else if (term.type === "optional" || term.type === "multiple") collectActiveOptionNames(term.terms, commandPath, names, fromExclusive, includeDirectAfterCommandOptions);
|
|
853
|
+
}
|
|
854
|
+
}
|
|
855
|
+
function isRootOptionToken(token, rootOptionSuggestions) {
|
|
856
|
+
return token != null && rootOptionSuggestions.some((suggestion) => token === suggestion.text || token.startsWith(`${suggestion.text}=`));
|
|
857
|
+
}
|
|
858
|
+
function collectOptionNamesAtCurrentCommandDepth(usage, names, afterMatchedCommand) {
|
|
859
|
+
for (const term of usage) if (collectOptionNamesAtCurrentCommandDepthFromTerm(term, names, afterMatchedCommand)) return;
|
|
860
|
+
}
|
|
861
|
+
function collectOptionNamesAtCurrentCommandDepthFromTerm(term, names, afterMatchedCommand) {
|
|
862
|
+
switch (term.type) {
|
|
863
|
+
case "command": return !afterMatchedCommand;
|
|
864
|
+
case "option":
|
|
865
|
+
if (term.metavar != null) for (const name of term.names) names.value.add(name);
|
|
866
|
+
else for (const name of term.names) names.flag.add(name);
|
|
867
|
+
return false;
|
|
868
|
+
case "optional":
|
|
869
|
+
case "multiple":
|
|
870
|
+
collectOptionNamesAtCurrentCommandDepth(term.terms, names, afterMatchedCommand);
|
|
871
|
+
return false;
|
|
872
|
+
case "exclusive":
|
|
873
|
+
for (const branch of term.terms) collectOptionNamesAtCurrentCommandDepth(branch, names, false);
|
|
874
|
+
return false;
|
|
875
|
+
case "argument":
|
|
876
|
+
case "literal":
|
|
877
|
+
case "passthrough":
|
|
878
|
+
case "ellipsis": return false;
|
|
879
|
+
}
|
|
880
|
+
}
|
|
881
|
+
function getRootMetaOptionSuggestions(helpOptionConfig, helpOptionNames, versionOptionConfig, versionOptionNames) {
|
|
882
|
+
const suggestions = [];
|
|
883
|
+
if (helpOptionConfig != null && !require_usage.isSuggestionHidden(helpOptionConfig.hidden)) suggestions.push(...helpOptionNames.map((name) => ({
|
|
884
|
+
kind: "literal",
|
|
885
|
+
text: name
|
|
886
|
+
})));
|
|
887
|
+
if (versionOptionConfig != null && !require_usage.isSuggestionHidden(versionOptionConfig.hidden)) suggestions.push(...versionOptionNames.map((name) => ({
|
|
888
|
+
kind: "literal",
|
|
889
|
+
text: name
|
|
890
|
+
})));
|
|
891
|
+
return suggestions;
|
|
892
|
+
}
|
|
782
893
|
/**
|
|
783
894
|
* Validates the configured version value.
|
|
784
895
|
*
|
|
@@ -852,6 +963,7 @@ function runParser(parserOrProgram, programNameOrArgs, argsOrOptions, optionsPar
|
|
|
852
963
|
const versionCommandNames = versionCommandConfig?.names ?? ["version"];
|
|
853
964
|
const completionCommandNames = completionCommandConfig?.names ?? ["completion"];
|
|
854
965
|
const completionOptionNames = completionOptionConfig?.names ?? ["--completion"];
|
|
966
|
+
const rootOptionSuggestions = getRootMetaOptionSuggestions(helpOptionConfig, helpOptionNames, versionOptionConfig, versionOptionNames);
|
|
855
967
|
const activeMetaEntries = [];
|
|
856
968
|
if (options.help && helpOptionConfig) activeMetaEntries.push([
|
|
857
969
|
"option",
|
|
@@ -915,7 +1027,7 @@ function runParser(parserOrProgram, programNameOrArgs, argsOrOptions, optionsPar
|
|
|
915
1027
|
versionOptionGroup: versionOptionConfig?.group,
|
|
916
1028
|
completionCommandGroup: completionCommandConfig?.group,
|
|
917
1029
|
completionOptionGroup: completionOptionConfig?.group
|
|
918
|
-
}
|
|
1030
|
+
});
|
|
919
1031
|
const handleResult = (classified) => {
|
|
920
1032
|
switch (classified.type) {
|
|
921
1033
|
case "success": return classified.value;
|
|
@@ -926,7 +1038,7 @@ function runParser(parserOrProgram, programNameOrArgs, argsOrOptions, optionsPar
|
|
|
926
1038
|
classified.shell,
|
|
927
1039
|
...classified.commandPath ?? [],
|
|
928
1040
|
...classified.args
|
|
929
|
-
], programName, parser, classified.source === "command" ? completionParsers.completionCommand : completionParsers.completionOption, stdout, stderr, onCompletionResult, onErrorResult, availableShells, colors, maxWidth, completionCommandNames[0], completionOptionNames[0], classified.source === "option", sectionOrder);
|
|
1041
|
+
], programName, parser, classified.source === "command" ? completionParsers.completionCommand : completionParsers.completionOption, stdout, stderr, onCompletionResult, onErrorResult, availableShells, colors, maxWidth, completionCommandNames[0], completionOptionNames[0], classified.source === "option", sectionOrder, rootOptionSuggestions);
|
|
930
1042
|
case "help": {
|
|
931
1043
|
let helpGeneratorParser;
|
|
932
1044
|
const helpAsCommand = helpCommandConfig != null;
|