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

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.
@@ -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 {
@@ -1781,6 +1794,22 @@ function command(name, parser, options = {}) {
1781
1794
  configurable: true,
1782
1795
  enumerable: false
1783
1796
  });
1797
+ require_passthrough.definePassThroughPriority(result, [parser], (state, token) => {
1798
+ const active = normalizeCommandState(state);
1799
+ if (active == null) return void 0;
1800
+ const childState = active[0] === "matched" ? parser.initialState : active[1];
1801
+ return require_passthrough.getPassThroughPriority(parser, getCommandParseChildState(state, childState, parser), token);
1802
+ });
1803
+ require_passthrough.defineOptionMatch(result, (state, token) => {
1804
+ const active = normalizeCommandState(state);
1805
+ if (active == null) return void 0;
1806
+ const childState = active[0] === "matched" ? parser.initialState : active[1];
1807
+ const match = require_passthrough.getOptionMatch(parser, getCommandParseChildState(state, childState, parser), token);
1808
+ return match == null ? void 0 : {
1809
+ ...match,
1810
+ continuesCommand: true
1811
+ };
1812
+ });
1784
1813
  return require_modifiers.fluent(require_short_option.scopeParser(result, commandScope.source, (context) => {
1785
1814
  if (normalizeCommandState(context.state) != null) commandScope.select(context, enteredScope);
1786
1815
  }));
@@ -1856,6 +1885,8 @@ function passThrough(options = {}) {
1856
1885
  consumed: 0,
1857
1886
  error: require_message.message`No input to pass through.`
1858
1887
  };
1888
+ const failure = require_passthrough.getPassThroughFailure(context, this?.priority ?? -10);
1889
+ if (failure != null) return failure.failure;
1859
1890
  const token = context.buffer[0];
1860
1891
  if (format === "greedy") {
1861
1892
  const captured = [...context.buffer];
@@ -1967,6 +1998,11 @@ function passThrough(options = {}) {
1967
1998
  return `passThrough(${format})`;
1968
1999
  }
1969
2000
  };
2001
+ require_passthrough.definePassThroughPriority(result, [result], (_state, token) => {
2002
+ if (token == null || format === "greedy") return result.priority;
2003
+ const accepts = format === "equalsOnly" ? equalsOptionPattern.test(token) : format === "nextToken" && optionPattern.test(token);
2004
+ return accepts ? result.priority : void 0;
2005
+ });
1970
2006
  return require_modifiers.fluent(result);
1971
2007
  }
1972
2008
 
@@ -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, defineOptionMatch, definePassThroughPriority, getOptionMatch, getPassThroughFailure, getPassThroughPriority } 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 {
@@ -1781,6 +1794,22 @@ function command(name, parser, options = {}) {
1781
1794
  configurable: true,
1782
1795
  enumerable: false
1783
1796
  });
1797
+ definePassThroughPriority(result, [parser], (state, token) => {
1798
+ const active = normalizeCommandState(state);
1799
+ if (active == null) return void 0;
1800
+ const childState = active[0] === "matched" ? parser.initialState : active[1];
1801
+ return getPassThroughPriority(parser, getCommandParseChildState(state, childState, parser), token);
1802
+ });
1803
+ defineOptionMatch(result, (state, token) => {
1804
+ const active = normalizeCommandState(state);
1805
+ if (active == null) return void 0;
1806
+ const childState = active[0] === "matched" ? parser.initialState : active[1];
1807
+ const match = getOptionMatch(parser, getCommandParseChildState(state, childState, parser), token);
1808
+ return match == null ? void 0 : {
1809
+ ...match,
1810
+ continuesCommand: true
1811
+ };
1812
+ });
1784
1813
  return fluent(scopeParser(result, commandScope.source, (context) => {
1785
1814
  if (normalizeCommandState(context.state) != null) commandScope.select(context, enteredScope);
1786
1815
  }));
@@ -1856,6 +1885,8 @@ function passThrough(options = {}) {
1856
1885
  consumed: 0,
1857
1886
  error: message`No input to pass through.`
1858
1887
  };
1888
+ const failure = getPassThroughFailure(context, this?.priority ?? -10);
1889
+ if (failure != null) return failure.failure;
1859
1890
  const token = context.buffer[0];
1860
1891
  if (format === "greedy") {
1861
1892
  const captured = [...context.buffer];
@@ -1967,6 +1998,11 @@ function passThrough(options = {}) {
1967
1998
  return `passThrough(${format})`;
1968
1999
  }
1969
2000
  };
2001
+ definePassThroughPriority(result, [result], (_state, token) => {
2002
+ if (token == null || format === "greedy") return result.priority;
2003
+ const accepts = format === "equalsOnly" ? equalsOptionPattern.test(token) : format === "nextToken" && optionPattern.test(token);
2004
+ return accepts ? result.priority : void 0;
2005
+ });
1970
2006
  return fluent(result);
1971
2007
  }
1972
2008
 
@@ -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.2661",
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.2661+04e7de36",
241
241
  "@types/node": "^24.0.0",
242
242
  "fast-check": "^4.7.0",
243
243
  "tsdown": "^0.13.0",