@optique/core 1.4.0-dev.2638 → 1.4.0-dev.2662

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.
@@ -11,6 +11,7 @@ import { annotationViewTargets, getWrappedChildParseState, getWrappedChildState,
11
11
  import { mergeChildExec, withChildContext, withChildExecPath } from "./execution-context.js";
12
12
  import { collectLeadingCandidates } from "./usage-internals.js";
13
13
  import { adoptOptionScope, combinedOptionScope, conditionalOptionScope, forkOptionScope, restoreOptionScope, scopeParser, selectableOptionScope, withOptionScope, withParserOptionScope } from "./short-option.js";
14
+ import { defineReachableChildren, delegateKnownCompletion, getKnownCompletion, getOptionMatch, getPassThroughFailureHint, getPassThroughPriority, hasPassThroughUsage, matchesOptionToken, retainConsumingFailure, retainConsumingFailureHint, withPassThroughFailure, withReturnedConsumingFailure } from "./internal/passthrough.js";
14
15
  import { allowDuplicateLeadingCommandNamesKey } from "./internal/command-alias.js";
15
16
  import { completeOrExtractPhase2Seed, extractPhase2Seed, extractPhase2SeedKey, phase2SeedFromValueResult } from "./phase2-seed.js";
16
17
  import { fluent } from "./modifiers.js";
@@ -605,6 +606,63 @@ function sharedBufferLeadingNames(parsers) {
605
606
  return names.size === 0 ? EMPTY_LEADING_NAMES : names;
606
607
  }
607
608
  /**
609
+ * Defers capture until a known option at an equal or higher lane priority
610
+ * has been tried.
611
+ * Other siblings retain their relative order, and explicit priorities win.
612
+ */
613
+ function orderBeforePassThrough(pairs, context, getParser, getState, passThroughParsers) {
614
+ const token = context.buffer[0];
615
+ if (passThroughParsers.size === 0 || context.optionsTerminated || token == null || token === "--" || !/^[-/+]/.test(token)) return pairs;
616
+ const matches = new Map(pairs.map((pair) => [pair, getOptionMatch(getParser(pair), getState(pair), token)]));
617
+ const normalizedOptions = /* @__PURE__ */ new Map();
618
+ const captures = new Map(pairs.flatMap((pair) => {
619
+ if (!passThroughParsers.has(getParser(pair))) return [];
620
+ const priority = getPassThroughPriority(getParser(pair), getState(pair), token);
621
+ const match = matches.get(pair);
622
+ if (match != null && (priority == null || match.priority >= priority)) {
623
+ const unfiltered = getPassThroughPriority(getParser(pair), getState(pair));
624
+ if (priority == null || unfiltered != null && unfiltered > match.priority) normalizedOptions.set(pair, match.priority);
625
+ return [];
626
+ }
627
+ return priority == null ? [] : [[pair, priority]];
628
+ }));
629
+ const matching = pairs.filter((pair) => !captures.has(pair)).flatMap((pair) => {
630
+ const match = matches.get(pair);
631
+ return match == null ? [] : [match];
632
+ });
633
+ const orderedCaptures = [...captures].sort((a, b) => b[1] - a[1]);
634
+ if (matching.length === 0) {
635
+ let captureIndex = 0;
636
+ return pairs.map((pair) => captures.has(pair) ? orderedCaptures[captureIndex++][0] : pair);
637
+ }
638
+ const matchingPriority = Math.max(...matching.map((match) => match.priority));
639
+ const ordinary = pairs.filter((pair) => !captures.has(pair) && !normalizedOptions.has(pair));
640
+ const positions = new Map(pairs.map((pair, index) => [pair, index]));
641
+ for (const [pair, priority] of [...normalizedOptions].sort((a, b) => b[1] - a[1])) {
642
+ let insertion = ordinary.findIndex((candidate) => {
643
+ const match = matches.get(candidate);
644
+ return match != null && (match.priority < priority || match.priority === priority && positions.get(pair) < positions.get(candidate));
645
+ });
646
+ if (insertion < 0) {
647
+ const lastMatch = ordinary.findLastIndex((candidate) => matches.get(candidate) != null);
648
+ insertion = lastMatch >= 0 ? lastMatch + 1 : ordinary.findIndex((candidate) => positions.get(candidate) > positions.get(pair));
649
+ if (insertion < 0) insertion = ordinary.length;
650
+ }
651
+ ordinary.splice(insertion, 0, pair);
652
+ }
653
+ const first = ordinary.findIndex((pair) => matches.get(pair) != null);
654
+ const last = ordinary.findLastIndex((pair) => matches.get(pair) != null);
655
+ const before = orderedCaptures.filter(([, priority]) => priority > matchingPriority).map(([pair]) => pair);
656
+ const after = orderedCaptures.filter(([, priority]) => priority <= matchingPriority).map(([pair]) => pair);
657
+ return [
658
+ ...ordinary.slice(0, first),
659
+ ...before,
660
+ ...ordinary.slice(first, last + 1),
661
+ ...after,
662
+ ...ordinary.slice(last + 1)
663
+ ];
664
+ }
665
+ /**
608
666
  * Internal symbol for exposing field-level parser pairs from `object()`
609
667
  * and `merge()` parsers. This allows `merge()` to pre-complete dependency
610
668
  * source fields from child parsers before resolving deferred states.
@@ -970,12 +1028,16 @@ function analyzeNoMatchContext(parsers) {
970
1028
  * construction. This is a programmer error, not a user error.
971
1029
  */
972
1030
  var DuplicateOptionError = class extends Error {
1031
+ /** The option name shared by multiple fields. */
1032
+ optionName;
1033
+ /** The fields declaring the option. */
1034
+ sources;
973
1035
  constructor(optionName$1, sources) {
974
1036
  const sourceNames = sources.map((s) => typeof s === "symbol" ? s.description ?? s.toString() : s);
975
1037
  super(`Duplicate option name "${optionName$1}" found in fields: ${sourceNames.join(", ")}. Each option name must be unique within a parser combinator.`);
1038
+ this.name = "DuplicateOptionError";
976
1039
  this.optionName = optionName$1;
977
1040
  this.sources = sources;
978
- this.name = "DuplicateOptionError";
979
1041
  }
980
1042
  };
981
1043
  /**
@@ -983,6 +1045,8 @@ var DuplicateOptionError = class extends Error {
983
1045
  * during parser construction. This is a programmer error, not a user error.
984
1046
  */
985
1047
  var DuplicateCommandNameError = class extends TypeError {
1048
+ commandName;
1049
+ sources;
986
1050
  constructor(commandName, sources) {
987
1051
  const sourceNames = sources.map((s) => typeof s === "symbol" ? s.description ?? s.toString() : s);
988
1052
  super(`Duplicate command name "${commandName}" found in parsers: ${sourceNames.join(", ")}. Each command name or alias must be unique within active parser alternatives.`);
@@ -1076,6 +1140,16 @@ function generateNoMatchError(context) {
1076
1140
  else if (hasOptions && hasCommands && hasArguments) return message`No matching option, command, or argument found.`;
1077
1141
  else return message`No value provided.`;
1078
1142
  }
1143
+ /** Potential alternatives; only parsing decides whether replay can switch. */
1144
+ function selectExclusiveChildren(parsers, state, activeFirst = false) {
1145
+ const active = normalizeExclusiveState(state);
1146
+ const children = parsers.map((parser, index) => ({
1147
+ parser,
1148
+ index,
1149
+ state: getWrappedChildParseState(state, active?.[0] === index && active[1].success ? active[1].next.state : parser.initialState, parser)
1150
+ }));
1151
+ return activeFirst ? children.sort((a, b) => active?.[0] === a.index ? -1 : active?.[0] === b.index ? 1 : a.index - b.index) : children;
1152
+ }
1079
1153
  function normalizeExclusiveState(state) {
1080
1154
  if (!Array.isArray(state) || state.length !== 2 || typeof state[0] !== "number") return void 0;
1081
1155
  return state;
@@ -1114,6 +1188,7 @@ function preserveExclusiveStateAfterOptionsTerminator(context, result) {
1114
1188
  success: true,
1115
1189
  next: {
1116
1190
  ...context,
1191
+ ...getPassThroughFailureHint(result.next),
1117
1192
  buffer: result.next.buffer,
1118
1193
  optionsTerminated: true,
1119
1194
  state: context.state,
@@ -1404,15 +1479,19 @@ function or(...args) {
1404
1479
  const parseSync = (context) => {
1405
1480
  let error = getInitialError(context);
1406
1481
  const activeState = normalizeExclusiveState(context.state);
1407
- const orderedParsers = syncParsers.map((p, i) => [p, i]);
1408
- orderedParsers.sort(([_, a], [__, b]) => activeState?.[0] === a ? -1 : activeState?.[0] === b ? 1 : a - b);
1482
+ const orderedParsers = selectExclusiveChildren(syncParsers, context.state, true);
1409
1483
  let zeroConsumedBranch = null;
1410
1484
  let zeroConsumedCount = 0;
1411
1485
  let provisionalConsuming = null;
1412
1486
  let optionsTerminatorResult = null;
1413
1487
  let provisionalAmbiguous = false;
1414
- for (const [parser, i] of orderedParsers) {
1415
- const result = parser.parse(withChildContext$1(forkOptionScope(context), i, activeState == null || activeState[0] !== i || !activeState[1].success ? parser.initialState : activeState[1].next.state, parser));
1488
+ for (const { parser, index: i, state: childState } of orderedParsers) {
1489
+ const childContext = withChildContext$1(forkOptionScope(context), i, childState, parser);
1490
+ const result = parser.parse(childContext);
1491
+ if (result.success && result.consumed.length === 0) {
1492
+ const own = retainConsumingFailureHint(void 0, childContext, result.next);
1493
+ if (own != null && error.consumed < own.failure.consumed) error = own.failure;
1494
+ }
1416
1495
  if (isOptionsTerminatorOnlyResult(context, result)) {
1417
1496
  if (activeState?.[0] === i && activeState[1].success && activeState[1].consumed.length > 0 && result.next.buffer.length < 1) return preserveExclusiveStateAfterOptionsTerminator(context, result);
1418
1497
  optionsTerminatorResult ??= result;
@@ -1448,6 +1527,7 @@ function or(...args) {
1448
1527
  success: true,
1449
1528
  next: {
1450
1529
  ...adoptOptionScope(context, result.next),
1530
+ ...getPassThroughFailureHint(result.next),
1451
1531
  buffer: result.next.buffer,
1452
1532
  optionsTerminated: result.next.optionsTerminated,
1453
1533
  state: createExclusiveState(context.state, i, parser, result),
@@ -1484,6 +1564,7 @@ function or(...args) {
1484
1564
  success: true,
1485
1565
  next: {
1486
1566
  ...adoptOptionScope(context, replayedResult.next),
1567
+ ...getPassThroughFailureHint(replayedResult.next),
1487
1568
  buffer: replayedResult.next.buffer,
1488
1569
  optionsTerminated: replayedResult.next.optionsTerminated,
1489
1570
  state: createExclusiveState(context.state, i, parser, {
@@ -1503,6 +1584,7 @@ function or(...args) {
1503
1584
  success: true,
1504
1585
  next: {
1505
1586
  ...adoptOptionScope(context, result.next),
1587
+ ...getPassThroughFailureHint(result.next),
1506
1588
  buffer: result.next.buffer,
1507
1589
  optionsTerminated: result.next.optionsTerminated,
1508
1590
  state: createExclusiveState(context.state, i, parser, result),
@@ -1547,6 +1629,7 @@ function or(...args) {
1547
1629
  provisional: true,
1548
1630
  next: {
1549
1631
  ...adoptOptionScope(context, provisionalConsuming.result.next),
1632
+ ...getPassThroughFailureHint(provisionalConsuming.result.next),
1550
1633
  buffer: provisionalConsuming.result.next.buffer,
1551
1634
  optionsTerminated: provisionalConsuming.result.next.optionsTerminated,
1552
1635
  state: createExclusiveState(context.state, provisionalConsuming.index, provisionalConsuming.parser, provisionalConsuming.result),
@@ -1581,6 +1664,7 @@ function or(...args) {
1581
1664
  provisional: true,
1582
1665
  next: {
1583
1666
  ...adoptOptionScope(context, replayedResult.next),
1667
+ ...getPassThroughFailureHint(replayedResult.next),
1584
1668
  buffer: replayedResult.next.buffer,
1585
1669
  optionsTerminated: replayedResult.next.optionsTerminated,
1586
1670
  state: createExclusiveState(context.state, provisionalConsuming.index, provisionalConsuming.parser, {
@@ -1607,16 +1691,20 @@ function or(...args) {
1607
1691
  const parseAsync = async (context) => {
1608
1692
  let error = getInitialError(context);
1609
1693
  const activeState = normalizeExclusiveState(context.state);
1610
- const orderedParsers = parsers.map((p, i) => [p, i]);
1611
- orderedParsers.sort(([_, a], [__, b]) => activeState?.[0] === a ? -1 : activeState?.[0] === b ? 1 : a - b);
1694
+ const orderedParsers = selectExclusiveChildren(parsers, context.state, true);
1612
1695
  let zeroConsumedBranch = null;
1613
1696
  let zeroConsumedCount = 0;
1614
1697
  let provisionalConsuming = null;
1615
1698
  let optionsTerminatorResult = null;
1616
1699
  let provisionalAmbiguous = false;
1617
- for (const [parser, i] of orderedParsers) {
1618
- const resultOrPromise = parser.parse(withChildContext$1(forkOptionScope(context), i, activeState == null || activeState[0] !== i || !activeState[1].success ? parser.initialState : activeState[1].next.state, parser));
1700
+ for (const { parser, index: i, state: childState } of orderedParsers) {
1701
+ const childContext = withChildContext$1(forkOptionScope(context), i, childState, parser);
1702
+ const resultOrPromise = parser.parse(childContext);
1619
1703
  const result = await resultOrPromise;
1704
+ if (result.success && result.consumed.length === 0) {
1705
+ const own = retainConsumingFailureHint(void 0, childContext, result.next);
1706
+ if (own != null && error.consumed < own.failure.consumed) error = own.failure;
1707
+ }
1620
1708
  if (isOptionsTerminatorOnlyResult(context, result)) {
1621
1709
  if (activeState?.[0] === i && activeState[1].success && activeState[1].consumed.length > 0 && result.next.buffer.length < 1) return preserveExclusiveStateAfterOptionsTerminator(context, result);
1622
1710
  optionsTerminatorResult ??= result;
@@ -1652,6 +1740,7 @@ function or(...args) {
1652
1740
  success: true,
1653
1741
  next: {
1654
1742
  ...adoptOptionScope(context, result.next),
1743
+ ...getPassThroughFailureHint(result.next),
1655
1744
  buffer: result.next.buffer,
1656
1745
  optionsTerminated: result.next.optionsTerminated,
1657
1746
  state: createExclusiveState(context.state, i, parser, result),
@@ -1690,6 +1779,7 @@ function or(...args) {
1690
1779
  success: true,
1691
1780
  next: {
1692
1781
  ...adoptOptionScope(context, replayedResult.next),
1782
+ ...getPassThroughFailureHint(replayedResult.next),
1693
1783
  buffer: replayedResult.next.buffer,
1694
1784
  optionsTerminated: replayedResult.next.optionsTerminated,
1695
1785
  state: createExclusiveState(context.state, i, parser, {
@@ -1709,6 +1799,7 @@ function or(...args) {
1709
1799
  success: true,
1710
1800
  next: {
1711
1801
  ...adoptOptionScope(context, result.next),
1802
+ ...getPassThroughFailureHint(result.next),
1712
1803
  buffer: result.next.buffer,
1713
1804
  optionsTerminated: result.next.optionsTerminated,
1714
1805
  state: createExclusiveState(context.state, i, parser, result),
@@ -1753,6 +1844,7 @@ function or(...args) {
1753
1844
  provisional: true,
1754
1845
  next: {
1755
1846
  ...adoptOptionScope(context, provisionalConsuming.result.next),
1847
+ ...getPassThroughFailureHint(provisionalConsuming.result.next),
1756
1848
  buffer: provisionalConsuming.result.next.buffer,
1757
1849
  optionsTerminated: provisionalConsuming.result.next.optionsTerminated,
1758
1850
  state: createExclusiveState(context.state, provisionalConsuming.index, provisionalConsuming.parser, provisionalConsuming.result),
@@ -1787,6 +1879,7 @@ function or(...args) {
1787
1879
  provisional: true,
1788
1880
  next: {
1789
1881
  ...adoptOptionScope(context, replayedResult.next),
1882
+ ...getPassThroughFailureHint(replayedResult.next),
1790
1883
  buffer: replayedResult.next.buffer,
1791
1884
  optionsTerminated: replayedResult.next.optionsTerminated,
1792
1885
  state: createExclusiveState(context.state, provisionalConsuming.index, provisionalConsuming.parser, {
@@ -1879,6 +1972,7 @@ function or(...args) {
1879
1972
  if (singleDependencyMetadata != null) singleResult.dependencyMetadata = singleDependencyMetadata;
1880
1973
  defineExclusiveSchedulingNodes(singleResult, parsers);
1881
1974
  defineInheritedAnnotationParser(singleResult);
1975
+ defineReachableChildren(singleResult, parsers, (state) => selectExclusiveChildren(parsers, state, true));
1882
1976
  return fluent(scopeParser(singleResult, combinedOptionScope(parsers, parsers.map((_, index) => index))));
1883
1977
  }
1884
1978
  /**
@@ -1913,24 +2007,27 @@ function createLongestMatch(...args) {
1913
2007
  return createUnexpectedInputErrorWithScopedSuggestions(defaultMsg, token, parsers, options?.errors?.suggestions);
1914
2008
  })()
1915
2009
  });
1916
- const commitLongestMatch = (context, match, optionsTerminatorResult) => {
2010
+ const commitLongestMatch = (context, match, optionsTerminatorResult, consumingFailure) => {
1917
2011
  const selectedResult = optionsTerminatorResult == null ? match.result : {
1918
2012
  ...match.result,
1919
2013
  next: {
1920
2014
  ...match.result.next,
2015
+ ...getPassThroughFailureHint(optionsTerminatorResult.next),
1921
2016
  buffer: optionsTerminatorResult.next.buffer,
1922
2017
  optionsTerminated: true
1923
2018
  },
1924
2019
  consumed: [...optionsTerminatorResult.consumed, ...match.result.consumed]
1925
2020
  };
2021
+ const next = selectedResult.consumed.length === 0 ? withReturnedConsumingFailure(selectedResult.next, consumingFailure) : selectedResult.next;
1926
2022
  const parser = parsers[match.index];
1927
- const mergedExec = mergeChildExec(context.exec, selectedResult.next.exec);
2023
+ const mergedExec = mergeChildExec(context.exec, next.exec);
1928
2024
  return {
1929
2025
  success: true,
1930
2026
  next: {
1931
- ...adoptOptionScope(context, selectedResult.next),
1932
- buffer: selectedResult.next.buffer,
1933
- optionsTerminated: selectedResult.next.optionsTerminated,
2027
+ ...adoptOptionScope(context, next),
2028
+ ...getPassThroughFailureHint(next),
2029
+ buffer: next.buffer,
2030
+ optionsTerminated: next.optionsTerminated,
1934
2031
  state: createExclusiveState(context.state, match.index, parser, selectedResult),
1935
2032
  ...mergedExec != null ? {
1936
2033
  exec: mergedExec,
@@ -1965,10 +2062,9 @@ function createLongestMatch(...args) {
1965
2062
  let bestMatch = null;
1966
2063
  const optionsTerminatorMatches = [];
1967
2064
  let error = getInitialError(context);
1968
- const activeState = normalizeExclusiveState(context.state);
1969
- for (let i = 0; i < syncParsers.length; i++) {
1970
- const parser = syncParsers[i];
1971
- const childContext = withChildContext$1(forkOptionScope(context), i, activeState == null || activeState[0] !== i || !activeState[1].success ? parser.initialState : activeState[1].next.state, parser);
2065
+ let consumingFailure;
2066
+ for (const { parser, index: i, state: childState } of selectExclusiveChildren(syncParsers, context.state)) {
2067
+ const childContext = withChildContext$1(forkOptionScope(context), i, childState, parser);
1972
2068
  const result = parser.parse(childContext);
1973
2069
  if (isOptionsTerminatorOnlyResult(context, result)) {
1974
2070
  optionsTerminatorMatches.push({
@@ -1980,6 +2076,8 @@ function createLongestMatch(...args) {
1980
2076
  continue;
1981
2077
  }
1982
2078
  if (result.success) {
2079
+ consumingFailure = retainConsumingFailureHint(consumingFailure, context, result.next);
2080
+ if (consumingFailure != null && error.consumed < consumingFailure.failure.consumed) error = consumingFailure.failure;
1983
2081
  const consumed = context.buffer.length - result.next.buffer.length;
1984
2082
  const bestIsProvisional = bestMatch != null && bestMatch.result.success && !!bestMatch.result.provisional;
1985
2083
  if (bestMatch === null || consumed > bestMatch.consumed || consumed === bestMatch.consumed && bestIsProvisional && !result.provisional) bestMatch = {
@@ -1987,11 +2085,15 @@ function createLongestMatch(...args) {
1987
2085
  result,
1988
2086
  consumed
1989
2087
  };
1990
- } else if (error.consumed < result.consumed) error = result;
2088
+ } else {
2089
+ const match = getOptionMatch(parser, childContext.state, context.buffer[0]);
2090
+ if (result.consumed > 0 && match != null) consumingFailure = retainConsumingFailure(consumingFailure, result, match.priority);
2091
+ if (error.consumed < result.consumed) error = result;
2092
+ }
1991
2093
  }
1992
2094
  const optionsTerminatorResolution = resolveLongestMatchOptionsTerminator(context, bestMatch, optionsTerminatorMatches);
1993
2095
  if (optionsTerminatorResolution != null) return optionsTerminatorResolution;
1994
- if (bestMatch != null) return commitLongestMatch(context, bestMatch);
2096
+ if (bestMatch != null) return commitLongestMatch(context, bestMatch, void 0, consumingFailure);
1995
2097
  return {
1996
2098
  ...error,
1997
2099
  success: false
@@ -2001,10 +2103,9 @@ function createLongestMatch(...args) {
2001
2103
  let bestMatch = null;
2002
2104
  const optionsTerminatorMatches = [];
2003
2105
  let error = getInitialError(context);
2004
- const activeState = normalizeExclusiveState(context.state);
2005
- for (let i = 0; i < parsers.length; i++) {
2006
- const parser = parsers[i];
2007
- const childContext = withChildContext$1(forkOptionScope(context), i, activeState == null || activeState[0] !== i || !activeState[1].success ? parser.initialState : activeState[1].next.state, parser);
2106
+ let consumingFailure;
2107
+ for (const { parser, index: i, state: childState } of selectExclusiveChildren(parsers, context.state)) {
2108
+ const childContext = withChildContext$1(forkOptionScope(context), i, childState, parser);
2008
2109
  const resultOrPromise = parser.parse(childContext);
2009
2110
  const result = await resultOrPromise;
2010
2111
  if (isOptionsTerminatorOnlyResult(context, result)) {
@@ -2017,6 +2118,8 @@ function createLongestMatch(...args) {
2017
2118
  continue;
2018
2119
  }
2019
2120
  if (result.success) {
2121
+ consumingFailure = retainConsumingFailureHint(consumingFailure, context, result.next);
2122
+ if (consumingFailure != null && error.consumed < consumingFailure.failure.consumed) error = consumingFailure.failure;
2020
2123
  const consumed = context.buffer.length - result.next.buffer.length;
2021
2124
  const bestIsProvisional = bestMatch != null && bestMatch.result.success && !!bestMatch.result.provisional;
2022
2125
  if (bestMatch === null || consumed > bestMatch.consumed || consumed === bestMatch.consumed && bestIsProvisional && !result.provisional) bestMatch = {
@@ -2024,11 +2127,15 @@ function createLongestMatch(...args) {
2024
2127
  result,
2025
2128
  consumed
2026
2129
  };
2027
- } else if (error.consumed < result.consumed) error = result;
2130
+ } else {
2131
+ const match = getOptionMatch(parser, childContext.state, context.buffer[0]);
2132
+ if (result.consumed > 0 && match != null) consumingFailure = retainConsumingFailure(consumingFailure, result, match.priority);
2133
+ if (error.consumed < result.consumed) error = result;
2134
+ }
2028
2135
  }
2029
2136
  const optionsTerminatorResolution = resolveLongestMatchOptionsTerminator(context, bestMatch, optionsTerminatorMatches);
2030
2137
  if (optionsTerminatorResolution != null) return optionsTerminatorResolution;
2031
- if (bestMatch != null) return commitLongestMatch(context, bestMatch);
2138
+ if (bestMatch != null) return commitLongestMatch(context, bestMatch, void 0, consumingFailure);
2032
2139
  return {
2033
2140
  ...error,
2034
2141
  success: false
@@ -2101,6 +2208,7 @@ function createLongestMatch(...args) {
2101
2208
  if (multiDependencyMetadata != null) multiResult.dependencyMetadata = multiDependencyMetadata;
2102
2209
  defineExclusiveSchedulingNodes(multiResult, parsers);
2103
2210
  defineInheritedAnnotationParser(multiResult);
2211
+ defineReachableChildren(multiResult, parsers, (state) => selectExclusiveChildren(parsers, state, false));
2104
2212
  return fluent(scopeParser(multiResult, combinedOptionScope(parsers, parsers.map((_, index) => index))));
2105
2213
  }
2106
2214
  /**
@@ -2504,6 +2612,7 @@ function object(labelOrParsers, maybeParsersOrOptions, maybeOptions) {
2504
2612
  const parserKeys = Reflect.ownKeys(parsers);
2505
2613
  const parserPairs = parserKeys.map((k) => [k, parsers[k]]);
2506
2614
  parserPairs.sort(([_, parserA], [__, parserB]) => parserB.priority - parserA.priority);
2615
+ const passThroughParsers = new Set(parserPairs.map(([, parser]) => parser).filter((parser) => hasPassThroughUsage(parser.usage)));
2507
2616
  const createInitialState = () => {
2508
2617
  const state = {};
2509
2618
  for (const key of parserKeys) state[key] = parsers[key].initialState;
@@ -2541,7 +2650,10 @@ function object(labelOrParsers, maybeParsersOrOptions, maybeOptions) {
2541
2650
  if (!result.success) return result;
2542
2651
  if (result.consumed.length === 0 && result.next.state === fieldState) return {
2543
2652
  success: true,
2544
- next: context,
2653
+ next: {
2654
+ ...context,
2655
+ ...getPassThroughFailureHint(result.next)
2656
+ },
2545
2657
  consumed: []
2546
2658
  };
2547
2659
  adoptOptionScope(context, result.next);
@@ -2554,6 +2666,7 @@ function object(labelOrParsers, maybeParsersOrOptions, maybeOptions) {
2554
2666
  success: true,
2555
2667
  next: {
2556
2668
  ...context,
2669
+ ...getPassThroughFailureHint(result.next),
2557
2670
  buffer: result.next.buffer,
2558
2671
  optionsTerminated: result.next.optionsTerminated,
2559
2672
  state: nextState,
@@ -2590,17 +2703,20 @@ function object(labelOrParsers, maybeParsersOrOptions, maybeOptions) {
2590
2703
  let anySuccess = false;
2591
2704
  const allConsumed = [];
2592
2705
  const consumedFields = /* @__PURE__ */ new Set();
2706
+ let consumingFailure;
2593
2707
  let madeProgress = true;
2594
2708
  while (madeProgress && currentContext.buffer.length > 0) {
2595
2709
  madeProgress = false;
2710
+ consumingFailure = void 0;
2596
2711
  const getFieldState = createFieldStateGetter(currentContext.state, getObjectParseChildState);
2597
- for (const [field, parser] of parserPairs) {
2598
- const result = parser.parse(withChildContext$1(forkOptionScope(currentContext), field, getFieldState(field, parser), parser));
2712
+ for (const [field, parser] of orderBeforePassThrough(parserPairs, currentContext, ([, parser$1]) => parser$1, ([field$1, parser$1]) => getFieldState(field$1, parser$1), passThroughParsers)) {
2713
+ const result = parser.parse(withPassThroughFailure(withChildContext$1(forkOptionScope(currentContext), field, getFieldState(field, parser), parser), consumingFailure, getPassThroughPriority(parser, getFieldState(field, parser), currentContext.buffer[0])));
2599
2714
  if (result.success && result.consumed.length > 0) {
2600
2715
  adoptOptionScope(currentContext, result.next);
2601
2716
  const mergedExec = mergeChildExec(currentContext.exec, result.next.exec);
2602
2717
  currentContext = {
2603
2718
  ...currentContext,
2719
+ ...getPassThroughFailureHint(result.next),
2604
2720
  buffer: result.next.buffer,
2605
2721
  optionsTerminated: result.next.optionsTerminated,
2606
2722
  state: {
@@ -2618,7 +2734,14 @@ function object(labelOrParsers, maybeParsersOrOptions, maybeOptions) {
2618
2734
  madeProgress = true;
2619
2735
  consumedFields.add(field);
2620
2736
  break;
2621
- } else if (!result.success && error.consumed < result.consumed) error = result;
2737
+ } else if (result.success) {
2738
+ consumingFailure = retainConsumingFailureHint(consumingFailure, currentContext, result.next);
2739
+ if (consumingFailure != null && error.consumed < consumingFailure.failure.consumed) error = consumingFailure.failure;
2740
+ } else {
2741
+ const match = getOptionMatch(parser, getFieldState(field, parser), currentContext.buffer[0]);
2742
+ if (result.consumed > 0 && match != null) consumingFailure = retainConsumingFailure(consumingFailure, result, match.priority);
2743
+ if (error.consumed < result.consumed) error = result;
2744
+ }
2622
2745
  }
2623
2746
  }
2624
2747
  {
@@ -2628,7 +2751,7 @@ function object(labelOrParsers, maybeParsersOrOptions, maybeOptions) {
2628
2751
  const typedParser = parser;
2629
2752
  if (parser.leadingNames.size > 0 || typedParser.acceptingAnyToken) continue;
2630
2753
  const fieldState = getFieldState(field, parser);
2631
- const result = typedParser.parse(withChildContext$1(forkOptionScope(currentContext), field, fieldState, parser));
2754
+ const result = typedParser.parse(withPassThroughFailure(withChildContext$1(forkOptionScope(currentContext), field, fieldState, parser), consumingFailure, getPassThroughPriority(parser, getFieldState(field, parser), currentContext.buffer[0])));
2632
2755
  if (result.success && result.consumed.length === 0 && result.next.state !== fieldState) {
2633
2756
  adoptOptionScope(currentContext, result.next);
2634
2757
  const mergedExec = mergeChildExec(currentContext.exec, result.next.exec);
@@ -2649,7 +2772,7 @@ function object(labelOrParsers, maybeParsersOrOptions, maybeOptions) {
2649
2772
  }
2650
2773
  if (anySuccess) return {
2651
2774
  success: true,
2652
- next: currentContext,
2775
+ next: withReturnedConsumingFailure(currentContext, consumingFailure),
2653
2776
  consumed: allConsumed
2654
2777
  };
2655
2778
  if (currentContext.buffer.length === 0) {
@@ -2698,18 +2821,21 @@ function object(labelOrParsers, maybeParsersOrOptions, maybeOptions) {
2698
2821
  let anySuccess = false;
2699
2822
  const allConsumed = [];
2700
2823
  const consumedFields = /* @__PURE__ */ new Set();
2824
+ let consumingFailure;
2701
2825
  let madeProgress = true;
2702
2826
  while (madeProgress && currentContext.buffer.length > 0) {
2703
2827
  madeProgress = false;
2828
+ consumingFailure = void 0;
2704
2829
  const getFieldState = createFieldStateGetter(currentContext.state, getObjectParseChildState);
2705
- for (const [field, parser] of parserPairs) {
2706
- const resultOrPromise = parser.parse(withChildContext$1(forkOptionScope(currentContext), field, getFieldState(field, parser), parser));
2830
+ for (const [field, parser] of orderBeforePassThrough(parserPairs, currentContext, ([, parser$1]) => parser$1, ([field$1, parser$1]) => getFieldState(field$1, parser$1), passThroughParsers)) {
2831
+ const resultOrPromise = parser.parse(withPassThroughFailure(withChildContext$1(forkOptionScope(currentContext), field, getFieldState(field, parser), parser), consumingFailure, getPassThroughPriority(parser, getFieldState(field, parser), currentContext.buffer[0])));
2707
2832
  const result = await resultOrPromise;
2708
2833
  if (result.success && result.consumed.length > 0) {
2709
2834
  adoptOptionScope(currentContext, result.next);
2710
2835
  const mergedExec = mergeChildExec(currentContext.exec, result.next.exec);
2711
2836
  currentContext = {
2712
2837
  ...currentContext,
2838
+ ...getPassThroughFailureHint(result.next),
2713
2839
  buffer: result.next.buffer,
2714
2840
  optionsTerminated: result.next.optionsTerminated,
2715
2841
  state: {
@@ -2727,7 +2853,14 @@ function object(labelOrParsers, maybeParsersOrOptions, maybeOptions) {
2727
2853
  madeProgress = true;
2728
2854
  consumedFields.add(field);
2729
2855
  break;
2730
- } else if (!result.success && error.consumed < result.consumed) error = result;
2856
+ } else if (result.success) {
2857
+ consumingFailure = retainConsumingFailureHint(consumingFailure, currentContext, result.next);
2858
+ if (consumingFailure != null && error.consumed < consumingFailure.failure.consumed) error = consumingFailure.failure;
2859
+ } else {
2860
+ const match = getOptionMatch(parser, getFieldState(field, parser), currentContext.buffer[0]);
2861
+ if (result.consumed > 0 && match != null) consumingFailure = retainConsumingFailure(consumingFailure, result, match.priority);
2862
+ if (error.consumed < result.consumed) error = result;
2863
+ }
2731
2864
  }
2732
2865
  }
2733
2866
  {
@@ -2736,7 +2869,7 @@ function object(labelOrParsers, maybeParsersOrOptions, maybeOptions) {
2736
2869
  if (consumedFields.has(field)) continue;
2737
2870
  if (parser.leadingNames.size > 0 || parser.acceptingAnyToken) continue;
2738
2871
  const fieldState = getFieldState(field, parser);
2739
- const resultOrPromise = parser.parse(withChildContext$1(forkOptionScope(currentContext), field, fieldState, parser));
2872
+ const resultOrPromise = parser.parse(withPassThroughFailure(withChildContext$1(forkOptionScope(currentContext), field, fieldState, parser), consumingFailure, getPassThroughPriority(parser, getFieldState(field, parser), currentContext.buffer[0])));
2740
2873
  const result = await resultOrPromise;
2741
2874
  if (result.success && result.consumed.length === 0 && result.next.state !== fieldState) {
2742
2875
  adoptOptionScope(currentContext, result.next);
@@ -2758,7 +2891,7 @@ function object(labelOrParsers, maybeParsersOrOptions, maybeOptions) {
2758
2891
  }
2759
2892
  if (anySuccess) return {
2760
2893
  success: true,
2761
- next: currentContext,
2894
+ next: withReturnedConsumingFailure(currentContext, consumingFailure),
2762
2895
  consumed: allConsumed
2763
2896
  };
2764
2897
  if (currentContext.buffer.length === 0) {
@@ -3128,6 +3261,13 @@ function object(labelOrParsers, maybeParsersOrOptions, maybeOptions) {
3128
3261
  });
3129
3262
  defineParseLanes(objectParser, objectParseLanes);
3130
3263
  defineInheritedAnnotationParser(objectParser);
3264
+ defineReachableChildren(objectParser, parserPairs.map(([, parser]) => parser), (state) => {
3265
+ const getFieldState = createFieldStateGetter(state, getObjectParseChildState);
3266
+ return parserPairs.map(([field, parser]) => ({
3267
+ parser,
3268
+ state: getWrappedChildParseState(state, getFieldState(field, parser), parser)
3269
+ }));
3270
+ });
3131
3271
  return fluent(scopeParser(objectParser, combinedOptionScope(parserPairs.map(([, p]) => p), parserPairs.map(([field]) => field)), void 0, true));
3132
3272
  }
3133
3273
  function isParserLike(value) {
@@ -3586,6 +3726,7 @@ function advanceTupleSuggestContextSync(context, parsers) {
3586
3726
  const mergedExec = mergeChildExec(currentContext.exec, result.next.exec);
3587
3727
  currentContext = {
3588
3728
  ...currentContext,
3729
+ ...getPassThroughFailureHint(result.next),
3589
3730
  buffer: result.next.buffer,
3590
3731
  optionsTerminated: result.next.optionsTerminated,
3591
3732
  state: newStateArray,
@@ -3652,6 +3793,7 @@ async function advanceTupleSuggestContextAsync(context, parsers) {
3652
3793
  const mergedExec = mergeChildExec(currentContext.exec, result.next.exec);
3653
3794
  currentContext = {
3654
3795
  ...currentContext,
3796
+ ...getPassThroughFailureHint(result.next),
3655
3797
  buffer: result.next.buffer,
3656
3798
  optionsTerminated: result.next.optionsTerminated,
3657
3799
  state: newStateArray,
@@ -3751,10 +3893,12 @@ function tuple(labelOrParsers, maybeParsersOrOptions, maybeOptions) {
3751
3893
  const combinedMode = parsers.some((p) => p.mode === "async") ? "async" : "sync";
3752
3894
  const syncParsers = parsers;
3753
3895
  if (!options.allowDuplicates) checkDuplicateOptionNames(parsers.map((parser, index) => [String(index), parser.usage]));
3896
+ const passThroughParsers = new Set(parsers.filter((parser) => hasPassThroughUsage(parser.usage)));
3754
3897
  const parseSync = (context) => {
3755
3898
  let currentContext = context;
3756
3899
  const allConsumed = [];
3757
3900
  const matchedParsers = /* @__PURE__ */ new Set();
3901
+ let consumingFailure;
3758
3902
  while (matchedParsers.size < syncParsers.length) {
3759
3903
  let foundMatch = false;
3760
3904
  let error = {
@@ -3762,14 +3906,15 @@ function tuple(labelOrParsers, maybeParsersOrOptions, maybeOptions) {
3762
3906
  error: message`No remaining parsers could match the input.`
3763
3907
  };
3764
3908
  const stateArray = currentContext.state;
3765
- const remainingParsers = syncParsers.map((parser, index) => [parser, index]).filter(([_, index]) => !matchedParsers.has(index)).sort(([parserA], [parserB]) => parserB.priority - parserA.priority);
3909
+ const remainingParsers = orderBeforePassThrough(syncParsers.map((parser, index) => [parser, index]).filter(([parser, index]) => !matchedParsers.has(index) || getOptionMatch(parser, stateArray[index], currentContext.buffer[0])?.continuesCommand === true || passThroughParsers.size > 0 && !currentContext.optionsTerminated && getOptionMatch(parser, stateArray[index], currentContext.buffer[0]) != null).sort(([parserA], [parserB]) => parserB.priority - parserA.priority), currentContext, ([parser]) => parser, ([, index]) => stateArray[index], passThroughParsers);
3766
3910
  for (const [parser, index] of remainingParsers) {
3767
- const result = parser.parse(withChildContext$1(currentContext, index, stateArray[index], parser));
3911
+ const result = parser.parse(withPassThroughFailure(withChildContext$1(currentContext, index, stateArray[index], parser), consumingFailure, getPassThroughPriority(parser, stateArray[index], currentContext.buffer[0])));
3768
3912
  if (result.success && result.consumed.length > 0) {
3769
3913
  const newStateArray = annotateFreshArray(currentContext.state, stateArray.map((s, idx) => idx === index ? getWrappedChildState(currentContext.state, result.next.state, parser) : s));
3770
3914
  const mergedExec = mergeChildExec(currentContext.exec, result.next.exec);
3771
3915
  currentContext = {
3772
3916
  ...currentContext,
3917
+ ...getPassThroughFailureHint(result.next),
3773
3918
  buffer: result.next.buffer,
3774
3919
  optionsTerminated: result.next.optionsTerminated,
3775
3920
  state: newStateArray,
@@ -3778,14 +3923,23 @@ function tuple(labelOrParsers, maybeParsersOrOptions, maybeOptions) {
3778
3923
  dependencyRegistry: mergedExec.dependencyRegistry
3779
3924
  } : {}
3780
3925
  };
3926
+ consumingFailure = void 0;
3781
3927
  allConsumed.push(...result.consumed);
3782
3928
  matchedParsers.add(index);
3783
3929
  foundMatch = true;
3784
3930
  break;
3785
- } else if (!result.success && error.consumed < result.consumed) error = result;
3931
+ } else if (result.success) {
3932
+ consumingFailure = retainConsumingFailureHint(consumingFailure, currentContext, result.next);
3933
+ if (consumingFailure != null && error.consumed < consumingFailure.failure.consumed) error = consumingFailure.failure;
3934
+ } else {
3935
+ const match = getOptionMatch(parser, stateArray[index], currentContext.buffer[0]);
3936
+ if (result.consumed > 0 && match != null) consumingFailure = retainConsumingFailure(consumingFailure, result, match.priority);
3937
+ if (error.consumed < result.consumed) error = result;
3938
+ }
3786
3939
  }
3787
3940
  if (!foundMatch) for (const [parser, index] of remainingParsers) {
3788
- const result = parser.parse(withChildContext$1(currentContext, index, stateArray[index], parser));
3941
+ if (matchedParsers.has(index)) continue;
3942
+ const result = parser.parse(withPassThroughFailure(withChildContext$1(currentContext, index, stateArray[index], parser), consumingFailure, getPassThroughPriority(parser, stateArray[index], currentContext.buffer[0])));
3789
3943
  if (result.success && result.consumed.length < 1) {
3790
3944
  const newStateArray = annotateFreshArray(currentContext.state, stateArray.map((s, idx) => idx === index ? getWrappedChildState(currentContext.state, result.next.state, parser) : s));
3791
3945
  const mergedExec = mergeChildExec(currentContext.exec, result.next.exec);
@@ -3813,7 +3967,7 @@ function tuple(labelOrParsers, maybeParsersOrOptions, maybeOptions) {
3813
3967
  }
3814
3968
  return {
3815
3969
  success: true,
3816
- next: currentContext,
3970
+ next: withReturnedConsumingFailure(currentContext, consumingFailure),
3817
3971
  consumed: allConsumed
3818
3972
  };
3819
3973
  };
@@ -3821,6 +3975,7 @@ function tuple(labelOrParsers, maybeParsersOrOptions, maybeOptions) {
3821
3975
  let currentContext = context;
3822
3976
  const allConsumed = [];
3823
3977
  const matchedParsers = /* @__PURE__ */ new Set();
3978
+ let consumingFailure;
3824
3979
  while (matchedParsers.size < parsers.length) {
3825
3980
  let foundMatch = false;
3826
3981
  let error = {
@@ -3828,15 +3983,16 @@ function tuple(labelOrParsers, maybeParsersOrOptions, maybeOptions) {
3828
3983
  error: message`No remaining parsers could match the input.`
3829
3984
  };
3830
3985
  const stateArray = currentContext.state;
3831
- const remainingParsers = parsers.map((parser, index) => [parser, index]).filter(([_, index]) => !matchedParsers.has(index)).sort(([parserA], [parserB]) => parserB.priority - parserA.priority);
3986
+ const remainingParsers = orderBeforePassThrough(parsers.map((parser, index) => [parser, index]).filter(([parser, index]) => !matchedParsers.has(index) || getOptionMatch(parser, stateArray[index], currentContext.buffer[0])?.continuesCommand === true || passThroughParsers.size > 0 && !currentContext.optionsTerminated && getOptionMatch(parser, stateArray[index], currentContext.buffer[0]) != null).sort(([parserA], [parserB]) => parserB.priority - parserA.priority), currentContext, ([parser]) => parser, ([, index]) => stateArray[index], passThroughParsers);
3832
3987
  for (const [parser, index] of remainingParsers) {
3833
- const resultOrPromise = parser.parse(withChildContext$1(currentContext, index, stateArray[index], parser));
3988
+ const resultOrPromise = parser.parse(withPassThroughFailure(withChildContext$1(currentContext, index, stateArray[index], parser), consumingFailure, getPassThroughPriority(parser, stateArray[index], currentContext.buffer[0])));
3834
3989
  const result = await resultOrPromise;
3835
3990
  if (result.success && result.consumed.length > 0) {
3836
3991
  const newStateArray = annotateFreshArray(currentContext.state, stateArray.map((s, idx) => idx === index ? getWrappedChildState(currentContext.state, result.next.state, parser) : s));
3837
3992
  const mergedExec = mergeChildExec(currentContext.exec, result.next.exec);
3838
3993
  currentContext = {
3839
3994
  ...currentContext,
3995
+ ...getPassThroughFailureHint(result.next),
3840
3996
  buffer: result.next.buffer,
3841
3997
  optionsTerminated: result.next.optionsTerminated,
3842
3998
  state: newStateArray,
@@ -3845,14 +4001,23 @@ function tuple(labelOrParsers, maybeParsersOrOptions, maybeOptions) {
3845
4001
  dependencyRegistry: mergedExec.dependencyRegistry
3846
4002
  } : {}
3847
4003
  };
4004
+ consumingFailure = void 0;
3848
4005
  allConsumed.push(...result.consumed);
3849
4006
  matchedParsers.add(index);
3850
4007
  foundMatch = true;
3851
4008
  break;
3852
- } else if (!result.success && error.consumed < result.consumed) error = result;
4009
+ } else if (result.success) {
4010
+ consumingFailure = retainConsumingFailureHint(consumingFailure, currentContext, result.next);
4011
+ if (consumingFailure != null && error.consumed < consumingFailure.failure.consumed) error = consumingFailure.failure;
4012
+ } else {
4013
+ const match = getOptionMatch(parser, stateArray[index], currentContext.buffer[0]);
4014
+ if (result.consumed > 0 && match != null) consumingFailure = retainConsumingFailure(consumingFailure, result, match.priority);
4015
+ if (error.consumed < result.consumed) error = result;
4016
+ }
3853
4017
  }
3854
4018
  if (!foundMatch) for (const [parser, index] of remainingParsers) {
3855
- const resultOrPromise = parser.parse(withChildContext$1(currentContext, index, stateArray[index], parser));
4019
+ if (matchedParsers.has(index)) continue;
4020
+ const resultOrPromise = parser.parse(withPassThroughFailure(withChildContext$1(currentContext, index, stateArray[index], parser), consumingFailure, getPassThroughPriority(parser, stateArray[index], currentContext.buffer[0])));
3856
4021
  const result = await resultOrPromise;
3857
4022
  if (result.success && result.consumed.length < 1) {
3858
4023
  const newStateArray = annotateFreshArray(currentContext.state, stateArray.map((s, idx) => idx === index ? getWrappedChildState(currentContext.state, result.next.state, parser) : s));
@@ -3881,7 +4046,7 @@ function tuple(labelOrParsers, maybeParsersOrOptions, maybeOptions) {
3881
4046
  }
3882
4047
  return {
3883
4048
  success: true,
3884
- next: currentContext,
4049
+ next: withReturnedConsumingFailure(currentContext, consumingFailure),
3885
4050
  consumed: allConsumed
3886
4051
  };
3887
4052
  };
@@ -4154,6 +4319,10 @@ function tuple(labelOrParsers, maybeParsersOrOptions, maybeOptions) {
4154
4319
  enumerable: false
4155
4320
  });
4156
4321
  defineInheritedAnnotationParser(tupleParser);
4322
+ defineReachableChildren(tupleParser, parsers, (state) => parsers.map((parser, index) => ({
4323
+ parser,
4324
+ state: getWrappedChildParseState(state, state[index], parser)
4325
+ })));
4157
4326
  return fluent(scopeParser(tupleParser, combinedOptionScope(parsers, parsers.map((_, index) => index))));
4158
4327
  }
4159
4328
  function seq(...rawArgs) {
@@ -4648,6 +4817,7 @@ function merge(...args) {
4648
4817
  success: true,
4649
4818
  next: {
4650
4819
  ...context,
4820
+ ...getPassThroughFailureHint(result.next),
4651
4821
  buffer: result.next.buffer,
4652
4822
  optionsTerminated: result.next.optionsTerminated,
4653
4823
  state: newState,
@@ -4753,6 +4923,7 @@ function merge(...args) {
4753
4923
  const mergedExec = mergeChildExec(settledContext.exec, result.next.exec);
4754
4924
  settledContext = {
4755
4925
  ...settledContext,
4926
+ ...getPassThroughFailureHint(result.next),
4756
4927
  buffer: result.next.buffer,
4757
4928
  optionsTerminated: result.next.optionsTerminated,
4758
4929
  state: nextState,
@@ -4785,6 +4956,7 @@ function merge(...args) {
4785
4956
  const newState = mergeResultState(parser, currentContext, parserState, result, i);
4786
4957
  const newContext = {
4787
4958
  ...currentContext,
4959
+ ...getPassThroughFailureHint(result.next),
4788
4960
  buffer: result.next.buffer,
4789
4961
  optionsTerminated: result.next.optionsTerminated,
4790
4962
  state: newState,
@@ -4830,6 +5002,7 @@ function merge(...args) {
4830
5002
  const newState = mergeResultState(parser, currentContext, parserState, result, i);
4831
5003
  const newContext = {
4832
5004
  ...currentContext,
5005
+ ...getPassThroughFailureHint(result.next),
4833
5006
  buffer: result.next.buffer,
4834
5007
  optionsTerminated: result.next.optionsTerminated,
4835
5008
  state: newState,
@@ -4869,17 +5042,20 @@ function merge(...args) {
4869
5042
  const consumedLanes = /* @__PURE__ */ new Set();
4870
5043
  const consumedGroups = /* @__PURE__ */ new Set();
4871
5044
  const laneResults = /* @__PURE__ */ new Map();
5045
+ let consumingFailure;
4872
5046
  let attemptedLane = false;
4873
5047
  let madeProgress = true;
4874
5048
  while (madeProgress && currentContext.buffer.length > 0) {
4875
5049
  madeProgress = false;
5050
+ consumingFailure = void 0;
4876
5051
  let consumingError = null;
4877
5052
  for (const lane of mergeParseLanes) {
4878
5053
  if (consumingError != null && lane.priority < consumingError.priority) {
4879
5054
  if (!canTryPositionalLaneAfterFailure(lane, currentContext)) continue;
4880
5055
  }
4881
5056
  attemptedLane = true;
4882
- const result = lane.parse(currentContext);
5057
+ const childContext = withPassThroughFailure(currentContext, consumingFailure);
5058
+ const result = lane.parse(childContext);
4883
5059
  laneResults.set(lane, result);
4884
5060
  if (result.success && result.consumed.length > 0) {
4885
5061
  currentContext = result.next;
@@ -4889,7 +5065,18 @@ function merge(...args) {
4889
5065
  madeProgress = true;
4890
5066
  break;
4891
5067
  }
5068
+ if (result.success) {
5069
+ const own = retainConsumingFailureHint(void 0, childContext, result.next);
5070
+ if (own != null) {
5071
+ consumingFailure = retainConsumingFailure(consumingFailure, own.failure, own.priority);
5072
+ if (error.consumed < own.failure.consumed) error = own.failure;
5073
+ }
5074
+ }
4892
5075
  if (!result.success) {
5076
+ if (result.consumed > 0 && matchesOptionToken({
5077
+ leadingNames: lane.leadingNames,
5078
+ usage: parsers.flatMap((parser) => parser.usage)
5079
+ }, currentContext.buffer[0])) consumingFailure = retainConsumingFailure(consumingFailure, result, lane.priority);
4893
5080
  if (result.consumed > 0 && consumingError == null) consumingError = {
4894
5081
  priority: lane.priority,
4895
5082
  result
@@ -4921,7 +5108,7 @@ function merge(...args) {
4921
5108
  }
4922
5109
  return {
4923
5110
  success: true,
4924
- next: currentContext,
5111
+ next: withReturnedConsumingFailure(currentContext, consumingFailure),
4925
5112
  consumed: allConsumed
4926
5113
  };
4927
5114
  };
@@ -4932,17 +5119,20 @@ function merge(...args) {
4932
5119
  const consumedLanes = /* @__PURE__ */ new Set();
4933
5120
  const consumedGroups = /* @__PURE__ */ new Set();
4934
5121
  const laneResults = /* @__PURE__ */ new Map();
5122
+ let consumingFailure;
4935
5123
  let attemptedLane = false;
4936
5124
  let madeProgress = true;
4937
5125
  while (madeProgress && currentContext.buffer.length > 0) {
4938
5126
  madeProgress = false;
5127
+ consumingFailure = void 0;
4939
5128
  let consumingError = null;
4940
5129
  for (const lane of mergeParseLanes) {
4941
5130
  if (consumingError != null && lane.priority < consumingError.priority) {
4942
5131
  if (!canTryPositionalLaneAfterFailure(lane, currentContext)) continue;
4943
5132
  }
4944
5133
  attemptedLane = true;
4945
- const result = await lane.parse(currentContext);
5134
+ const childContext = withPassThroughFailure(currentContext, consumingFailure);
5135
+ const result = await lane.parse(childContext);
4946
5136
  laneResults.set(lane, result);
4947
5137
  if (result.success && result.consumed.length > 0) {
4948
5138
  currentContext = result.next;
@@ -4952,7 +5142,18 @@ function merge(...args) {
4952
5142
  madeProgress = true;
4953
5143
  break;
4954
5144
  }
5145
+ if (result.success) {
5146
+ const own = retainConsumingFailureHint(void 0, childContext, result.next);
5147
+ if (own != null) {
5148
+ consumingFailure = retainConsumingFailure(consumingFailure, own.failure, own.priority);
5149
+ if (error.consumed < own.failure.consumed) error = own.failure;
5150
+ }
5151
+ }
4955
5152
  if (!result.success) {
5153
+ if (result.consumed > 0 && matchesOptionToken({
5154
+ leadingNames: lane.leadingNames,
5155
+ usage: parsers.flatMap((parser) => parser.usage)
5156
+ }, currentContext.buffer[0])) consumingFailure = retainConsumingFailure(consumingFailure, result, lane.priority);
4956
5157
  if (result.consumed > 0 && consumingError == null) consumingError = {
4957
5158
  priority: lane.priority,
4958
5159
  result
@@ -4984,7 +5185,7 @@ function merge(...args) {
4984
5185
  }
4985
5186
  return {
4986
5187
  success: true,
4987
- next: currentContext,
5188
+ next: withReturnedConsumingFailure(currentContext, consumingFailure),
4988
5189
  consumed: allConsumed
4989
5190
  };
4990
5191
  };
@@ -5527,6 +5728,10 @@ function merge(...args) {
5527
5728
  };
5528
5729
  defineParseLanes(mergeParser, mergeParseLanes);
5529
5730
  defineInheritedAnnotationParser(mergeParser);
5731
+ defineReachableChildren(mergeParser, parsers, (state) => sorted.map(([parser], index) => ({
5732
+ parser,
5733
+ state: getWrappedChildParseState(state, extractParserStateFromState(parser, state, index), parser)
5734
+ })));
5530
5735
  return fluent(scopeParser(mergeParser, combinedOptionScope(parsers, parsers.map((_, index) => index))));
5531
5736
  }
5532
5737
  /**
@@ -5717,6 +5922,7 @@ function tryParseSuggestList(context, stateArray, parsers, matchedParsers, remai
5717
5922
  const mergedExec = mergeChildExec(context.exec, result$1.next.exec);
5718
5923
  return preParseSuggestLoop({
5719
5924
  ...context,
5925
+ ...getPassThroughFailureHint(result$1.next),
5720
5926
  buffer: result$1.next.buffer,
5721
5927
  optionsTerminated: result$1.next.optionsTerminated,
5722
5928
  state: stateArray,
@@ -5744,6 +5950,7 @@ function tryParseSuggestList(context, stateArray, parsers, matchedParsers, remai
5744
5950
  const mergedExec = mergeChildExec(context.exec, result.next.exec);
5745
5951
  return {
5746
5952
  ...context,
5953
+ ...getPassThroughFailureHint(result.next),
5747
5954
  buffer: result.next.buffer,
5748
5955
  optionsTerminated: result.next.optionsTerminated,
5749
5956
  state: stateArray,
@@ -5763,10 +5970,12 @@ function concat(...parsers) {
5763
5970
  const isAsync = combinedMode === "async";
5764
5971
  const syncParsers = parsers;
5765
5972
  const initialState = parsers.map((parser) => parser.initialState);
5973
+ const passThroughParsers = new Set(parsers.filter((parser) => hasPassThroughUsage(parser.usage)));
5766
5974
  const parseSync = (context) => {
5767
5975
  let currentContext = context;
5768
5976
  const allConsumed = [];
5769
5977
  const matchedParsers = /* @__PURE__ */ new Set();
5978
+ let consumingFailure;
5770
5979
  while (matchedParsers.size < syncParsers.length) {
5771
5980
  let foundMatch = false;
5772
5981
  let error = {
@@ -5774,14 +5983,15 @@ function concat(...parsers) {
5774
5983
  error: message`No remaining parsers could match the input.`
5775
5984
  };
5776
5985
  const stateArray = currentContext.state;
5777
- const remainingParsers = syncParsers.map((parser, index) => [parser, index]).filter(([_, index]) => !matchedParsers.has(index)).sort(([parserA], [parserB]) => parserB.priority - parserA.priority);
5986
+ const remainingParsers = orderBeforePassThrough(syncParsers.map((parser, index) => [parser, index]).filter(([parser, index]) => !matchedParsers.has(index) || getOptionMatch(parser, stateArray[index], currentContext.buffer[0])?.continuesCommand === true || passThroughParsers.size > 0 && !currentContext.optionsTerminated && getOptionMatch(parser, stateArray[index], currentContext.buffer[0]) != null).sort(([parserA], [parserB]) => parserB.priority - parserA.priority), currentContext, ([parser]) => parser, ([, index]) => stateArray[index], passThroughParsers);
5778
5987
  for (const [parser, index] of remainingParsers) {
5779
- const result = parser.parse(withChildContext$1(currentContext, index, stateArray[index], parser));
5988
+ const result = parser.parse(withPassThroughFailure(withChildContext$1(currentContext, index, stateArray[index], parser), consumingFailure, getPassThroughPriority(parser, stateArray[index], currentContext.buffer[0])));
5780
5989
  if (result.success && result.consumed.length > 0) {
5781
5990
  const newStateArray = annotateFreshArray(currentContext.state, stateArray.map((s, idx) => idx === index ? getWrappedChildState(currentContext.state, result.next.state, parser) : s));
5782
5991
  const mergedExec = mergeChildExec(currentContext.exec, result.next.exec);
5783
5992
  currentContext = {
5784
5993
  ...currentContext,
5994
+ ...getPassThroughFailureHint(result.next),
5785
5995
  buffer: result.next.buffer,
5786
5996
  optionsTerminated: result.next.optionsTerminated,
5787
5997
  state: newStateArray,
@@ -5790,14 +6000,23 @@ function concat(...parsers) {
5790
6000
  dependencyRegistry: mergedExec.dependencyRegistry
5791
6001
  } : {}
5792
6002
  };
6003
+ consumingFailure = void 0;
5793
6004
  allConsumed.push(...result.consumed);
5794
6005
  matchedParsers.add(index);
5795
6006
  foundMatch = true;
5796
6007
  break;
5797
- } else if (!result.success && error.consumed < result.consumed) error = result;
6008
+ } else if (result.success) {
6009
+ consumingFailure = retainConsumingFailureHint(consumingFailure, currentContext, result.next);
6010
+ if (consumingFailure != null && error.consumed < consumingFailure.failure.consumed) error = consumingFailure.failure;
6011
+ } else {
6012
+ const match = getOptionMatch(parser, stateArray[index], currentContext.buffer[0]);
6013
+ if (result.consumed > 0 && match != null) consumingFailure = retainConsumingFailure(consumingFailure, result, match.priority);
6014
+ if (error.consumed < result.consumed) error = result;
6015
+ }
5798
6016
  }
5799
6017
  if (!foundMatch) for (const [parser, index] of remainingParsers) {
5800
- const result = parser.parse(withChildContext$1(currentContext, index, stateArray[index], parser));
6018
+ if (matchedParsers.has(index)) continue;
6019
+ const result = parser.parse(withPassThroughFailure(withChildContext$1(currentContext, index, stateArray[index], parser), consumingFailure, getPassThroughPriority(parser, stateArray[index], currentContext.buffer[0])));
5801
6020
  if (result.success && result.consumed.length < 1) {
5802
6021
  const newStateArray = annotateFreshArray(currentContext.state, stateArray.map((s, idx) => idx === index ? getWrappedChildState(currentContext.state, result.next.state, parser) : s));
5803
6022
  const mergedExec = mergeChildExec(currentContext.exec, result.next.exec);
@@ -5825,7 +6044,7 @@ function concat(...parsers) {
5825
6044
  }
5826
6045
  return {
5827
6046
  success: true,
5828
- next: currentContext,
6047
+ next: withReturnedConsumingFailure(currentContext, consumingFailure),
5829
6048
  consumed: allConsumed
5830
6049
  };
5831
6050
  };
@@ -5833,6 +6052,7 @@ function concat(...parsers) {
5833
6052
  let currentContext = context;
5834
6053
  const allConsumed = [];
5835
6054
  const matchedParsers = /* @__PURE__ */ new Set();
6055
+ let consumingFailure;
5836
6056
  while (matchedParsers.size < parsers.length) {
5837
6057
  let foundMatch = false;
5838
6058
  let error = {
@@ -5840,14 +6060,15 @@ function concat(...parsers) {
5840
6060
  error: message`No remaining parsers could match the input.`
5841
6061
  };
5842
6062
  const stateArray = currentContext.state;
5843
- const remainingParsers = parsers.map((parser, index) => [parser, index]).filter(([_, index]) => !matchedParsers.has(index)).sort(([parserA], [parserB]) => parserB.priority - parserA.priority);
6063
+ const remainingParsers = orderBeforePassThrough(parsers.map((parser, index) => [parser, index]).filter(([parser, index]) => !matchedParsers.has(index) || getOptionMatch(parser, stateArray[index], currentContext.buffer[0])?.continuesCommand === true || passThroughParsers.size > 0 && !currentContext.optionsTerminated && getOptionMatch(parser, stateArray[index], currentContext.buffer[0]) != null).sort(([parserA], [parserB]) => parserB.priority - parserA.priority), currentContext, ([parser]) => parser, ([, index]) => stateArray[index], passThroughParsers);
5844
6064
  for (const [parser, index] of remainingParsers) {
5845
- const result = await parser.parse(withChildContext$1(currentContext, index, stateArray[index], parser));
6065
+ const result = await parser.parse(withPassThroughFailure(withChildContext$1(currentContext, index, stateArray[index], parser), consumingFailure, getPassThroughPriority(parser, stateArray[index], currentContext.buffer[0])));
5846
6066
  if (result.success && result.consumed.length > 0) {
5847
6067
  const newStateArray = annotateFreshArray(currentContext.state, stateArray.map((s, idx) => idx === index ? getWrappedChildState(currentContext.state, result.next.state, parser) : s));
5848
6068
  const mergedExec = mergeChildExec(currentContext.exec, result.next.exec);
5849
6069
  currentContext = {
5850
6070
  ...currentContext,
6071
+ ...getPassThroughFailureHint(result.next),
5851
6072
  buffer: result.next.buffer,
5852
6073
  optionsTerminated: result.next.optionsTerminated,
5853
6074
  state: newStateArray,
@@ -5856,14 +6077,23 @@ function concat(...parsers) {
5856
6077
  dependencyRegistry: mergedExec.dependencyRegistry
5857
6078
  } : {}
5858
6079
  };
6080
+ consumingFailure = void 0;
5859
6081
  allConsumed.push(...result.consumed);
5860
6082
  matchedParsers.add(index);
5861
6083
  foundMatch = true;
5862
6084
  break;
5863
- } else if (!result.success && error.consumed < result.consumed) error = result;
6085
+ } else if (result.success) {
6086
+ consumingFailure = retainConsumingFailureHint(consumingFailure, currentContext, result.next);
6087
+ if (consumingFailure != null && error.consumed < consumingFailure.failure.consumed) error = consumingFailure.failure;
6088
+ } else {
6089
+ const match = getOptionMatch(parser, stateArray[index], currentContext.buffer[0]);
6090
+ if (result.consumed > 0 && match != null) consumingFailure = retainConsumingFailure(consumingFailure, result, match.priority);
6091
+ if (error.consumed < result.consumed) error = result;
6092
+ }
5864
6093
  }
5865
6094
  if (!foundMatch) for (const [parser, index] of remainingParsers) {
5866
- const result = await parser.parse(withChildContext$1(currentContext, index, stateArray[index], parser));
6095
+ if (matchedParsers.has(index)) continue;
6096
+ const result = await parser.parse(withPassThroughFailure(withChildContext$1(currentContext, index, stateArray[index], parser), consumingFailure, getPassThroughPriority(parser, stateArray[index], currentContext.buffer[0])));
5867
6097
  if (result.success && result.consumed.length < 1) {
5868
6098
  const newStateArray = annotateFreshArray(currentContext.state, stateArray.map((s, idx) => idx === index ? getWrappedChildState(currentContext.state, result.next.state, parser) : s));
5869
6099
  const mergedExec = mergeChildExec(currentContext.exec, result.next.exec);
@@ -5891,7 +6121,7 @@ function concat(...parsers) {
5891
6121
  }
5892
6122
  return {
5893
6123
  success: true,
5894
- next: currentContext,
6124
+ next: withReturnedConsumingFailure(currentContext, consumingFailure),
5895
6125
  consumed: allConsumed
5896
6126
  };
5897
6127
  };
@@ -6162,6 +6392,10 @@ function concat(...parsers) {
6162
6392
  }
6163
6393
  };
6164
6394
  defineInheritedAnnotationParser(concatParser);
6395
+ defineReachableChildren(concatParser, parsers, (state) => parsers.map((parser, index) => ({
6396
+ parser,
6397
+ state: getWrappedChildParseState(state, state[index], parser)
6398
+ })));
6165
6399
  return fluent(scopeParser(concatParser, combinedOptionScope(parsers, parsers.map((_, index) => index))));
6166
6400
  }
6167
6401
  function group(label, parser, options = {}) {
@@ -6280,6 +6514,11 @@ function group(label, parser, options = {}) {
6280
6514
  configurable: true,
6281
6515
  enumerable: false
6282
6516
  });
6517
+ delegateKnownCompletion(groupParser, parser);
6518
+ defineReachableChildren(groupParser, [parser], (state) => [{
6519
+ parser,
6520
+ state
6521
+ }]);
6283
6522
  return fluent(scopeParser(groupParser, combinedOptionScope([parser])));
6284
6523
  }
6285
6524
  /**
@@ -6390,13 +6629,14 @@ function conditional(discriminator, branches, defaultBranch, options) {
6390
6629
  return options?.errors?.noMatch ? typeof options.errors.noMatch === "function" ? options.errors.noMatch(noMatchContext) : options.errors.noMatch : generateNoMatchError(noMatchContext);
6391
6630
  };
6392
6631
  const optionScope = conditionalOptionScope(discriminator, defaultBranch, branchParsers.map(([, p]) => p));
6632
+ const selectBranch = (selected, table, fallback) => selected.kind === "default" ? fallback : table[selected.key];
6393
6633
  const parseSync = (context) => {
6394
6634
  const state = context.state ?? initialState;
6395
6635
  const syncDiscriminator = discriminator;
6396
6636
  const syncBranches = branches;
6397
6637
  const syncDefaultBranch = defaultBranch;
6398
6638
  if (state.selectedBranch !== void 0) {
6399
- const branchParser = state.selectedBranch.kind === "default" ? syncDefaultBranch : syncBranches[state.selectedBranch.key];
6639
+ const branchParser = selectBranch(state.selectedBranch, syncBranches, syncDefaultBranch);
6400
6640
  const branchResult = branchParser.parse(withChildContext$1(context, "_branch", state.branchState, branchParser, branchParser.usage));
6401
6641
  if (branchResult.success) {
6402
6642
  const mergedExec = mergeChildExec(context.exec, branchResult.next.exec);
@@ -6437,6 +6677,7 @@ function conditional(discriminator, branches, defaultBranch, options) {
6437
6677
  dependencyRegistry: discriminatorExec.dependencyRegistry
6438
6678
  } : {}
6439
6679
  }, "_branch", branchParser.initialState, branchParser, branchParser.usage),
6680
+ ...getPassThroughFailureHint(discriminatorResult.next),
6440
6681
  buffer: discriminatorResult.next.buffer,
6441
6682
  optionsTerminated: discriminatorResult.next.optionsTerminated
6442
6683
  });
@@ -6536,7 +6777,7 @@ function conditional(discriminator, branches, defaultBranch, options) {
6536
6777
  const parseAsync = async (context) => {
6537
6778
  const state = context.state ?? initialState;
6538
6779
  if (state.selectedBranch !== void 0) {
6539
- const branchParser = state.selectedBranch.kind === "default" ? defaultBranch : branches[state.selectedBranch.key];
6780
+ const branchParser = selectBranch(state.selectedBranch, branches, defaultBranch);
6540
6781
  const branchResult = await branchParser.parse(withChildContext$1(context, "_branch", state.branchState, branchParser, branchParser.usage));
6541
6782
  if (branchResult.success) {
6542
6783
  const mergedExec = mergeChildExec(context.exec, branchResult.next.exec);
@@ -6565,6 +6806,7 @@ function conditional(discriminator, branches, defaultBranch, options) {
6565
6806
  const discriminatorExec = mergeChildExec(context.exec, discriminatorResult.next.exec);
6566
6807
  const speculationContext = {
6567
6808
  ...withOptionScope(context, unionLeadingNames([...branchParsers.map(([, p]) => p), ...defaultBranch ? [defaultBranch] : []])),
6809
+ ...getPassThroughFailureHint(discriminatorResult.next),
6568
6810
  buffer: discriminatorResult.next.buffer,
6569
6811
  optionsTerminated: discriminatorResult.next.optionsTerminated,
6570
6812
  ...discriminatorExec != null ? {
@@ -6696,6 +6938,7 @@ function conditional(discriminator, branches, defaultBranch, options) {
6696
6938
  dependencyRegistry: discriminatorExec.dependencyRegistry
6697
6939
  } : {}
6698
6940
  }, "_branch", branchParser.initialState, branchParser, branchParser.usage),
6941
+ ...getPassThroughFailureHint(discriminatorResult.next),
6699
6942
  buffer: discriminatorResult.next.buffer,
6700
6943
  optionsTerminated: discriminatorResult.next.optionsTerminated
6701
6944
  });
@@ -7650,10 +7893,39 @@ function conditional(discriminator, branches, defaultBranch, options) {
7650
7893
  configurable: true,
7651
7894
  enumerable: false
7652
7895
  });
7896
+ const reachableBranches = (state) => {
7897
+ if (state.selectedBranch != null) {
7898
+ const branch = selectBranch(state.selectedBranch, branches, defaultBranch);
7899
+ return branch == null ? [] : [{
7900
+ branch,
7901
+ state: state.branchState
7902
+ }];
7903
+ }
7904
+ const known = getKnownCompletion(discriminator, state.discriminatorState);
7905
+ if (known != null) {
7906
+ const branch = typeof known.value === "string" ? branches[known.value] : void 0;
7907
+ const reachable = branch ?? defaultBranch;
7908
+ return reachable == null ? [] : [{
7909
+ branch: reachable,
7910
+ state: reachable.initialState
7911
+ }];
7912
+ }
7913
+ return allBranchParsers.map((branch) => ({
7914
+ branch,
7915
+ state: branch.initialState
7916
+ }));
7917
+ };
7918
+ defineReachableChildren(conditionalParser, [discriminator, ...allBranchParsers], (state) => [...state.selectedBranch == null ? [{
7919
+ parser: discriminator,
7920
+ state: getWrappedChildParseState(state, state.discriminatorState, discriminator)
7921
+ }] : [], ...reachableBranches(state).map(({ branch, state: childState }) => ({
7922
+ parser: branch,
7923
+ state: getWrappedChildParseState(state, childState, branch)
7924
+ }))]);
7653
7925
  return fluent(scopeParser(conditionalParser, optionScope.source, (context) => {
7654
7926
  const selected = context.state?.selectedBranch;
7655
7927
  if (selected != null) {
7656
- const branch = selected.kind === "default" ? defaultBranch : branches[selected.key];
7928
+ const branch = selectBranch(selected, branches, defaultBranch);
7657
7929
  if (branch != null) optionScope.select(context, branch);
7658
7930
  }
7659
7931
  }));