@optique/core 1.1.0-dev.2087 → 1.1.0-dev.2146

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.
Files changed (74) hide show
  1. package/dist/annotation-state.cjs +26 -26
  2. package/dist/annotation-state.d.cts +133 -1
  3. package/dist/annotation-state.d.ts +133 -1
  4. package/dist/annotations.cjs +2 -2
  5. package/dist/constructs.cjs +873 -73
  6. package/dist/constructs.d.cts +72 -1
  7. package/dist/constructs.d.ts +72 -1
  8. package/dist/constructs.js +808 -9
  9. package/dist/dependency-metadata.cjs +12 -12
  10. package/dist/dependency-metadata.d.cts +34 -3
  11. package/dist/dependency-metadata.d.ts +34 -3
  12. package/dist/dependency-runtime.cjs +37 -13
  13. package/dist/dependency-runtime.d.cts +197 -2
  14. package/dist/dependency-runtime.d.ts +197 -2
  15. package/dist/dependency-runtime.js +22 -1
  16. package/dist/dependency.cjs +7 -7
  17. package/dist/displaywidth.d.cts +12 -0
  18. package/dist/displaywidth.d.ts +12 -0
  19. package/dist/doc.cjs +3 -0
  20. package/dist/doc.js +3 -0
  21. package/dist/execution-context.d.cts +23 -0
  22. package/dist/execution-context.d.ts +23 -0
  23. package/dist/extension.cjs +14 -14
  24. package/dist/facade.cjs +49 -37
  25. package/dist/facade.js +34 -22
  26. package/dist/index.cjs +23 -21
  27. package/dist/index.d.cts +3 -3
  28. package/dist/index.d.ts +3 -3
  29. package/dist/index.js +4 -4
  30. package/dist/input-trace.d.cts +2 -1
  31. package/dist/input-trace.d.ts +2 -1
  32. package/dist/internal/annotations.cjs +3 -0
  33. package/dist/internal/annotations.d.cts +47 -5
  34. package/dist/internal/annotations.d.ts +47 -5
  35. package/dist/internal/annotations.js +1 -1
  36. package/dist/internal/command-alias.cjs +16 -0
  37. package/dist/internal/command-alias.js +14 -0
  38. package/dist/internal/dependency.cjs +131 -0
  39. package/dist/internal/dependency.d.cts +311 -2
  40. package/dist/internal/dependency.d.ts +311 -2
  41. package/dist/internal/dependency.js +119 -1
  42. package/dist/internal/parser.cjs +108 -23
  43. package/dist/internal/parser.d.cts +58 -3
  44. package/dist/internal/parser.d.ts +58 -3
  45. package/dist/internal/parser.js +101 -16
  46. package/dist/modifiers.cjs +74 -44
  47. package/dist/modifiers.js +34 -4
  48. package/dist/parser.cjs +11 -11
  49. package/dist/phase2-seed.cjs +2 -2
  50. package/dist/phase2-seed.d.cts +50 -0
  51. package/dist/phase2-seed.d.ts +50 -0
  52. package/dist/primitives.cjs +104 -33
  53. package/dist/primitives.d.cts +10 -0
  54. package/dist/primitives.d.ts +10 -0
  55. package/dist/primitives.js +84 -13
  56. package/dist/suggestion.cjs +72 -2
  57. package/dist/suggestion.d.cts +188 -0
  58. package/dist/suggestion.d.ts +188 -0
  59. package/dist/suggestion.js +71 -3
  60. package/dist/usage-internals.cjs +14 -6
  61. package/dist/usage-internals.js +14 -6
  62. package/dist/usage.cjs +33 -8
  63. package/dist/usage.d.cts +31 -0
  64. package/dist/usage.d.ts +31 -0
  65. package/dist/usage.js +33 -8
  66. package/dist/validate.cjs +1 -0
  67. package/dist/validate.d.cts +99 -0
  68. package/dist/validate.d.ts +99 -0
  69. package/dist/validate.js +1 -1
  70. package/dist/valueparser.cjs +333 -79
  71. package/dist/valueparser.d.cts +197 -1
  72. package/dist/valueparser.d.ts +197 -1
  73. package/dist/valueparser.js +334 -81
  74. package/package.json +19 -4
@@ -8,9 +8,10 @@ import { createDependencySourceState, dependencyId, isDependencySourceState, isP
8
8
  import { buildRuntimeNodesFromArray, buildRuntimeNodesFromPairs, collectExplicitSourceValues, collectExplicitSourceValuesAsync, collectSourcesFromState, createDependencyRuntimeContext, fillMissingSourceDefaults, fillMissingSourceDefaultsAsync, resolveStateWithRuntime, resolveStateWithRuntimeAsync } from "./dependency-runtime.js";
9
9
  import { defineInheritedAnnotationParser, getParserSuggestRuntimeNodes, unmatchedNonCliDependencySourceStateMarker } from "./internal/parser.js";
10
10
  import { annotationViewTargets, getWrappedChildParseState, getWrappedChildState, reconcileObjectChildState, unwrapAnnotationView } from "./annotation-state.js";
11
+ import { allowDuplicateLeadingCommandNamesKey } from "./internal/command-alias.js";
11
12
  import { mergeChildExec, withChildContext, withChildExecPath } from "./execution-context.js";
12
13
  import { completeOrExtractPhase2Seed, extractPhase2Seed, extractPhase2SeedKey, phase2SeedFromValueResult } from "./phase2-seed.js";
13
- import { DEFAULT_FIND_SIMILAR_OPTIONS, createErrorWithSuggestions, createSuggestionMessage, deduplicateSuggestions, findSimilar } from "./suggestion.js";
14
+ import { DEFAULT_FIND_SIMILAR_OPTIONS, createErrorWithSuggestions, createSuggestionMessage, deduplicateSuggestions, expandCommandAliasSuggestions, findSimilar } from "./suggestion.js";
14
15
  import { collectLeadingCandidates } from "./usage-internals.js";
15
16
 
16
17
  //#region src/constructs.ts
@@ -301,7 +302,12 @@ function createUnexpectedInputErrorWithScopedSuggestions(baseError, invalidInput
301
302
  for (const parser of parsers) collectLeadingCandidates(parser.usage, options, commands);
302
303
  const candidates = new Set([...options, ...commands]);
303
304
  const suggestions = findSimilar(invalidInput, candidates, DEFAULT_FIND_SIMILAR_OPTIONS);
304
- const suggestionMsg = customFormatter ? customFormatter(suggestions) : createSuggestionMessage(suggestions);
305
+ const aliasUsage = [{
306
+ type: "exclusive",
307
+ terms: parsers.map((parser) => parser.usage)
308
+ }];
309
+ const displaySuggestions = expandCommandAliasSuggestions(aliasUsage, suggestions);
310
+ const suggestionMsg = customFormatter ? customFormatter(displaySuggestions) : createSuggestionMessage(displaySuggestions);
305
311
  return suggestionMsg.length > 0 ? [
306
312
  ...baseError,
307
313
  text("\n\n"),
@@ -319,6 +325,10 @@ function applyHiddenToUsageTerm(term, hidden) {
319
325
  terms: applyHiddenToUsage(term.terms, hidden),
320
326
  min: term.min
321
327
  };
328
+ if (term.type === "sequence") return {
329
+ type: "sequence",
330
+ terms: applyHiddenToUsage(term.terms, hidden)
331
+ };
322
332
  if (term.type === "exclusive") return {
323
333
  type: "exclusive",
324
334
  terms: term.terms.map((u) => applyHiddenToUsage(u, hidden))
@@ -374,7 +384,7 @@ function isOptionRequiringValue(usage, token) {
374
384
  if (!terms || !Array.isArray(terms)) return false;
375
385
  for (const term of terms) if (term.type === "option") {
376
386
  if (term.metavar && term.names.includes(token)) return true;
377
- } else if (term.type === "optional" || term.type === "multiple") {
387
+ } else if (term.type === "optional" || term.type === "multiple" || term.type === "sequence") {
378
388
  if (traverse(term.terms)) return true;
379
389
  } else if (term.type === "exclusive") {
380
390
  for (const exclusiveUsage of term.terms) if (traverse(exclusiveUsage)) return true;
@@ -453,6 +463,18 @@ var DuplicateOptionError = class extends Error {
453
463
  }
454
464
  };
455
465
  /**
466
+ * Error class thrown when duplicate command names or aliases are detected
467
+ * during parser construction. This is a programmer error, not a user error.
468
+ */
469
+ var DuplicateCommandNameError = class extends TypeError {
470
+ constructor(commandName, sources) {
471
+ const sourceNames = sources.map((s) => typeof s === "symbol" ? s.description ?? s.toString() : s);
472
+ super(`Duplicate command name "${commandName}" found in parsers: ${sourceNames.join(", ")}. Each command name or alias must be unique within active parser alternatives.`);
473
+ this.commandName = commandName;
474
+ this.sources = sources;
475
+ }
476
+ };
477
+ /**
456
478
  * Checks for duplicate option names across parser sources and throws an error
457
479
  * if duplicates are found. This should be called at construction time.
458
480
  * @param parserSources Array of [source, usage] tuples
@@ -469,6 +491,48 @@ function checkDuplicateOptionNames(parserSources) {
469
491
  }
470
492
  for (const [name, sources] of optionNameSources) if (sources.length > 1) throw new DuplicateOptionError(name, sources);
471
493
  }
494
+ function checkDuplicateLeadingCommandNames(parserSources) {
495
+ const commandNameSources = /* @__PURE__ */ new Map();
496
+ for (const [source, parser] of parserSources) {
497
+ const commandNames = extractCommandNames(parser.usage, true);
498
+ for (const name of parser.leadingNames) {
499
+ if (!commandNames.has(name)) continue;
500
+ const sources = commandNameSources.get(name);
501
+ commandNameSources.set(name, sources == null ? [source] : [...sources, source]);
502
+ }
503
+ }
504
+ for (const [name, sources] of commandNameSources) if (sources.length > 1) throw new DuplicateCommandNameError(name, sources);
505
+ }
506
+ function checkDuplicateReachableLeadingCommandNames(parserSources) {
507
+ const commandNameSources = /* @__PURE__ */ new Map();
508
+ const sortedSources = [...parserSources].sort(([, parserA], [, parserB]) => parserB.priority - parserA.priority);
509
+ const blockedNames = /* @__PURE__ */ new Set();
510
+ let positionalBlocked = false;
511
+ for (let i = 0; i < sortedSources.length;) {
512
+ const priority = sortedSources[i][1].priority;
513
+ const priorityGroup = [];
514
+ while (i < sortedSources.length && sortedSources[i][1].priority === priority) {
515
+ priorityGroup.push(sortedSources[i]);
516
+ i++;
517
+ }
518
+ const groupNames = /* @__PURE__ */ new Set();
519
+ let groupAcceptsAnyToken = false;
520
+ for (const [source, parser] of priorityGroup) {
521
+ if (parser.acceptingAnyToken) groupAcceptsAnyToken = true;
522
+ const commandNames = extractCommandNames(parser.usage, true);
523
+ for (const name of parser.leadingNames) {
524
+ if (!commandNames.has(name)) continue;
525
+ if (positionalBlocked || blockedNames.has(name)) continue;
526
+ groupNames.add(name);
527
+ const sources = commandNameSources.get(name);
528
+ commandNameSources.set(name, sources == null ? [source] : [...sources, source]);
529
+ }
530
+ }
531
+ for (const name of groupNames) blockedNames.add(name);
532
+ if (groupAcceptsAnyToken) positionalBlocked = true;
533
+ }
534
+ for (const [name, sources] of commandNameSources) if (sources.length > 1) throw new DuplicateCommandNameError(name, sources);
535
+ }
472
536
  /**
473
537
  * Extracts option names that participate in CLI syntax.
474
538
  *
@@ -733,6 +797,7 @@ function or(...args) {
733
797
  }
734
798
  if (parsers.length < 1) throw new TypeError("or() requires at least one parser argument.");
735
799
  assertParsers(parsers, "or()");
800
+ checkDuplicateLeadingCommandNames(parsers.map((parser, index) => [String(index), parser]));
736
801
  const noMatchContext = analyzeNoMatchContext(parsers);
737
802
  const combinedMode = parsers.some((p) => p.mode === "async") ? "async" : "sync";
738
803
  const syncParsers = parsers;
@@ -1152,6 +1217,15 @@ function or(...args) {
1152
1217
  leadingNames: unionLeadingNames(parsers),
1153
1218
  acceptingAnyToken: parsers.some((p) => p.acceptingAnyToken),
1154
1219
  initialState: void 0,
1220
+ canSkip(state, exec) {
1221
+ const activeState = normalizeExclusiveState(state);
1222
+ if (activeState != null) {
1223
+ const [index, result] = activeState;
1224
+ const parser = parsers[index];
1225
+ return result.success && parser?.canSkip?.(result.next.state, exec) === true;
1226
+ }
1227
+ return parsers.some((parser) => parser.canSkip?.(parser.initialState, exec) === true);
1228
+ },
1155
1229
  complete: createExclusiveComplete(parsers, options, noMatchContext, combinedMode),
1156
1230
  [extractPhase2SeedKey](state, exec) {
1157
1231
  return extractExclusivePhase2Seed(parsers, state, exec, combinedMode);
@@ -1199,6 +1273,9 @@ function or(...args) {
1199
1273
  * @since 0.5.0
1200
1274
  */
1201
1275
  function longestMatch(...args) {
1276
+ return createLongestMatch(...args);
1277
+ }
1278
+ function createLongestMatch(...args) {
1202
1279
  let parsers;
1203
1280
  let options;
1204
1281
  if (args.length > 0 && args[args.length - 1] && typeof args[args.length - 1] === "object" && !("$valueType" in args[args.length - 1])) {
@@ -1210,6 +1287,8 @@ function longestMatch(...args) {
1210
1287
  }
1211
1288
  if (parsers.length < 1) throw new TypeError("longestMatch() requires at least one parser argument.");
1212
1289
  assertParsers(parsers, "longestMatch()");
1290
+ const allowDuplicateLeadingCommandNames = options?.[allowDuplicateLeadingCommandNamesKey] === true;
1291
+ if (!allowDuplicateLeadingCommandNames) checkDuplicateLeadingCommandNames(parsers.map((parser, index) => [String(index), parser]));
1213
1292
  const noMatchContext = analyzeNoMatchContext(parsers);
1214
1293
  const combinedMode = parsers.some((p) => p.mode === "async") ? "async" : "sync";
1215
1294
  const syncParsers = parsers;
@@ -1755,6 +1834,7 @@ function object(labelOrParsers, maybeParsersOrOptions, maybeOptions) {
1755
1834
  };
1756
1835
  };
1757
1836
  if (!options.allowDuplicates) checkDuplicateOptionNames(parserPairs.map(([field, parser]) => [field, parser.usage]));
1837
+ checkDuplicateReachableLeadingCommandNames(parserPairs.map(([field, parser]) => [field, parser]));
1758
1838
  const noMatchContext = analyzeNoMatchContext(parserKeys.map((k) => parsers[k]));
1759
1839
  const combinedMode = parserKeys.some((k) => parsers[k].mode === "async") ? "async" : "sync";
1760
1840
  const getInitialError = (context) => ({
@@ -1992,6 +2072,13 @@ function object(labelOrParsers, maybeParsersOrOptions, maybeOptions) {
1992
2072
  usage: applyHiddenToUsage(parserPairs.flatMap(([_, p]) => p.usage), options.hidden),
1993
2073
  leadingNames: sharedBufferLeadingNames(parserPairs.map(([_, p]) => p)),
1994
2074
  acceptingAnyToken: parserPairs.some(([_, p]) => p.acceptingAnyToken),
2075
+ canSkip(state, exec) {
2076
+ const getFieldState = createFieldStateGetter(state);
2077
+ return parserKeys.every((field) => {
2078
+ const parser = parsers[field];
2079
+ return parser.canSkip?.(getFieldState(field, parser), withChildExecPath(exec, field)) === true;
2080
+ });
2081
+ },
1995
2082
  get initialState() {
1996
2083
  return createInitialState();
1997
2084
  },
@@ -2284,6 +2371,369 @@ function object(labelOrParsers, maybeParsersOrOptions, maybeOptions) {
2284
2371
  defineInheritedAnnotationParser(objectParser);
2285
2372
  return objectParser;
2286
2373
  }
2374
+ function isParserLike(value) {
2375
+ return value != null && (typeof value === "object" || typeof value === "function") && "parse" in value && "$valueType" in value && "$stateType" in value;
2376
+ }
2377
+ function tokenMatchesLeadingName(token, candidates) {
2378
+ if (token == null) return false;
2379
+ for (const name of candidates.optionNames) if (token === name) return true;
2380
+ for (const name of candidates.joinedOptionNames) if (name.startsWith("/") && token.startsWith(`${name}:`) || (name.startsWith("--") || name.startsWith("-") && name.length > 2) && token.startsWith(`${name}=`)) return true;
2381
+ for (const name of candidates.commandNames) if (token === name) return true;
2382
+ return false;
2383
+ }
2384
+ function parserCanSkipAt(parser, state, exec, index) {
2385
+ return parser.canSkip?.(getWrappedChildState(void 0, state, parser), withChildExecPath(exec, index)) === true;
2386
+ }
2387
+ function collectLeadingJoinedOptionNames(terms, optionNames) {
2388
+ for (const term of terms) {
2389
+ if (term.type === "option") {
2390
+ if (term.metavar != null) for (const name of term.names) optionNames.add(name);
2391
+ return false;
2392
+ }
2393
+ if (term.type === "command" || term.type === "argument") return false;
2394
+ if (term.type === "optional") {
2395
+ collectLeadingJoinedOptionNames(term.terms, optionNames);
2396
+ continue;
2397
+ }
2398
+ if (term.type === "multiple") {
2399
+ collectLeadingJoinedOptionNames(term.terms, optionNames);
2400
+ if (term.min === 0) continue;
2401
+ return false;
2402
+ }
2403
+ if (term.type === "sequence") {
2404
+ if (collectLeadingJoinedOptionNames(term.terms, optionNames)) continue;
2405
+ return false;
2406
+ }
2407
+ if (term.type === "exclusive") {
2408
+ let allSkippable = true;
2409
+ for (const branch of term.terms) {
2410
+ const branchSkippable = collectLeadingJoinedOptionNames(branch, optionNames);
2411
+ allSkippable = allSkippable && branchSkippable;
2412
+ }
2413
+ if (allSkippable) continue;
2414
+ return false;
2415
+ }
2416
+ }
2417
+ return true;
2418
+ }
2419
+ function sequenceLeadingCandidates(parsers) {
2420
+ const optionNames = /* @__PURE__ */ new Set();
2421
+ const joinedOptionNames = /* @__PURE__ */ new Set();
2422
+ const commandNames = /* @__PURE__ */ new Set();
2423
+ let positionalBlocked = false;
2424
+ for (let i = 0; i < parsers.length; i++) {
2425
+ const parser = parsers[i];
2426
+ const parserOptions = /* @__PURE__ */ new Set();
2427
+ const parserJoinedOptions = /* @__PURE__ */ new Set();
2428
+ const parserCommands = /* @__PURE__ */ new Set();
2429
+ collectLeadingCandidates(parser.usage, parserOptions, parserCommands);
2430
+ collectLeadingJoinedOptionNames(parser.usage, parserJoinedOptions);
2431
+ for (const name of parserOptions) optionNames.add(name);
2432
+ for (const name of parserJoinedOptions) joinedOptionNames.add(name);
2433
+ if (!positionalBlocked) {
2434
+ for (const name of parserCommands) commandNames.add(name);
2435
+ for (const name of parser.leadingNames) if (!parserOptions.has(name)) commandNames.add(name);
2436
+ } else for (const name of parser.leadingNames) if (!parserOptions.has(name) && name.startsWith("-")) commandNames.add(name);
2437
+ if (parser.acceptingAnyToken) positionalBlocked = true;
2438
+ if (!parserCanSkipAt(parser, parser.initialState, void 0, i)) break;
2439
+ }
2440
+ return {
2441
+ optionNames: optionNames.size === 0 ? EMPTY_LEADING_NAMES : optionNames,
2442
+ joinedOptionNames: joinedOptionNames.size === 0 ? EMPTY_LEADING_NAMES : joinedOptionNames,
2443
+ commandNames: commandNames.size === 0 ? EMPTY_LEADING_NAMES : commandNames
2444
+ };
2445
+ }
2446
+ function sequenceLeadingNames(parsers) {
2447
+ const candidates = sequenceLeadingCandidates(parsers);
2448
+ const names = new Set([
2449
+ ...candidates.optionNames,
2450
+ ...candidates.joinedOptionNames,
2451
+ ...candidates.commandNames
2452
+ ]);
2453
+ return names.size === 0 ? EMPTY_LEADING_NAMES : names;
2454
+ }
2455
+ function sequenceAcceptingAnyToken(parsers) {
2456
+ for (let i = 0; i < parsers.length; i++) {
2457
+ const parser = parsers[i];
2458
+ if (parser.acceptingAnyToken) return true;
2459
+ if (!parserCanSkipAt(parser, parser.initialState, void 0, i)) break;
2460
+ }
2461
+ return false;
2462
+ }
2463
+ function sequencePriority(parsers) {
2464
+ let priority = 0;
2465
+ for (let i = 0; i < parsers.length; i++) {
2466
+ const parser = parsers[i];
2467
+ priority = Math.max(priority, parser.priority);
2468
+ if (!parserCanSkipAt(parser, parser.initialState, void 0, i)) break;
2469
+ }
2470
+ return priority;
2471
+ }
2472
+ function leadingCandidatesAfter(parsers, startIndex) {
2473
+ return sequenceLeadingCandidates(parsers.slice(startIndex));
2474
+ }
2475
+ function checkSequentialDuplicateOptionNames(parsers) {
2476
+ const active = /* @__PURE__ */ new Map();
2477
+ for (let i = 0; i < parsers.length; i++) {
2478
+ const parser = parsers[i];
2479
+ const optionNames = /* @__PURE__ */ new Set();
2480
+ collectLeadingCandidates(parser.usage, optionNames, /* @__PURE__ */ new Set(), true);
2481
+ const retainedOptionNames = collectRetainedLeadingCandidates(parser.usage).optionNames;
2482
+ for (const name of optionNames) {
2483
+ const sources = active.get(name);
2484
+ if (sources != null) throw new DuplicateOptionError(name, [...sources, String(i)]);
2485
+ }
2486
+ for (const name of optionNames) {
2487
+ const sources = active.get(name);
2488
+ active.set(name, sources == null ? [String(i)] : [...sources, String(i)]);
2489
+ }
2490
+ if (!parserCanSkipAt(parser, parser.initialState, void 0, i)) active.clear();
2491
+ for (const name of retainedOptionNames) {
2492
+ const sources = active.get(name);
2493
+ active.set(name, sources == null ? [String(i)] : [...sources, String(i)]);
2494
+ }
2495
+ }
2496
+ }
2497
+ function collectRetainedLeadingCandidates(terms) {
2498
+ const optionNames = /* @__PURE__ */ new Set();
2499
+ const joinedOptionNames = /* @__PURE__ */ new Set();
2500
+ collectRetainedLeadingCandidatesInto(terms, optionNames, joinedOptionNames);
2501
+ return {
2502
+ optionNames,
2503
+ joinedOptionNames,
2504
+ commandNames: EMPTY_LEADING_NAMES
2505
+ };
2506
+ }
2507
+ function collectRetainedLeadingCandidatesInto(terms, optionNames, joinedOptionNames) {
2508
+ for (const term of terms) {
2509
+ if (term.type === "optional") {
2510
+ collectLeadingOptionCandidates(term.terms, optionNames, joinedOptionNames);
2511
+ collectRetainedLeadingCandidatesInto(term.terms, optionNames, joinedOptionNames);
2512
+ continue;
2513
+ }
2514
+ if (term.type === "multiple") {
2515
+ collectLeadingOptionCandidates(term.terms, optionNames, joinedOptionNames);
2516
+ collectRetainedLeadingCandidatesInto(term.terms, optionNames, joinedOptionNames);
2517
+ continue;
2518
+ }
2519
+ if (term.type === "sequence") {
2520
+ collectRetainedLeadingCandidatesInto(term.terms, optionNames, joinedOptionNames);
2521
+ continue;
2522
+ }
2523
+ if (term.type === "exclusive") {
2524
+ let canSkipBranch = false;
2525
+ const branchOptionNames = [];
2526
+ const branchJoinedOptionNames = [];
2527
+ for (const branch of term.terms) {
2528
+ const branchOptions = /* @__PURE__ */ new Set();
2529
+ const branchJoinedOptions = /* @__PURE__ */ new Set();
2530
+ const branchCanSkip = collectLeadingCandidates(branch, branchOptions, /* @__PURE__ */ new Set(), true);
2531
+ collectLeadingJoinedOptionNames(branch, branchJoinedOptions);
2532
+ canSkipBranch = canSkipBranch || branchCanSkip;
2533
+ branchOptionNames.push(branchOptions);
2534
+ branchJoinedOptionNames.push(branchJoinedOptions);
2535
+ collectRetainedLeadingCandidatesInto(branch, optionNames, joinedOptionNames);
2536
+ }
2537
+ if (canSkipBranch) {
2538
+ for (const branchOptions of branchOptionNames) for (const name of branchOptions) optionNames.add(name);
2539
+ for (const branchJoinedOptions of branchJoinedOptionNames) for (const name of branchJoinedOptions) joinedOptionNames.add(name);
2540
+ }
2541
+ }
2542
+ }
2543
+ }
2544
+ function collectLeadingOptionCandidates(terms, optionNames, joinedOptionNames) {
2545
+ collectLeadingCandidates(terms, optionNames, /* @__PURE__ */ new Set(), true);
2546
+ collectLeadingJoinedOptionNames(terms, joinedOptionNames);
2547
+ }
2548
+ function collectRetainedLeadingCandidatesAtState(terms, state) {
2549
+ if (terms.length === 1 && terms[0].type === "optional" && Array.isArray(state)) return collectRetainedLeadingCandidates(terms[0].terms);
2550
+ return collectRetainedLeadingCandidates(terms);
2551
+ }
2552
+ function createSeqState(sourceState, index, states) {
2553
+ const seqState = {
2554
+ index,
2555
+ states: annotateFreshArray(sourceState, states)
2556
+ };
2557
+ return inheritAnnotations(sourceState, seqState);
2558
+ }
2559
+ function getSeqChildState(seqState, index, parser) {
2560
+ return getWrappedChildState(seqState, seqState.states[index], parser);
2561
+ }
2562
+ function updateSeqChildState(sourceState, index, childState, parser) {
2563
+ return annotateFreshArray(sourceState.states, sourceState.states.map((state, stateIndex) => stateIndex === index ? getWrappedChildState(sourceState.states, childState, parser) : state));
2564
+ }
2565
+ function shouldAdvanceSeqBeforeParse(parser, parserState, initialParserState, currentContext, index, parsers) {
2566
+ const token = currentContext.buffer[0];
2567
+ if (token !== "--") {
2568
+ const laterLeadingCandidates = leadingCandidatesAfter(parsers, index + 1);
2569
+ if (!tokenMatchesLeadingName(token, laterLeadingCandidates)) return false;
2570
+ }
2571
+ if (!parserCanSkipAt(parser, parserState, currentContext.exec, index)) return false;
2572
+ if (token === "--") return true;
2573
+ if (currentContext.state.states[index] === initialParserState) {
2574
+ const currentLeadingCandidates = sequenceLeadingCandidates([parser]);
2575
+ return !tokenMatchesLeadingName(token, currentLeadingCandidates);
2576
+ }
2577
+ return !tokenMatchesLeadingName(token, collectRetainedLeadingCandidatesAtState(parser.usage, currentContext.state.states[index]));
2578
+ }
2579
+ function advanceSeqContext(currentContext, nextIndex, consumedTerminator) {
2580
+ return {
2581
+ ...currentContext,
2582
+ buffer: consumedTerminator ? currentContext.buffer.slice(1) : currentContext.buffer,
2583
+ optionsTerminated: consumedTerminator ? true : currentContext.optionsTerminated,
2584
+ state: createSeqState(currentContext.state, nextIndex, currentContext.state.states)
2585
+ };
2586
+ }
2587
+ function updateSeqContextFromChildResult(currentContext, index, parser, result, nextIndex) {
2588
+ const states = updateSeqChildState(currentContext.state, index, result.next.state, parser);
2589
+ const mergedExec = mergeChildExec(currentContext.exec, result.next.exec);
2590
+ return {
2591
+ ...currentContext,
2592
+ buffer: result.next.buffer,
2593
+ optionsTerminated: result.next.optionsTerminated,
2594
+ state: createSeqState(currentContext.state, nextIndex, states),
2595
+ ...mergedExec != null ? {
2596
+ exec: mergedExec,
2597
+ dependencyRegistry: mergedExec.dependencyRegistry
2598
+ } : {}
2599
+ };
2600
+ }
2601
+ function advanceSeqSuggestContextSync(context, parsers, initialStates) {
2602
+ let currentContext = context;
2603
+ while (currentContext.state.index < parsers.length) {
2604
+ const index = currentContext.state.index;
2605
+ const parser = parsers[index];
2606
+ const parserState = getSeqChildState(currentContext.state, index, parser);
2607
+ if (currentContext.buffer.length < 1) break;
2608
+ if (shouldAdvanceSeqBeforeParse(parser, parserState, initialStates[index], currentContext, index, parsers)) {
2609
+ const consumedTerminator = currentContext.buffer[0] === "--";
2610
+ currentContext = advanceSeqContext(currentContext, index + 1, consumedTerminator);
2611
+ continue;
2612
+ }
2613
+ const result = parser.parse(withChildContext$1(currentContext, index, parserState, parser));
2614
+ if (!result.success) {
2615
+ if (result.consumed > 0) break;
2616
+ if (parserCanSkipAt(parser, parserState, currentContext.exec, index)) {
2617
+ currentContext = advanceSeqContext(currentContext, index + 1, false);
2618
+ continue;
2619
+ }
2620
+ break;
2621
+ }
2622
+ const nextIndex = result.consumed.length > 0 ? index : index + 1;
2623
+ currentContext = updateSeqContextFromChildResult(currentContext, index, parser, result, nextIndex);
2624
+ }
2625
+ return currentContext;
2626
+ }
2627
+ async function advanceSeqSuggestContextAsync(context, parsers, initialStates) {
2628
+ let currentContext = context;
2629
+ while (currentContext.state.index < parsers.length) {
2630
+ const index = currentContext.state.index;
2631
+ const parser = parsers[index];
2632
+ const parserState = getSeqChildState(currentContext.state, index, parser);
2633
+ if (currentContext.buffer.length < 1) break;
2634
+ if (shouldAdvanceSeqBeforeParse(parser, parserState, initialStates[index], currentContext, index, parsers)) {
2635
+ const consumedTerminator = currentContext.buffer[0] === "--";
2636
+ currentContext = advanceSeqContext(currentContext, index + 1, consumedTerminator);
2637
+ continue;
2638
+ }
2639
+ const result = await parser.parse(withChildContext$1(currentContext, index, parserState, parser));
2640
+ if (!result.success) {
2641
+ if (result.consumed > 0) break;
2642
+ if (parserCanSkipAt(parser, parserState, currentContext.exec, index)) {
2643
+ currentContext = advanceSeqContext(currentContext, index + 1, false);
2644
+ continue;
2645
+ }
2646
+ break;
2647
+ }
2648
+ const nextIndex = result.consumed.length > 0 ? index : index + 1;
2649
+ currentContext = updateSeqContextFromChildResult(currentContext, index, parser, result, nextIndex);
2650
+ }
2651
+ return currentContext;
2652
+ }
2653
+ function createSeqComplete(parsers, combinedMode) {
2654
+ const syncParsers = parsers;
2655
+ return (state, exec) => dispatchByMode(combinedMode, () => {
2656
+ const stateArray = annotateFreshArray(state, state.states);
2657
+ const runtime = exec?.dependencyRuntime ?? createDependencyRuntimeContext(exec?.dependencyRegistry);
2658
+ const childExec = {
2659
+ ...exec,
2660
+ dependencyRuntime: runtime
2661
+ };
2662
+ const pairs = buildIndexedParserPairs(syncParsers);
2663
+ const stateRecord = createAnnotatedArrayStateRecord(stateArray);
2664
+ const preCompleted = preCompleteAndRegisterDependencies(stateRecord, pairs, runtime.registry, childExec);
2665
+ collectExplicitSourceValues(filterPreCompletedRuntimeNodes(buildRuntimeNodesFromArray(syncParsers, stateArray, exec?.path), new Set(preCompleted.keys())), runtime);
2666
+ const phase3Exec = {
2667
+ ...childExec,
2668
+ preCompletedByParser: void 0
2669
+ };
2670
+ const resolvedArray = resolveStateWithRuntime(stateArray, runtime);
2671
+ const result = [];
2672
+ const deferredKeys = /* @__PURE__ */ new Map();
2673
+ let hasDeferred = false;
2674
+ for (let i = 0; i < syncParsers.length; i++) {
2675
+ const elementParser = syncParsers[i];
2676
+ const preCompletedResult = preCompleted.get(String(i));
2677
+ const valueResult = preCompletedResult !== void 0 ? unwrapCompleteResult(preCompletedResult) : unwrapCompleteResult(elementParser.complete(prepareStateForCompletion(getWrappedChildState(stateArray, resolvedArray[i], elementParser), elementParser), withChildExecPath(phase3Exec, i)));
2678
+ if (!valueResult.success) return {
2679
+ success: false,
2680
+ error: valueResult.error
2681
+ };
2682
+ result[i] = valueResult.value;
2683
+ if (valueResult.deferred) if (valueResult.deferredKeys) deferredKeys.set(i, valueResult.deferredKeys);
2684
+ else if (valueResult.value == null || typeof valueResult.value !== "object") deferredKeys.set(i, null);
2685
+ else hasDeferred = true;
2686
+ }
2687
+ return {
2688
+ success: true,
2689
+ value: result,
2690
+ ...deferredKeys.size > 0 || hasDeferred ? {
2691
+ deferred: true,
2692
+ ...deferredKeys.size > 0 ? { deferredKeys } : {}
2693
+ } : {}
2694
+ };
2695
+ }, async () => {
2696
+ const stateArray = annotateFreshArray(state, state.states);
2697
+ const runtime = exec?.dependencyRuntime ?? createDependencyRuntimeContext(exec?.dependencyRegistry);
2698
+ const childExec = {
2699
+ ...exec,
2700
+ dependencyRuntime: runtime
2701
+ };
2702
+ const pairs = buildIndexedParserPairs(parsers);
2703
+ const stateRecord = createAnnotatedArrayStateRecord(stateArray);
2704
+ const preCompleted = await preCompleteAndRegisterDependenciesAsync(stateRecord, pairs, runtime.registry, childExec);
2705
+ await collectExplicitSourceValuesAsync(filterPreCompletedRuntimeNodes(buildRuntimeNodesFromArray(parsers, stateArray, exec?.path), new Set(preCompleted.keys())), runtime);
2706
+ const phase3Exec = {
2707
+ ...childExec,
2708
+ preCompletedByParser: void 0
2709
+ };
2710
+ const resolvedArray = await resolveStateWithRuntimeAsync(stateArray, runtime);
2711
+ const result = [];
2712
+ const deferredKeys = /* @__PURE__ */ new Map();
2713
+ let hasDeferred = false;
2714
+ for (let i = 0; i < parsers.length; i++) {
2715
+ const elementParser = parsers[i];
2716
+ const preCompletedResult = preCompleted.get(String(i));
2717
+ const valueResult = preCompletedResult !== void 0 ? unwrapCompleteResult(preCompletedResult) : unwrapCompleteResult(await elementParser.complete(prepareStateForCompletion(getWrappedChildState(stateArray, resolvedArray[i], elementParser), elementParser), withChildExecPath(phase3Exec, i)));
2718
+ if (!valueResult.success) return {
2719
+ success: false,
2720
+ error: valueResult.error
2721
+ };
2722
+ result[i] = valueResult.value;
2723
+ if (valueResult.deferred) if (valueResult.deferredKeys) deferredKeys.set(i, valueResult.deferredKeys);
2724
+ else if (valueResult.value == null || typeof valueResult.value !== "object") deferredKeys.set(i, null);
2725
+ else hasDeferred = true;
2726
+ }
2727
+ return {
2728
+ success: true,
2729
+ value: result,
2730
+ ...deferredKeys.size > 0 || hasDeferred ? {
2731
+ deferred: true,
2732
+ ...deferredKeys.size > 0 ? { deferredKeys } : {}
2733
+ } : {}
2734
+ };
2735
+ });
2736
+ }
2287
2737
  function suggestTupleSync(context, prefix, parsers) {
2288
2738
  const suggestions = [];
2289
2739
  const advanced = advanceTupleSuggestContextSync(context, parsers);
@@ -2678,6 +3128,10 @@ function tuple(labelOrParsers, maybeParsersOrOptions, maybeOptions) {
2678
3128
  acceptingAnyToken: parsers.some((p) => p.acceptingAnyToken),
2679
3129
  priority: parsers.length > 0 ? Math.max(...parsers.map((p) => p.priority)) : 0,
2680
3130
  initialState: parsers.map((parser) => parser.initialState),
3131
+ canSkip(state, exec) {
3132
+ const stateArray = state;
3133
+ return parsers.every((parser, index) => parser.canSkip?.(getWrappedChildState(stateArray, stateArray[index], parser), withChildExecPath(exec, index)) === true);
3134
+ },
2681
3135
  parse(context) {
2682
3136
  return dispatchByMode(combinedMode, () => parseSync(context), () => parseAsync(context));
2683
3137
  },
@@ -2915,6 +3369,334 @@ function tuple(labelOrParsers, maybeParsersOrOptions, maybeOptions) {
2915
3369
  defineInheritedAnnotationParser(tupleParser);
2916
3370
  return tupleParser;
2917
3371
  }
3372
+ function seq(...rawArgs) {
3373
+ const label = typeof rawArgs[0] === "string" ? rawArgs[0] : void 0;
3374
+ if (label != null) validateLabel(label);
3375
+ const args = label == null ? rawArgs : rawArgs.slice(1);
3376
+ const lastArg = args.at(-1);
3377
+ const hasOptions = lastArg != null && !isParserLike(lastArg);
3378
+ const options = hasOptions ? lastArg : {};
3379
+ const parsers = hasOptions ? args.slice(0, -1) : args;
3380
+ const combinedMode = parsers.some((p) => p.mode === "async") ? "async" : "sync";
3381
+ const syncParsers = parsers;
3382
+ if (!options.allowDuplicates) checkSequentialDuplicateOptionNames(parsers);
3383
+ const initialState = createSeqState(void 0, 0, parsers.map((parser) => parser.initialState));
3384
+ const withSeqConsumedDepth = (result, consumed) => ({
3385
+ ...result,
3386
+ consumed: consumed.length + result.consumed
3387
+ });
3388
+ const parseSync = (context) => {
3389
+ let currentContext = context;
3390
+ const allConsumed = [];
3391
+ while (currentContext.state.index < syncParsers.length) {
3392
+ const index = currentContext.state.index;
3393
+ const parser = syncParsers[index];
3394
+ const parserState = getSeqChildState(currentContext.state, index, parser);
3395
+ if (currentContext.buffer.length < 1) break;
3396
+ if (shouldAdvanceSeqBeforeParse(parser, parserState, initialState.states[index], currentContext, index, syncParsers)) {
3397
+ const consumedTerminator = currentContext.buffer[0] === "--";
3398
+ if (consumedTerminator) allConsumed.push("--");
3399
+ currentContext = advanceSeqContext(currentContext, index + 1, consumedTerminator);
3400
+ continue;
3401
+ }
3402
+ const result = parser.parse(withChildContext$1(currentContext, index, parserState, parser));
3403
+ if (!result.success) {
3404
+ if (result.consumed > 0) return withSeqConsumedDepth(result, allConsumed);
3405
+ if (!parserCanSkipAt(parser, parserState, currentContext.exec, index)) return withSeqConsumedDepth(result, allConsumed);
3406
+ currentContext = advanceSeqContext(currentContext, index + 1, false);
3407
+ continue;
3408
+ }
3409
+ const states = updateSeqChildState(currentContext.state, index, result.next.state, parser);
3410
+ const nextIndex = result.consumed.length > 0 ? index : index + 1;
3411
+ const mergedExec = mergeChildExec(currentContext.exec, result.next.exec);
3412
+ currentContext = {
3413
+ ...currentContext,
3414
+ buffer: result.next.buffer,
3415
+ optionsTerminated: result.next.optionsTerminated,
3416
+ state: createSeqState(currentContext.state, nextIndex, states),
3417
+ ...mergedExec != null ? {
3418
+ exec: mergedExec,
3419
+ dependencyRegistry: mergedExec.dependencyRegistry
3420
+ } : {}
3421
+ };
3422
+ allConsumed.push(...result.consumed);
3423
+ }
3424
+ return {
3425
+ success: true,
3426
+ next: currentContext,
3427
+ consumed: allConsumed
3428
+ };
3429
+ };
3430
+ const parseAsync = async (context) => {
3431
+ let currentContext = context;
3432
+ const allConsumed = [];
3433
+ while (currentContext.state.index < parsers.length) {
3434
+ const index = currentContext.state.index;
3435
+ const parser = parsers[index];
3436
+ const parserState = getSeqChildState(currentContext.state, index, parser);
3437
+ if (currentContext.buffer.length < 1) break;
3438
+ if (shouldAdvanceSeqBeforeParse(parser, parserState, initialState.states[index], currentContext, index, parsers)) {
3439
+ const consumedTerminator = currentContext.buffer[0] === "--";
3440
+ if (consumedTerminator) allConsumed.push("--");
3441
+ currentContext = advanceSeqContext(currentContext, index + 1, consumedTerminator);
3442
+ continue;
3443
+ }
3444
+ const result = await parser.parse(withChildContext$1(currentContext, index, parserState, parser));
3445
+ if (!result.success) {
3446
+ if (result.consumed > 0) return withSeqConsumedDepth(result, allConsumed);
3447
+ if (!parserCanSkipAt(parser, parserState, currentContext.exec, index)) return withSeqConsumedDepth(result, allConsumed);
3448
+ currentContext = advanceSeqContext(currentContext, index + 1, false);
3449
+ continue;
3450
+ }
3451
+ const states = updateSeqChildState(currentContext.state, index, result.next.state, parser);
3452
+ const nextIndex = result.consumed.length > 0 ? index : index + 1;
3453
+ const mergedExec = mergeChildExec(currentContext.exec, result.next.exec);
3454
+ currentContext = {
3455
+ ...currentContext,
3456
+ buffer: result.next.buffer,
3457
+ optionsTerminated: result.next.optionsTerminated,
3458
+ state: createSeqState(currentContext.state, nextIndex, states),
3459
+ ...mergedExec != null ? {
3460
+ exec: mergedExec,
3461
+ dependencyRegistry: mergedExec.dependencyRegistry
3462
+ } : {}
3463
+ };
3464
+ allConsumed.push(...result.consumed);
3465
+ }
3466
+ return {
3467
+ success: true,
3468
+ next: currentContext,
3469
+ consumed: allConsumed
3470
+ };
3471
+ };
3472
+ const leadingNames = sequenceLeadingNames(parsers);
3473
+ const seqParser = {
3474
+ mode: combinedMode,
3475
+ $valueType: [],
3476
+ $stateType: [],
3477
+ [fieldParsersKey]: parsers.map((parser, index) => [String(index), parser]),
3478
+ usage: [{
3479
+ type: "sequence",
3480
+ terms: parsers.flatMap((parser) => parser.usage)
3481
+ }],
3482
+ leadingNames,
3483
+ acceptingAnyToken: sequenceAcceptingAnyToken(parsers),
3484
+ priority: sequencePriority(parsers),
3485
+ initialState,
3486
+ canSkip(state, exec) {
3487
+ for (let i = state.index; i < parsers.length; i++) {
3488
+ const parser = parsers[i];
3489
+ if (parser.canSkip?.(getSeqChildState(state, i, parser), withChildExecPath(exec, i)) !== true) return false;
3490
+ }
3491
+ return true;
3492
+ },
3493
+ parse(context) {
3494
+ return dispatchByMode(combinedMode, () => parseSync(context), () => parseAsync(context));
3495
+ },
3496
+ complete: void 0,
3497
+ [extractPhase2SeedKey](state, exec) {
3498
+ return dispatchByMode(combinedMode, () => {
3499
+ const stateArray = state.states;
3500
+ const runtime = exec?.dependencyRuntime ?? createDependencyRuntimeContext(exec?.dependencyRegistry);
3501
+ const childExec = withDependencyRuntimeExec(seqParser.usage, exec, runtime);
3502
+ const pairs = buildIndexedParserPairs(syncParsers);
3503
+ const stateRecord = createAnnotatedArrayStateRecord(stateArray);
3504
+ const preCompleted = preCompleteAndRegisterDependencies(stateRecord, pairs, runtime.registry, childExec);
3505
+ collectExplicitSourceValues(filterPreCompletedRuntimeNodes(buildRuntimeNodesFromArray(syncParsers, stateArray, exec?.path), new Set(preCompleted.keys())), runtime);
3506
+ const phase3Exec = {
3507
+ ...childExec,
3508
+ preCompletedByParser: void 0
3509
+ };
3510
+ const resolvedArray = resolveStateWithRuntime(stateArray, runtime);
3511
+ const result = [];
3512
+ const deferredKeys = /* @__PURE__ */ new Map();
3513
+ let hasDeferred = false;
3514
+ let hasAnySeed = false;
3515
+ for (let i = 0; i < syncParsers.length; i++) {
3516
+ const elementParser = syncParsers[i];
3517
+ const childExec$1 = withChildExecPath(phase3Exec, i);
3518
+ const preCompletedResult = preCompleted.get(String(i));
3519
+ const seed = preCompletedResult !== void 0 ? reusePreCompletedPhase2Seed(elementParser, prepareStateForCompletion(resolvedArray[i], elementParser), preCompletedResult, childExec$1) : completeOrExtractPhase2Seed(elementParser, prepareStateForCompletion(resolvedArray[i], elementParser), childExec$1);
3520
+ if (seed == null) continue;
3521
+ hasAnySeed = true;
3522
+ result[i] = seed.value;
3523
+ if (seed.deferred) if (seed.deferredKeys) deferredKeys.set(i, seed.deferredKeys);
3524
+ else if (seed.value == null || typeof seed.value !== "object") deferredKeys.set(i, null);
3525
+ else hasDeferred = true;
3526
+ }
3527
+ if (!hasAnySeed) return null;
3528
+ return {
3529
+ value: result,
3530
+ ...deferredKeys.size > 0 || hasDeferred ? {
3531
+ deferred: true,
3532
+ ...deferredKeys.size > 0 ? { deferredKeys } : {}
3533
+ } : {}
3534
+ };
3535
+ }, async () => {
3536
+ const stateArray = state.states;
3537
+ const runtime = exec?.dependencyRuntime ?? createDependencyRuntimeContext(exec?.dependencyRegistry);
3538
+ const childExec = withDependencyRuntimeExec(seqParser.usage, exec, runtime);
3539
+ const pairs = buildIndexedParserPairs(parsers);
3540
+ const stateRecord = createAnnotatedArrayStateRecord(stateArray);
3541
+ const preCompleted = await preCompleteAndRegisterDependenciesAsync(stateRecord, pairs, runtime.registry, childExec);
3542
+ await collectExplicitSourceValuesAsync(filterPreCompletedRuntimeNodes(buildRuntimeNodesFromArray(parsers, stateArray, exec?.path), new Set(preCompleted.keys())), runtime);
3543
+ const phase3Exec = {
3544
+ ...childExec,
3545
+ preCompletedByParser: void 0
3546
+ };
3547
+ const resolvedArray = await resolveStateWithRuntimeAsync(stateArray, runtime);
3548
+ const result = [];
3549
+ const deferredKeys = /* @__PURE__ */ new Map();
3550
+ let hasDeferred = false;
3551
+ let hasAnySeed = false;
3552
+ for (let i = 0; i < parsers.length; i++) {
3553
+ const elementParser = parsers[i];
3554
+ const childExec$1 = withChildExecPath(phase3Exec, i);
3555
+ const preCompletedResult = preCompleted.get(String(i));
3556
+ const seed = preCompletedResult !== void 0 ? await reusePreCompletedPhase2SeedAsync(elementParser, prepareStateForCompletion(resolvedArray[i], elementParser), preCompletedResult, childExec$1) : await completeOrExtractPhase2Seed(elementParser, prepareStateForCompletion(resolvedArray[i], elementParser), childExec$1);
3557
+ if (seed == null) continue;
3558
+ hasAnySeed = true;
3559
+ result[i] = seed.value;
3560
+ if (seed.deferred) if (seed.deferredKeys) deferredKeys.set(i, seed.deferredKeys);
3561
+ else if (seed.value == null || typeof seed.value !== "object") deferredKeys.set(i, null);
3562
+ else hasDeferred = true;
3563
+ }
3564
+ if (!hasAnySeed) return null;
3565
+ return {
3566
+ value: result,
3567
+ ...deferredKeys.size > 0 || hasDeferred ? {
3568
+ deferred: true,
3569
+ ...deferredKeys.size > 0 ? { deferredKeys } : {}
3570
+ } : {}
3571
+ };
3572
+ });
3573
+ },
3574
+ suggest(context, prefix) {
3575
+ return dispatchIterableByMode(combinedMode, () => {
3576
+ const suggestions = [];
3577
+ const advancedContext = advanceSeqSuggestContextSync(context, syncParsers, initialState.states);
3578
+ const runtime = createDependencyRuntimeContext(advancedContext.dependencyRegistry?.clone());
3579
+ const state = advancedContext.state;
3580
+ const stateArray = state.states;
3581
+ const nodes = buildSuggestRuntimeNodesFromArray(syncParsers, stateArray, advancedContext.exec?.path);
3582
+ collectExplicitSourceValues(nodes, runtime);
3583
+ fillMissingSourceDefaults(nodes, runtime);
3584
+ collectSourcesFromState(stateArray, runtime);
3585
+ completeDependencySourceDefaults({
3586
+ ...advancedContext,
3587
+ state: createAnnotatedArrayStateRecord(stateArray)
3588
+ }, buildIndexedParserPairs(syncParsers), runtime.registry, advancedContext.exec);
3589
+ const contextWithRegistry = {
3590
+ ...advancedContext,
3591
+ dependencyRegistry: runtime.registry,
3592
+ ...advancedContext.exec != null ? { exec: {
3593
+ ...advancedContext.exec,
3594
+ dependencyRuntime: runtime,
3595
+ dependencyRegistry: runtime.registry
3596
+ } } : {}
3597
+ };
3598
+ for (let i = state.index; i < syncParsers.length; i++) {
3599
+ const parser = syncParsers[i];
3600
+ const parserState = getSeqChildState(state, i, parser);
3601
+ suggestions.push(...parser.suggest(withChildContext$1(contextWithRegistry, i, parserState, parser), prefix));
3602
+ if (parser.canSkip?.(parserState, withChildExecPath(contextWithRegistry.exec, i)) !== true) break;
3603
+ }
3604
+ return deduplicateSuggestions(suggestions);
3605
+ }, async function* () {
3606
+ const suggestions = [];
3607
+ const advancedContext = await advanceSeqSuggestContextAsync(context, parsers, initialState.states);
3608
+ const runtime = createDependencyRuntimeContext(advancedContext.dependencyRegistry?.clone());
3609
+ const state = advancedContext.state;
3610
+ const stateArray = state.states;
3611
+ const nodes = buildSuggestRuntimeNodesFromArray(parsers, stateArray, advancedContext.exec?.path);
3612
+ await collectExplicitSourceValuesAsync(nodes, runtime);
3613
+ await fillMissingSourceDefaultsAsync(nodes, runtime);
3614
+ collectSourcesFromState(stateArray, runtime);
3615
+ await completeDependencySourceDefaultsAsync({
3616
+ ...advancedContext,
3617
+ state: createAnnotatedArrayStateRecord(stateArray)
3618
+ }, buildIndexedParserPairs(parsers), runtime.registry, advancedContext.exec);
3619
+ const contextWithRegistry = {
3620
+ ...advancedContext,
3621
+ dependencyRegistry: runtime.registry,
3622
+ ...advancedContext.exec != null ? { exec: {
3623
+ ...advancedContext.exec,
3624
+ dependencyRuntime: runtime,
3625
+ dependencyRegistry: runtime.registry
3626
+ } } : {}
3627
+ };
3628
+ for (let i = state.index; i < parsers.length; i++) {
3629
+ const parser = parsers[i];
3630
+ const parserState = getSeqChildState(state, i, parser);
3631
+ const parserSuggestions = parser.suggest(withChildContext$1(contextWithRegistry, i, parserState, parser), prefix);
3632
+ if (parser.mode === "async") for await (const suggestion of parserSuggestions) suggestions.push(suggestion);
3633
+ else suggestions.push(...parserSuggestions);
3634
+ if (parser.canSkip?.(parserState, withChildExecPath(contextWithRegistry.exec, i)) !== true) break;
3635
+ }
3636
+ yield* deduplicateSuggestions(suggestions);
3637
+ });
3638
+ },
3639
+ getDocFragments(state, defaultValue) {
3640
+ const fragments = syncParsers.flatMap((parser, index) => {
3641
+ const indexState = state.kind === "unavailable" ? { kind: "unavailable" } : {
3642
+ kind: "available",
3643
+ state: state.state.states[index]
3644
+ };
3645
+ return parser.getDocFragments(indexState, defaultValue?.[index]).fragments;
3646
+ });
3647
+ const entries = fragments.filter((d) => d.type === "entry");
3648
+ const sections = [];
3649
+ for (const fragment of fragments) {
3650
+ if (fragment.type !== "section") continue;
3651
+ if (fragment.title == null) entries.push(...fragment.entries);
3652
+ else sections.push(fragment);
3653
+ }
3654
+ sections.push({
3655
+ title: label,
3656
+ entries
3657
+ });
3658
+ return { fragments: sections.map((s) => ({
3659
+ ...s,
3660
+ type: "section"
3661
+ })) };
3662
+ },
3663
+ [Symbol.for("Deno.customInspect")]() {
3664
+ const parsersStr = parsers.length === 1 ? "1 parser" : `${parsers.length} parsers`;
3665
+ return label == null ? `seq(${parsersStr})` : `seq(${JSON.stringify(label)}, ${parsersStr})`;
3666
+ }
3667
+ };
3668
+ Object.defineProperty(seqParser, "complete", {
3669
+ value: createSeqComplete(parsers, combinedMode),
3670
+ configurable: true,
3671
+ enumerable: true
3672
+ });
3673
+ const normalizers = [];
3674
+ for (let i = 0; i < parsers.length; i++) {
3675
+ const parser = parsers[i];
3676
+ if (typeof parser.normalizeValue === "function") normalizers.push([i, parser.normalizeValue.bind(parser)]);
3677
+ }
3678
+ if (normalizers.length > 0) Object.defineProperty(seqParser, "normalizeValue", {
3679
+ value(arr) {
3680
+ if (!Array.isArray(arr)) return arr;
3681
+ let changed = false;
3682
+ let result;
3683
+ for (const [index, normalize] of normalizers) if (index < arr.length && Object.hasOwn(arr, index)) try {
3684
+ const original = arr[index];
3685
+ const normalized = normalize(original);
3686
+ if (normalized !== original) {
3687
+ result ??= [...arr];
3688
+ result[index] = normalized;
3689
+ changed = true;
3690
+ }
3691
+ } catch {}
3692
+ return changed ? result : arr;
3693
+ },
3694
+ configurable: true,
3695
+ enumerable: false
3696
+ });
3697
+ defineInheritedAnnotationParser(seqParser);
3698
+ return seqParser;
3699
+ }
2918
3700
  function merge(...args) {
2919
3701
  const label = typeof args[0] === "string" ? args[0] : void 0;
2920
3702
  if (label != null) validateLabel(label);
@@ -2936,6 +3718,7 @@ function merge(...args) {
2936
3718
  const syncSorted = syncWithIndex.toSorted(([a], [b]) => b.priority - a.priority);
2937
3719
  const syncParsers = syncSorted.map(([p]) => p);
2938
3720
  if (!options.allowDuplicates) checkDuplicateOptionNames(sorted.map(([parser, originalIndex]) => [String(originalIndex), parser.usage]));
3721
+ checkDuplicateReachableLeadingCommandNames(sorted.map(([parser, originalIndex]) => [String(originalIndex), parser]));
2939
3722
  const mergedFieldParsers = collectChildFieldParsers(parsers);
2940
3723
  const duplicateOutputFieldNames = collectDuplicateFieldNames(mergedFieldParsers);
2941
3724
  const parserStateKey = (index) => `__parser_${index}`;
@@ -2947,23 +3730,24 @@ function merge(...args) {
2947
3730
  if (parser.initialState === void 0) initialState[parserStateKey(i)] = void 0;
2948
3731
  else if (parser.initialState && typeof parser.initialState === "object") for (const field in parser.initialState) initialState[field] = parser.initialState[field];
2949
3732
  }
2950
- const extractParserState = (parser, context, index) => {
3733
+ const extractParserStateFromState = (parser, state, index) => {
2951
3734
  if (parser.initialState === void 0) {
2952
3735
  const key = parserStateKey(index);
2953
- if (context.state && typeof context.state === "object" && key in context.state) return context.state[key];
3736
+ if (state && typeof state === "object" && key in state) return state[key];
2954
3737
  return void 0;
2955
3738
  } else if (parser.initialState && typeof parser.initialState === "object") {
2956
3739
  const localStateKey = localObjectStateKey(index);
2957
- if (shouldPreserveLocalChildState(parser) && context.state && typeof context.state === "object" && localStateKey in context.state) return context.state[localStateKey];
2958
- if (context.state && typeof context.state === "object") {
3740
+ if (shouldPreserveLocalChildState(parser) && state && typeof state === "object" && localStateKey in state) return state[localStateKey];
3741
+ if (state && typeof state === "object") {
2959
3742
  const extractedState = {};
2960
- for (const field in parser.initialState) extractedState[field] = field in context.state ? context.state[field] : parser.initialState[field];
3743
+ for (const field in parser.initialState) extractedState[field] = field in state ? state[field] : parser.initialState[field];
2961
3744
  return extractedState;
2962
3745
  }
2963
3746
  return parser.initialState;
2964
3747
  }
2965
3748
  return parser.initialState;
2966
3749
  };
3750
+ const extractParserState = (parser, context, index) => extractParserStateFromState(parser, context.state, index);
2967
3751
  const mergeResultState = (parser, context, parserState, result, index) => {
2968
3752
  if (parser.initialState === void 0) {
2969
3753
  const key = parserStateKey(index);
@@ -3088,6 +3872,12 @@ function merge(...args) {
3088
3872
  leadingNames: sharedBufferLeadingNames(parsers),
3089
3873
  acceptingAnyToken: parsers.some((p) => p.acceptingAnyToken),
3090
3874
  initialState,
3875
+ canSkip(state, exec) {
3876
+ return parsers.every((parser, index) => {
3877
+ const parserState = extractParserStateFromState(parser, state, index);
3878
+ return parser.canSkip?.(getWrappedChildState(state, parserState, parser), withChildExecPath(exec, index)) === true;
3879
+ });
3880
+ },
3091
3881
  parse(context) {
3092
3882
  if (isAsync) return parseAsync(context);
3093
3883
  return parseSync(context);
@@ -4033,6 +4823,10 @@ function concat(...parsers) {
4033
4823
  leadingNames: sharedBufferLeadingNames(parsers),
4034
4824
  acceptingAnyToken: parsers.some((p) => p.acceptingAnyToken),
4035
4825
  initialState,
4826
+ canSkip(state, exec) {
4827
+ const stateArray = state;
4828
+ return parsers.every((parser, index) => parser.canSkip?.(getWrappedChildState(stateArray, stateArray[index], parser), withChildExecPath(exec, index)) === true);
4829
+ },
4036
4830
  parse(context) {
4037
4831
  if (isAsync) return parseAsync(context);
4038
4832
  return parseSync(context);
@@ -4181,6 +4975,7 @@ function group(label, parser, options = {}) {
4181
4975
  initialState: parser.initialState,
4182
4976
  ...fieldParsersKey in parser ? { [fieldParsersKey]: parser[fieldParsersKey] } : {},
4183
4977
  ...typeof parser.shouldDeferCompletion === "function" ? { shouldDeferCompletion: parser.shouldDeferCompletion.bind(parser) } : {},
4978
+ ...typeof parser.canSkip === "function" ? { canSkip: parser.canSkip.bind(parser) } : {},
4184
4979
  getSuggestRuntimeNodes(state, path) {
4185
4980
  return parser.getSuggestRuntimeNodes?.(state, path) ?? (parser.dependencyMetadata?.source != null ? [{
4186
4981
  path,
@@ -4338,6 +5133,10 @@ function conditional(discriminator, branches, defaultBranch, options) {
4338
5133
  ...term,
4339
5134
  terms: appendLiteralToUsage(term.terms, literalValue)
4340
5135
  });
5136
+ else if (term.type === "sequence") result.push({
5137
+ ...term,
5138
+ terms: appendLiteralToUsage(term.terms, literalValue)
5139
+ });
4341
5140
  else if (term.type === "exclusive") result.push({
4342
5141
  ...term,
4343
5142
  terms: term.terms.map((t) => appendLiteralToUsage(t, literalValue))
@@ -5225,4 +6024,4 @@ function conditional(discriminator, branches, defaultBranch, options) {
5225
6024
  }
5226
6025
 
5227
6026
  //#endregion
5228
- export { DuplicateOptionError, concat, conditional, group, longestMatch, merge, object, or, tuple };
6027
+ export { DuplicateOptionError, concat, conditional, group, longestMatch, merge, object, or, seq, tuple };