@optique/core 1.0.0-dev.1692 → 1.0.0-dev.1693

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.
@@ -5,6 +5,7 @@ const require_validate = require('./validate.cjs');
5
5
  const require_usage = require('./usage.cjs');
6
6
  const require_doc = require('./doc.cjs');
7
7
  const require_mode_dispatch = require('./mode-dispatch.cjs');
8
+ const require_modifiers = require('./modifiers.cjs');
8
9
  const require_suggestion = require('./suggestion.cjs');
9
10
  const require_usage_internals = require('./usage-internals.cjs');
10
11
  const require_parser = require('./parser.cjs');
@@ -512,10 +513,81 @@ function createExclusiveComplete(parsers, options, noMatchContext, mode) {
512
513
  const syncParsers = parsers;
513
514
  return (state, exec) => {
514
515
  const activeState = normalizeExclusiveState(state);
515
- if (activeState == null) return {
516
- success: false,
517
- error: getNoMatchError(options, noMatchContext)
518
- };
516
+ if (activeState == null) {
517
+ const annotations = require_annotations.getAnnotations(state);
518
+ const annotateInitial = (initial) => annotations != null && initial != null && typeof initial === "object" ? require_annotations.injectAnnotations(initial, annotations) : initial;
519
+ return require_mode_dispatch.dispatchByMode(mode, () => {
520
+ const emptyCtx = {
521
+ buffer: [],
522
+ optionsTerminated: false,
523
+ usage: []
524
+ };
525
+ let candidateIndex = -1;
526
+ let candidateCount = 0;
527
+ for (let i$1 = 0; i$1 < syncParsers.length; i$1++) {
528
+ const p = syncParsers[i$1];
529
+ if (p.leadingNames.size > 0 || p.acceptingAnyToken) continue;
530
+ const parseResult = p.parse({
531
+ ...emptyCtx,
532
+ state: annotateInitial(p.initialState)
533
+ });
534
+ if (!parseResult.success || parseResult.provisional) continue;
535
+ candidateCount++;
536
+ if (candidateIndex < 0) candidateIndex = i$1;
537
+ if (candidateCount > 1) break;
538
+ }
539
+ if (candidateCount === 1 && candidateIndex >= 0) {
540
+ const p = syncParsers[candidateIndex];
541
+ const parseResult = p.parse({
542
+ ...emptyCtx,
543
+ state: annotateInitial(p.initialState)
544
+ });
545
+ if (parseResult.success) {
546
+ const annotatedState = getAnnotatedChildState(state, parseResult.next.state, p);
547
+ return p.complete(annotatedState, withChildExecPath(exec, candidateIndex));
548
+ }
549
+ }
550
+ return {
551
+ success: false,
552
+ error: getNoMatchError(options, noMatchContext)
553
+ };
554
+ }, async () => {
555
+ const emptyCtx = {
556
+ buffer: [],
557
+ optionsTerminated: false,
558
+ usage: []
559
+ };
560
+ let candidateIndex = -1;
561
+ let candidateCount = 0;
562
+ for (let i$1 = 0; i$1 < parsers.length; i$1++) {
563
+ const p = parsers[i$1];
564
+ if (p.leadingNames.size > 0 || p.acceptingAnyToken) continue;
565
+ const parseResult = await p.parse({
566
+ ...emptyCtx,
567
+ state: annotateInitial(p.initialState)
568
+ });
569
+ if (!parseResult.success || parseResult.provisional) continue;
570
+ candidateCount++;
571
+ if (candidateIndex < 0) candidateIndex = i$1;
572
+ if (candidateCount > 1) break;
573
+ }
574
+ if (candidateCount === 1 && candidateIndex >= 0 && exec?.phase !== "parse" && exec?.phase !== "suggest") {
575
+ const p = parsers[candidateIndex];
576
+ const parseResult = await p.parse({
577
+ ...emptyCtx,
578
+ state: annotateInitial(p.initialState)
579
+ });
580
+ if (parseResult.success) {
581
+ const annotatedState = getAnnotatedChildState(state, parseResult.next.state, p);
582
+ return await p.complete(annotatedState, withChildExecPath(exec, candidateIndex));
583
+ }
584
+ }
585
+ return {
586
+ success: false,
587
+ error: getNoMatchError(options, noMatchContext)
588
+ };
589
+ });
590
+ }
519
591
  const [i, result] = activeState;
520
592
  if (!result.success) return {
521
593
  success: false,
@@ -537,7 +609,7 @@ function createExclusiveSuggest(parsers, mode) {
537
609
  return require_mode_dispatch.dispatchIterableByMode(mode, function* () {
538
610
  const suggestions = [];
539
611
  const activeState = normalizeExclusiveState(context.state);
540
- if (activeState == null) for (let i = 0; i < syncParsers.length; i++) {
612
+ if (activeState == null || activeState[1].success && activeState[1].consumed.length === 0) for (let i = 0; i < syncParsers.length; i++) {
541
613
  const parser = syncParsers[i];
542
614
  const parserSuggestions = parser.suggest(withChildContext(context, i, parser.initialState, parser), prefix);
543
615
  suggestions.push(...parserSuggestions);
@@ -554,7 +626,7 @@ function createExclusiveSuggest(parsers, mode) {
554
626
  }, async function* () {
555
627
  const suggestions = [];
556
628
  const activeState = normalizeExclusiveState(context.state);
557
- if (activeState == null) for (let i = 0; i < parsers.length; i++) {
629
+ if (activeState == null || activeState[1].success && activeState[1].consumed.length === 0) for (let i = 0; i < parsers.length; i++) {
558
630
  const parser = parsers[i];
559
631
  const parserSuggestions = parser.suggest(withChildContext(context, i, parser.initialState, parser), prefix);
560
632
  if (parser.$mode === "async") for await (const s of parserSuggestions) suggestions.push(s);
@@ -642,10 +714,29 @@ function or(...args) {
642
714
  const activeState = normalizeExclusiveState(context.state);
643
715
  const orderedParsers = syncParsers.map((p, i) => [p, i]);
644
716
  orderedParsers.sort(([_, a], [__, b]) => activeState?.[0] === a ? -1 : activeState?.[0] === b ? 1 : a - b);
717
+ let zeroConsumedBranch = null;
718
+ let zeroConsumedCount = 0;
645
719
  for (const [parser, i] of orderedParsers) {
646
720
  const result = parser.parse(withChildContext(context, i, activeState == null || activeState[0] !== i || !activeState[1].success ? parser.initialState : activeState[1].next.state, parser));
647
721
  if (result.success && result.consumed.length > 0) {
648
722
  if (activeState?.[0] !== i && activeState?.[1].success) {
723
+ if (activeState[1].consumed.length === 0) {
724
+ const mergedExec$2 = mergeChildExec(context.exec, result.next.exec);
725
+ return {
726
+ success: true,
727
+ next: {
728
+ ...context,
729
+ buffer: result.next.buffer,
730
+ optionsTerminated: result.next.optionsTerminated,
731
+ state: createExclusiveState(context.state, i, parser, result),
732
+ ...mergedExec$2 != null ? {
733
+ exec: mergedExec$2,
734
+ dependencyRegistry: mergedExec$2.dependencyRegistry
735
+ } : {}
736
+ },
737
+ consumed: result.consumed
738
+ };
739
+ }
649
740
  const previouslyConsumed = activeState[1].consumed;
650
741
  const checkResult = parser.parse({
651
742
  ...withChildContext(context, i, parser.initialState, parser),
@@ -700,8 +791,31 @@ function or(...args) {
700
791
  },
701
792
  consumed: result.consumed
702
793
  };
794
+ } else if (result.success && result.consumed.length === 0 && !result.provisional && parser.leadingNames.size === 0 && !parser.acceptingAnyToken) {
795
+ if (zeroConsumedBranch === null) zeroConsumedBranch = {
796
+ index: i,
797
+ parser,
798
+ result
799
+ };
800
+ zeroConsumedCount++;
703
801
  } else if (!result.success && error.consumed < result.consumed) error = result;
704
802
  }
803
+ if (zeroConsumedBranch !== null && zeroConsumedCount === 1 && error.consumed === 0 && context.buffer.length === 0) {
804
+ const mergedExec = mergeChildExec(context.exec, zeroConsumedBranch.result.next.exec);
805
+ return {
806
+ success: true,
807
+ ...zeroConsumedBranch.result.provisional ? { provisional: true } : {},
808
+ next: {
809
+ ...context,
810
+ state: createExclusiveState(context.state, zeroConsumedBranch.index, zeroConsumedBranch.parser, zeroConsumedBranch.result),
811
+ ...mergedExec != null ? {
812
+ exec: mergedExec,
813
+ dependencyRegistry: mergedExec.dependencyRegistry
814
+ } : {}
815
+ },
816
+ consumed: []
817
+ };
818
+ }
705
819
  return {
706
820
  ...error,
707
821
  success: false
@@ -712,11 +826,30 @@ function or(...args) {
712
826
  const activeState = normalizeExclusiveState(context.state);
713
827
  const orderedParsers = parsers.map((p, i) => [p, i]);
714
828
  orderedParsers.sort(([_, a], [__, b]) => activeState?.[0] === a ? -1 : activeState?.[0] === b ? 1 : a - b);
829
+ let zeroConsumedBranch = null;
830
+ let zeroConsumedCount = 0;
715
831
  for (const [parser, i] of orderedParsers) {
716
832
  const resultOrPromise = parser.parse(withChildContext(context, i, activeState == null || activeState[0] !== i || !activeState[1].success ? parser.initialState : activeState[1].next.state, parser));
717
833
  const result = await resultOrPromise;
718
834
  if (result.success && result.consumed.length > 0) {
719
835
  if (activeState?.[0] !== i && activeState?.[1].success) {
836
+ if (activeState[1].consumed.length === 0) {
837
+ const mergedExec$2 = mergeChildExec(context.exec, result.next.exec);
838
+ return {
839
+ success: true,
840
+ next: {
841
+ ...context,
842
+ buffer: result.next.buffer,
843
+ optionsTerminated: result.next.optionsTerminated,
844
+ state: createExclusiveState(context.state, i, parser, result),
845
+ ...mergedExec$2 != null ? {
846
+ exec: mergedExec$2,
847
+ dependencyRegistry: mergedExec$2.dependencyRegistry
848
+ } : {}
849
+ },
850
+ consumed: result.consumed
851
+ };
852
+ }
720
853
  const previouslyConsumed = activeState[1].consumed;
721
854
  const checkResultOrPromise = parser.parse({
722
855
  ...withChildContext(context, i, parser.initialState, parser),
@@ -773,8 +906,31 @@ function or(...args) {
773
906
  },
774
907
  consumed: result.consumed
775
908
  };
909
+ } else if (result.success && result.consumed.length === 0 && !result.provisional && parser.leadingNames.size === 0 && !parser.acceptingAnyToken) {
910
+ if (zeroConsumedBranch === null) zeroConsumedBranch = {
911
+ index: i,
912
+ parser,
913
+ result
914
+ };
915
+ zeroConsumedCount++;
776
916
  } else if (!result.success && error.consumed < result.consumed) error = result;
777
917
  }
918
+ if (zeroConsumedBranch !== null && zeroConsumedCount === 1 && error.consumed === 0 && context.buffer.length === 0) {
919
+ const mergedExec = mergeChildExec(context.exec, zeroConsumedBranch.result.next.exec);
920
+ return {
921
+ success: true,
922
+ ...zeroConsumedBranch.result.provisional ? { provisional: true } : {},
923
+ next: {
924
+ ...context,
925
+ state: createExclusiveState(context.state, zeroConsumedBranch.index, zeroConsumedBranch.parser, zeroConsumedBranch.result),
926
+ ...mergedExec != null ? {
927
+ exec: mergedExec,
928
+ dependencyRegistry: mergedExec.dependencyRegistry
929
+ } : {}
930
+ },
931
+ consumed: []
932
+ };
933
+ }
778
934
  return {
779
935
  ...error,
780
936
  success: false
@@ -1407,6 +1563,7 @@ function object(labelOrParsers, maybeParsersOrOptions, maybeOptions) {
1407
1563
  let currentContext = context;
1408
1564
  let anySuccess = false;
1409
1565
  const allConsumed = [];
1566
+ const consumedFields = /* @__PURE__ */ new Set();
1410
1567
  let madeProgress = true;
1411
1568
  while (madeProgress && currentContext.buffer.length > 0) {
1412
1569
  madeProgress = false;
@@ -1432,21 +1589,47 @@ function object(labelOrParsers, maybeParsersOrOptions, maybeOptions) {
1432
1589
  allConsumed.push(...result.consumed);
1433
1590
  anySuccess = true;
1434
1591
  madeProgress = true;
1592
+ consumedFields.add(field);
1435
1593
  break;
1436
1594
  } else if (!result.success && error.consumed < result.consumed) error = result;
1437
1595
  }
1438
1596
  }
1597
+ {
1598
+ const getFieldState = createFieldStateGetter(currentContext.state, getObjectParseChildState);
1599
+ for (const [field, parser] of parserPairs) {
1600
+ if (consumedFields.has(field)) continue;
1601
+ const typedParser = parser;
1602
+ if (parser.leadingNames.size > 0 || typedParser.acceptingAnyToken || Reflect.get(parser, require_modifiers.optionalStyleWrapperKey) === true) continue;
1603
+ const fieldState = getFieldState(field, parser);
1604
+ const result = typedParser.parse(withChildContext(currentContext, field, fieldState, parser));
1605
+ if (result.success && result.consumed.length === 0 && result.next.state !== fieldState) {
1606
+ const mergedExec = mergeChildExec(currentContext.exec, result.next.exec);
1607
+ currentContext = {
1608
+ ...currentContext,
1609
+ state: {
1610
+ ...currentContext.state,
1611
+ [field]: getAnnotatedChildState(currentContext.state, result.next.state, parser)
1612
+ },
1613
+ ...mergedExec != null ? {
1614
+ trace: mergedExec.trace,
1615
+ exec: mergedExec,
1616
+ dependencyRegistry: mergedExec.dependencyRegistry
1617
+ } : {}
1618
+ };
1619
+ }
1620
+ }
1621
+ }
1439
1622
  if (anySuccess) return {
1440
1623
  success: true,
1441
1624
  next: currentContext,
1442
1625
  consumed: allConsumed
1443
1626
  };
1444
- if (context.buffer.length === 0) {
1627
+ if (currentContext.buffer.length === 0) {
1445
1628
  let allCanComplete = true;
1446
- const getFieldState = createFieldStateGetter(context.state);
1629
+ const getFieldState = createFieldStateGetter(currentContext.state);
1447
1630
  for (const [field, parser] of parserPairs) {
1448
1631
  const fieldState = getFieldState(field, parser);
1449
- const completeResult = parser.complete(fieldState, withChildExecPath(context.exec, field));
1632
+ const completeResult = parser.complete(fieldState, withChildExecPath(currentContext.exec, field));
1450
1633
  if (!completeResult.success) {
1451
1634
  allCanComplete = false;
1452
1635
  break;
@@ -1454,7 +1637,7 @@ function object(labelOrParsers, maybeParsersOrOptions, maybeOptions) {
1454
1637
  }
1455
1638
  if (allCanComplete) return {
1456
1639
  success: true,
1457
- next: context,
1640
+ next: currentContext,
1458
1641
  consumed: []
1459
1642
  };
1460
1643
  }
@@ -1468,6 +1651,7 @@ function object(labelOrParsers, maybeParsersOrOptions, maybeOptions) {
1468
1651
  let currentContext = context;
1469
1652
  let anySuccess = false;
1470
1653
  const allConsumed = [];
1654
+ const consumedFields = /* @__PURE__ */ new Set();
1471
1655
  let madeProgress = true;
1472
1656
  while (madeProgress && currentContext.buffer.length > 0) {
1473
1657
  madeProgress = false;
@@ -1494,21 +1678,47 @@ function object(labelOrParsers, maybeParsersOrOptions, maybeOptions) {
1494
1678
  allConsumed.push(...result.consumed);
1495
1679
  anySuccess = true;
1496
1680
  madeProgress = true;
1681
+ consumedFields.add(field);
1497
1682
  break;
1498
1683
  } else if (!result.success && error.consumed < result.consumed) error = result;
1499
1684
  }
1500
1685
  }
1686
+ {
1687
+ const getFieldState = createFieldStateGetter(currentContext.state, getObjectParseChildState);
1688
+ for (const [field, parser] of parserPairs) {
1689
+ if (consumedFields.has(field)) continue;
1690
+ if (parser.leadingNames.size > 0 || parser.acceptingAnyToken || Reflect.get(parser, require_modifiers.optionalStyleWrapperKey) === true) continue;
1691
+ const fieldState = getFieldState(field, parser);
1692
+ const resultOrPromise = parser.parse(withChildContext(currentContext, field, fieldState, parser));
1693
+ const result = await resultOrPromise;
1694
+ if (result.success && result.consumed.length === 0 && result.next.state !== fieldState) {
1695
+ const mergedExec = mergeChildExec(currentContext.exec, result.next.exec);
1696
+ currentContext = {
1697
+ ...currentContext,
1698
+ state: {
1699
+ ...currentContext.state,
1700
+ [field]: getAnnotatedChildState(currentContext.state, result.next.state, parser)
1701
+ },
1702
+ ...mergedExec != null ? {
1703
+ trace: mergedExec.trace,
1704
+ exec: mergedExec,
1705
+ dependencyRegistry: mergedExec.dependencyRegistry
1706
+ } : {}
1707
+ };
1708
+ }
1709
+ }
1710
+ }
1501
1711
  if (anySuccess) return {
1502
1712
  success: true,
1503
1713
  next: currentContext,
1504
1714
  consumed: allConsumed
1505
1715
  };
1506
- if (context.buffer.length === 0) {
1716
+ if (currentContext.buffer.length === 0) {
1507
1717
  let allCanComplete = true;
1508
- const getFieldState = createFieldStateGetter(context.state);
1718
+ const getFieldState = createFieldStateGetter(currentContext.state);
1509
1719
  for (const [field, parser] of parserPairs) {
1510
1720
  const fieldState = getFieldState(field, parser);
1511
- const completeResult = await parser.complete(fieldState, withChildExecPath(context.exec, field));
1721
+ const completeResult = await parser.complete(fieldState, withChildExecPath(currentContext.exec, field));
1512
1722
  if (!completeResult.success) {
1513
1723
  allCanComplete = false;
1514
1724
  break;
@@ -1516,7 +1726,7 @@ function object(labelOrParsers, maybeParsersOrOptions, maybeOptions) {
1516
1726
  }
1517
1727
  if (allCanComplete) return {
1518
1728
  success: true,
1519
- next: context,
1729
+ next: currentContext,
1520
1730
  consumed: []
1521
1731
  };
1522
1732
  }
@@ -3432,6 +3642,19 @@ function group(label, parser, options = {}) {
3432
3642
  * // defaultResult.value = [undefined, {}]
3433
3643
  * ```
3434
3644
  *
3645
+ * ### Async discriminator limitation
3646
+ *
3647
+ * When the discriminator is an async parser that succeeds without consuming
3648
+ * input (e.g., `prompt(option(...))` with no CLI input), branch selection
3649
+ * is deferred to the complete phase. If the selected branch needs to
3650
+ * consume remaining tokens, those tokens cannot be consumed because the
3651
+ * branch is not known during parse. In practice, this means
3652
+ * `conditional(prompt(option(...)), { key: option(...) })` cannot parse
3653
+ * branch-specific tokens when the discriminator requires interactive
3654
+ * resolution. Provide a default branch or ensure the discriminator
3655
+ * can resolve synchronously (e.g., via `bindEnv()` or `withDefault()`)
3656
+ * to avoid this limitation.
3657
+ *
3435
3658
  * @since 0.8.0
3436
3659
  */
3437
3660
  function conditional(discriminator, branches, defaultBranch, options) {
@@ -3510,7 +3733,7 @@ function conditional(discriminator, branches, defaultBranch, options) {
3510
3733
  return branchResult;
3511
3734
  }
3512
3735
  const discriminatorResult = syncDiscriminator.parse({ ...withChildContext(context, "_discriminator", state.discriminatorState, syncDiscriminator) });
3513
- if (discriminatorResult.success && discriminatorResult.consumed.length > 0) {
3736
+ if (discriminatorResult.success) {
3514
3737
  const annotatedDiscriminatorState = getAnnotatedChildState(state, discriminatorResult.next.state, syncDiscriminator);
3515
3738
  const completionResult = syncDiscriminator.complete(annotatedDiscriminatorState, withChildExecPath(context.exec, "_discriminator"));
3516
3739
  if (completionResult.success) {
@@ -3531,8 +3754,10 @@ function conditional(discriminator, branches, defaultBranch, options) {
3531
3754
  });
3532
3755
  if (branchParseResult.success) {
3533
3756
  const mergedExec = mergeChildExec(discriminatorExec, branchParseResult.next.exec);
3757
+ const isProvisional = branchParseResult.provisional || discriminatorResult.consumed.length === 0 && branchParseResult.consumed.length === 0 && branchParser.leadingNames.size > 0;
3534
3758
  return {
3535
3759
  success: true,
3760
+ ...isProvisional ? { provisional: true } : {},
3536
3761
  next: {
3537
3762
  ...branchParseResult.next,
3538
3763
  state: {
@@ -3552,7 +3777,7 @@ function conditional(discriminator, branches, defaultBranch, options) {
3552
3777
  consumed: [...discriminatorResult.consumed, ...branchParseResult.consumed]
3553
3778
  };
3554
3779
  }
3555
- return {
3780
+ if (discriminatorResult.consumed.length > 0) return {
3556
3781
  success: true,
3557
3782
  next: {
3558
3783
  ...discriminatorResult.next,
@@ -3572,20 +3797,24 @@ function conditional(discriminator, branches, defaultBranch, options) {
3572
3797
  },
3573
3798
  consumed: discriminatorResult.consumed
3574
3799
  };
3800
+ return branchParseResult;
3575
3801
  }
3576
3802
  }
3577
3803
  }
3804
+ const discriminatorConsumed = discriminatorResult.success ? discriminatorResult.consumed.length : discriminatorResult.consumed;
3578
3805
  if (syncDefaultBranch !== void 0) {
3579
3806
  const defaultResult = syncDefaultBranch.parse(withChildContext(context, "_branch", state.branchState ?? syncDefaultBranch.initialState, syncDefaultBranch, syncDefaultBranch.usage));
3580
- if (defaultResult.success && defaultResult.consumed.length > 0) {
3807
+ if (defaultResult.success && (defaultResult.consumed.length > 0 || discriminatorConsumed === 0 && context.buffer.length === 0)) {
3581
3808
  const mergedExec = mergeChildExec(context.exec, defaultResult.next.exec);
3809
+ const commitDefault = defaultResult.consumed.length > 0 || context.buffer.length === 0;
3582
3810
  return {
3583
3811
  success: true,
3812
+ ...defaultResult.provisional ? { provisional: true } : {},
3584
3813
  next: {
3585
3814
  ...defaultResult.next,
3586
3815
  state: {
3587
3816
  ...state,
3588
- selectedBranch: { kind: "default" },
3817
+ ...commitDefault ? { selectedBranch: { kind: "default" } } : {},
3589
3818
  branchState: getAnnotatedChildState(state, defaultResult.next.state, syncDefaultBranch)
3590
3819
  },
3591
3820
  ...mergedExec != null ? {
@@ -3629,7 +3858,49 @@ function conditional(discriminator, branches, defaultBranch, options) {
3629
3858
  return branchResult;
3630
3859
  }
3631
3860
  const discriminatorResult = await discriminator.parse({ ...withChildContext(context, "_discriminator", state.discriminatorState, discriminator) });
3632
- if (discriminatorResult.success && discriminatorResult.consumed.length > 0) {
3861
+ if (discriminatorResult.success) {
3862
+ if (discriminatorResult.consumed.length === 0 && discriminator.$mode === "async") {
3863
+ if (defaultBranch !== void 0) {
3864
+ const defaultResult = await defaultBranch.parse(withChildContext(context, "_branch", state.branchState ?? defaultBranch.initialState, defaultBranch, defaultBranch.usage));
3865
+ if (defaultResult.success && defaultResult.consumed.length > 0) {
3866
+ const defaultExec = mergeChildExec(context.exec, defaultResult.next.exec);
3867
+ return {
3868
+ success: true,
3869
+ next: {
3870
+ ...defaultResult.next,
3871
+ state: {
3872
+ ...state,
3873
+ selectedBranch: { kind: "default" },
3874
+ branchState: getAnnotatedChildState(state, defaultResult.next.state, defaultBranch)
3875
+ },
3876
+ ...defaultExec != null ? {
3877
+ exec: defaultExec,
3878
+ dependencyRegistry: defaultExec.dependencyRegistry
3879
+ } : {}
3880
+ },
3881
+ consumed: defaultResult.consumed
3882
+ };
3883
+ }
3884
+ }
3885
+ const annotatedDiscriminatorState$1 = getAnnotatedChildState(state, discriminatorResult.next.state, discriminator);
3886
+ const mergedExec = mergeChildExec(context.exec, discriminatorResult.next.exec);
3887
+ return {
3888
+ success: true,
3889
+ provisional: true,
3890
+ next: {
3891
+ ...context,
3892
+ state: {
3893
+ ...state,
3894
+ discriminatorState: annotatedDiscriminatorState$1
3895
+ },
3896
+ ...mergedExec != null ? {
3897
+ exec: mergedExec,
3898
+ dependencyRegistry: mergedExec.dependencyRegistry
3899
+ } : {}
3900
+ },
3901
+ consumed: []
3902
+ };
3903
+ }
3633
3904
  const annotatedDiscriminatorState = getAnnotatedChildState(state, discriminatorResult.next.state, discriminator);
3634
3905
  const completionResult = await discriminator.complete(annotatedDiscriminatorState, withChildExecPath(context.exec, "_discriminator"));
3635
3906
  if (completionResult.success) {
@@ -3652,6 +3923,7 @@ function conditional(discriminator, branches, defaultBranch, options) {
3652
3923
  const mergedExec = mergeChildExec(discriminatorExec, branchParseResult.next.exec);
3653
3924
  return {
3654
3925
  success: true,
3926
+ ...branchParseResult.provisional || discriminatorResult.consumed.length === 0 && branchParseResult.consumed.length === 0 && branchParser.leadingNames.size > 0 ? { provisional: true } : {},
3655
3927
  next: {
3656
3928
  ...branchParseResult.next,
3657
3929
  state: {
@@ -3671,7 +3943,7 @@ function conditional(discriminator, branches, defaultBranch, options) {
3671
3943
  consumed: [...discriminatorResult.consumed, ...branchParseResult.consumed]
3672
3944
  };
3673
3945
  }
3674
- return {
3946
+ if (discriminatorResult.consumed.length > 0) return {
3675
3947
  success: true,
3676
3948
  next: {
3677
3949
  ...discriminatorResult.next,
@@ -3691,20 +3963,24 @@ function conditional(discriminator, branches, defaultBranch, options) {
3691
3963
  },
3692
3964
  consumed: discriminatorResult.consumed
3693
3965
  };
3966
+ return branchParseResult;
3694
3967
  }
3695
3968
  }
3696
3969
  }
3970
+ const discriminatorConsumed = discriminatorResult.success ? discriminatorResult.consumed.length : discriminatorResult.consumed;
3697
3971
  if (defaultBranch !== void 0) {
3698
3972
  const defaultResult = await defaultBranch.parse(withChildContext(context, "_branch", state.branchState ?? defaultBranch.initialState, defaultBranch, defaultBranch.usage));
3699
- if (defaultResult.success && defaultResult.consumed.length > 0) {
3973
+ if (defaultResult.success && (defaultResult.consumed.length > 0 || discriminatorConsumed === 0 && context.buffer.length === 0)) {
3700
3974
  const mergedExec = mergeChildExec(context.exec, defaultResult.next.exec);
3975
+ const commitDefault = defaultResult.consumed.length > 0 || context.buffer.length === 0;
3701
3976
  return {
3702
3977
  success: true,
3978
+ ...defaultResult.provisional ? { provisional: true } : {},
3703
3979
  next: {
3704
3980
  ...defaultResult.next,
3705
3981
  state: {
3706
3982
  ...state,
3707
- selectedBranch: { kind: "default" },
3983
+ ...commitDefault ? { selectedBranch: { kind: "default" } } : {},
3708
3984
  branchState: getAnnotatedChildState(state, defaultResult.next.state, defaultBranch)
3709
3985
  },
3710
3986
  ...mergedExec != null ? {
@@ -3727,6 +4003,46 @@ function conditional(discriminator, branches, defaultBranch, options) {
3727
4003
  const syncDefaultBranch = defaultBranch;
3728
4004
  const syncBranches = branches;
3729
4005
  if (state.selectedBranch === void 0) {
4006
+ {
4007
+ const annotatedDiscriminatorStateForDeferred = getAnnotatedChildState(state, state.discriminatorState, syncDiscriminator);
4008
+ const deferredDiscriminatorResult = unwrapCompleteResult(syncDiscriminator.complete(annotatedDiscriminatorStateForDeferred, withChildExecPath(exec, "_discriminator")));
4009
+ if (deferredDiscriminatorResult.success) {
4010
+ const deferredValue = deferredDiscriminatorResult.value;
4011
+ const deferredBranch = syncBranches[deferredValue];
4012
+ if (deferredBranch) {
4013
+ const emptyCtx = {
4014
+ buffer: [],
4015
+ optionsTerminated: false,
4016
+ usage: []
4017
+ };
4018
+ const annotatedInitial = getAnnotatedChildState(state, deferredBranch.initialState, deferredBranch);
4019
+ const replayResult = deferredBranch.parse({
4020
+ ...emptyCtx,
4021
+ state: annotatedInitial
4022
+ });
4023
+ const branchState = replayResult.success ? replayResult.next.state : annotatedInitial;
4024
+ const annotatedBranchState = getAnnotatedChildState(state, branchState, deferredBranch);
4025
+ const branchResult$1 = unwrapCompleteResult(deferredBranch.complete(annotatedBranchState, withChildExecPath(exec, "_branch")));
4026
+ if (branchResult$1.success) return {
4027
+ success: true,
4028
+ value: [deferredValue, branchResult$1.value],
4029
+ ...branchResult$1.deferred ? {
4030
+ deferred: true,
4031
+ ...branchResult$1.deferredKeys ? { deferredKeys: new Map([[1, branchResult$1.deferredKeys]]) } : branchResult$1.value == null || typeof branchResult$1.value !== "object" ? { deferredKeys: new Map([[1, null]]) } : {}
4032
+ } : {}
4033
+ };
4034
+ if (options?.errors?.branchError) return {
4035
+ success: false,
4036
+ error: options.errors.branchError(deferredValue, branchResult$1.error)
4037
+ };
4038
+ return branchResult$1;
4039
+ }
4040
+ if (syncDefaultBranch === void 0) return {
4041
+ success: false,
4042
+ error: getNoMatchError$1()
4043
+ };
4044
+ } else if (syncDefaultBranch === void 0) return deferredDiscriminatorResult;
4045
+ }
3730
4046
  if (syncDefaultBranch !== void 0) {
3731
4047
  const branchState = getAnnotatedChildState(state, state.branchState ?? syncDefaultBranch.initialState, syncDefaultBranch);
3732
4048
  const defaultResult = unwrapCompleteResult(syncDefaultBranch.complete(branchState, withChildExecPath(exec, "_branch")));
@@ -3765,7 +4081,8 @@ function conditional(discriminator, branches, defaultBranch, options) {
3765
4081
  dependencyRuntime: runtime,
3766
4082
  dependencyRegistry: runtime.registry
3767
4083
  };
3768
- const discriminatorCompleteResult = state.selectedBranch.kind === "default" ? void 0 : syncDiscriminator.complete(annotatedDiscriminatorState, withChildExecPath(completionExec, "_discriminator"));
4084
+ const needsDiscriminatorCompletion = state.selectedBranch.kind !== "default" && !(state.discriminatorValue != null && state.discriminatorValue === state.selectedBranch.key);
4085
+ const discriminatorCompleteResult = needsDiscriminatorCompletion ? syncDiscriminator.complete(annotatedDiscriminatorState, withChildExecPath(completionExec, "_discriminator")) : void 0;
3769
4086
  const branchResult = unwrapCompleteResult(branchParser.complete(resolvedBranchState, withChildExecPath(completionExec, "_branch")));
3770
4087
  if (!branchResult.success) {
3771
4088
  if (state.discriminatorValue !== void 0 && options?.errors?.branchError) return {
@@ -3776,6 +4093,7 @@ function conditional(discriminator, branches, defaultBranch, options) {
3776
4093
  }
3777
4094
  let discriminatorValue;
3778
4095
  if (state.selectedBranch.kind === "default") discriminatorValue = void 0;
4096
+ else if (state.discriminatorValue != null && state.discriminatorValue === state.selectedBranch.key) discriminatorValue = state.discriminatorValue;
3779
4097
  else {
3780
4098
  const completedDiscriminator = unwrapCompleteResult(discriminatorCompleteResult);
3781
4099
  discriminatorValue = completedDiscriminator.success ? completedDiscriminator.value : state.selectedBranch.key;
@@ -3791,6 +4109,46 @@ function conditional(discriminator, branches, defaultBranch, options) {
3791
4109
  };
3792
4110
  const completeAsync = async (state, exec) => {
3793
4111
  if (state.selectedBranch === void 0) {
4112
+ if (exec?.phase !== "parse" && exec?.phase !== "suggest") {
4113
+ const annotatedDiscriminatorStateForDeferred = getAnnotatedChildState(state, state.discriminatorState, discriminator);
4114
+ const deferredDiscriminatorResult = unwrapCompleteResult(await discriminator.complete(annotatedDiscriminatorStateForDeferred, withChildExecPath(exec, "_discriminator")));
4115
+ if (deferredDiscriminatorResult.success) {
4116
+ const deferredValue = deferredDiscriminatorResult.value;
4117
+ const deferredBranch = branches[deferredValue];
4118
+ if (deferredBranch) {
4119
+ const emptyCtx = {
4120
+ buffer: [],
4121
+ optionsTerminated: false,
4122
+ usage: []
4123
+ };
4124
+ const annotatedInitial = getAnnotatedChildState(state, deferredBranch.initialState, deferredBranch);
4125
+ const replayResult = await deferredBranch.parse({
4126
+ ...emptyCtx,
4127
+ state: annotatedInitial
4128
+ });
4129
+ const branchState = replayResult.success ? replayResult.next.state : annotatedInitial;
4130
+ const annotatedBranchState = getAnnotatedChildState(state, branchState, deferredBranch);
4131
+ const branchResult$1 = unwrapCompleteResult(await deferredBranch.complete(annotatedBranchState, withChildExecPath(exec, "_branch")));
4132
+ if (branchResult$1.success) return {
4133
+ success: true,
4134
+ value: [deferredValue, branchResult$1.value],
4135
+ ...branchResult$1.deferred ? {
4136
+ deferred: true,
4137
+ ...branchResult$1.deferredKeys ? { deferredKeys: new Map([[1, branchResult$1.deferredKeys]]) } : branchResult$1.value == null || typeof branchResult$1.value !== "object" ? { deferredKeys: new Map([[1, null]]) } : {}
4138
+ } : {}
4139
+ };
4140
+ if (options?.errors?.branchError) return {
4141
+ success: false,
4142
+ error: options.errors.branchError(deferredValue, branchResult$1.error)
4143
+ };
4144
+ return branchResult$1;
4145
+ }
4146
+ if (defaultBranch === void 0) return {
4147
+ success: false,
4148
+ error: getNoMatchError$1()
4149
+ };
4150
+ } else if (defaultBranch === void 0) return deferredDiscriminatorResult;
4151
+ }
3794
4152
  if (defaultBranch !== void 0) {
3795
4153
  const branchState = getAnnotatedChildState(state, state.branchState ?? defaultBranch.initialState, defaultBranch);
3796
4154
  const defaultResult = unwrapCompleteResult(await defaultBranch.complete(branchState, withChildExecPath(exec, "_branch")));
@@ -3829,7 +4187,8 @@ function conditional(discriminator, branches, defaultBranch, options) {
3829
4187
  dependencyRuntime: runtime,
3830
4188
  dependencyRegistry: runtime.registry
3831
4189
  };
3832
- const discriminatorCompleteResult = state.selectedBranch.kind === "default" ? void 0 : await discriminator.complete(annotatedDiscriminatorState, withChildExecPath(completionExec, "_discriminator"));
4190
+ const needsDiscriminatorCompletion = state.selectedBranch.kind !== "default" && !(state.discriminatorValue != null && state.discriminatorValue === state.selectedBranch.key);
4191
+ const discriminatorCompleteResult = needsDiscriminatorCompletion ? await discriminator.complete(annotatedDiscriminatorState, withChildExecPath(completionExec, "_discriminator")) : void 0;
3833
4192
  const branchResult = unwrapCompleteResult(await branchParser.complete(resolvedBranchState, withChildExecPath(completionExec, "_branch")));
3834
4193
  if (!branchResult.success) {
3835
4194
  if (state.discriminatorValue !== void 0 && options?.errors?.branchError) return {
@@ -3840,6 +4199,7 @@ function conditional(discriminator, branches, defaultBranch, options) {
3840
4199
  }
3841
4200
  let discriminatorValue;
3842
4201
  if (state.selectedBranch.kind === "default") discriminatorValue = void 0;
4202
+ else if (state.discriminatorValue != null && state.discriminatorValue === state.selectedBranch.key) discriminatorValue = state.discriminatorValue;
3843
4203
  else {
3844
4204
  const completedDiscriminator = unwrapCompleteResult(discriminatorCompleteResult);
3845
4205
  discriminatorValue = completedDiscriminator.success ? completedDiscriminator.value : state.selectedBranch.key;
@@ -3877,7 +4237,15 @@ function conditional(discriminator, branches, defaultBranch, options) {
3877
4237
  } } : {}
3878
4238
  };
3879
4239
  yield* syncDiscriminator.suggest(withChildContext(suggestContext, "_discriminator", state.discriminatorState, syncDiscriminator), prefix);
3880
- if (syncDefaultBranch !== void 0) yield* syncDefaultBranch.suggest(withChildContext(suggestContext, "_branch", state.branchState ?? syncDefaultBranch.initialState, syncDefaultBranch), prefix);
4240
+ const annotatedDiscState = getAnnotatedChildState(state, state.discriminatorState, syncDiscriminator);
4241
+ const discComplete = syncDiscriminator.complete(annotatedDiscState, withChildExecPath(suggestContext.exec ? {
4242
+ ...suggestContext.exec,
4243
+ phase: "suggest"
4244
+ } : void 0, "_discriminator"));
4245
+ if (discComplete.success && syncBranches[discComplete.value] !== void 0) {
4246
+ const resolvedBranch = syncBranches[discComplete.value];
4247
+ yield* resolvedBranch.suggest(withChildContext(suggestContext, "_branch", state.branchState ?? resolvedBranch.initialState, resolvedBranch), prefix);
4248
+ } else if (syncDefaultBranch !== void 0) yield* syncDefaultBranch.suggest(withChildContext(suggestContext, "_branch", state.branchState ?? syncDefaultBranch.initialState, syncDefaultBranch), prefix);
3881
4249
  } else {
3882
4250
  const branchParser = state.selectedBranch.kind === "default" ? syncDefaultBranch : syncBranches[state.selectedBranch.key];
3883
4251
  const runtime = require_dependency_runtime.createDependencyRuntimeContext(context.dependencyRegistry?.clone());
@@ -3921,7 +4289,22 @@ function conditional(discriminator, branches, defaultBranch, options) {
3921
4289
  } } : {}
3922
4290
  };
3923
4291
  yield* discriminator.suggest(withChildContext(suggestContext, "_discriminator", state.discriminatorState, discriminator), prefix);
3924
- if (defaultBranch !== void 0) yield* defaultBranch.suggest(withChildContext(suggestContext, "_branch", state.branchState ?? defaultBranch.initialState, defaultBranch), prefix);
4292
+ let discResolved = false;
4293
+ if (discriminator.$mode === "sync") {
4294
+ const annotatedDiscState = getAnnotatedChildState(state, state.discriminatorState, discriminator);
4295
+ const discComplete = discriminator.complete(annotatedDiscState, withChildExecPath(suggestContext.exec ? {
4296
+ ...suggestContext.exec,
4297
+ phase: "suggest"
4298
+ } : void 0, "_discriminator"));
4299
+ if (discComplete.success && branches[discComplete.value] !== void 0) {
4300
+ const resolvedBranch = branches[discComplete.value];
4301
+ yield* resolvedBranch.suggest(withChildContext(suggestContext, "_branch", state.branchState ?? resolvedBranch.initialState, resolvedBranch), prefix);
4302
+ discResolved = true;
4303
+ }
4304
+ }
4305
+ if (!discResolved) {
4306
+ if (defaultBranch !== void 0) yield* defaultBranch.suggest(withChildContext(suggestContext, "_branch", state.branchState ?? defaultBranch.initialState, defaultBranch), prefix);
4307
+ }
3925
4308
  } else {
3926
4309
  const branchParser = state.selectedBranch.kind === "default" ? defaultBranch : branches[state.selectedBranch.key];
3927
4310
  const runtime = require_dependency_runtime.createDependencyRuntimeContext(context.dependencyRegistry?.clone());