@optique/core 1.3.1 → 1.3.3

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.
package/dist/message.cjs CHANGED
@@ -347,7 +347,8 @@ function renderMessage(msg, options, theme, ambient) {
347
347
  yield {
348
348
  text: match[0],
349
349
  width: require_displaywidth.getDisplayWidth(match[0]),
350
- scopes: []
350
+ scopes: [],
351
+ trimOnWrap: true
351
352
  };
352
353
  }
353
354
  }
@@ -356,7 +357,8 @@ function renderMessage(msg, options, theme, ambient) {
356
357
  if (normalizedText.trim() === "" && normalizedText.length > 0) yield {
357
358
  text: " ",
358
359
  width: 1,
359
- scopes: []
360
+ scopes: [],
361
+ trimOnWrap: true
360
362
  };
361
363
  else {
362
364
  wordPattern.lastIndex = 0;
@@ -366,7 +368,8 @@ function renderMessage(msg, options, theme, ambient) {
366
368
  yield {
367
369
  text: match[0],
368
370
  width: require_displaywidth.getDisplayWidth(match[0]),
369
- scopes: []
371
+ scopes: [],
372
+ trimOnWrap: true
370
373
  };
371
374
  }
372
375
  }
@@ -383,22 +386,46 @@ function renderMessage(msg, options, theme, ambient) {
383
386
  }
384
387
  const tokens = [];
385
388
  let totalWidth = initialWidth;
386
- for (const token of stream()) {
389
+ let pendingWrap = false;
390
+ let atWrappedLineStart = false;
391
+ for (let token of stream()) {
387
392
  if (token.width === -1) {
388
393
  tokens.push(token);
389
394
  totalWidth = 0;
395
+ pendingWrap = false;
396
+ atWrappedLineStart = false;
397
+ continue;
398
+ }
399
+ const wraps = pendingWrap || options.maxWidth != null && totalWidth > 0 && totalWidth + token.width > options.maxWidth;
400
+ if ((wraps || atWrappedLineStart) && token.trimOnWrap) {
401
+ const text$1 = token.text.trimStart();
402
+ token = {
403
+ ...token,
404
+ text: text$1,
405
+ width: token.width - require_displaywidth.getDisplayWidth(token.text.slice(0, token.text.length - text$1.length))
406
+ };
407
+ if (text$1 === "") {
408
+ if (wraps) pendingWrap = true;
409
+ continue;
410
+ }
411
+ }
412
+ if (pendingWrap && require_displaywidth.stripAnsi(token.text) === "") {
413
+ tokens.push(token);
390
414
  continue;
391
415
  }
392
- if (options.maxWidth != null && totalWidth > 0 && totalWidth + token.width > options.maxWidth) {
416
+ if (wraps) {
393
417
  tokens.push({
394
418
  text: "\n",
395
419
  width: -1,
396
420
  scopes: []
397
421
  });
398
422
  totalWidth = 0;
423
+ pendingWrap = false;
424
+ atWrappedLineStart = true;
399
425
  }
400
426
  tokens.push(token);
401
427
  totalWidth += token.width;
428
+ if (token.width > 0) atWrappedLineStart = false;
402
429
  }
403
430
  return require_terminal_internal.serializeTokens(tokens, useColors, ambient == null ? resetSuffix : "", ambient);
404
431
  }
package/dist/message.js CHANGED
@@ -1,4 +1,4 @@
1
- import { getDisplayWidth } from "./displaywidth.js";
1
+ import { getDisplayWidth, stripAnsi } from "./displaywidth.js";
2
2
  import { formatTerminalTerm, fragmentTokens, serializeTokens } from "./terminal-internal.js";
3
3
  import { messageRenderers } from "./message-registry.js";
4
4
 
@@ -347,7 +347,8 @@ function renderMessage(msg, options, theme, ambient) {
347
347
  yield {
348
348
  text: match[0],
349
349
  width: getDisplayWidth(match[0]),
350
- scopes: []
350
+ scopes: [],
351
+ trimOnWrap: true
351
352
  };
352
353
  }
353
354
  }
@@ -356,7 +357,8 @@ function renderMessage(msg, options, theme, ambient) {
356
357
  if (normalizedText.trim() === "" && normalizedText.length > 0) yield {
357
358
  text: " ",
358
359
  width: 1,
359
- scopes: []
360
+ scopes: [],
361
+ trimOnWrap: true
360
362
  };
361
363
  else {
362
364
  wordPattern.lastIndex = 0;
@@ -366,7 +368,8 @@ function renderMessage(msg, options, theme, ambient) {
366
368
  yield {
367
369
  text: match[0],
368
370
  width: getDisplayWidth(match[0]),
369
- scopes: []
371
+ scopes: [],
372
+ trimOnWrap: true
370
373
  };
371
374
  }
372
375
  }
@@ -383,22 +386,46 @@ function renderMessage(msg, options, theme, ambient) {
383
386
  }
384
387
  const tokens = [];
385
388
  let totalWidth = initialWidth;
386
- for (const token of stream()) {
389
+ let pendingWrap = false;
390
+ let atWrappedLineStart = false;
391
+ for (let token of stream()) {
387
392
  if (token.width === -1) {
388
393
  tokens.push(token);
389
394
  totalWidth = 0;
395
+ pendingWrap = false;
396
+ atWrappedLineStart = false;
397
+ continue;
398
+ }
399
+ const wraps = pendingWrap || options.maxWidth != null && totalWidth > 0 && totalWidth + token.width > options.maxWidth;
400
+ if ((wraps || atWrappedLineStart) && token.trimOnWrap) {
401
+ const text$1 = token.text.trimStart();
402
+ token = {
403
+ ...token,
404
+ text: text$1,
405
+ width: token.width - getDisplayWidth(token.text.slice(0, token.text.length - text$1.length))
406
+ };
407
+ if (text$1 === "") {
408
+ if (wraps) pendingWrap = true;
409
+ continue;
410
+ }
411
+ }
412
+ if (pendingWrap && stripAnsi(token.text) === "") {
413
+ tokens.push(token);
390
414
  continue;
391
415
  }
392
- if (options.maxWidth != null && totalWidth > 0 && totalWidth + token.width > options.maxWidth) {
416
+ if (wraps) {
393
417
  tokens.push({
394
418
  text: "\n",
395
419
  width: -1,
396
420
  scopes: []
397
421
  });
398
422
  totalWidth = 0;
423
+ pendingWrap = false;
424
+ atWrappedLineStart = true;
399
425
  }
400
426
  tokens.push(token);
401
427
  totalWidth += token.width;
428
+ if (token.width > 0) atWrappedLineStart = false;
402
429
  }
403
430
  return serializeTokens(tokens, useColors, ambient == null ? resetSuffix : "", ambient);
404
431
  }
@@ -4,6 +4,7 @@ const require_mode_dispatch = require('./internal/mode-dispatch.cjs');
4
4
  const require_dependency_runtime = require('./dependency-runtime.cjs');
5
5
  const require_internal_parser = require('./internal/parser.cjs');
6
6
  const require_annotation_state = require('./annotation-state.cjs');
7
+ const require_passthrough = require('./internal/passthrough.cjs');
7
8
  const require_execution_context = require('./execution-context.cjs');
8
9
  const require_phase2_seed = require('./phase2-seed.cjs');
9
10
  const require_dependency_metadata = require('./dependency-metadata.cjs');
@@ -478,6 +479,9 @@ function optional(parser) {
478
479
  require_internal_parser.defineParseLanes(optionalParser, adaptOptionalStyleParseLanes(parser));
479
480
  require_internal_parser.defineInheritedAnnotationParser(optionalParser);
480
481
  require_internal_parser.defineSourceBindingOnlyAnnotationCompletionParser(optionalParser);
482
+ require_passthrough.defineOptionMatch(optionalParser, (state, token) => require_passthrough.getOptionMatch(parser, normalizeOptionalLikeSuggestState(state, parser.initialState, parser), token));
483
+ require_passthrough.definePassThroughPriority(optionalParser, [parser], (state, token) => require_passthrough.getPassThroughPriority(parser, normalizeOptionalLikeSuggestState(state, parser.initialState, parser), token));
484
+ require_passthrough.defineKnownCompletionLookup(optionalParser, (state) => require_passthrough.getKnownCompletion(parser, deriveOptionalInnerParseState(state, parser)));
481
485
  return fluent(optionalParser);
482
486
  }
483
487
  /**
@@ -729,6 +733,9 @@ function withDefault(parser, defaultValue, options) {
729
733
  require_internal_parser.defineParseLanes(withDefaultParser, adaptOptionalStyleParseLanes(parser));
730
734
  require_internal_parser.defineInheritedAnnotationParser(withDefaultParser);
731
735
  require_internal_parser.defineSourceBindingOnlyAnnotationCompletionParser(withDefaultParser);
736
+ require_passthrough.defineOptionMatch(withDefaultParser, (state, token) => require_passthrough.getOptionMatch(parser, normalizeOptionalLikeSuggestState(state, parser.initialState, parser), token));
737
+ require_passthrough.definePassThroughPriority(withDefaultParser, [parser], (state, token) => require_passthrough.getPassThroughPriority(parser, normalizeOptionalLikeSuggestState(state, parser.initialState, parser), token));
738
+ require_passthrough.defineKnownCompletionLookup(withDefaultParser, (state) => require_passthrough.getKnownCompletion(parser, deriveOptionalInnerParseState(state, parser)));
732
739
  return fluent(withDefaultParser);
733
740
  }
734
741
  /**
@@ -1714,6 +1721,19 @@ function multiple(parser, options = {}) {
1714
1721
  enumerable: false
1715
1722
  });
1716
1723
  }
1724
+ const matchingItem = (state) => {
1725
+ const current = state.at(-1);
1726
+ if (current != null && !isTerminalMultipleItemState(current)) return { state: unwrapInjectedWrapper(current) };
1727
+ return state.length < max ? { state: parser.initialState } : void 0;
1728
+ };
1729
+ require_passthrough.defineOptionMatch(resultParser, (state, token) => {
1730
+ const item = matchingItem(state);
1731
+ return item == null ? void 0 : require_passthrough.getOptionMatch(parser, item.state, token);
1732
+ });
1733
+ require_passthrough.definePassThroughPriority(resultParser, [parser], (state, token) => {
1734
+ const item = matchingItem(state);
1735
+ return item == null ? void 0 : require_passthrough.getPassThroughPriority(parser, item.state, token);
1736
+ });
1717
1737
  return fluent(resultParser);
1718
1738
  }
1719
1739
  /**
@@ -1850,6 +1870,8 @@ function nonEmpty(parser) {
1850
1870
  enumerable: false
1851
1871
  });
1852
1872
  require_dependency_runtime.defineForwardedEffectfulSchedulingNodes(nonEmptyParser, parser);
1873
+ require_passthrough.defineOptionMatch(nonEmptyParser, (state, token) => require_passthrough.getOptionMatch(parser, state, token));
1874
+ require_passthrough.definePassThroughPriority(nonEmptyParser, [parser], (state, token) => require_passthrough.getPassThroughPriority(parser, state, token));
1853
1875
  return fluent(nonEmptyParser);
1854
1876
  }
1855
1877
  const fluentParserMarker = Symbol.for("@optique/core/fluent");
package/dist/modifiers.js CHANGED
@@ -4,6 +4,7 @@ import { dispatchByMode, dispatchIterableByMode, mapModeValue, wrapForMode } fro
4
4
  import { defineForwardedEffectfulSchedulingNodes } from "./dependency-runtime.js";
5
5
  import { defineInheritedAnnotationParser, defineParseLanes, defineSourceBindingOnlyAnnotationCompletionParser, getOwnParseLanes, unmatchedNonCliDependencySourceStateMarker } from "./internal/parser.js";
6
6
  import { getDelegatedAnnotationState, hasDelegatedAnnotationCarrier, isAnnotationWrappedInitialState, normalizeDelegatedAnnotationState, normalizeNestedDelegatedAnnotationState } from "./annotation-state.js";
7
+ import { defineKnownCompletionLookup, defineOptionMatch, definePassThroughPriority, getKnownCompletion, getOptionMatch, getPassThroughPriority } from "./internal/passthrough.js";
7
8
  import { mergeChildExec, withChildContext, withChildExecPath } from "./execution-context.js";
8
9
  import { completeOrExtractPhase2Seed, extractPhase2Seed, extractPhase2SeedKey, phase2SeedFromValueResult } from "./phase2-seed.js";
9
10
  import { composeDependencyMetadata } from "./dependency-metadata.js";
@@ -478,6 +479,9 @@ function optional(parser) {
478
479
  defineParseLanes(optionalParser, adaptOptionalStyleParseLanes(parser));
479
480
  defineInheritedAnnotationParser(optionalParser);
480
481
  defineSourceBindingOnlyAnnotationCompletionParser(optionalParser);
482
+ defineOptionMatch(optionalParser, (state, token) => getOptionMatch(parser, normalizeOptionalLikeSuggestState(state, parser.initialState, parser), token));
483
+ definePassThroughPriority(optionalParser, [parser], (state, token) => getPassThroughPriority(parser, normalizeOptionalLikeSuggestState(state, parser.initialState, parser), token));
484
+ defineKnownCompletionLookup(optionalParser, (state) => getKnownCompletion(parser, deriveOptionalInnerParseState(state, parser)));
481
485
  return fluent(optionalParser);
482
486
  }
483
487
  /**
@@ -729,6 +733,9 @@ function withDefault(parser, defaultValue, options) {
729
733
  defineParseLanes(withDefaultParser, adaptOptionalStyleParseLanes(parser));
730
734
  defineInheritedAnnotationParser(withDefaultParser);
731
735
  defineSourceBindingOnlyAnnotationCompletionParser(withDefaultParser);
736
+ defineOptionMatch(withDefaultParser, (state, token) => getOptionMatch(parser, normalizeOptionalLikeSuggestState(state, parser.initialState, parser), token));
737
+ definePassThroughPriority(withDefaultParser, [parser], (state, token) => getPassThroughPriority(parser, normalizeOptionalLikeSuggestState(state, parser.initialState, parser), token));
738
+ defineKnownCompletionLookup(withDefaultParser, (state) => getKnownCompletion(parser, deriveOptionalInnerParseState(state, parser)));
732
739
  return fluent(withDefaultParser);
733
740
  }
734
741
  /**
@@ -1714,6 +1721,19 @@ function multiple(parser, options = {}) {
1714
1721
  enumerable: false
1715
1722
  });
1716
1723
  }
1724
+ const matchingItem = (state) => {
1725
+ const current = state.at(-1);
1726
+ if (current != null && !isTerminalMultipleItemState(current)) return { state: unwrapInjectedWrapper(current) };
1727
+ return state.length < max ? { state: parser.initialState } : void 0;
1728
+ };
1729
+ defineOptionMatch(resultParser, (state, token) => {
1730
+ const item = matchingItem(state);
1731
+ return item == null ? void 0 : getOptionMatch(parser, item.state, token);
1732
+ });
1733
+ definePassThroughPriority(resultParser, [parser], (state, token) => {
1734
+ const item = matchingItem(state);
1735
+ return item == null ? void 0 : getPassThroughPriority(parser, item.state, token);
1736
+ });
1717
1737
  return fluent(resultParser);
1718
1738
  }
1719
1739
  /**
@@ -1850,6 +1870,8 @@ function nonEmpty(parser) {
1850
1870
  enumerable: false
1851
1871
  });
1852
1872
  defineForwardedEffectfulSchedulingNodes(nonEmptyParser, parser);
1873
+ defineOptionMatch(nonEmptyParser, (state, token) => getOptionMatch(parser, state, token));
1874
+ definePassThroughPriority(nonEmptyParser, [parser], (state, token) => getPassThroughPriority(parser, state, token));
1853
1875
  return fluent(nonEmptyParser);
1854
1876
  }
1855
1877
  const fluentParserMarker = Symbol.for("@optique/core/fluent");
@@ -6,6 +6,7 @@ const require_mode_dispatch = require('./internal/mode-dispatch.cjs');
6
6
  const require_internal_dependency = require('./internal/dependency.cjs');
7
7
  const require_dependency_runtime = require('./dependency-runtime.cjs');
8
8
  const require_annotation_state = require('./annotation-state.cjs');
9
+ const require_passthrough = require('./internal/passthrough.cjs');
9
10
  const require_command_alias = require('./internal/command-alias.cjs');
10
11
  const require_execution_context = require('./execution-context.cjs');
11
12
  const require_phase2_seed = require('./phase2-seed.cjs');
@@ -151,6 +152,7 @@ function constant(value) {
151
152
  return { fragments: [] };
152
153
  }
153
154
  };
155
+ require_passthrough.defineKnownCompletion(result, (state) => require_annotation_state.normalizeInjectedAnnotationState(state));
154
156
  Object.defineProperty(result, "placeholder", {
155
157
  value,
156
158
  configurable: true,
@@ -590,10 +592,15 @@ function option(...args) {
590
592
  }
591
593
  const invalidOption = context.buffer[0];
592
594
  if (options.errors?.noMatch) {
595
+ if (typeof options.errors.noMatch !== "function") return {
596
+ success: false,
597
+ consumed: 0,
598
+ error: options.errors.noMatch
599
+ };
593
600
  const candidates = /* @__PURE__ */ new Set();
594
601
  for (const name of require_usage.extractOptionNames(context.usage)) candidates.add(name);
595
602
  const suggestions = require_suggestion.findSimilar(invalidOption, candidates, require_suggestion.DEFAULT_FIND_SIMILAR_OPTIONS);
596
- const errorMessage = typeof options.errors.noMatch === "function" ? options.errors.noMatch(invalidOption, suggestions) : options.errors.noMatch;
603
+ const errorMessage = options.errors.noMatch(invalidOption, suggestions);
597
604
  return {
598
605
  success: false,
599
606
  consumed: 0,
@@ -878,10 +885,15 @@ function flag(...args) {
878
885
  }
879
886
  const invalidOption = context.buffer[0];
880
887
  if (options.errors?.noMatch) {
888
+ if (typeof options.errors.noMatch !== "function") return {
889
+ success: false,
890
+ consumed: 0,
891
+ error: options.errors.noMatch
892
+ };
881
893
  const candidates = /* @__PURE__ */ new Set();
882
894
  for (const name of require_usage.extractOptionNames(context.usage)) candidates.add(name);
883
895
  const suggestions = require_suggestion.findSimilar(invalidOption, candidates, require_suggestion.DEFAULT_FIND_SIMILAR_OPTIONS);
884
- const errorMessage = typeof options.errors.noMatch === "function" ? options.errors.noMatch(invalidOption, suggestions) : options.errors.noMatch;
896
+ const errorMessage = options.errors.noMatch(invalidOption, suggestions);
885
897
  return {
886
898
  success: false,
887
899
  consumed: 0,
@@ -1190,7 +1202,7 @@ function argument(valueParser, options = {}) {
1190
1202
  const syncValueParser = valueParser;
1191
1203
  const dependencyMetadata = require_dependency_metadata.extractDependencyMetadata(valueParser);
1192
1204
  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}`;
1193
- const optionPattern = /^--?[a-z0-9-]+$/i;
1205
+ const optionPattern = /^(?!--=)(--?[a-z0-9-]+)(?:=|$)/i;
1194
1206
  const term = {
1195
1207
  type: "argument",
1196
1208
  metavar: valueParser.metavar,
@@ -1217,14 +1229,15 @@ function argument(valueParser, options = {}) {
1217
1229
  };
1218
1230
  let i = 0;
1219
1231
  let optionsTerminated = context.optionsTerminated;
1220
- if (!optionsTerminated) {
1221
- if (context.buffer[i] === "--") {
1222
- optionsTerminated = true;
1223
- i++;
1224
- } else if (context.buffer[i].match(optionPattern)) return {
1232
+ if (!optionsTerminated) if (context.buffer[i] === "--") {
1233
+ optionsTerminated = true;
1234
+ i++;
1235
+ } else {
1236
+ const optionMatch = context.buffer[i].match(optionPattern);
1237
+ if (optionMatch != null) return {
1225
1238
  success: false,
1226
1239
  consumed: i,
1227
- error: require_message.message`Expected an argument, but got an option: ${require_message.optionName(context.buffer[i])}.`
1240
+ error: require_message.message`Expected an argument, but got an option: ${require_message.optionName(optionMatch[1])}.`
1228
1241
  };
1229
1242
  }
1230
1243
  if (context.buffer.length < i + 1) return {
@@ -1734,6 +1747,22 @@ function command(name, parser, options = {}) {
1734
1747
  configurable: true,
1735
1748
  enumerable: false
1736
1749
  });
1750
+ require_passthrough.definePassThroughPriority(result, [parser], (state, token) => {
1751
+ const active = normalizeCommandState(state);
1752
+ if (active == null) return void 0;
1753
+ const childState = active[0] === "matched" ? parser.initialState : active[1];
1754
+ return require_passthrough.getPassThroughPriority(parser, getCommandParseChildState(state, childState, parser), token);
1755
+ });
1756
+ require_passthrough.defineOptionMatch(result, (state, token) => {
1757
+ const active = normalizeCommandState(state);
1758
+ if (active == null) return void 0;
1759
+ const childState = active[0] === "matched" ? parser.initialState : active[1];
1760
+ const match = require_passthrough.getOptionMatch(parser, getCommandParseChildState(state, childState, parser), token);
1761
+ return match == null ? void 0 : {
1762
+ ...match,
1763
+ continuesCommand: true
1764
+ };
1765
+ });
1737
1766
  return require_modifiers.fluent(result);
1738
1767
  }
1739
1768
  /**
@@ -1807,6 +1836,8 @@ function passThrough(options = {}) {
1807
1836
  consumed: 0,
1808
1837
  error: require_message.message`No input to pass through.`
1809
1838
  };
1839
+ const failure = require_passthrough.getPassThroughFailure(context, this?.priority ?? -10);
1840
+ if (failure != null) return failure.failure;
1810
1841
  const token = context.buffer[0];
1811
1842
  if (format === "greedy") {
1812
1843
  const captured = [...context.buffer];
@@ -1918,6 +1949,11 @@ function passThrough(options = {}) {
1918
1949
  return `passThrough(${format})`;
1919
1950
  }
1920
1951
  };
1952
+ require_passthrough.definePassThroughPriority(result, [result], (_state, token) => {
1953
+ if (token == null || format === "greedy") return result.priority;
1954
+ const accepts = format === "equalsOnly" ? equalsOptionPattern.test(token) : format === "nextToken" && optionPattern.test(token);
1955
+ return accepts ? result.priority : void 0;
1956
+ });
1921
1957
  return require_modifiers.fluent(result);
1922
1958
  }
1923
1959
 
@@ -6,6 +6,7 @@ import { dispatchByMode, dispatchIterableByMode, wrapForMode } from "./internal/
6
6
  import { getDefaultValuesFunction, getDependencyIds, getSnapshottedDefaultDependencyValues, isDerivedValueParser, suggestWithDependency } from "./internal/dependency.js";
7
7
  import { effectfulSchedulingNodesKey, exclusiveSourceScopeKey, includeSourceFailureChain, recordDerivedRawInput, replayDerivedParser, replayDerivedParserAsync, sourceCollectionExpansionKey } from "./dependency-runtime.js";
8
8
  import { getWrappedChildParseState, getWrappedChildState, isAnnotationWrappedInitialState, normalizeInjectedAnnotationState } from "./annotation-state.js";
9
+ import { defineKnownCompletion, defineOptionMatch, definePassThroughPriority, getOptionMatch, getPassThroughFailure, getPassThroughPriority } from "./internal/passthrough.js";
9
10
  import { hiddenCommandAliasesKey } from "./internal/command-alias.js";
10
11
  import { mergeChildExec, withChildContext, withChildExecPath } from "./execution-context.js";
11
12
  import { completeOrExtractPhase2Seed, extractPhase2SeedKey } from "./phase2-seed.js";
@@ -151,6 +152,7 @@ function constant(value) {
151
152
  return { fragments: [] };
152
153
  }
153
154
  };
155
+ defineKnownCompletion(result, (state) => normalizeInjectedAnnotationState(state));
154
156
  Object.defineProperty(result, "placeholder", {
155
157
  value,
156
158
  configurable: true,
@@ -590,10 +592,15 @@ function option(...args) {
590
592
  }
591
593
  const invalidOption = context.buffer[0];
592
594
  if (options.errors?.noMatch) {
595
+ if (typeof options.errors.noMatch !== "function") return {
596
+ success: false,
597
+ consumed: 0,
598
+ error: options.errors.noMatch
599
+ };
593
600
  const candidates = /* @__PURE__ */ new Set();
594
601
  for (const name of extractOptionNames(context.usage)) candidates.add(name);
595
602
  const suggestions = findSimilar(invalidOption, candidates, DEFAULT_FIND_SIMILAR_OPTIONS);
596
- const errorMessage = typeof options.errors.noMatch === "function" ? options.errors.noMatch(invalidOption, suggestions) : options.errors.noMatch;
603
+ const errorMessage = options.errors.noMatch(invalidOption, suggestions);
597
604
  return {
598
605
  success: false,
599
606
  consumed: 0,
@@ -878,10 +885,15 @@ function flag(...args) {
878
885
  }
879
886
  const invalidOption = context.buffer[0];
880
887
  if (options.errors?.noMatch) {
888
+ if (typeof options.errors.noMatch !== "function") return {
889
+ success: false,
890
+ consumed: 0,
891
+ error: options.errors.noMatch
892
+ };
881
893
  const candidates = /* @__PURE__ */ new Set();
882
894
  for (const name of extractOptionNames(context.usage)) candidates.add(name);
883
895
  const suggestions = findSimilar(invalidOption, candidates, DEFAULT_FIND_SIMILAR_OPTIONS);
884
- const errorMessage = typeof options.errors.noMatch === "function" ? options.errors.noMatch(invalidOption, suggestions) : options.errors.noMatch;
896
+ const errorMessage = options.errors.noMatch(invalidOption, suggestions);
885
897
  return {
886
898
  success: false,
887
899
  consumed: 0,
@@ -1190,7 +1202,7 @@ function argument(valueParser, options = {}) {
1190
1202
  const syncValueParser = valueParser;
1191
1203
  const dependencyMetadata = extractDependencyMetadata(valueParser);
1192
1204
  const formatInvalidValueError = (error) => options.errors?.invalidValue ? typeof options.errors.invalidValue === "function" ? options.errors.invalidValue(error) : options.errors.invalidValue : message`${metavar(valueParser.metavar)}: ${error}`;
1193
- const optionPattern = /^--?[a-z0-9-]+$/i;
1205
+ const optionPattern = /^(?!--=)(--?[a-z0-9-]+)(?:=|$)/i;
1194
1206
  const term = {
1195
1207
  type: "argument",
1196
1208
  metavar: valueParser.metavar,
@@ -1217,14 +1229,15 @@ function argument(valueParser, options = {}) {
1217
1229
  };
1218
1230
  let i = 0;
1219
1231
  let optionsTerminated = context.optionsTerminated;
1220
- if (!optionsTerminated) {
1221
- if (context.buffer[i] === "--") {
1222
- optionsTerminated = true;
1223
- i++;
1224
- } else if (context.buffer[i].match(optionPattern)) return {
1232
+ if (!optionsTerminated) if (context.buffer[i] === "--") {
1233
+ optionsTerminated = true;
1234
+ i++;
1235
+ } else {
1236
+ const optionMatch = context.buffer[i].match(optionPattern);
1237
+ if (optionMatch != null) return {
1225
1238
  success: false,
1226
1239
  consumed: i,
1227
- error: message`Expected an argument, but got an option: ${optionName(context.buffer[i])}.`
1240
+ error: message`Expected an argument, but got an option: ${optionName(optionMatch[1])}.`
1228
1241
  };
1229
1242
  }
1230
1243
  if (context.buffer.length < i + 1) return {
@@ -1734,6 +1747,22 @@ function command(name, parser, options = {}) {
1734
1747
  configurable: true,
1735
1748
  enumerable: false
1736
1749
  });
1750
+ definePassThroughPriority(result, [parser], (state, token) => {
1751
+ const active = normalizeCommandState(state);
1752
+ if (active == null) return void 0;
1753
+ const childState = active[0] === "matched" ? parser.initialState : active[1];
1754
+ return getPassThroughPriority(parser, getCommandParseChildState(state, childState, parser), token);
1755
+ });
1756
+ defineOptionMatch(result, (state, token) => {
1757
+ const active = normalizeCommandState(state);
1758
+ if (active == null) return void 0;
1759
+ const childState = active[0] === "matched" ? parser.initialState : active[1];
1760
+ const match = getOptionMatch(parser, getCommandParseChildState(state, childState, parser), token);
1761
+ return match == null ? void 0 : {
1762
+ ...match,
1763
+ continuesCommand: true
1764
+ };
1765
+ });
1737
1766
  return fluent(result);
1738
1767
  }
1739
1768
  /**
@@ -1807,6 +1836,8 @@ function passThrough(options = {}) {
1807
1836
  consumed: 0,
1808
1837
  error: message`No input to pass through.`
1809
1838
  };
1839
+ const failure = getPassThroughFailure(context, this?.priority ?? -10);
1840
+ if (failure != null) return failure.failure;
1810
1841
  const token = context.buffer[0];
1811
1842
  if (format === "greedy") {
1812
1843
  const captured = [...context.buffer];
@@ -1918,6 +1949,11 @@ function passThrough(options = {}) {
1918
1949
  return `passThrough(${format})`;
1919
1950
  }
1920
1951
  };
1952
+ definePassThroughPriority(result, [result], (_state, token) => {
1953
+ if (token == null || format === "greedy") return result.priority;
1954
+ const accepts = format === "equalsOnly" ? equalsOptionPattern.test(token) : format === "nextToken" && optionPattern.test(token);
1955
+ return accepts ? result.priority : void 0;
1956
+ });
1921
1957
  return fluent(result);
1922
1958
  }
1923
1959
 
@@ -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,
@@ -1,4 +1,5 @@
1
1
  const require_displaywidth = require('./displaywidth.cjs');
2
+ const require_terminal_separators = require('./terminal-separators.cjs');
2
3
  const require_terminal = require('./terminal.cjs');
3
4
 
4
5
  //#region src/terminal-internal.ts
@@ -151,6 +152,7 @@ function sameStyle(a, b) {
151
152
  }
152
153
  function* fragmentTokens(fragment, scopes = [], inherited = {}) {
153
154
  if (fragment.type === "text") {
155
+ const marks = require_terminal_separators.wrapTrimmableFragments.has(fragment) ? { trimOnWrap: true } : {};
154
156
  const lines = fragment.text.split("\n");
155
157
  for (let i = 0; i < lines.length; i++) {
156
158
  if (i > 0) yield {
@@ -161,7 +163,8 @@ function* fragmentTokens(fragment, scopes = [], inherited = {}) {
161
163
  if (lines[i].length > 0 || lines.length === 1) yield {
162
164
  text: lines[i],
163
165
  width: require_displaywidth.getDisplayWidth(lines[i]),
164
- scopes
166
+ scopes,
167
+ ...marks
165
168
  };
166
169
  }
167
170
  return;
@@ -16,6 +16,11 @@ interface TerminalToken {
16
16
  readonly programBoundary?: boolean;
17
17
  /** Enables only the legacy default formatter whitespace behavior. */
18
18
  readonly legacyWhitespace?: boolean;
19
+ /**
20
+ * Leading whitespace only separates the token from preceding content, so
21
+ * message wrapping may drop it when the token starts a wrapped line.
22
+ */
23
+ readonly trimOnWrap?: boolean;
19
24
  }
20
25
  declare function terminalText(text: string): TerminalFragment;
21
26
  declare function formatTerminalTerm(term: TerminalTerm, theme?: TerminalTheme, quotes?: boolean, usage?: TerminalFormatContext["usage"]): TerminalFragment;
@@ -16,6 +16,11 @@ interface TerminalToken {
16
16
  readonly programBoundary?: boolean;
17
17
  /** Enables only the legacy default formatter whitespace behavior. */
18
18
  readonly legacyWhitespace?: boolean;
19
+ /**
20
+ * Leading whitespace only separates the token from preceding content, so
21
+ * message wrapping may drop it when the token starts a wrapped line.
22
+ */
23
+ readonly trimOnWrap?: boolean;
19
24
  }
20
25
  declare function terminalText(text: string): TerminalFragment;
21
26
  declare function formatTerminalTerm(term: TerminalTerm, theme?: TerminalTheme, quotes?: boolean, usage?: TerminalFormatContext["usage"]): TerminalFragment;
@@ -1,4 +1,5 @@
1
1
  import { getDisplayWidth } from "./displaywidth.js";
2
+ import { wrapTrimmableFragments } from "./terminal-separators.js";
2
3
  import { defaultTerminalTheme } from "./terminal.js";
3
4
 
4
5
  //#region src/terminal-internal.ts
@@ -151,6 +152,7 @@ function sameStyle(a, b) {
151
152
  }
152
153
  function* fragmentTokens(fragment, scopes = [], inherited = {}) {
153
154
  if (fragment.type === "text") {
155
+ const marks = wrapTrimmableFragments.has(fragment) ? { trimOnWrap: true } : {};
154
156
  const lines = fragment.text.split("\n");
155
157
  for (let i = 0; i < lines.length; i++) {
156
158
  if (i > 0) yield {
@@ -161,7 +163,8 @@ function* fragmentTokens(fragment, scopes = [], inherited = {}) {
161
163
  if (lines[i].length > 0 || lines.length === 1) yield {
162
164
  text: lines[i],
163
165
  width: getDisplayWidth(lines[i]),
164
- scopes
166
+ scopes,
167
+ ...marks
165
168
  };
166
169
  }
167
170
  return;
@@ -0,0 +1,13 @@
1
+
2
+ //#region src/terminal-separators.ts
3
+ /**
4
+ * Text fragments that only separate the items around them, such as the
5
+ * spaces the default `values` formatter puts between values. When message
6
+ * wrapping moves such a fragment to the start of a new line, its leading
7
+ * whitespace may be dropped.
8
+ * @internal
9
+ */
10
+ const wrapTrimmableFragments = /* @__PURE__ */ new WeakSet();
11
+
12
+ //#endregion
13
+ exports.wrapTrimmableFragments = wrapTrimmableFragments;
@@ -0,0 +1,12 @@
1
+ //#region src/terminal-separators.ts
2
+ /**
3
+ * Text fragments that only separate the items around them, such as the
4
+ * spaces the default `values` formatter puts between values. When message
5
+ * wrapping moves such a fragment to the start of a new line, its leading
6
+ * whitespace may be dropped.
7
+ * @internal
8
+ */
9
+ const wrapTrimmableFragments = /* @__PURE__ */ new WeakSet();
10
+
11
+ //#endregion
12
+ export { wrapTrimmableFragments };