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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -6,6 +6,7 @@ const require_internal_parser = require('./internal/parser.cjs');
6
6
  const require_annotation_state = require('./annotation-state.cjs');
7
7
  const require_execution_context = require('./execution-context.cjs');
8
8
  const require_short_option = require('./short-option.cjs');
9
+ const require_passthrough = require('./internal/passthrough.cjs');
9
10
  const require_phase2_seed = require('./phase2-seed.cjs');
10
11
  const require_dependency_metadata = require('./dependency-metadata.cjs');
11
12
 
@@ -479,6 +480,11 @@ function optional(parser) {
479
480
  require_internal_parser.defineParseLanes(optionalParser, adaptOptionalStyleParseLanes(parser));
480
481
  require_internal_parser.defineInheritedAnnotationParser(optionalParser);
481
482
  require_internal_parser.defineSourceBindingOnlyAnnotationCompletionParser(optionalParser);
483
+ require_passthrough.defineReachableChildren(optionalParser, [parser], (state) => [{
484
+ parser,
485
+ state: deriveOptionalInnerParseState(state, parser)
486
+ }]);
487
+ require_passthrough.defineKnownCompletionLookup(optionalParser, (state) => require_passthrough.getKnownCompletion(parser, deriveOptionalInnerParseState(state, parser)));
482
488
  return fluent(require_short_option.scopeParser(optionalParser, require_short_option.combinedOptionScope([parser])));
483
489
  }
484
490
  /**
@@ -730,6 +736,11 @@ function withDefault(parser, defaultValue, options) {
730
736
  require_internal_parser.defineParseLanes(withDefaultParser, adaptOptionalStyleParseLanes(parser));
731
737
  require_internal_parser.defineInheritedAnnotationParser(withDefaultParser);
732
738
  require_internal_parser.defineSourceBindingOnlyAnnotationCompletionParser(withDefaultParser);
739
+ require_passthrough.defineReachableChildren(withDefaultParser, [parser], (state) => [{
740
+ parser,
741
+ state: deriveOptionalInnerParseState(state, parser)
742
+ }]);
743
+ require_passthrough.defineKnownCompletionLookup(withDefaultParser, (state) => require_passthrough.getKnownCompletion(parser, deriveOptionalInnerParseState(state, parser)));
733
744
  return fluent(require_short_option.scopeParser(withDefaultParser, require_short_option.combinedOptionScope([parser])));
734
745
  }
735
746
  /**
@@ -1188,12 +1199,28 @@ function multiple(parser, options = {}) {
1188
1199
  parser,
1189
1200
  state
1190
1201
  }] : []);
1202
+ const selectItems = (state) => {
1203
+ const current = state.at(-1);
1204
+ return [...current != null && !isTerminalMultipleItemState(current) ? [{
1205
+ parser,
1206
+ state: current,
1207
+ index: state.length - 1,
1208
+ fresh: false
1209
+ }] : [], ...state.length < max ? [{
1210
+ parser,
1211
+ state: parser.initialState,
1212
+ index: state.length,
1213
+ fresh: true
1214
+ }] : []];
1215
+ };
1191
1216
  const canExtendMultipleItem = (state, itemIndex, exec) => state != null && !isTerminalMultipleItemState(state) && (isMatchedCommandParserState(parser, state) || parser.canSkip?.(state, require_execution_context.withChildExecPath(exec, itemIndex)) !== true);
1192
1217
  const parseSync = (context) => {
1193
- const currentItemState = context.state.at(-1);
1194
- const currentItemIndex = context.state.length - 1;
1195
- const canExtendCurrent = canExtendMultipleItem(currentItemState, currentItemIndex, context.exec);
1196
- const canOpenFreshItem = context.state.length < max;
1218
+ const items = selectItems(context.state);
1219
+ const current = items.find((item) => !item.fresh);
1220
+ const fresh = items.find((item) => item.fresh);
1221
+ const currentItemState = current?.state;
1222
+ const canExtendCurrent = current != null && canExtendMultipleItem(current.state, current.index, context.exec);
1223
+ const canOpenFreshItem = fresh != null;
1197
1224
  if (!canExtendCurrent && !canOpenFreshItem) return {
1198
1225
  success: true,
1199
1226
  next: context,
@@ -1201,7 +1228,7 @@ function multiple(parser, options = {}) {
1201
1228
  };
1202
1229
  let added = !canExtendCurrent;
1203
1230
  let itemIndex = canExtendCurrent ? context.state.length - 1 : context.state.length;
1204
- const currentItemStateWithAnnotations = canExtendCurrent ? currentItemState : require_internal_annotations.inheritAnnotations(context.state, syncParser.initialState);
1231
+ const currentItemStateWithAnnotations = canExtendCurrent ? currentItemState : require_internal_annotations.inheritAnnotations(context.state, fresh?.state ?? parser.initialState);
1205
1232
  let result = parseSyncWithUnwrappedFallback(require_execution_context.withChildContext(context, itemIndex, currentItemStateWithAnnotations));
1206
1233
  if (!result.success) {
1207
1234
  if (result.consumed !== 0) return result;
@@ -1271,10 +1298,12 @@ function multiple(parser, options = {}) {
1271
1298
  };
1272
1299
  };
1273
1300
  const parseAsync = async (context) => {
1274
- const currentItemState = context.state.at(-1);
1275
- const currentItemIndex = context.state.length - 1;
1276
- const canExtendCurrent = canExtendMultipleItem(currentItemState, currentItemIndex, context.exec);
1277
- const canOpenFreshItem = context.state.length < max;
1301
+ const items = selectItems(context.state);
1302
+ const current = items.find((item) => !item.fresh);
1303
+ const fresh = items.find((item) => item.fresh);
1304
+ const currentItemState = current?.state;
1305
+ const canExtendCurrent = current != null && canExtendMultipleItem(current.state, current.index, context.exec);
1306
+ const canOpenFreshItem = fresh != null;
1278
1307
  if (!canExtendCurrent && !canOpenFreshItem) return {
1279
1308
  success: true,
1280
1309
  next: context,
@@ -1282,7 +1311,7 @@ function multiple(parser, options = {}) {
1282
1311
  };
1283
1312
  let added = !canExtendCurrent;
1284
1313
  let itemIndex = canExtendCurrent ? context.state.length - 1 : context.state.length;
1285
- const currentItemStateWithAnnotations = canExtendCurrent ? currentItemState : require_internal_annotations.inheritAnnotations(context.state, parser.initialState);
1314
+ const currentItemStateWithAnnotations = canExtendCurrent ? currentItemState : require_internal_annotations.inheritAnnotations(context.state, fresh?.state ?? parser.initialState);
1286
1315
  let result = await parseAsyncWithUnwrappedFallback(require_execution_context.withChildContext(context, itemIndex, currentItemStateWithAnnotations));
1287
1316
  if (!result.success) {
1288
1317
  if (result.consumed !== 0) return result;
@@ -1715,6 +1744,10 @@ function multiple(parser, options = {}) {
1715
1744
  enumerable: false
1716
1745
  });
1717
1746
  }
1747
+ require_passthrough.defineReachableChildren(resultParser, [parser], (state) => selectItems(state).map((item) => ({
1748
+ parser,
1749
+ state: unwrapInjectedWrapper(item.state)
1750
+ })));
1718
1751
  return fluent(require_short_option.scopeParser(resultParser, require_short_option.repeatedOptionScope(parser)));
1719
1752
  }
1720
1753
  /**
@@ -1851,6 +1884,10 @@ function nonEmpty(parser) {
1851
1884
  enumerable: false
1852
1885
  });
1853
1886
  require_dependency_runtime.defineForwardedEffectfulSchedulingNodes(nonEmptyParser, parser);
1887
+ require_passthrough.defineReachableChildren(nonEmptyParser, [parser], (state) => [{
1888
+ parser,
1889
+ state
1890
+ }]);
1854
1891
  return fluent(require_short_option.scopeParser(nonEmptyParser, require_short_option.combinedOptionScope([parser])));
1855
1892
  }
1856
1893
  const fluentParserMarker = Symbol.for("@optique/core/fluent");
package/dist/modifiers.js CHANGED
@@ -6,6 +6,7 @@ import { defineInheritedAnnotationParser, defineParseLanes, defineSourceBindingO
6
6
  import { getDelegatedAnnotationState, hasDelegatedAnnotationCarrier, isAnnotationWrappedInitialState, normalizeDelegatedAnnotationState, normalizeNestedDelegatedAnnotationState } from "./annotation-state.js";
7
7
  import { mergeChildExec, withChildContext, withChildExecPath } from "./execution-context.js";
8
8
  import { combinedOptionScope, repeatedOptionScope, scopeParser } from "./short-option.js";
9
+ import { defineKnownCompletionLookup, defineReachableChildren, getKnownCompletion } from "./internal/passthrough.js";
9
10
  import { completeOrExtractPhase2Seed, extractPhase2Seed, extractPhase2SeedKey, phase2SeedFromValueResult } from "./phase2-seed.js";
10
11
  import { composeDependencyMetadata } from "./dependency-metadata.js";
11
12
 
@@ -479,6 +480,11 @@ function optional(parser) {
479
480
  defineParseLanes(optionalParser, adaptOptionalStyleParseLanes(parser));
480
481
  defineInheritedAnnotationParser(optionalParser);
481
482
  defineSourceBindingOnlyAnnotationCompletionParser(optionalParser);
483
+ defineReachableChildren(optionalParser, [parser], (state) => [{
484
+ parser,
485
+ state: deriveOptionalInnerParseState(state, parser)
486
+ }]);
487
+ defineKnownCompletionLookup(optionalParser, (state) => getKnownCompletion(parser, deriveOptionalInnerParseState(state, parser)));
482
488
  return fluent(scopeParser(optionalParser, combinedOptionScope([parser])));
483
489
  }
484
490
  /**
@@ -730,6 +736,11 @@ function withDefault(parser, defaultValue, options) {
730
736
  defineParseLanes(withDefaultParser, adaptOptionalStyleParseLanes(parser));
731
737
  defineInheritedAnnotationParser(withDefaultParser);
732
738
  defineSourceBindingOnlyAnnotationCompletionParser(withDefaultParser);
739
+ defineReachableChildren(withDefaultParser, [parser], (state) => [{
740
+ parser,
741
+ state: deriveOptionalInnerParseState(state, parser)
742
+ }]);
743
+ defineKnownCompletionLookup(withDefaultParser, (state) => getKnownCompletion(parser, deriveOptionalInnerParseState(state, parser)));
733
744
  return fluent(scopeParser(withDefaultParser, combinedOptionScope([parser])));
734
745
  }
735
746
  /**
@@ -1188,12 +1199,28 @@ function multiple(parser, options = {}) {
1188
1199
  parser,
1189
1200
  state
1190
1201
  }] : []);
1202
+ const selectItems = (state) => {
1203
+ const current = state.at(-1);
1204
+ return [...current != null && !isTerminalMultipleItemState(current) ? [{
1205
+ parser,
1206
+ state: current,
1207
+ index: state.length - 1,
1208
+ fresh: false
1209
+ }] : [], ...state.length < max ? [{
1210
+ parser,
1211
+ state: parser.initialState,
1212
+ index: state.length,
1213
+ fresh: true
1214
+ }] : []];
1215
+ };
1191
1216
  const canExtendMultipleItem = (state, itemIndex, exec) => state != null && !isTerminalMultipleItemState(state) && (isMatchedCommandParserState(parser, state) || parser.canSkip?.(state, withChildExecPath(exec, itemIndex)) !== true);
1192
1217
  const parseSync = (context) => {
1193
- const currentItemState = context.state.at(-1);
1194
- const currentItemIndex = context.state.length - 1;
1195
- const canExtendCurrent = canExtendMultipleItem(currentItemState, currentItemIndex, context.exec);
1196
- const canOpenFreshItem = context.state.length < max;
1218
+ const items = selectItems(context.state);
1219
+ const current = items.find((item) => !item.fresh);
1220
+ const fresh = items.find((item) => item.fresh);
1221
+ const currentItemState = current?.state;
1222
+ const canExtendCurrent = current != null && canExtendMultipleItem(current.state, current.index, context.exec);
1223
+ const canOpenFreshItem = fresh != null;
1197
1224
  if (!canExtendCurrent && !canOpenFreshItem) return {
1198
1225
  success: true,
1199
1226
  next: context,
@@ -1201,7 +1228,7 @@ function multiple(parser, options = {}) {
1201
1228
  };
1202
1229
  let added = !canExtendCurrent;
1203
1230
  let itemIndex = canExtendCurrent ? context.state.length - 1 : context.state.length;
1204
- const currentItemStateWithAnnotations = canExtendCurrent ? currentItemState : inheritAnnotations(context.state, syncParser.initialState);
1231
+ const currentItemStateWithAnnotations = canExtendCurrent ? currentItemState : inheritAnnotations(context.state, fresh?.state ?? parser.initialState);
1205
1232
  let result = parseSyncWithUnwrappedFallback(withChildContext(context, itemIndex, currentItemStateWithAnnotations));
1206
1233
  if (!result.success) {
1207
1234
  if (result.consumed !== 0) return result;
@@ -1271,10 +1298,12 @@ function multiple(parser, options = {}) {
1271
1298
  };
1272
1299
  };
1273
1300
  const parseAsync = async (context) => {
1274
- const currentItemState = context.state.at(-1);
1275
- const currentItemIndex = context.state.length - 1;
1276
- const canExtendCurrent = canExtendMultipleItem(currentItemState, currentItemIndex, context.exec);
1277
- const canOpenFreshItem = context.state.length < max;
1301
+ const items = selectItems(context.state);
1302
+ const current = items.find((item) => !item.fresh);
1303
+ const fresh = items.find((item) => item.fresh);
1304
+ const currentItemState = current?.state;
1305
+ const canExtendCurrent = current != null && canExtendMultipleItem(current.state, current.index, context.exec);
1306
+ const canOpenFreshItem = fresh != null;
1278
1307
  if (!canExtendCurrent && !canOpenFreshItem) return {
1279
1308
  success: true,
1280
1309
  next: context,
@@ -1282,7 +1311,7 @@ function multiple(parser, options = {}) {
1282
1311
  };
1283
1312
  let added = !canExtendCurrent;
1284
1313
  let itemIndex = canExtendCurrent ? context.state.length - 1 : context.state.length;
1285
- const currentItemStateWithAnnotations = canExtendCurrent ? currentItemState : inheritAnnotations(context.state, parser.initialState);
1314
+ const currentItemStateWithAnnotations = canExtendCurrent ? currentItemState : inheritAnnotations(context.state, fresh?.state ?? parser.initialState);
1286
1315
  let result = await parseAsyncWithUnwrappedFallback(withChildContext(context, itemIndex, currentItemStateWithAnnotations));
1287
1316
  if (!result.success) {
1288
1317
  if (result.consumed !== 0) return result;
@@ -1715,6 +1744,10 @@ function multiple(parser, options = {}) {
1715
1744
  enumerable: false
1716
1745
  });
1717
1746
  }
1747
+ defineReachableChildren(resultParser, [parser], (state) => selectItems(state).map((item) => ({
1748
+ parser,
1749
+ state: unwrapInjectedWrapper(item.state)
1750
+ })));
1718
1751
  return fluent(scopeParser(resultParser, repeatedOptionScope(parser)));
1719
1752
  }
1720
1753
  /**
@@ -1851,6 +1884,10 @@ function nonEmpty(parser) {
1851
1884
  enumerable: false
1852
1885
  });
1853
1886
  defineForwardedEffectfulSchedulingNodes(nonEmptyParser, parser);
1887
+ defineReachableChildren(nonEmptyParser, [parser], (state) => [{
1888
+ parser,
1889
+ state
1890
+ }]);
1854
1891
  return fluent(scopeParser(nonEmptyParser, combinedOptionScope([parser])));
1855
1892
  }
1856
1893
  const fluentParserMarker = Symbol.for("@optique/core/fluent");
@@ -9,6 +9,7 @@ const require_annotation_state = require('./annotation-state.cjs');
9
9
  const require_execution_context = require('./execution-context.cjs');
10
10
  const require_usage_internals = require('./usage-internals.cjs');
11
11
  const require_short_option = require('./short-option.cjs');
12
+ const require_passthrough = require('./internal/passthrough.cjs');
12
13
  const require_command_alias = require('./internal/command-alias.cjs');
13
14
  const require_phase2_seed = require('./phase2-seed.cjs');
14
15
  const require_dependency_metadata = require('./dependency-metadata.cjs');
@@ -155,6 +156,7 @@ function constant(value) {
155
156
  };
156
157
  }
157
158
  };
159
+ require_passthrough.defineKnownCompletion(result, (state) => require_annotation_state.normalizeInjectedAnnotationState(state));
158
160
  Object.defineProperty(result, "placeholder", {
159
161
  value,
160
162
  configurable: true,
@@ -633,10 +635,15 @@ function option(...args) {
633
635
  }
634
636
  const invalidOption = context.buffer[0];
635
637
  if (options.errors?.noMatch) {
638
+ if (typeof options.errors.noMatch !== "function") return {
639
+ success: false,
640
+ consumed: 0,
641
+ error: options.errors.noMatch
642
+ };
636
643
  const candidates = /* @__PURE__ */ new Set();
637
644
  for (const name of require_usage.extractOptionNames(context.usage)) candidates.add(name);
638
645
  const suggestions = require_suggestion.findSimilar(invalidOption, candidates, require_suggestion.DEFAULT_FIND_SIMILAR_OPTIONS);
639
- const errorMessage = typeof options.errors.noMatch === "function" ? options.errors.noMatch(invalidOption, suggestions) : options.errors.noMatch;
646
+ const errorMessage = options.errors.noMatch(invalidOption, suggestions);
640
647
  return {
641
648
  success: false,
642
649
  consumed: 0,
@@ -922,10 +929,15 @@ function flag(...args) {
922
929
  }
923
930
  const invalidOption = context.buffer[0];
924
931
  if (options.errors?.noMatch) {
932
+ if (typeof options.errors.noMatch !== "function") return {
933
+ success: false,
934
+ consumed: 0,
935
+ error: options.errors.noMatch
936
+ };
925
937
  const candidates = /* @__PURE__ */ new Set();
926
938
  for (const name of require_usage.extractOptionNames(context.usage)) candidates.add(name);
927
939
  const suggestions = require_suggestion.findSimilar(invalidOption, candidates, require_suggestion.DEFAULT_FIND_SIMILAR_OPTIONS);
928
- const errorMessage = typeof options.errors.noMatch === "function" ? options.errors.noMatch(invalidOption, suggestions) : options.errors.noMatch;
940
+ const errorMessage = options.errors.noMatch(invalidOption, suggestions);
929
941
  return {
930
942
  success: false,
931
943
  consumed: 0,
@@ -1234,7 +1246,7 @@ function argument(valueParser, options = {}) {
1234
1246
  const syncValueParser = valueParser;
1235
1247
  const dependencyMetadata = require_dependency_metadata.extractDependencyMetadata(valueParser);
1236
1248
  const formatInvalidValueError = (error) => options.errors?.invalidValue ? typeof options.errors.invalidValue === "function" ? options.errors.invalidValue(error) : options.errors.invalidValue : require_message.message`${require_message.metavar(valueParser.metavar)}: ${error}`;
1237
- const optionPattern = /^--?[a-z0-9-]+$/i;
1249
+ const optionPattern = /^(?!--=)(--?[a-z0-9-]+)(?:=|$)/i;
1238
1250
  const term = {
1239
1251
  type: "argument",
1240
1252
  metavar: valueParser.metavar,
@@ -1261,14 +1273,15 @@ function argument(valueParser, options = {}) {
1261
1273
  };
1262
1274
  let i = 0;
1263
1275
  let optionsTerminated = context.optionsTerminated;
1264
- if (!optionsTerminated) {
1265
- if (context.buffer[i] === "--") {
1266
- optionsTerminated = true;
1267
- i++;
1268
- } else if (context.buffer[i].match(optionPattern)) return {
1276
+ if (!optionsTerminated) if (context.buffer[i] === "--") {
1277
+ optionsTerminated = true;
1278
+ i++;
1279
+ } else {
1280
+ const optionMatch = context.buffer[i].match(optionPattern);
1281
+ if (optionMatch != null) return {
1269
1282
  success: false,
1270
1283
  consumed: i,
1271
- error: require_message.message`Expected an argument, but got an option: ${require_message.optionName(context.buffer[i])}.`
1284
+ error: require_message.message`Expected an argument, but got an option: ${require_message.optionName(optionMatch[1])}.`
1272
1285
  };
1273
1286
  }
1274
1287
  if (context.buffer.length < i + 1) return {
@@ -1531,6 +1544,15 @@ function command(name, parser, options = {}) {
1531
1544
  const isAsync = parser.mode === "async";
1532
1545
  const syncInnerParser = parser;
1533
1546
  const asyncInnerParser = parser;
1547
+ const getChildState = (state, active) => getCommandParseChildState(state, active[0] === "matched" ? parser.initialState : active[1], parser);
1548
+ const selectChild = (state) => {
1549
+ const active = normalizeCommandState(state);
1550
+ return active == null ? void 0 : {
1551
+ parser,
1552
+ state: getChildState(state, active),
1553
+ continuesCommand: true
1554
+ };
1555
+ };
1534
1556
  const commandScope = require_short_option.selectableOptionScope(() => /* @__PURE__ */ new Set());
1535
1557
  const enteredScope = require_short_option.combinedOptionScope([parser], [name]);
1536
1558
  const result = {
@@ -1612,7 +1634,7 @@ function command(name, parser, options = {}) {
1612
1634
  consumed: context.buffer.slice(0, 1)
1613
1635
  };
1614
1636
  } else if (state[0] === "matched" || state[0] === "parsing") {
1615
- const innerState = state[0] === "matched" ? getCommandParseChildState(context.state, parser.initialState, parser) : getCommandParseChildState(context.state, state[1], parser);
1637
+ const innerState = getChildState(context.state, state);
1616
1638
  const wrapState = (parseResult) => {
1617
1639
  if (parseResult.success) {
1618
1640
  const mergedExec = require_execution_context.mergeChildExec(context.exec, parseResult.next.exec);
@@ -1781,6 +1803,10 @@ function command(name, parser, options = {}) {
1781
1803
  configurable: true,
1782
1804
  enumerable: false
1783
1805
  });
1806
+ require_passthrough.defineReachableChildren(result, [parser], (state) => {
1807
+ const child = selectChild(state);
1808
+ return child == null ? [] : [child];
1809
+ });
1784
1810
  return require_modifiers.fluent(require_short_option.scopeParser(result, commandScope.source, (context) => {
1785
1811
  if (normalizeCommandState(context.state) != null) commandScope.select(context, enteredScope);
1786
1812
  }));
@@ -1856,6 +1882,8 @@ function passThrough(options = {}) {
1856
1882
  consumed: 0,
1857
1883
  error: require_message.message`No input to pass through.`
1858
1884
  };
1885
+ const failure = require_passthrough.getPassThroughFailure(context, this?.priority ?? -10);
1886
+ if (failure != null) return failure.failure;
1859
1887
  const token = context.buffer[0];
1860
1888
  if (format === "greedy") {
1861
1889
  const captured = [...context.buffer];
@@ -1967,6 +1995,11 @@ function passThrough(options = {}) {
1967
1995
  return `passThrough(${format})`;
1968
1996
  }
1969
1997
  };
1998
+ require_passthrough.definePassThroughPriority(result, [result], (_state, token) => {
1999
+ if (token == null || format === "greedy") return result.priority;
2000
+ const accepts = format === "equalsOnly" ? equalsOptionPattern.test(token) : format === "nextToken" && optionPattern.test(token);
2001
+ return accepts ? result.priority : void 0;
2002
+ });
1970
2003
  return require_modifiers.fluent(result);
1971
2004
  }
1972
2005
 
@@ -9,6 +9,7 @@ import { getWrappedChildParseState, getWrappedChildState, isAnnotationWrappedIni
9
9
  import { mergeChildExec, withChildContext, withChildExecPath } from "./execution-context.js";
10
10
  import { extractLeadingCommandNames } from "./usage-internals.js";
11
11
  import { attachedValuePrefix, combinedOptionScope, fullNameOwnsToken, prefixSuggestion, scopeParser, selectableOptionScope } from "./short-option.js";
12
+ import { defineKnownCompletion, definePassThroughPriority, defineReachableChildren, getPassThroughFailure } from "./internal/passthrough.js";
12
13
  import { hiddenCommandAliasesKey } from "./internal/command-alias.js";
13
14
  import { completeOrExtractPhase2Seed, extractPhase2SeedKey } from "./phase2-seed.js";
14
15
  import { extractDependencyMetadata } from "./dependency-metadata.js";
@@ -155,6 +156,7 @@ function constant(value) {
155
156
  };
156
157
  }
157
158
  };
159
+ defineKnownCompletion(result, (state) => normalizeInjectedAnnotationState(state));
158
160
  Object.defineProperty(result, "placeholder", {
159
161
  value,
160
162
  configurable: true,
@@ -633,10 +635,15 @@ function option(...args) {
633
635
  }
634
636
  const invalidOption = context.buffer[0];
635
637
  if (options.errors?.noMatch) {
638
+ if (typeof options.errors.noMatch !== "function") return {
639
+ success: false,
640
+ consumed: 0,
641
+ error: options.errors.noMatch
642
+ };
636
643
  const candidates = /* @__PURE__ */ new Set();
637
644
  for (const name of extractOptionNames(context.usage)) candidates.add(name);
638
645
  const suggestions = findSimilar(invalidOption, candidates, DEFAULT_FIND_SIMILAR_OPTIONS);
639
- const errorMessage = typeof options.errors.noMatch === "function" ? options.errors.noMatch(invalidOption, suggestions) : options.errors.noMatch;
646
+ const errorMessage = options.errors.noMatch(invalidOption, suggestions);
640
647
  return {
641
648
  success: false,
642
649
  consumed: 0,
@@ -922,10 +929,15 @@ function flag(...args) {
922
929
  }
923
930
  const invalidOption = context.buffer[0];
924
931
  if (options.errors?.noMatch) {
932
+ if (typeof options.errors.noMatch !== "function") return {
933
+ success: false,
934
+ consumed: 0,
935
+ error: options.errors.noMatch
936
+ };
925
937
  const candidates = /* @__PURE__ */ new Set();
926
938
  for (const name of extractOptionNames(context.usage)) candidates.add(name);
927
939
  const suggestions = findSimilar(invalidOption, candidates, DEFAULT_FIND_SIMILAR_OPTIONS);
928
- const errorMessage = typeof options.errors.noMatch === "function" ? options.errors.noMatch(invalidOption, suggestions) : options.errors.noMatch;
940
+ const errorMessage = options.errors.noMatch(invalidOption, suggestions);
929
941
  return {
930
942
  success: false,
931
943
  consumed: 0,
@@ -1234,7 +1246,7 @@ function argument(valueParser, options = {}) {
1234
1246
  const syncValueParser = valueParser;
1235
1247
  const dependencyMetadata = extractDependencyMetadata(valueParser);
1236
1248
  const formatInvalidValueError = (error) => options.errors?.invalidValue ? typeof options.errors.invalidValue === "function" ? options.errors.invalidValue(error) : options.errors.invalidValue : message`${metavar(valueParser.metavar)}: ${error}`;
1237
- const optionPattern = /^--?[a-z0-9-]+$/i;
1249
+ const optionPattern = /^(?!--=)(--?[a-z0-9-]+)(?:=|$)/i;
1238
1250
  const term = {
1239
1251
  type: "argument",
1240
1252
  metavar: valueParser.metavar,
@@ -1261,14 +1273,15 @@ function argument(valueParser, options = {}) {
1261
1273
  };
1262
1274
  let i = 0;
1263
1275
  let optionsTerminated = context.optionsTerminated;
1264
- if (!optionsTerminated) {
1265
- if (context.buffer[i] === "--") {
1266
- optionsTerminated = true;
1267
- i++;
1268
- } else if (context.buffer[i].match(optionPattern)) return {
1276
+ if (!optionsTerminated) if (context.buffer[i] === "--") {
1277
+ optionsTerminated = true;
1278
+ i++;
1279
+ } else {
1280
+ const optionMatch = context.buffer[i].match(optionPattern);
1281
+ if (optionMatch != null) return {
1269
1282
  success: false,
1270
1283
  consumed: i,
1271
- error: message`Expected an argument, but got an option: ${optionName(context.buffer[i])}.`
1284
+ error: message`Expected an argument, but got an option: ${optionName(optionMatch[1])}.`
1272
1285
  };
1273
1286
  }
1274
1287
  if (context.buffer.length < i + 1) return {
@@ -1531,6 +1544,15 @@ function command(name, parser, options = {}) {
1531
1544
  const isAsync = parser.mode === "async";
1532
1545
  const syncInnerParser = parser;
1533
1546
  const asyncInnerParser = parser;
1547
+ const getChildState = (state, active) => getCommandParseChildState(state, active[0] === "matched" ? parser.initialState : active[1], parser);
1548
+ const selectChild = (state) => {
1549
+ const active = normalizeCommandState(state);
1550
+ return active == null ? void 0 : {
1551
+ parser,
1552
+ state: getChildState(state, active),
1553
+ continuesCommand: true
1554
+ };
1555
+ };
1534
1556
  const commandScope = selectableOptionScope(() => /* @__PURE__ */ new Set());
1535
1557
  const enteredScope = combinedOptionScope([parser], [name]);
1536
1558
  const result = {
@@ -1612,7 +1634,7 @@ function command(name, parser, options = {}) {
1612
1634
  consumed: context.buffer.slice(0, 1)
1613
1635
  };
1614
1636
  } else if (state[0] === "matched" || state[0] === "parsing") {
1615
- const innerState = state[0] === "matched" ? getCommandParseChildState(context.state, parser.initialState, parser) : getCommandParseChildState(context.state, state[1], parser);
1637
+ const innerState = getChildState(context.state, state);
1616
1638
  const wrapState = (parseResult) => {
1617
1639
  if (parseResult.success) {
1618
1640
  const mergedExec = mergeChildExec(context.exec, parseResult.next.exec);
@@ -1781,6 +1803,10 @@ function command(name, parser, options = {}) {
1781
1803
  configurable: true,
1782
1804
  enumerable: false
1783
1805
  });
1806
+ defineReachableChildren(result, [parser], (state) => {
1807
+ const child = selectChild(state);
1808
+ return child == null ? [] : [child];
1809
+ });
1784
1810
  return fluent(scopeParser(result, commandScope.source, (context) => {
1785
1811
  if (normalizeCommandState(context.state) != null) commandScope.select(context, enteredScope);
1786
1812
  }));
@@ -1856,6 +1882,8 @@ function passThrough(options = {}) {
1856
1882
  consumed: 0,
1857
1883
  error: message`No input to pass through.`
1858
1884
  };
1885
+ const failure = getPassThroughFailure(context, this?.priority ?? -10);
1886
+ if (failure != null) return failure.failure;
1859
1887
  const token = context.buffer[0];
1860
1888
  if (format === "greedy") {
1861
1889
  const captured = [...context.buffer];
@@ -1967,6 +1995,11 @@ function passThrough(options = {}) {
1967
1995
  return `passThrough(${format})`;
1968
1996
  }
1969
1997
  };
1998
+ definePassThroughPriority(result, [result], (_state, token) => {
1999
+ if (token == null || format === "greedy") return result.priority;
2000
+ const accepts = format === "equalsOnly" ? equalsOptionPattern.test(token) : format === "nextToken" && optionPattern.test(token);
2001
+ return accepts ? result.priority : void 0;
2002
+ });
1970
2003
  return fluent(result);
1971
2004
  }
1972
2005
 
@@ -86,8 +86,10 @@ function findSimilar(input, candidates, options = {}) {
86
86
  const normalizedCandidate = caseSensitive ? candidate : candidate.toLowerCase();
87
87
  if (seen.has(candidate)) continue;
88
88
  seen.add(candidate);
89
+ if (normalizedInput === normalizedCandidate) return [candidate];
90
+ const minimumDistance = Math.abs(normalizedInput.length - normalizedCandidate.length);
91
+ if (minimumDistance > maxDistance || minimumDistance / input.length > maxDistanceRatio) continue;
89
92
  const distance = levenshteinDistance(normalizedInput, normalizedCandidate);
90
- if (distance === 0) return [candidate];
91
93
  const distanceRatio = distance / input.length;
92
94
  if (distance <= maxDistance && distanceRatio <= maxDistanceRatio) matches.push({
93
95
  candidate,
@@ -86,8 +86,10 @@ function findSimilar(input, candidates, options = {}) {
86
86
  const normalizedCandidate = caseSensitive ? candidate : candidate.toLowerCase();
87
87
  if (seen.has(candidate)) continue;
88
88
  seen.add(candidate);
89
+ if (normalizedInput === normalizedCandidate) return [candidate];
90
+ const minimumDistance = Math.abs(normalizedInput.length - normalizedCandidate.length);
91
+ if (minimumDistance > maxDistance || minimumDistance / input.length > maxDistanceRatio) continue;
89
92
  const distance = levenshteinDistance(normalizedInput, normalizedCandidate);
90
- if (distance === 0) return [candidate];
91
93
  const distanceRatio = distance / input.length;
92
94
  if (distance <= maxDistance && distanceRatio <= maxDistanceRatio) matches.push({
93
95
  candidate,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@optique/core",
3
- "version": "1.4.0-dev.2638",
3
+ "version": "1.4.0-dev.2662",
4
4
  "description": "Type-safe combinatorial command-line interface parser",
5
5
  "keywords": [
6
6
  "CLI",
@@ -237,7 +237,7 @@
237
237
  },
238
238
  "sideEffects": false,
239
239
  "devDependencies": {
240
- "@optique/env": "1.4.0-dev.2638+75cb8142",
240
+ "@optique/env": "1.4.0-dev.2662+8add1ff9",
241
241
  "@types/node": "^24.0.0",
242
242
  "fast-check": "^4.7.0",
243
243
  "tsdown": "^0.13.0",