@optique/core 0.9.0-dev.206 → 0.9.0-dev.211

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.
@@ -1,7 +1,7 @@
1
1
  import { Message } from "./message.js";
2
2
  import { OptionName } from "./usage.js";
3
3
  import { ValueParser, ValueParserResult } from "./valueparser.js";
4
- import { Mode, Parser } from "./parser.js";
4
+ import { Parser } from "./parser.js";
5
5
 
6
6
  //#region src/primitives.d.ts
7
7
 
@@ -10,7 +10,7 @@ import { Mode, Parser } from "./parser.js";
10
10
  * produces a constant value of the type {@link T}.
11
11
  * @template T The type of the constant value produced by the parser.
12
12
  */
13
- declare function constant<const T>(value: T): Parser<"sync", T, T>;
13
+ declare function constant<const T>(value: T): Parser<T, T>;
14
14
  /**
15
15
  * Options for the {@link option} parser.
16
16
  */
@@ -78,7 +78,6 @@ interface OptionErrorOptions {
78
78
  /**
79
79
  * Creates a parser for various styles of command-line options that take an
80
80
  * argument value, such as `--option=value`, `-o value`, or `/option:value`.
81
- * @template M The execution mode of the parser.
82
81
  * @template T The type of value this parser produces.
83
82
  * @param args The {@link OptionName}s to parse, followed by
84
83
  * a {@link ValueParser} that defines how to parse the value of
@@ -87,11 +86,10 @@ interface OptionErrorOptions {
87
86
  * @returns A {@link Parser} that can parse the specified options and their
88
87
  * values.
89
88
  */
90
- declare function option<M extends Mode, T>(...args: readonly [...readonly OptionName[], ValueParser<M, T>]): Parser<M, T, ValueParserResult<T> | undefined>;
89
+ declare function option<T>(...args: readonly [...readonly OptionName[], ValueParser<T>]): Parser<T, ValueParserResult<T> | undefined>;
91
90
  /**
92
91
  * Creates a parser for various styles of command-line options that take an
93
92
  * argument value, such as `--option=value`, `-o value`, or `/option:value`.
94
- * @template M The execution mode of the parser.
95
93
  * @template T The type of value this parser produces.
96
94
  * @param args The {@link OptionName}s to parse, followed by
97
95
  * a {@link ValueParser} that defines how to parse the value of
@@ -100,7 +98,7 @@ declare function option<M extends Mode, T>(...args: readonly [...readonly Option
100
98
  * @returns A {@link Parser} that can parse the specified options and their
101
99
  * values.
102
100
  */
103
- declare function option<M extends Mode, T>(...args: readonly [...readonly OptionName[], ValueParser<M, T>, OptionOptions]): Parser<M, T, ValueParserResult<T> | undefined>;
101
+ declare function option<T>(...args: readonly [...readonly OptionName[], ValueParser<T>, OptionOptions]): Parser<T, ValueParserResult<T> | undefined>;
104
102
  /**
105
103
  * Creates a parser for various styles of command-line options that do not
106
104
  * take an argument value, such as `--option`, `-o`, or `/option`.
@@ -108,7 +106,7 @@ declare function option<M extends Mode, T>(...args: readonly [...readonly Option
108
106
  * @return A {@link Parser} that can parse the specified options as Boolean
109
107
  * flags, producing `true` if the option is present.
110
108
  */
111
- declare function option(...optionNames: readonly OptionName[]): Parser<"sync", boolean, ValueParserResult<boolean> | undefined>;
109
+ declare function option(...optionNames: readonly OptionName[]): Parser<boolean, ValueParserResult<boolean> | undefined>;
112
110
  /**
113
111
  * Creates a parser for various styles of command-line options that take an
114
112
  * argument value, such as `--option=value`, `-o value`, or `/option:value`.
@@ -118,7 +116,7 @@ declare function option(...optionNames: readonly OptionName[]): Parser<"sync", b
118
116
  * @returns A {@link Parser} that can parse the specified options and their
119
117
  * values.
120
118
  */
121
- declare function option(...args: readonly [...readonly OptionName[], OptionOptions]): Parser<"sync", boolean, ValueParserResult<boolean> | undefined>;
119
+ declare function option(...args: readonly [...readonly OptionName[], OptionOptions]): Parser<boolean, ValueParserResult<boolean> | undefined>;
122
120
  /**
123
121
  * Options for the {@link flag} parser.
124
122
  */
@@ -204,7 +202,7 @@ interface FlagErrorOptions {
204
202
  * });
205
203
  * ```
206
204
  */
207
- declare function flag(...args: readonly [...readonly OptionName[], FlagOptions] | readonly OptionName[]): Parser<"sync", true, ValueParserResult<true> | undefined>;
205
+ declare function flag(...args: readonly [...readonly OptionName[], FlagOptions] | readonly OptionName[]): Parser<true, ValueParserResult<true> | undefined>;
208
206
  /**
209
207
  * Options for the {@link argument} parser.
210
208
  */
@@ -250,7 +248,6 @@ interface ArgumentErrorOptions {
250
248
  * Creates a parser that expects a single argument value.
251
249
  * This parser is typically used for positional arguments
252
250
  * that are not options or flags.
253
- * @template M The execution mode of the parser.
254
251
  * @template T The type of the value produced by the parser.
255
252
  * @param valueParser The {@link ValueParser} that defines how to parse
256
253
  * the argument value.
@@ -259,7 +256,7 @@ interface ArgumentErrorOptions {
259
256
  * @returns A {@link Parser} that expects a single argument value and produces
260
257
  * the parsed value of type {@link T}.
261
258
  */
262
- declare function argument<M extends Mode, T>(valueParser: ValueParser<M, T>, options?: ArgumentOptions): Parser<M, T, ValueParserResult<T> | undefined>;
259
+ declare function argument<T>(valueParser: ValueParser<T>, options?: ArgumentOptions): Parser<T, ValueParserResult<T> | undefined>;
263
260
  /**
264
261
  * Options for the {@link command} parser.
265
262
  * @since 0.5.0
@@ -328,7 +325,6 @@ type CommandState<TState> = undefined | ["matched", string] | ["parsing", TState
328
325
  * Creates a parser that matches a specific subcommand name and then applies
329
326
  * an inner parser to the remaining arguments.
330
327
  * This is useful for building CLI tools with subcommands like git, npm, etc.
331
- * @template M The execution mode of the parser.
332
328
  * @template T The type of the value returned by the inner parser.
333
329
  * @template TState The type of the state used by the inner parser.
334
330
  * @param name The subcommand name to match (e.g., `"show"`, `"edit"`).
@@ -338,7 +334,7 @@ type CommandState<TState> = undefined | ["matched", string] | ["parsing", TState
338
334
  * @returns A {@link Parser} that matches the command name and delegates
339
335
  * to the inner parser for the remaining arguments.
340
336
  */
341
- declare function command<M extends Mode, T, TState>(name: string, parser: Parser<M, T, TState>, options?: CommandOptions): Parser<M, T, CommandState<TState>>;
337
+ declare function command<T, TState>(name: string, parser: Parser<T, TState>, options?: CommandOptions): Parser<T, CommandState<TState>>;
342
338
  /**
343
339
  * Format options for how {@link passThrough} captures options.
344
340
  * @since 0.8.0
@@ -421,6 +417,6 @@ interface PassThroughOptions {
421
417
  *
422
418
  * @since 0.8.0
423
419
  */
424
- declare function passThrough(options?: PassThroughOptions): Parser<"sync", readonly string[], readonly string[]>;
420
+ declare function passThrough(options?: PassThroughOptions): Parser<readonly string[], readonly string[]>;
425
421
  //#endregion
426
422
  export { ArgumentErrorOptions, ArgumentOptions, CommandErrorOptions, CommandOptions, FlagErrorOptions, FlagOptions, OptionErrorOptions, OptionOptions, PassThroughFormat, PassThroughOptions, argument, command, constant, flag, option, passThrough };
@@ -13,7 +13,6 @@ function constant(value) {
13
13
  return {
14
14
  $valueType: [],
15
15
  $stateType: [],
16
- $mode: "sync",
17
16
  priority: 0,
18
17
  usage: [],
19
18
  initialState: value,
@@ -38,112 +37,6 @@ function constant(value) {
38
37
  }
39
38
  };
40
39
  }
41
- /**
42
- * Internal sync helper for option suggest functionality.
43
- * @internal
44
- */
45
- function* suggestOptionSync(optionNames$1, valueParser, hidden, context, prefix) {
46
- if (hidden) return;
47
- const equalsIndex = prefix.indexOf("=");
48
- if (equalsIndex >= 0) {
49
- const optionPart = prefix.slice(0, equalsIndex);
50
- const valuePart = prefix.slice(equalsIndex + 1);
51
- if (optionNames$1.includes(optionPart)) {
52
- if (valueParser && valueParser.suggest) {
53
- const valueSuggestions = valueParser.suggest(valuePart);
54
- for (const suggestion of valueSuggestions) if (suggestion.kind === "literal") yield {
55
- kind: "literal",
56
- text: `${optionPart}=${suggestion.text}`,
57
- description: suggestion.description
58
- };
59
- else yield {
60
- kind: "literal",
61
- text: `${optionPart}=${suggestion.pattern || ""}`,
62
- description: suggestion.description
63
- };
64
- }
65
- }
66
- } else {
67
- if (prefix.startsWith("--") || prefix.startsWith("-") || prefix.startsWith("/")) {
68
- for (const optionName$1 of optionNames$1) if (optionName$1.startsWith(prefix)) {
69
- if (prefix === "-" && optionName$1.length !== 2) continue;
70
- yield {
71
- kind: "literal",
72
- text: optionName$1
73
- };
74
- }
75
- }
76
- if (valueParser && valueParser.suggest) {
77
- let shouldSuggestValues = false;
78
- if (context.buffer.length > 0) {
79
- const lastToken = context.buffer[context.buffer.length - 1];
80
- if (optionNames$1.includes(lastToken)) shouldSuggestValues = true;
81
- } else if (context.state === void 0 && context.buffer.length === 0) shouldSuggestValues = true;
82
- if (shouldSuggestValues) yield* valueParser.suggest(prefix);
83
- }
84
- }
85
- }
86
- /**
87
- * Internal async helper for option suggest functionality.
88
- * @internal
89
- */
90
- async function* suggestOptionAsync(optionNames$1, valueParser, hidden, context, prefix) {
91
- if (hidden) return;
92
- const equalsIndex = prefix.indexOf("=");
93
- if (equalsIndex >= 0) {
94
- const optionPart = prefix.slice(0, equalsIndex);
95
- const valuePart = prefix.slice(equalsIndex + 1);
96
- if (optionNames$1.includes(optionPart)) {
97
- if (valueParser && valueParser.suggest) {
98
- const valueSuggestions = valueParser.suggest(valuePart);
99
- for await (const suggestion of valueSuggestions) if (suggestion.kind === "literal") yield {
100
- kind: "literal",
101
- text: `${optionPart}=${suggestion.text}`,
102
- description: suggestion.description
103
- };
104
- else yield {
105
- kind: "literal",
106
- text: `${optionPart}=${suggestion.pattern || ""}`,
107
- description: suggestion.description
108
- };
109
- }
110
- }
111
- } else {
112
- if (prefix.startsWith("--") || prefix.startsWith("-") || prefix.startsWith("/")) {
113
- for (const optionName$1 of optionNames$1) if (optionName$1.startsWith(prefix)) {
114
- if (prefix === "-" && optionName$1.length !== 2) continue;
115
- yield {
116
- kind: "literal",
117
- text: optionName$1
118
- };
119
- }
120
- }
121
- if (valueParser && valueParser.suggest) {
122
- let shouldSuggestValues = false;
123
- if (context.buffer.length > 0) {
124
- const lastToken = context.buffer[context.buffer.length - 1];
125
- if (optionNames$1.includes(lastToken)) shouldSuggestValues = true;
126
- } else if (context.state === void 0 && context.buffer.length === 0) shouldSuggestValues = true;
127
- if (shouldSuggestValues) for await (const suggestion of valueParser.suggest(prefix)) yield suggestion;
128
- }
129
- }
130
- }
131
- /**
132
- * Internal sync helper for argument suggest functionality.
133
- * @internal
134
- */
135
- function* suggestArgumentSync(valueParser, hidden, prefix) {
136
- if (hidden) return;
137
- if (valueParser.suggest) yield* valueParser.suggest(prefix);
138
- }
139
- /**
140
- * Internal async helper for argument suggest functionality.
141
- * @internal
142
- */
143
- async function* suggestArgumentAsync(valueParser, hidden, prefix) {
144
- if (hidden) return;
145
- if (valueParser.suggest) for await (const suggestion of valueParser.suggest(prefix)) yield suggestion;
146
- }
147
40
  function option(...args) {
148
41
  const lastArg = args.at(-1);
149
42
  const secondLastArg = args.at(-2);
@@ -166,10 +59,7 @@ function option(...args) {
166
59
  optionNames$1 = args;
167
60
  valueParser = void 0;
168
61
  }
169
- const mode = valueParser?.$mode ?? "sync";
170
- const isAsync = mode === "async";
171
- const result = {
172
- $mode: mode,
62
+ return {
173
63
  $valueType: [],
174
64
  $stateType: [],
175
65
  priority: 10,
@@ -215,7 +105,7 @@ function option(...args) {
215
105
  consumed: context.buffer.slice(0, 1)
216
106
  };
217
107
  if (optionNames$1.includes(context.buffer[0])) {
218
- if (context.state?.success && (valueParser != null || context.state.value)) return {
108
+ if (context.state.success && (valueParser != null || context.state.value)) return {
219
109
  success: false,
220
110
  consumed: 1,
221
111
  error: options.errors?.duplicate ? typeof options.errors.duplicate === "function" ? options.errors.duplicate(context.buffer[0]) : options.errors.duplicate : message`${optionName(context.buffer[0])} cannot be used multiple times.`
@@ -237,21 +127,12 @@ function option(...args) {
237
127
  consumed: 1,
238
128
  error: message`Option ${optionName(context.buffer[0])} requires a value, but got no value.`
239
129
  };
240
- const parseResultOrPromise = valueParser.parse(context.buffer[1]);
241
- if (isAsync) return parseResultOrPromise.then((parseResult) => ({
242
- success: true,
243
- next: {
244
- ...context,
245
- state: parseResult,
246
- buffer: context.buffer.slice(2)
247
- },
248
- consumed: context.buffer.slice(0, 2)
249
- }));
130
+ const result = valueParser.parse(context.buffer[1]);
250
131
  return {
251
132
  success: true,
252
133
  next: {
253
134
  ...context,
254
- state: parseResultOrPromise,
135
+ state: result,
255
136
  buffer: context.buffer.slice(2)
256
137
  },
257
138
  consumed: context.buffer.slice(0, 2)
@@ -260,7 +141,7 @@ function option(...args) {
260
141
  const prefixes = optionNames$1.filter((name) => name.startsWith("--") || name.startsWith("/")).map((name) => name.startsWith("/") ? `${name}:` : `${name}=`);
261
142
  for (const prefix of prefixes) {
262
143
  if (!context.buffer[0].startsWith(prefix)) continue;
263
- if (context.state?.success && (valueParser != null || context.state.value)) return {
144
+ if (context.state.success && (valueParser != null || context.state.value)) return {
264
145
  success: false,
265
146
  consumed: 1,
266
147
  error: options.errors?.duplicate ? typeof options.errors.duplicate === "function" ? options.errors.duplicate(prefix) : options.errors.duplicate : message`${optionName(prefix)} cannot be used multiple times.`
@@ -271,21 +152,12 @@ function option(...args) {
271
152
  consumed: 1,
272
153
  error: options.errors?.unexpectedValue ? typeof options.errors.unexpectedValue === "function" ? options.errors.unexpectedValue(value) : options.errors.unexpectedValue : message`Option ${optionName(prefix)} is a Boolean flag, but got a value: ${value}.`
273
154
  };
274
- const parseResultOrPromise = valueParser.parse(value);
275
- if (isAsync) return parseResultOrPromise.then((parseResult) => ({
276
- success: true,
277
- next: {
278
- ...context,
279
- state: parseResult,
280
- buffer: context.buffer.slice(1)
281
- },
282
- consumed: context.buffer.slice(0, 1)
283
- }));
155
+ const result = valueParser.parse(value);
284
156
  return {
285
157
  success: true,
286
158
  next: {
287
159
  ...context,
288
- state: parseResultOrPromise,
160
+ state: result,
289
161
  buffer: context.buffer.slice(1)
290
162
  },
291
163
  consumed: context.buffer.slice(0, 1)
@@ -295,7 +167,7 @@ function option(...args) {
295
167
  const shortOptions = optionNames$1.filter((name) => name.match(/^-[^-]$/));
296
168
  for (const shortOption of shortOptions) {
297
169
  if (!context.buffer[0].startsWith(shortOption)) continue;
298
- if (context.state?.success && (valueParser != null || context.state.value)) return {
170
+ if (context.state.success && (valueParser != null || context.state.value)) return {
299
171
  success: false,
300
172
  consumed: 1,
301
173
  error: options.errors?.duplicate ? typeof options.errors.duplicate === "function" ? options.errors.duplicate(shortOption) : options.errors.duplicate : message`${optionName(shortOption)} cannot be used multiple times.`
@@ -348,8 +220,50 @@ function option(...args) {
348
220
  };
349
221
  },
350
222
  suggest(context, prefix) {
351
- if (isAsync) return suggestOptionAsync(optionNames$1, valueParser, options.hidden ?? false, context, prefix);
352
- return suggestOptionSync(optionNames$1, valueParser, options.hidden ?? false, context, prefix);
223
+ if (options.hidden) return [];
224
+ const suggestions = [];
225
+ const equalsIndex = prefix.indexOf("=");
226
+ if (equalsIndex >= 0) {
227
+ const optionPart = prefix.slice(0, equalsIndex);
228
+ const valuePart = prefix.slice(equalsIndex + 1);
229
+ if (optionNames$1.includes(optionPart)) {
230
+ if (valueParser && valueParser.suggest) {
231
+ const valueSuggestions = valueParser.suggest(valuePart);
232
+ for (const suggestion of valueSuggestions) if (suggestion.kind === "literal") suggestions.push({
233
+ kind: "literal",
234
+ text: `${optionPart}=${suggestion.text}`,
235
+ description: suggestion.description
236
+ });
237
+ else suggestions.push({
238
+ kind: "literal",
239
+ text: `${optionPart}=${suggestion.pattern || ""}`,
240
+ description: suggestion.description
241
+ });
242
+ }
243
+ }
244
+ } else {
245
+ if (prefix.startsWith("--") || prefix.startsWith("-") || prefix.startsWith("/")) {
246
+ for (const optionName$1 of optionNames$1) if (optionName$1.startsWith(prefix)) {
247
+ if (prefix === "-" && optionName$1.length !== 2) continue;
248
+ suggestions.push({
249
+ kind: "literal",
250
+ text: optionName$1
251
+ });
252
+ }
253
+ }
254
+ if (valueParser && valueParser.suggest) {
255
+ let shouldSuggestValues = false;
256
+ if (context.buffer.length > 0) {
257
+ const lastToken = context.buffer[context.buffer.length - 1];
258
+ if (optionNames$1.includes(lastToken)) shouldSuggestValues = true;
259
+ } else if (context.state === void 0 && context.buffer.length === 0) shouldSuggestValues = true;
260
+ if (shouldSuggestValues) {
261
+ const valueSuggestions = valueParser.suggest(prefix);
262
+ suggestions.push(...valueSuggestions);
263
+ }
264
+ }
265
+ }
266
+ return suggestions;
353
267
  },
354
268
  getDocFragments(_state, defaultValue) {
355
269
  if (options.hidden) return {
@@ -375,7 +289,6 @@ function option(...args) {
375
289
  return `option(${optionNames$1.map((o) => JSON.stringify(o)).join(", ")})`;
376
290
  }
377
291
  };
378
- return result;
379
292
  }
380
293
  /**
381
294
  * Creates a parser for command-line flags that must be explicitly provided.
@@ -419,7 +332,6 @@ function flag(...args) {
419
332
  return {
420
333
  $valueType: [],
421
334
  $stateType: [],
422
- $mode: "sync",
423
335
  priority: 10,
424
336
  usage: [{
425
337
  type: "option",
@@ -571,7 +483,6 @@ function flag(...args) {
571
483
  * Creates a parser that expects a single argument value.
572
484
  * This parser is typically used for positional arguments
573
485
  * that are not options or flags.
574
- * @template M The execution mode of the parser.
575
486
  * @template T The type of the value produced by the parser.
576
487
  * @param valueParser The {@link ValueParser} that defines how to parse
577
488
  * the argument value.
@@ -581,15 +492,13 @@ function flag(...args) {
581
492
  * the parsed value of type {@link T}.
582
493
  */
583
494
  function argument(valueParser, options = {}) {
584
- const isAsync = valueParser.$mode === "async";
585
495
  const optionPattern = /^--?[a-z0-9-]+$/i;
586
496
  const term = {
587
497
  type: "argument",
588
498
  metavar: valueParser.metavar,
589
499
  ...options.hidden && { hidden: true }
590
500
  };
591
- const result = {
592
- $mode: valueParser.$mode,
501
+ return {
593
502
  $valueType: [],
594
503
  $stateType: [],
595
504
  priority: 5,
@@ -623,23 +532,13 @@ function argument(valueParser, options = {}) {
623
532
  consumed: i,
624
533
  error: options.errors?.multiple ? typeof options.errors.multiple === "function" ? options.errors.multiple(valueParser.metavar) : options.errors.multiple : message`The argument ${metavar(valueParser.metavar)} cannot be used multiple times.`
625
534
  };
626
- const parseResultOrPromise = valueParser.parse(context.buffer[i]);
627
- if (isAsync) return parseResultOrPromise.then((parseResult) => ({
628
- success: true,
629
- next: {
630
- ...context,
631
- buffer: context.buffer.slice(i + 1),
632
- state: parseResult,
633
- optionsTerminated
634
- },
635
- consumed: context.buffer.slice(0, i + 1)
636
- }));
535
+ const result = valueParser.parse(context.buffer[i]);
637
536
  return {
638
537
  success: true,
639
538
  next: {
640
539
  ...context,
641
540
  buffer: context.buffer.slice(i + 1),
642
- state: parseResultOrPromise,
541
+ state: result,
643
542
  optionsTerminated
644
543
  },
645
544
  consumed: context.buffer.slice(0, i + 1)
@@ -657,8 +556,13 @@ function argument(valueParser, options = {}) {
657
556
  };
658
557
  },
659
558
  suggest(_context, prefix) {
660
- if (isAsync) return suggestArgumentAsync(valueParser, options.hidden ?? false, prefix);
661
- return suggestArgumentSync(valueParser, options.hidden ?? false, prefix);
559
+ if (options.hidden) return [];
560
+ const suggestions = [];
561
+ if (valueParser.suggest) {
562
+ const valueSuggestions = valueParser.suggest(prefix);
563
+ suggestions.push(...valueSuggestions);
564
+ }
565
+ return suggestions;
662
566
  },
663
567
  getDocFragments(_state, defaultValue) {
664
568
  if (options.hidden) return {
@@ -680,52 +584,11 @@ function argument(valueParser, options = {}) {
680
584
  return `argument()`;
681
585
  }
682
586
  };
683
- return result;
684
- }
685
- function* suggestCommandSync(context, prefix, name, parser, options) {
686
- if (options.hidden) return;
687
- if (context.state === void 0) {
688
- if (name.startsWith(prefix)) yield {
689
- kind: "literal",
690
- text: name,
691
- ...options.description && { description: options.description }
692
- };
693
- } else if (context.state[0] === "matched") yield* parser.suggest({
694
- ...context,
695
- state: parser.initialState
696
- }, prefix);
697
- else if (context.state[0] === "parsing") yield* parser.suggest({
698
- ...context,
699
- state: context.state[1]
700
- }, prefix);
701
- }
702
- async function* suggestCommandAsync(context, prefix, name, parser, options) {
703
- if (options.hidden) return;
704
- if (context.state === void 0) {
705
- if (name.startsWith(prefix)) yield {
706
- kind: "literal",
707
- text: name,
708
- ...options.description && { description: options.description }
709
- };
710
- } else if (context.state[0] === "matched") {
711
- const suggestions = parser.suggest({
712
- ...context,
713
- state: parser.initialState
714
- }, prefix);
715
- for await (const s of suggestions) yield s;
716
- } else if (context.state[0] === "parsing") {
717
- const suggestions = parser.suggest({
718
- ...context,
719
- state: context.state[1]
720
- }, prefix);
721
- for await (const s of suggestions) yield s;
722
- }
723
587
  }
724
588
  /**
725
589
  * Creates a parser that matches a specific subcommand name and then applies
726
590
  * an inner parser to the remaining arguments.
727
591
  * This is useful for building CLI tools with subcommands like git, npm, etc.
728
- * @template M The execution mode of the parser.
729
592
  * @template T The type of the value returned by the inner parser.
730
593
  * @template TState The type of the state used by the inner parser.
731
594
  * @param name The subcommand name to match (e.g., `"show"`, `"edit"`).
@@ -736,9 +599,7 @@ async function* suggestCommandAsync(context, prefix, name, parser, options) {
736
599
  * to the inner parser for the remaining arguments.
737
600
  */
738
601
  function command(name, parser, options = {}) {
739
- const isAsync = parser.$mode === "async";
740
- const result = {
741
- $mode: parser.$mode,
602
+ return {
742
603
  $valueType: [],
743
604
  $stateType: [],
744
605
  priority: 15,
@@ -785,57 +646,33 @@ function command(name, parser, options = {}) {
785
646
  consumed: context.buffer.slice(0, 1)
786
647
  };
787
648
  } else if (context.state[0] === "matched") {
788
- const parseResultOrPromise = parser.parse({
649
+ const result = parser.parse({
789
650
  ...context,
790
651
  state: parser.initialState
791
652
  });
792
- if (isAsync) return parseResultOrPromise.then((parseResult$1) => {
793
- if (parseResult$1.success) return {
794
- success: true,
795
- next: {
796
- ...parseResult$1.next,
797
- state: ["parsing", parseResult$1.next.state]
798
- },
799
- consumed: parseResult$1.consumed
800
- };
801
- return parseResult$1;
802
- });
803
- const parseResult = parseResultOrPromise;
804
- if (parseResult.success) return {
653
+ if (result.success) return {
805
654
  success: true,
806
655
  next: {
807
- ...parseResult.next,
808
- state: ["parsing", parseResult.next.state]
656
+ ...result.next,
657
+ state: ["parsing", result.next.state]
809
658
  },
810
- consumed: parseResult.consumed
659
+ consumed: result.consumed
811
660
  };
812
- return parseResult;
661
+ return result;
813
662
  } else if (context.state[0] === "parsing") {
814
- const parseResultOrPromise = parser.parse({
663
+ const result = parser.parse({
815
664
  ...context,
816
665
  state: context.state[1]
817
666
  });
818
- if (isAsync) return parseResultOrPromise.then((parseResult$1) => {
819
- if (parseResult$1.success) return {
820
- success: true,
821
- next: {
822
- ...parseResult$1.next,
823
- state: ["parsing", parseResult$1.next.state]
824
- },
825
- consumed: parseResult$1.consumed
826
- };
827
- return parseResult$1;
828
- });
829
- const parseResult = parseResultOrPromise;
830
- if (parseResult.success) return {
667
+ if (result.success) return {
831
668
  success: true,
832
669
  next: {
833
- ...parseResult.next,
834
- state: ["parsing", parseResult.next.state]
670
+ ...result.next,
671
+ state: ["parsing", result.next.state]
835
672
  },
836
- consumed: parseResult.consumed
673
+ consumed: result.consumed
837
674
  };
838
- return parseResult;
675
+ return result;
839
676
  }
840
677
  return {
841
678
  success: false,
@@ -856,8 +693,28 @@ function command(name, parser, options = {}) {
856
693
  };
857
694
  },
858
695
  suggest(context, prefix) {
859
- if (isAsync) return suggestCommandAsync(context, prefix, name, parser, options);
860
- return suggestCommandSync(context, prefix, name, parser, options);
696
+ if (options.hidden) return [];
697
+ const suggestions = [];
698
+ if (context.state === void 0) {
699
+ if (name.startsWith(prefix)) suggestions.push({
700
+ kind: "literal",
701
+ text: name,
702
+ ...options.description && { description: options.description }
703
+ });
704
+ } else if (context.state[0] === "matched") {
705
+ const innerSuggestions = parser.suggest({
706
+ ...context,
707
+ state: parser.initialState
708
+ }, prefix);
709
+ suggestions.push(...innerSuggestions);
710
+ } else if (context.state[0] === "parsing") {
711
+ const innerSuggestions = parser.suggest({
712
+ ...context,
713
+ state: context.state[1]
714
+ }, prefix);
715
+ suggestions.push(...innerSuggestions);
716
+ }
717
+ return suggestions;
861
718
  },
862
719
  getDocFragments(state, defaultValue) {
863
720
  if (options.hidden) return {
@@ -893,7 +750,6 @@ function command(name, parser, options = {}) {
893
750
  return `command(${JSON.stringify(name)})`;
894
751
  }
895
752
  };
896
- return result;
897
753
  }
898
754
  /**
899
755
  * Creates a parser that collects unrecognized options and passes them through.
@@ -948,7 +804,6 @@ function passThrough(options = {}) {
948
804
  return {
949
805
  $valueType: [],
950
806
  $stateType: [],
951
- $mode: "sync",
952
807
  priority: -10,
953
808
  usage: [{
954
809
  type: "passthrough",