cli-kiss 0.2.7 → 0.2.8

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.
Files changed (39) hide show
  1. package/dist/index.d.ts +127 -137
  2. package/dist/index.js +2 -2
  3. package/dist/index.js.map +1 -1
  4. package/docs/.vitepress/config.mts +1 -1
  5. package/docs/.vitepress/theme/Layout.vue +16 -0
  6. package/docs/.vitepress/theme/index.ts +5 -1
  7. package/docs/.vitepress/theme/style.css +5 -1
  8. package/docs/guide/02_commands.md +1 -1
  9. package/docs/guide/03_options.md +11 -11
  10. package/docs/guide/05_input_types.md +9 -10
  11. package/docs/guide/06_run_as_cli.md +1 -1
  12. package/docs/index.md +2 -2
  13. package/docs/public/favicon.ico +0 -0
  14. package/docs/public/logo.png +0 -0
  15. package/package.json +1 -1
  16. package/src/index.ts +1 -1
  17. package/src/lib/Command.ts +45 -39
  18. package/src/lib/Operation.ts +28 -20
  19. package/src/lib/Option.ts +196 -127
  20. package/src/lib/Positional.ts +44 -23
  21. package/src/lib/Reader.ts +194 -226
  22. package/src/lib/Run.ts +19 -8
  23. package/src/lib/Suggest.ts +78 -0
  24. package/src/lib/Type.ts +36 -37
  25. package/src/lib/Typo.ts +58 -55
  26. package/src/lib/Usage.ts +12 -12
  27. package/tests/unit.Reader.commons.ts +92 -116
  28. package/tests/unit.Reader.parsings.ts +14 -26
  29. package/tests/unit.Reader.shortBig.ts +81 -96
  30. package/tests/unit.command.aliases.ts +100 -0
  31. package/tests/unit.command.execute.ts +1 -1
  32. package/tests/unit.command.usage.ts +12 -6
  33. package/tests/unit.fuzzed.alternatives.ts +35 -26
  34. package/tests/unit.runner.colors.ts +8 -33
  35. package/tests/unit.runner.cycle.ts +118 -146
  36. package/tests/unit.runner.errors.ts +25 -22
  37. package/docs/public/hero.png +0 -0
  38. package/src/lib/Similarity.ts +0 -41
  39. package/tests/unit.Reader.aliases.ts +0 -62
package/dist/index.d.ts CHANGED
@@ -1,47 +1,43 @@
1
1
  /**
2
- * Opaque key returned by {@link ReaderArgs.registerOption}.
3
2
  */
4
- type ReaderOptionKey = (string | {
5
- __brand: "ReaderOptionKey";
6
- }) & {
7
- __brand: "ReaderOptionKey";
3
+ type ReaderOptionLongSpec = {
4
+ key: string;
5
+ nextGuard: ReaderOptionNextGuard;
6
+ };
7
+ /**
8
+ */
9
+ type ReaderOptionShortSpec = {
10
+ key: string;
11
+ restGuard: ReaderOptionRestGuard;
12
+ nextGuard: ReaderOptionNextGuard;
8
13
  };
9
14
  /**
10
- * Parsing behaviour for a registered option, passed to {@link ReaderArgs.registerOption}.
11
15
  */
12
- type ReaderOptionParsing = {
13
- consumeShortGroup: boolean;
14
- consumeNextArg: (inlined: string | null, separated: Array<string>, nextArg: string | undefined) => boolean;
16
+ type ReaderOptionRestGuard = (rest: string) => boolean;
17
+ /**
18
+ */
19
+ type ReaderOptionNextGuard = (value: ReaderOptionValue, next: string | undefined) => boolean;
20
+ /**
21
+ */
22
+ type ReaderOptionResult = {
23
+ identifier: string;
24
+ values: ReadonlyArray<ReaderOptionValue>;
15
25
  };
16
26
  /**
17
- * Result of parsing an option, including its inlined value and any following separated values.
18
27
  */
19
28
  type ReaderOptionValue = {
20
29
  inlined: string | null;
21
- separated: Array<string>;
30
+ separated: ReadonlyArray<string>;
22
31
  };
32
+ /**
33
+ */
34
+ type ReaderOptionGetter = () => ReaderOptionResult;
23
35
  /**
24
36
  * Option registration/query interface. Subset of {@link ReaderArgs}.
25
37
  */
26
38
  type ReaderOptions = {
27
- /**
28
- * Registers an option; all `longs` and `shorts` share the same key.
29
- *
30
- * @param definition.longs - Long-form names (without `--`).
31
- * @param definition.shorts - Short-form names (without `-`).
32
- * @param definition.parsing - Parsing behaviour.
33
- * @returns A {@link ReaderOptionKey} for later retrieval.
34
- * @throws `Error` if a name is already registered or short names overlap.
35
- */
36
- registerOption(definition: {
37
- longs: Array<string>;
38
- shorts: Array<string>;
39
- parsing: ReaderOptionParsing;
40
- }): ReaderOptionKey;
41
- /**
42
- * Returns all values collected for `key`.
43
- */
44
- getOptionValues(key: ReaderOptionKey): Array<ReaderOptionValue>;
39
+ registerOptionLong(longSpec: ReaderOptionLongSpec): ReaderOptionGetter;
40
+ registerOptionShort(shortSpec: ReaderOptionShortSpec): ReaderOptionGetter;
45
41
  };
46
42
  /**
47
43
  * Positional consumption interface. Subset of {@link ReaderArgs}.
@@ -51,7 +47,7 @@ type ReaderPositionals = {
51
47
  * Returns the next positional token, parsing intervening options as side-effects.
52
48
  *
53
49
  * @returns The next positional, or `undefined` when exhausted.
54
- * @throws {@link TypoError} on an unrecognised option.
50
+ * @throws on an unrecognised option.
55
51
  */
56
52
  consumePositional(): string | undefined;
57
53
  };
@@ -67,38 +63,21 @@ type ReaderPositionals = {
67
63
  declare class ReaderArgs {
68
64
  #private;
69
65
  /**
70
- * @param args - Raw CLI tokens (e.g. `process.argv.slice(2)`). Not mutated.
66
+ * @param tokens - Raw CLI tokens (e.g. `process.argv.slice(2)`).
71
67
  */
72
- constructor(args: ReadonlyArray<string>);
68
+ constructor(tokens: ReadonlyArray<string>);
69
+ /**
70
+ */
71
+ registerOptionLong(longSpec: ReaderOptionLongSpec): ReaderOptionGetter;
73
72
  /**
74
- * Registers an option; all `longs` and `shorts` share the same key.
75
- * Short names must not be prefixes of one another.
76
- *
77
- * @param definition.longs - Long-form names (without `--`).
78
- * @param definition.shorts - Short-form names (without `-`).
79
- * @param definition.parsing - Parsing behaviour.
80
- * @returns A {@link ReaderOptionKey} for {@link ReaderArgs.getOptionValues}.
81
- * @throws `Error` if any name is already registered or short names overlap.
82
- */
83
- registerOption(definition: {
84
- longs: Array<string>;
85
- shorts: Array<string>;
86
- parsing: ReaderOptionParsing;
87
- }): ReaderOptionKey;
88
- /**
89
- * Returns all values collected for `key`.
90
- *
91
- * @param key - Key from {@link ReaderArgs.registerOption}.
92
- * @returns One entry per occurrence.
93
- * @throws `Error` if `key` was not registered.
94
73
  */
95
- getOptionValues(key: ReaderOptionKey): Array<ReaderOptionValue>;
74
+ registerOptionShort(shortSpec: ReaderOptionShortSpec): ReaderOptionGetter;
96
75
  /**
97
76
  * Returns the next positional token; parses intervening options as a side-effect.
98
77
  * All tokens after `--` are treated as positionals.
99
78
  *
100
79
  * @returns The next positional, or `undefined` when exhausted.
101
- * @throws {@link TypoError} on an unrecognised option.
80
+ * @throws on an unrecognised option.
102
81
  */
103
82
  consumePositional(): string | undefined;
104
83
  }
@@ -115,7 +94,7 @@ declare class ReaderArgs {
115
94
  */
116
95
  type Type<Value> = {
117
96
  /**
118
- * Human-readable name shown in help and errors (e.g. `"name"`, `"number"`).
97
+ * Human-readable name shown in help and errors (e.g. `"name"`, `"context"`).
119
98
  */
120
99
  content: string;
121
100
  /**
@@ -123,7 +102,7 @@ type Type<Value> = {
123
102
  *
124
103
  * @param input - Raw string from the command line.
125
104
  * @returns The decoded value.
126
- * @throws {@link TypoError} on invalid input.
105
+ * @throws on invalid input.
127
106
  */
128
107
  decoder(input: string): Value;
129
108
  };
@@ -142,8 +121,6 @@ type Type<Value> = {
142
121
  * ```
143
122
  */
144
123
  declare function typeBoolean(name?: string): Type<boolean>;
145
- declare const typeBooleanValuesTrue: Set<string>;
146
- declare const typeBooleanValuesFalse: Set<string>;
147
124
  /**
148
125
  * Parses a date/time string via `Date.parse`.
149
126
  * Accepts any format supported by `Date.parse`, including ISO 8601.
@@ -157,7 +134,7 @@ declare const typeBooleanValuesFalse: Set<string>;
157
134
  */
158
135
  declare function typeDatetime(name?: string): Type<Date>;
159
136
  /**
160
- * Parses a string to `number` via `Number()`; `NaN` throws {@link TypoError}.
137
+ * Parses a string to `number` via `Number()`; `NaN` throws.
161
138
  *
162
139
  * @example
163
140
  * ```ts
@@ -169,7 +146,7 @@ declare function typeDatetime(name?: string): Type<Date>;
169
146
  declare function typeNumber(name?: string): Type<number>;
170
147
  /**
171
148
  * Parses an integer string to `bigint` via `BigInt()`.
172
- * Floats and non-numeric strings throw {@link TypoError}.
149
+ * Floats and non-numeric strings throws.
173
150
  *
174
151
  * @example
175
152
  * ```ts
@@ -181,7 +158,7 @@ declare function typeNumber(name?: string): Type<number>;
181
158
  declare function typeInteger(name?: string): Type<bigint>;
182
159
  /**
183
160
  * Parses an absolute URL string to a `URL` object.
184
- * Relative or malformed URLs throw {@link TypoError}.
161
+ * Relative or malformed URLs throws.
185
162
  *
186
163
  * @example
187
164
  * ```ts
@@ -241,7 +218,6 @@ declare function typePath(name?: string, checks?: {
241
218
  }): Type<string>;
242
219
  /**
243
220
  * Creates a {@link Type}`<string>` that only accepts a fixed set of values.
244
- * Out-of-set inputs throw {@link TypoError} listing up to 5 valid options.
245
221
  *
246
222
  * @param name - Name shown in help and errors.
247
223
  * @param values - Ordered list of accepted values.
@@ -251,13 +227,13 @@ declare function typePath(name?: string, checks?: {
251
227
  * ```ts
252
228
  * const typeEnv = typeChoice("environment", ["dev", "staging", "prod"]);
253
229
  * typeEnv.decoder("prod") // → "prod"
254
- * typeEnv.decoder("unknown") // throws TypoError: Invalid value: "unknown" (expected one of: "dev" | "staging" | "prod")
230
+ * typeEnv.decoder("unknown") // throws
255
231
  * ```
256
232
  */
257
233
  declare function typeChoice<const Value extends string>(name: string, values: Array<Value>, caseSensitive?: boolean): Type<Value>;
258
234
  /**
259
235
  * Splits a delimited string into a typed tuple.
260
- * Each part is decoded by the corresponding element type; wrong count or decode failure throws {@link TypoError}.
236
+ * Each part is decoded by the corresponding element type; wrong count or decode failure throws.
261
237
  *
262
238
  * @typeParam Elements - Tuple of decoded value types (inferred from `elementTypes`).
263
239
  *
@@ -269,8 +245,9 @@ declare function typeChoice<const Value extends string>(name: string, values: Ar
269
245
  * ```ts
270
246
  * const typePoint = typeTuple([typeNumber("x"), typeNumber("y")]);
271
247
  * typePoint.decoder("3.14,2.71") // → [3.14, 2.71]
272
- * typePoint.decoder("1,2,3") // → [1, 2]
273
- * typePoint.decoder("x,2") // throws TypoError: at 0: Number: Unable to parse: "x"
248
+ * typePoint.decoder("1") // throws
249
+ * typePoint.decoder("1,2,3") // throws
250
+ * typePoint.decoder("x,2") // throws
274
251
  * ```
275
252
  */
276
253
  declare function typeTuple<const Elements extends Array<any>>(elementTypes: {
@@ -278,7 +255,7 @@ declare function typeTuple<const Elements extends Array<any>>(elementTypes: {
278
255
  }, separator?: string): Type<Elements>;
279
256
  /**
280
257
  * Splits a delimited string into a typed array.
281
- * Each part is decoded by `elementType`; failed decodes throw {@link TypoError}.
258
+ * Each part is decoded by `elementType`; failed decodes throws.
282
259
  * Note: splitting an empty string yields one empty element — prefer {@link optionRepeatable} for a zero-default.
283
260
  *
284
261
  * @typeParam Value - Element type produced by `elementType.decoder`.
@@ -289,10 +266,9 @@ declare function typeTuple<const Elements extends Array<any>>(elementTypes: {
289
266
  *
290
267
  * @example
291
268
  * ```ts
292
- * const typeNumbers = typeList(typeNumber);
269
+ * const typeNumbers = typeList(typeNumber("v"));
293
270
  * typeNumbers.decoder("1,2,3") // → [1, 2, 3]
294
- * typeNumbers.decoder("1,x,3") // throws TypoError: at 1: Number: Unable to parse: "x"
295
- *
271
+ * typeNumbers.decoder("1,x,3") // throws
296
272
  * const typePaths = typeList(typePath(), ":");
297
273
  * typePaths.decoder("/usr/bin:/usr/local/bin") // → ["/usr/bin", "/usr/local/bin"]
298
274
  * ```
@@ -381,9 +357,9 @@ declare class TypoString {
381
357
  #private;
382
358
  /**
383
359
  * @param value - Raw text content.
384
- * @param typoStyle - Style to apply when rendering. Defaults to `undefined` (no style).
360
+ * @param style - Style to apply when rendering.
385
361
  */
386
- constructor(value: string, typoStyle?: TypoStyle);
362
+ constructor(value: string, style?: TypoStyle);
387
363
  /**
388
364
  * Returns the text styled by `typoSupport`.
389
365
  *
@@ -394,11 +370,15 @@ declare class TypoString {
394
370
  * Returns the raw text.
395
371
  */
396
372
  getRawString(): string;
373
+ /**
374
+ * Predefined ellipsis segment with subtle styling.
375
+ */
376
+ static elipsis: TypoString;
397
377
  }
398
378
  /**
399
379
  * A segment of styled text, a string, or an array of segments.
400
380
  */
401
- type TypoSegment = TypoText | TypoString | string | Array<TypoSegment>;
381
+ type TypoSegment = TypoText | TypoString | Array<TypoSegment>;
402
382
  /**
403
383
  * Mutable sequence of {@link TypoString} segments.
404
384
  */
@@ -407,13 +387,15 @@ declare class TypoText {
407
387
  /**
408
388
  * @param segments - Initial text segments
409
389
  */
410
- constructor(...segments: TypoSegment[]);
390
+ constructor(...segments: Array<TypoSegment>);
411
391
  /**
412
392
  * Appends new text segment(s).
413
- *
414
- * @param segment - Text segment(s) to append.
415
393
  */
416
- push(segment: TypoSegment): void;
394
+ push(...segments: Array<TypoSegment>): void;
395
+ /**
396
+ * Appends separated segments, optionally truncating with an ellipsis.
397
+ */
398
+ pushJoined(segments: Array<TypoSegment>, separator: TypoSegment, ellipsisLimit: number): void;
417
399
  /**
418
400
  * Renders all segments into a single styled string.
419
401
  *
@@ -429,11 +411,6 @@ declare class TypoText {
429
411
  * Returns the total raw character count.
430
412
  */
431
413
  computeRawLength(): number;
432
- /**
433
- * Joins multiple segments with a separator.
434
- * @returns A new {@link TypoText} containing the joined segments.
435
- */
436
- static join(segments: Array<TypoSegment>, separator: TypoSegment): TypoText;
437
414
  }
438
415
  /**
439
416
  * Column-aligned grid of {@link TypoText} cells.
@@ -680,7 +657,7 @@ type Option<Value> = {
680
657
  /**
681
658
  * Registers the option on `readerOptions` and returns an {@link OptionDecoder}.
682
659
  */
683
- registerAndMakeDecoder(readerOptions: ReaderArgs): OptionDecoder<Value>;
660
+ registerAndMakeDecoder(readerOptions: ReaderOptions): OptionDecoder<Value>;
684
661
  };
685
662
  /**
686
663
  * Produced by {@link Option.registerAndMakeDecoder}.
@@ -691,15 +668,19 @@ type OptionDecoder<Value> = {
691
668
  /**
692
669
  * Returns the decoded option value.
693
670
  *
694
- * @throws {@link TypoError} if decoding failed.
671
+ * @throws if decoding failed.
695
672
  */
696
673
  getAndDecodeValue(): Value;
697
674
  };
698
675
  /**
699
676
  * Creates a boolean flag option (`--verbose`, optionally `--flag=no`).
700
677
  *
701
- * Parsing: absent → default value; `--flag` / `--flag=yes` `true`; `--flag=no` → `false`;
702
- * specified more than once → throws {@link TypoError}.
678
+ * Syntax: `--long`, `--long=no`, `-s`, `-s=no`.
679
+ * Parsing logic:
680
+ * - absent → default value
681
+ * - `--flag` / `--flag=yes` → `true`
682
+ * - `--flag=no` → `false`
683
+ * - specified more than once → throws.
703
684
  *
704
685
  * @param definition.long - Long-form name (without `--`).
705
686
  * @param definition.short - Short-form name (without `-`).
@@ -716,11 +697,6 @@ type OptionDecoder<Value> = {
716
697
  * short: "v",
717
698
  * description: "Enable verbose output",
718
699
  * });
719
- * // Usage:
720
- * // my-cli → false
721
- * // my-cli --verbose → true
722
- * // my-cli --verbose=yes → true
723
- * // my-cli -v=no → false
724
700
  * ```
725
701
  */
726
702
  declare function optionFlag(definition: {
@@ -737,8 +713,13 @@ declare function optionFlag(definition: {
737
713
  /**
738
714
  * Creates an option that accepts exactly one value (e.g. `--output dist/`).
739
715
  *
740
- * Parsing: absent `defaultValue()`; once decoded with `type`; more than once → {@link TypoError}.
741
- * Value syntax: `--long value`, `--long=value`, `-s value`, `-s=value`, `-svalue`.
716
+ * Syntax: `--long value`, `--long=value`, `-s value`, `-s=value`, `-svalue`.
717
+ * Parsing logic:
718
+ * - absent → `fallbackValueIfAbsent()`
719
+ * - `--long value` → decoded with `type.decoder("value")`
720
+ * - more than once → throws
721
+ * - if `impliedValueIfNotInlined` is not provided, then: `--long` / `-s` without a value → throws
722
+ * - if `impliedValueIfNotInlined` is provided, then: `--long` / `-s` without an inline value → `impliedValueIfNotInlined()`
742
723
  *
743
724
  * @typeParam Value - Type produced by the decoder.
744
725
  *
@@ -748,8 +729,8 @@ declare function optionFlag(definition: {
748
729
  * @param definition.hint - Short note shown in parentheses.
749
730
  * @param definition.aliases - Additional names.
750
731
  * @param definition.type - Decoder for the raw string value.
751
- * @param definition.defaultIfNotSpecified - Default value when the option is not specified at all.
752
- * @param definition.valueIfNothingInlined - Default value when the option is specified without an inline value (e.g. `--option` or `-o`).
732
+ * @param definition.fallbackValueIfAbsent - Default value when the option is not specified at all.
733
+ * @param definition.impliedValueIfNotInlined - Default value when the option is specified without an inline value (e.g. `--option` or `-o`).
753
734
  * @returns An {@link Option}`<Value>`.
754
735
  *
755
736
  * @example
@@ -759,12 +740,8 @@ declare function optionFlag(definition: {
759
740
  * short: "o",
760
741
  * type: typePath(),
761
742
  * description: "Output directory",
762
- * defaultIfNotSpecified: () => "dist",
743
+ * fallbackValueIfAbsent: () => "dist",
763
744
  * });
764
- * // Usage:
765
- * // my-cli → "dist"
766
- * // my-cli --output folder → "folder"
767
- * // my-cli -o folder → "folder"
768
745
  * ```
769
746
  */
770
747
  declare function optionSingleValue<Value>(definition: {
@@ -777,14 +754,16 @@ declare function optionSingleValue<Value>(definition: {
777
754
  shorts?: Array<string>;
778
755
  };
779
756
  type: Type<Value>;
780
- defaultIfNotSpecified: () => Value;
781
- valueIfNothingInlined?: () => Value;
757
+ fallbackValueIfAbsent?: () => Value;
758
+ impliedValueIfNotInlined?: () => Value;
782
759
  }): Option<Value>;
783
760
  /**
784
761
  * Creates an option that collects every occurrence into an array (e.g. `--file a.ts --file b.ts`).
785
762
  *
786
- * Parsing: absent `[]`; N occurrences array of N decoded values in order.
787
- * Value syntax: `--long value`, `--long=value`, `-s value`, `-s=value`, `-svalue`.
763
+ * Syntax: `--long value`, `--long=value`, `-s value`, `-s=value`, `-svalue`.
764
+ * Parsing logic:
765
+ * - absent → `[]`
766
+ * - N occurrences → array of N decoded values in order.
788
767
  *
789
768
  * @typeParam Value - Type produced by the decoder for each occurrence.
790
769
  *
@@ -805,7 +784,6 @@ declare function optionSingleValue<Value>(definition: {
805
784
  * label: "PATH",
806
785
  * description: "Input file (may be repeated)",
807
786
  * });
808
- * // Usage: my-cli --file a.ts --file b.ts → ["a.ts", "b.ts"]
809
787
  * ```
810
788
  */
811
789
  declare function optionRepeatable<Value>(definition: {
@@ -846,18 +824,24 @@ type PositionalDecoder<Value> = {
846
824
  /**
847
825
  * Returns the decoded positional value.
848
826
  *
849
- * @throws {@link TypoError} if decoding failed.
827
+ * @throws if decoding failed.
850
828
  */
851
829
  decodeValue(): Value;
852
830
  };
853
831
  /**
854
- * Creates a required positional — missing token throws {@link TypoError}.
832
+ * Creates a required positional — missing token throws.
833
+ *
834
+ * Syntax: `<type>`, e.g. `<NAME>`.
835
+ * Parsing logic:
836
+ * - "token" → decoded with `type.decoder("token")`
837
+ * - token missing → throws
855
838
  *
856
839
  * @typeParam Value - Type produced by the decoder.
857
840
  *
858
841
  * @param definition.description - Help text.
859
842
  * @param definition.hint - Short note shown in parentheses.
860
843
  * @param definition.type - Decoder for the raw token.
844
+ * @param definition.missing - Message shown when the token is missing.
861
845
  * @returns A {@link Positional}`<Value>`.
862
846
  *
863
847
  * @example
@@ -866,8 +850,6 @@ type PositionalDecoder<Value> = {
866
850
  * type: type("name"),
867
851
  * description: "The name to greet",
868
852
  * });
869
- * // Usage:
870
- * // my-cli Alice → "Alice"
871
853
  * ```
872
854
  */
873
855
  declare function positionalRequired<Value>(definition: {
@@ -878,6 +860,11 @@ declare function positionalRequired<Value>(definition: {
878
860
  /**
879
861
  * Creates an optional positional — absent token falls back to `default()`.
880
862
  *
863
+ * Syntax: `[type]`, e.g. `[NAME]`.
864
+ * Parsing logic:
865
+ * - "token" → decoded with `type.decoder("token")`
866
+ * - token missing → `default()`
867
+ *
881
868
  * @typeParam Value - Type produced by the decoder (or the default).
882
869
  *
883
870
  * @param definition.description - Help text.
@@ -894,9 +881,6 @@ declare function positionalRequired<Value>(definition: {
894
881
  * hint: "Defaults to \"world\"",
895
882
  * default: () => "world",
896
883
  * });
897
- * // Usage:
898
- * // my-cli → "world"
899
- * // my-cli Alice → "Alice"
900
884
  * ```
901
885
  */
902
886
  declare function positionalOptional<Value>(definition: {
@@ -909,6 +893,12 @@ declare function positionalOptional<Value>(definition: {
909
893
  * Creates a variadic positional that collects zero or more remaining tokens into an array.
910
894
  * Optionally stops at `endDelimiter` (consumed, not included).
911
895
  *
896
+ * Syntax: `[type]...`, e.g. `[NAME]...`.
897
+ * Parsing logic:
898
+ * - "a b ..." → decoded with `[type.decoder("a")`, `type.decoder("b"), ...]``
899
+ * - token missing → stops collection
900
+ * - endDelimiter encountered → stops collection
901
+ *
912
902
  * @typeParam Value - Type produced by the decoder for each token.
913
903
  *
914
904
  * @param definition.endDelimiter - Sentinel token that stops collection (consumed, not included).
@@ -923,9 +913,6 @@ declare function positionalOptional<Value>(definition: {
923
913
  * type: typePath(),
924
914
  * description: "Files to process",
925
915
  * });
926
- * // Usage:
927
- * // my-cli → []
928
- * // my-cli a.ts b.ts c.ts → ["a.ts", "b.ts", "c.ts"]
929
916
  * ```
930
917
  */
931
918
  declare function positionalVariadics<Value>(definition: {
@@ -973,7 +960,7 @@ type OperationDecoder<Context, Result> = {
973
960
  /**
974
961
  * Creates a ready-to-execute {@link OperationInterpreter}.
975
962
  *
976
- * @throws {@link TypoError} if parsing or decoding failed.
963
+ * @throws if parsing or decoding failed.
977
964
  */
978
965
  decodeAndMakeInterpreter(): OperationInterpreter<Context, Result>;
979
966
  };
@@ -1023,18 +1010,22 @@ type OperationInterpreter<Context, Result> = {
1023
1010
  * );
1024
1011
  * ```
1025
1012
  */
1026
- declare function operation<Context, Result, Options extends {
1013
+ declare function operation<Context, Result, const Options extends {
1027
1014
  [option: string]: any;
1028
- }, const Positionals extends Array<any>>(inputs: {
1029
- options: {
1015
+ } = {}, const Positionals extends Array<any> = []>(inputs: {
1016
+ options?: {
1030
1017
  [K in keyof Options]: Option<Options[K]>;
1031
1018
  };
1032
- positionals: {
1019
+ positionals?: {
1033
1020
  [K in keyof Positionals]: Positional<Positionals[K]>;
1034
1021
  };
1035
1022
  }, handler: (context: Context, inputs: {
1036
- options: Options;
1037
- positionals: Positionals;
1023
+ options: {
1024
+ [K in keyof Options]: Options[K];
1025
+ };
1026
+ positionals: {
1027
+ [K in keyof Positionals]: Positionals[K];
1028
+ };
1038
1029
  }) => Promise<Result>): Operation<Context, Result>;
1039
1030
 
1040
1031
  /**
@@ -1067,7 +1058,7 @@ type CommandDecoder<Context, Result> = {
1067
1058
  /**
1068
1059
  * Creates a ready-to-execute {@link CommandInterpreter}.
1069
1060
  *
1070
- * @throws {@link TypoError} if parsing or decoding failed.
1061
+ * @throws if parsing or decoding failed.
1071
1062
  */
1072
1063
  decodeAndMakeInterpreter(): CommandInterpreter<Context, Result>;
1073
1064
  };
@@ -1142,15 +1133,16 @@ type CommandInformation = {
1142
1133
  * const greet = command(
1143
1134
  * { description: "Greet a user" },
1144
1135
  * operation(
1145
- * { options: {}, positionals: [positionalRequired({ type: type("name") })] },
1136
+ * { positionals: [positionalRequired({ type: type("name") })] },
1146
1137
  * async (_ctx, { positionals: [name] }) => console.log(`Hello, ${name}!`),
1147
1138
  * ),
1148
1139
  * );
1149
1140
  * ```
1150
1141
  */
1151
- declare function command<Context, Result>(information: CommandInformation, operation: Operation<Context, Result>): Command<Context, Result>;
1142
+ declare function command<Context, Result = void>(information: CommandInformation, operation: Operation<Context, Result>): Command<Context, Result>;
1152
1143
  /**
1153
- * Creates a command that runs `operation` first, then dispatches to a named subcommand.
1144
+ * Creates a command that runs `operation` first,
1145
+ * then dispatches result to a named subcommand.
1154
1146
  *
1155
1147
  * @typeParam Context - Context accepted by `operation`.
1156
1148
  * @typeParam Payload - Output of `operation`; becomes the subcommand's context.
@@ -1173,12 +1165,12 @@ declare function command<Context, Result>(information: CommandInformation, opera
1173
1165
  * );
1174
1166
  * ```
1175
1167
  */
1176
- declare function commandWithSubcommands<Context, Payload, Result>(information: CommandInformation, operation: Operation<Context, Payload>, subcommands: {
1168
+ declare function commandWithSubcommands<Context, Payload, Result = void>(information: CommandInformation, operation: Operation<Context, Payload>, subcommands: {
1177
1169
  [subcommand: string]: Command<Payload, Result>;
1178
1170
  }): Command<Context, Result>;
1179
1171
  /**
1180
- * Chains an {@link Operation} and a {@link Command}: `operation` runs first, its
1181
- * output becomes `subcommand`'s context. No token is consumed for routing.
1172
+ * Chains an {@link Operation} and a {@link Command}: `operation` runs first,
1173
+ * its output becomes `subcommand`'s context. No token is consumed for routing.
1182
1174
  *
1183
1175
  * @typeParam Context - Context accepted by `operation`.
1184
1176
  * @typeParam Payload - Output of `operation`; becomes `subcommand`'s context.
@@ -1189,7 +1181,7 @@ declare function commandWithSubcommands<Context, Payload, Result>(information: C
1189
1181
  * @param subcommand - Runs after `operation`.
1190
1182
  * @returns A {@link Command} composing both stages.
1191
1183
  */
1192
- declare function commandChained<Context, Payload, Result>(information: CommandInformation, operation: Operation<Context, Payload>, subcommand: Command<Payload, Result>): Command<Context, Result>;
1184
+ declare function commandChained<Context, Payload, Result = void>(information: CommandInformation, operation: Operation<Context, Payload>, subcommand: Command<Payload, Result>): Command<Context, Result>;
1193
1185
 
1194
1186
  /**
1195
1187
  * Color selection modes availables
@@ -1246,11 +1238,9 @@ declare function runAndExit<Context>(cliName: string, cliArgs: ReadonlyArray<str
1246
1238
  onExit?: ((code: number) => never) | undefined;
1247
1239
  }): Promise<never>;
1248
1240
 
1249
- declare function similaritySort<Value>(reference: string, candidates: {
1250
- [key: string]: Value;
1251
- } | Array<{
1252
- key: string;
1253
- value: Value;
1254
- }>): Array<Value>;
1241
+ declare function suggestTextPushMessage(text: TypoText, query: string, candidates: Array<{
1242
+ reference: string;
1243
+ hint: TypoSegment;
1244
+ }>): void;
1255
1245
 
1256
- export { type Command, type CommandDecoder, type CommandInformation, type CommandInterpreter, type Operation, type OperationDecoder, type OperationInterpreter, type Option, type OptionDecoder, type Positional, type PositionalDecoder, ReaderArgs, type ReaderOptionKey, type ReaderOptionParsing, type ReaderOptionValue, type ReaderOptions, type ReaderPositionals, type RunColorMode, type Type, type TypoColor, TypoError, TypoGrid, type TypoSegment, TypoString, type TypoStyle, TypoSupport, TypoText, type UsageCommand, type UsageOption, type UsagePositional, type UsageSubcommand, command, commandChained, commandWithSubcommands, operation, optionFlag, optionRepeatable, optionSingleValue, positionalOptional, positionalRequired, positionalVariadics, runAndExit, similaritySort, type, typeBoolean, typeBooleanValuesFalse, typeBooleanValuesTrue, typeChoice, typeConverted, typeDatetime, typeInteger, typeList, typeNumber, typePath, typeRenamed, typeTuple, typeUrl, typoStyleConstants, typoStyleFailure, typoStyleLogic, typoStyleQuote, typoStyleRegularStrong, typoStyleRegularWeaker, typoStyleTitle, typoStyleUserInput, usageToStyledLines };
1246
+ export { type Command, type CommandDecoder, type CommandInformation, type CommandInterpreter, type Operation, type OperationDecoder, type OperationInterpreter, type Option, type OptionDecoder, type Positional, type PositionalDecoder, ReaderArgs, type ReaderOptionGetter, type ReaderOptionLongSpec, type ReaderOptionNextGuard, type ReaderOptionRestGuard, type ReaderOptionResult, type ReaderOptionShortSpec, type ReaderOptionValue, type ReaderOptions, type ReaderPositionals, type RunColorMode, type Type, type TypoColor, TypoError, TypoGrid, type TypoSegment, TypoString, type TypoStyle, TypoSupport, TypoText, type UsageCommand, type UsageOption, type UsagePositional, type UsageSubcommand, command, commandChained, commandWithSubcommands, operation, optionFlag, optionRepeatable, optionSingleValue, positionalOptional, positionalRequired, positionalVariadics, runAndExit, suggestTextPushMessage, type, typeBoolean, typeChoice, typeConverted, typeDatetime, typeInteger, typeList, typeNumber, typePath, typeRenamed, typeTuple, typeUrl, typoStyleConstants, typoStyleFailure, typoStyleLogic, typoStyleQuote, typoStyleRegularStrong, typoStyleRegularWeaker, typoStyleTitle, typoStyleUserInput, usageToStyledLines };