@optique/core 1.1.0-dev.2006 → 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/primitives.cjs +5 -5
- package/dist/primitives.js +5 -5
- package/dist/valueparser.cjs +19 -64
- package/dist/valueparser.js +19 -64
- package/package.json +1 -1
package/dist/facade.js
CHANGED
|
@@ -2,12 +2,12 @@ import { injectAnnotations, isInjectedAnnotationWrapper, unwrapInjectedAnnotatio
|
|
|
2
2
|
import { commandLine, formatMessage, lineBreak, message, optionName, text, value } from "./message.js";
|
|
3
3
|
import { bash, fish, nu, pwsh, zsh } from "./completion.js";
|
|
4
4
|
import { validateCommandNames, validateContextIds, validateMetaNameCollisions, validateOptionNames, validateProgramName } from "./validate.js";
|
|
5
|
-
import { formatUsage } from "./usage.js";
|
|
5
|
+
import { formatUsage, isSuggestionHidden } from "./usage.js";
|
|
6
6
|
import { formatDocPage } from "./doc.js";
|
|
7
7
|
import { dispatchByMode } from "./internal/mode-dispatch.js";
|
|
8
|
-
import { createDependencyRuntimeContext } from "./dependency-runtime.js";
|
|
8
|
+
import { collectExplicitSourceValues, collectExplicitSourceValuesAsync, createDependencyRuntimeContext } from "./dependency-runtime.js";
|
|
9
9
|
import { createInputTrace } from "./input-trace.js";
|
|
10
|
-
import { createParserContext, getDocPage
|
|
10
|
+
import { createParserContext, getDocPage } from "./internal/parser.js";
|
|
11
11
|
import { completeOrExtractPhase2Seed } from "./phase2-seed.js";
|
|
12
12
|
import { group, longestMatch, object } from "./constructs.js";
|
|
13
13
|
import { multiple, optional, withDefault } from "./modifiers.js";
|
|
@@ -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: 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: 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: 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: message`Flag ${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 ? group(groups.helpOptionGroup, lenientHelpParser) : lenientHelpParser;
|
|
416
|
+
const helpOptionDocParser = createMetaOptionDocParser(helpParsers.helpOption);
|
|
417
|
+
const wrappedHelp = groups?.helpOptionGroup ? 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: 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: 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: message`Flag ${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 ? group(groups.versionOptionGroup, lenientVersionParser) : lenientVersionParser;
|
|
421
|
+
const versionOptionDocParser = createMetaOptionDocParser(versionParsers.versionOption);
|
|
422
|
+
const wrappedVersion = groups?.versionOptionGroup ? 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 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 = createDependencyRuntimeContext();
|
|
746
|
+
const nodes = getCompletionSuggestRuntimeNodes(parser, context.state, context.exec?.path ?? []);
|
|
747
|
+
if (nodes.length > 0) collectExplicitSourceValues(nodes, runtime);
|
|
748
|
+
return addCompletionSuggestRuntime(context, runtime);
|
|
749
|
+
}
|
|
750
|
+
async function withCompletionSuggestRuntimeAsync(parser, context) {
|
|
751
|
+
const runtime = createDependencyRuntimeContext();
|
|
752
|
+
const nodes = getCompletionSuggestRuntimeNodes(parser, context.state, context.exec?.path ?? []);
|
|
753
|
+
if (nodes.length > 0) await 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 createParserContext({
|
|
778
|
+
buffer: args,
|
|
779
|
+
state: parser.initialState,
|
|
780
|
+
optionsTerminated: false
|
|
781
|
+
}, {
|
|
782
|
+
usage: parser.usage,
|
|
783
|
+
phase: "suggest",
|
|
784
|
+
path: [],
|
|
785
|
+
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 && !isSuggestionHidden(helpOptionConfig.hidden)) suggestions.push(...helpOptionNames.map((name) => ({
|
|
884
|
+
kind: "literal",
|
|
885
|
+
text: name
|
|
886
|
+
})));
|
|
887
|
+
if (versionOptionConfig != null && !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;
|
package/dist/primitives.cjs
CHANGED
|
@@ -260,7 +260,7 @@ function* suggestOptionSync(optionNames$1, valueParser, hidden, context, prefix)
|
|
|
260
260
|
}
|
|
261
261
|
} else {
|
|
262
262
|
const expectingValue = context.buffer.length > 0 && optionNames$1.includes(context.buffer[context.buffer.length - 1]);
|
|
263
|
-
if (!expectingValue && (prefix.startsWith("--") || prefix.startsWith("-") || prefix.startsWith("/"))) {
|
|
263
|
+
if (!expectingValue && (prefix.startsWith("--") || prefix.startsWith("-") || prefix.startsWith("/") || prefix.startsWith("+"))) {
|
|
264
264
|
for (const optionName$1 of optionNames$1) if (optionName$1.startsWith(prefix)) {
|
|
265
265
|
if (prefix === "-" && optionName$1.length !== 2) continue;
|
|
266
266
|
yield {
|
|
@@ -274,7 +274,7 @@ function* suggestOptionSync(optionNames$1, valueParser, hidden, context, prefix)
|
|
|
274
274
|
if (context.buffer.length > 0) {
|
|
275
275
|
const lastToken = context.buffer[context.buffer.length - 1];
|
|
276
276
|
if (optionNames$1.includes(lastToken)) shouldSuggestValues = true;
|
|
277
|
-
} else if (require_annotation_state.isAnnotationWrappedInitialState(context.state) && context.buffer.length === 0 && (context.exec?.path?.length ?? 0) === 0 && !(prefix.startsWith("--") || prefix.startsWith("-") || prefix.startsWith("/"))) shouldSuggestValues = true;
|
|
277
|
+
} else if (require_annotation_state.isAnnotationWrappedInitialState(context.state) && context.buffer.length === 0 && (context.exec?.path?.length ?? 0) === 0 && !(prefix.startsWith("--") || prefix.startsWith("-") || prefix.startsWith("/") || prefix.startsWith("+"))) shouldSuggestValues = true;
|
|
278
278
|
if (shouldSuggestValues) yield* getSuggestionsWithDependency(valueParser, prefix, context.dependencyRegistry, context.exec);
|
|
279
279
|
}
|
|
280
280
|
}
|
|
@@ -344,7 +344,7 @@ async function* suggestOptionAsync(optionNames$1, valueParser, hidden, context,
|
|
|
344
344
|
}
|
|
345
345
|
} else {
|
|
346
346
|
const expectingValue = context.buffer.length > 0 && optionNames$1.includes(context.buffer[context.buffer.length - 1]);
|
|
347
|
-
if (!expectingValue && (prefix.startsWith("--") || prefix.startsWith("-") || prefix.startsWith("/"))) {
|
|
347
|
+
if (!expectingValue && (prefix.startsWith("--") || prefix.startsWith("-") || prefix.startsWith("/") || prefix.startsWith("+"))) {
|
|
348
348
|
for (const optionName$1 of optionNames$1) if (optionName$1.startsWith(prefix)) {
|
|
349
349
|
if (prefix === "-" && optionName$1.length !== 2) continue;
|
|
350
350
|
yield {
|
|
@@ -358,7 +358,7 @@ async function* suggestOptionAsync(optionNames$1, valueParser, hidden, context,
|
|
|
358
358
|
if (context.buffer.length > 0) {
|
|
359
359
|
const lastToken = context.buffer[context.buffer.length - 1];
|
|
360
360
|
if (optionNames$1.includes(lastToken)) shouldSuggestValues = true;
|
|
361
|
-
} else if (require_annotation_state.isAnnotationWrappedInitialState(context.state) && context.buffer.length === 0 && (context.exec?.path?.length ?? 0) === 0 && !(prefix.startsWith("--") || prefix.startsWith("-") || prefix.startsWith("/"))) shouldSuggestValues = true;
|
|
361
|
+
} else if (require_annotation_state.isAnnotationWrappedInitialState(context.state) && context.buffer.length === 0 && (context.exec?.path?.length ?? 0) === 0 && !(prefix.startsWith("--") || prefix.startsWith("-") || prefix.startsWith("/") || prefix.startsWith("+"))) shouldSuggestValues = true;
|
|
362
362
|
if (shouldSuggestValues) for await (const suggestion of getSuggestionsWithDependencyAsync(valueParser, prefix, context.dependencyRegistry, context.exec)) yield suggestion;
|
|
363
363
|
}
|
|
364
364
|
}
|
|
@@ -888,7 +888,7 @@ function flag(...args) {
|
|
|
888
888
|
suggest(_context, prefix) {
|
|
889
889
|
if (require_usage.isSuggestionHidden(options.hidden)) return [];
|
|
890
890
|
const suggestions = [];
|
|
891
|
-
if (prefix.startsWith("--") || prefix.startsWith("-") || prefix.startsWith("/")) {
|
|
891
|
+
if (prefix.startsWith("--") || prefix.startsWith("-") || prefix.startsWith("/") || prefix.startsWith("+")) {
|
|
892
892
|
for (const optionName$1 of optionNames$1) if (optionName$1.startsWith(prefix)) {
|
|
893
893
|
if (prefix === "-" && optionName$1.length !== 2) continue;
|
|
894
894
|
suggestions.push({
|
package/dist/primitives.js
CHANGED
|
@@ -260,7 +260,7 @@ function* suggestOptionSync(optionNames$1, valueParser, hidden, context, prefix)
|
|
|
260
260
|
}
|
|
261
261
|
} else {
|
|
262
262
|
const expectingValue = context.buffer.length > 0 && optionNames$1.includes(context.buffer[context.buffer.length - 1]);
|
|
263
|
-
if (!expectingValue && (prefix.startsWith("--") || prefix.startsWith("-") || prefix.startsWith("/"))) {
|
|
263
|
+
if (!expectingValue && (prefix.startsWith("--") || prefix.startsWith("-") || prefix.startsWith("/") || prefix.startsWith("+"))) {
|
|
264
264
|
for (const optionName$1 of optionNames$1) if (optionName$1.startsWith(prefix)) {
|
|
265
265
|
if (prefix === "-" && optionName$1.length !== 2) continue;
|
|
266
266
|
yield {
|
|
@@ -274,7 +274,7 @@ function* suggestOptionSync(optionNames$1, valueParser, hidden, context, prefix)
|
|
|
274
274
|
if (context.buffer.length > 0) {
|
|
275
275
|
const lastToken = context.buffer[context.buffer.length - 1];
|
|
276
276
|
if (optionNames$1.includes(lastToken)) shouldSuggestValues = true;
|
|
277
|
-
} else if (isAnnotationWrappedInitialState(context.state) && context.buffer.length === 0 && (context.exec?.path?.length ?? 0) === 0 && !(prefix.startsWith("--") || prefix.startsWith("-") || prefix.startsWith("/"))) shouldSuggestValues = true;
|
|
277
|
+
} else if (isAnnotationWrappedInitialState(context.state) && context.buffer.length === 0 && (context.exec?.path?.length ?? 0) === 0 && !(prefix.startsWith("--") || prefix.startsWith("-") || prefix.startsWith("/") || prefix.startsWith("+"))) shouldSuggestValues = true;
|
|
278
278
|
if (shouldSuggestValues) yield* getSuggestionsWithDependency(valueParser, prefix, context.dependencyRegistry, context.exec);
|
|
279
279
|
}
|
|
280
280
|
}
|
|
@@ -344,7 +344,7 @@ async function* suggestOptionAsync(optionNames$1, valueParser, hidden, context,
|
|
|
344
344
|
}
|
|
345
345
|
} else {
|
|
346
346
|
const expectingValue = context.buffer.length > 0 && optionNames$1.includes(context.buffer[context.buffer.length - 1]);
|
|
347
|
-
if (!expectingValue && (prefix.startsWith("--") || prefix.startsWith("-") || prefix.startsWith("/"))) {
|
|
347
|
+
if (!expectingValue && (prefix.startsWith("--") || prefix.startsWith("-") || prefix.startsWith("/") || prefix.startsWith("+"))) {
|
|
348
348
|
for (const optionName$1 of optionNames$1) if (optionName$1.startsWith(prefix)) {
|
|
349
349
|
if (prefix === "-" && optionName$1.length !== 2) continue;
|
|
350
350
|
yield {
|
|
@@ -358,7 +358,7 @@ async function* suggestOptionAsync(optionNames$1, valueParser, hidden, context,
|
|
|
358
358
|
if (context.buffer.length > 0) {
|
|
359
359
|
const lastToken = context.buffer[context.buffer.length - 1];
|
|
360
360
|
if (optionNames$1.includes(lastToken)) shouldSuggestValues = true;
|
|
361
|
-
} else if (isAnnotationWrappedInitialState(context.state) && context.buffer.length === 0 && (context.exec?.path?.length ?? 0) === 0 && !(prefix.startsWith("--") || prefix.startsWith("-") || prefix.startsWith("/"))) shouldSuggestValues = true;
|
|
361
|
+
} else if (isAnnotationWrappedInitialState(context.state) && context.buffer.length === 0 && (context.exec?.path?.length ?? 0) === 0 && !(prefix.startsWith("--") || prefix.startsWith("-") || prefix.startsWith("/") || prefix.startsWith("+"))) shouldSuggestValues = true;
|
|
362
362
|
if (shouldSuggestValues) for await (const suggestion of getSuggestionsWithDependencyAsync(valueParser, prefix, context.dependencyRegistry, context.exec)) yield suggestion;
|
|
363
363
|
}
|
|
364
364
|
}
|
|
@@ -888,7 +888,7 @@ function flag(...args) {
|
|
|
888
888
|
suggest(_context, prefix) {
|
|
889
889
|
if (isSuggestionHidden(options.hidden)) return [];
|
|
890
890
|
const suggestions = [];
|
|
891
|
-
if (prefix.startsWith("--") || prefix.startsWith("-") || prefix.startsWith("/")) {
|
|
891
|
+
if (prefix.startsWith("--") || prefix.startsWith("-") || prefix.startsWith("/") || prefix.startsWith("+")) {
|
|
892
892
|
for (const optionName$1 of optionNames$1) if (optionName$1.startsWith(prefix)) {
|
|
893
893
|
if (prefix === "-" && optionName$1.length !== 2) continue;
|
|
894
894
|
suggestions.push({
|