cli-kiss 0.2.2 → 0.2.4
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/README.md +1 -1
- package/dist/index.d.ts +711 -1046
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/docs/.vitepress/config.mts +1 -0
- package/docs/.vitepress/theme/index.ts +4 -0
- package/docs/.vitepress/theme/style.css +4 -0
- package/docs/guide/01_getting_started.md +4 -4
- package/docs/guide/02_commands.md +72 -41
- package/docs/guide/03_options.md +13 -14
- package/docs/guide/04_positionals.md +6 -8
- package/docs/guide/05_types.md +9 -11
- package/docs/guide/06_run.md +4 -5
- package/docs/index.md +8 -3
- package/docs/public/hero.png +0 -0
- package/package.json +1 -1
- package/src/lib/Command.ts +151 -275
- package/src/lib/Operation.ts +57 -95
- package/src/lib/Option.ts +194 -181
- package/src/lib/Positional.ts +54 -112
- package/src/lib/Reader.ts +155 -156
- package/src/lib/Run.ts +64 -69
- package/src/lib/Type.ts +89 -145
- package/src/lib/Typo.ts +131 -195
- package/src/lib/Usage.ts +203 -69
- package/tests/unit.Reader.aliases.ts +31 -15
- package/tests/unit.Reader.commons.ts +99 -43
- package/tests/unit.Reader.shortBig.ts +75 -31
- package/tests/unit.command.execute.ts +146 -91
- package/tests/unit.command.usage.ts +235 -114
- package/tests/unit.runner.cycle.ts +50 -20
- package/tests/unit.runner.errors.ts +19 -3
package/src/lib/Option.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ReaderArgs as ReaderOptions } from "./Reader";
|
|
1
|
+
import { ReaderOptionParsing, ReaderArgs as ReaderOptions } from "./Reader";
|
|
2
2
|
import { Type, typeBoolean } from "./Type";
|
|
3
3
|
import {
|
|
4
4
|
TypoError,
|
|
@@ -8,91 +8,51 @@ import {
|
|
|
8
8
|
typoStyleUserInput,
|
|
9
9
|
TypoText,
|
|
10
10
|
} from "./Typo";
|
|
11
|
+
import { UsageOption } from "./Usage";
|
|
11
12
|
|
|
12
13
|
/**
|
|
13
|
-
*
|
|
14
|
-
*
|
|
14
|
+
* A CLI option. Created with {@link optionFlag}, {@link optionSingleValue},
|
|
15
|
+
* or {@link optionRepeatable}.
|
|
15
16
|
*
|
|
16
|
-
*
|
|
17
|
-
* {@link optionRepeatable} and are passed via the `options` map of {@link operation}.
|
|
18
|
-
*
|
|
19
|
-
* @typeParam Value - The TypeScript type of the parsed option value.
|
|
20
|
-
* - `boolean` for flags created with {@link optionFlag}.
|
|
21
|
-
* - `T` for single-value options created with {@link optionSingleValue}.
|
|
22
|
-
* - `Array<T>` for repeatable options created with {@link optionRepeatable}.
|
|
17
|
+
* @typeParam Value - Decoded value type.
|
|
23
18
|
*/
|
|
24
19
|
export type Option<Value> = {
|
|
25
|
-
/** Returns human-readable metadata used to render the `Options:` section of help. */
|
|
26
|
-
generateUsage(): OptionUsage;
|
|
27
20
|
/**
|
|
28
|
-
*
|
|
29
|
-
* returns an {@link OptionParser} that can later retrieve the parsed value(s).
|
|
30
|
-
*
|
|
31
|
-
* @param readerOptions - The shared {@link ReaderArgs} that will parse the raw
|
|
32
|
-
* command-line tokens.
|
|
21
|
+
* Returns metadata for the `Options:` section.
|
|
33
22
|
*/
|
|
34
|
-
|
|
23
|
+
generateUsage(): UsageOption;
|
|
24
|
+
/**
|
|
25
|
+
* Registers the option on `readerOptions` and returns an {@link OptionDecoder}.
|
|
26
|
+
*/
|
|
27
|
+
registerAndMakeDecoder(readerOptions: ReaderOptions): OptionDecoder<Value>;
|
|
35
28
|
};
|
|
36
29
|
|
|
37
30
|
/**
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
* Returned by {@link Option.createParser} and called by {@link OperationFactory.createInstance}.
|
|
31
|
+
* Produced by {@link Option.registerAndMakeDecoder}.
|
|
41
32
|
*
|
|
42
|
-
* @typeParam Value -
|
|
43
|
-
*/
|
|
44
|
-
export type OptionParser<Value> = {
|
|
45
|
-
parseValue(): Value;
|
|
46
|
-
};
|
|
47
|
-
|
|
48
|
-
/**
|
|
49
|
-
* Human-readable metadata for a single CLI option, used to render the `Options:` section
|
|
50
|
-
* of the help output produced by {@link usageToStyledLines}.
|
|
33
|
+
* @typeParam Value - Decoded value type.
|
|
51
34
|
*/
|
|
52
|
-
export type
|
|
53
|
-
/** Short description of what the option does. */
|
|
54
|
-
description: string | undefined;
|
|
35
|
+
export type OptionDecoder<Value> = {
|
|
55
36
|
/**
|
|
56
|
-
*
|
|
57
|
-
*
|
|
58
|
-
|
|
59
|
-
hint: string | undefined;
|
|
60
|
-
/**
|
|
61
|
-
* The primary long-form name of the option, without the `--` prefix (e.g. `"verbose"`).
|
|
62
|
-
* The user passes this as `--verbose` on the command line.
|
|
63
|
-
*/
|
|
64
|
-
long: Lowercase<string>; // TODO - better type for long option names ?
|
|
65
|
-
/**
|
|
66
|
-
* The optional short-form name of the option, without the `-` prefix (e.g. `"v"`).
|
|
67
|
-
* The user passes this as `-v` on the command line.
|
|
68
|
-
*/
|
|
69
|
-
short: string | undefined;
|
|
70
|
-
/**
|
|
71
|
-
* The value placeholder label shown after the long option name in the help output
|
|
72
|
-
* (e.g. `"<FILE>"`). `undefined` for flags that take no value.
|
|
37
|
+
* Returns the decoded option value.
|
|
38
|
+
*
|
|
39
|
+
* @throws {@link TypoError} if decoding failed.
|
|
73
40
|
*/
|
|
74
|
-
|
|
41
|
+
getAndDecodeValue(): Value;
|
|
75
42
|
};
|
|
76
43
|
|
|
77
44
|
/**
|
|
78
|
-
* Creates a boolean flag option
|
|
79
|
-
* `--verbose`) to signal `true`, or can explicitly set with `--flag=true` / `--flag=no`.
|
|
45
|
+
* Creates a boolean flag option (`--verbose`, optionally `--flag=no`).
|
|
80
46
|
*
|
|
81
|
-
*
|
|
82
|
-
*
|
|
83
|
-
* - `--flag` / `--flag=true` / `--flag=yes` → `true`.
|
|
84
|
-
* - `--flag=false` / `--flag=no` → `false`.
|
|
85
|
-
* - Specified more than once → {@link TypoError} ("Must not be set multiple times").
|
|
47
|
+
* Parsing: absent → `false`; `--flag` / `--flag=yes` → `true`; `--flag=no` → `false`;
|
|
48
|
+
* specified more than once → {@link TypoError}.
|
|
86
49
|
*
|
|
87
|
-
* @param definition -
|
|
88
|
-
* @param definition.
|
|
89
|
-
* @param definition.
|
|
90
|
-
* @param definition.
|
|
91
|
-
* @param definition.
|
|
92
|
-
* @param definition.
|
|
93
|
-
* recognises as this flag.
|
|
94
|
-
* @param definition.default - Factory for the default value when the flag is absent.
|
|
95
|
-
* Defaults to `() => false` when omitted.
|
|
50
|
+
* @param definition.long - Long-form name (without `--`).
|
|
51
|
+
* @param definition.short - Short-form name (without `-`).
|
|
52
|
+
* @param definition.description - Help text.
|
|
53
|
+
* @param definition.hint - Short note shown in parentheses.
|
|
54
|
+
* @param definition.aliases - Additional names.
|
|
55
|
+
* @param definition.default - Default when absent. Defaults to `false`.
|
|
96
56
|
* @returns An {@link Option}`<boolean>`.
|
|
97
57
|
*
|
|
98
58
|
* @example
|
|
@@ -110,28 +70,44 @@ export function optionFlag(definition: {
|
|
|
110
70
|
description?: string;
|
|
111
71
|
hint?: string;
|
|
112
72
|
aliases?: { longs?: Array<Lowercase<string>>; shorts?: Array<string> };
|
|
113
|
-
default?:
|
|
73
|
+
default?: boolean;
|
|
114
74
|
}): Option<boolean> {
|
|
115
75
|
const label = `<${typeBoolean.content.toUpperCase()}>`;
|
|
116
76
|
return {
|
|
117
77
|
generateUsage() {
|
|
118
78
|
return {
|
|
119
|
-
description: definition.description,
|
|
120
|
-
hint: definition.hint,
|
|
121
|
-
long: definition.long,
|
|
122
79
|
short: definition.short,
|
|
80
|
+
long: definition.long,
|
|
123
81
|
label: undefined,
|
|
82
|
+
annotation: "[=no]",
|
|
83
|
+
description: definition.description,
|
|
84
|
+
hint: definition.hint,
|
|
124
85
|
};
|
|
125
86
|
},
|
|
126
|
-
|
|
127
|
-
const
|
|
128
|
-
|
|
129
|
-
|
|
87
|
+
registerAndMakeDecoder(readerOptions: ReaderOptions) {
|
|
88
|
+
const longNegative = `no-${definition.long}` as Lowercase<string>;
|
|
89
|
+
const aliasesLongsNegatives = definition.aliases?.longs?.map(
|
|
90
|
+
(aliasLong) => `no-${aliasLong}` as Lowercase<string>,
|
|
91
|
+
);
|
|
92
|
+
const keyNegative = registerOption(readerOptions, {
|
|
93
|
+
long: longNegative,
|
|
94
|
+
short: undefined,
|
|
95
|
+
aliasesShorts: undefined,
|
|
96
|
+
aliasesLongs: aliasesLongsNegatives,
|
|
97
|
+
parsing: { consumeShortGroup: false, consumeNextArg: () => false },
|
|
98
|
+
});
|
|
99
|
+
const keyPositive = registerOption(readerOptions, {
|
|
100
|
+
long: definition.long,
|
|
101
|
+
short: definition.short,
|
|
102
|
+
aliasesLongs: definition.aliases?.longs,
|
|
103
|
+
aliasesShorts: definition.aliases?.shorts,
|
|
104
|
+
parsing: { consumeShortGroup: false, consumeNextArg: () => false },
|
|
130
105
|
});
|
|
131
106
|
return {
|
|
132
|
-
|
|
133
|
-
const
|
|
134
|
-
|
|
107
|
+
getAndDecodeValue() {
|
|
108
|
+
const negativeResults = readerOptions.getOptionValues(keyNegative);
|
|
109
|
+
const positiveResults = readerOptions.getOptionValues(keyPositive);
|
|
110
|
+
if (positiveResults.length > 1) {
|
|
135
111
|
throw new TypoError(
|
|
136
112
|
new TypoText(
|
|
137
113
|
new TypoString(`--${definition.long}`, typoStyleConstants),
|
|
@@ -139,21 +115,49 @@ export function optionFlag(definition: {
|
|
|
139
115
|
),
|
|
140
116
|
);
|
|
141
117
|
}
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
118
|
+
if (negativeResults.length > 1) {
|
|
119
|
+
throw new TypoError(
|
|
120
|
+
new TypoText(
|
|
121
|
+
new TypoString(`--${longNegative}`, typoStyleConstants),
|
|
122
|
+
new TypoString(`: Must not be set multiple times`),
|
|
123
|
+
),
|
|
124
|
+
);
|
|
125
|
+
}
|
|
126
|
+
if (negativeResults.length > 0 && positiveResults.length > 0) {
|
|
127
|
+
throw new TypoError(
|
|
128
|
+
new TypoText(
|
|
129
|
+
new TypoString(`--${definition.long}`, typoStyleConstants),
|
|
130
|
+
new TypoString(`: Must not be set in combination with: `),
|
|
131
|
+
new TypoString(`--${longNegative}`, typoStyleConstants),
|
|
132
|
+
),
|
|
133
|
+
);
|
|
134
|
+
}
|
|
135
|
+
if (negativeResults.length > 0) {
|
|
136
|
+
const negativeResult = negativeResults[0]!;
|
|
137
|
+
if (negativeResult.inlined) {
|
|
147
138
|
throw new TypoError(
|
|
148
139
|
new TypoText(
|
|
149
|
-
new TypoString(`--${
|
|
150
|
-
new TypoString(`:
|
|
140
|
+
new TypoString(`--${longNegative}`, typoStyleConstants),
|
|
141
|
+
new TypoString(`: Must not have a value`),
|
|
151
142
|
),
|
|
152
|
-
error,
|
|
153
143
|
);
|
|
154
144
|
}
|
|
145
|
+
return false;
|
|
155
146
|
}
|
|
156
|
-
|
|
147
|
+
if (positiveResults.length > 0) {
|
|
148
|
+
const positiveResult = positiveResults[0]!;
|
|
149
|
+
return decodeValue({
|
|
150
|
+
long: definition.long,
|
|
151
|
+
short: definition.short,
|
|
152
|
+
label,
|
|
153
|
+
type: typeBoolean,
|
|
154
|
+
input:
|
|
155
|
+
positiveResult.inlined === null
|
|
156
|
+
? "true"
|
|
157
|
+
: positiveResult.inlined,
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
return definition.default ?? false;
|
|
157
161
|
},
|
|
158
162
|
};
|
|
159
163
|
},
|
|
@@ -161,32 +165,21 @@ export function optionFlag(definition: {
|
|
|
161
165
|
}
|
|
162
166
|
|
|
163
167
|
/**
|
|
164
|
-
* Creates an option that accepts exactly one value (e.g. `--output dist/`
|
|
165
|
-
* `--output=dist/`).
|
|
166
|
-
*
|
|
167
|
-
* **Parsing rules:**
|
|
168
|
-
* - Absent → `definition.default()` is called. If the default factory throws, a
|
|
169
|
-
* {@link TypoError} is produced.
|
|
170
|
-
* - Specified once → the value is decoded with `definition.type`.
|
|
171
|
-
* - Specified more than once → {@link TypoError} ("Requires a single value, but got
|
|
172
|
-
* multiple").
|
|
168
|
+
* Creates an option that accepts exactly one value (e.g. `--output dist/`).
|
|
173
169
|
*
|
|
174
|
-
*
|
|
175
|
-
* `-s=value`,
|
|
170
|
+
* Parsing: absent → `default()`; once → decoded with `type`; more than once → {@link TypoError}.
|
|
171
|
+
* Value syntax: `--long value`, `--long=value`, `-s value`, `-s=value`, `-svalue`.
|
|
176
172
|
*
|
|
177
|
-
* @typeParam Value -
|
|
173
|
+
* @typeParam Value - Type produced by the decoder.
|
|
178
174
|
*
|
|
179
|
-
* @param definition -
|
|
180
|
-
* @param definition.
|
|
181
|
-
* @param definition.
|
|
182
|
-
* @param definition.
|
|
183
|
-
* @param definition.
|
|
184
|
-
* @param definition.
|
|
185
|
-
* @param definition.
|
|
186
|
-
*
|
|
187
|
-
* @param definition.type - The {@link Type} used to decode the raw string value.
|
|
188
|
-
* @param definition.default - Factory for the default value when the option is absent.
|
|
189
|
-
* Throw an error from this factory to make the option effectively required.
|
|
175
|
+
* @param definition.long - Long-form name (without `--`).
|
|
176
|
+
* @param definition.short - Short-form name (without `-`).
|
|
177
|
+
* @param definition.description - Help text.
|
|
178
|
+
* @param definition.hint - Short note shown in parentheses.
|
|
179
|
+
* @param definition.aliases - Additional names.
|
|
180
|
+
* @param definition.label - Value placeholder in help. Defaults to uppercased `type.content`.
|
|
181
|
+
* @param definition.type - Decoder for the raw string value.
|
|
182
|
+
* @param definition.default - Default when absent. Throw to make the option required.
|
|
190
183
|
* @returns An {@link Option}`<Value>`.
|
|
191
184
|
*
|
|
192
185
|
* @example
|
|
@@ -215,22 +208,30 @@ export function optionSingleValue<Value>(definition: {
|
|
|
215
208
|
return {
|
|
216
209
|
generateUsage() {
|
|
217
210
|
return {
|
|
218
|
-
description: definition.description,
|
|
219
|
-
hint: definition.hint,
|
|
220
|
-
long: definition.long,
|
|
221
211
|
short: definition.short,
|
|
212
|
+
long: definition.long,
|
|
222
213
|
label: label as Uppercase<string>,
|
|
214
|
+
annotation: undefined,
|
|
215
|
+
description: definition.description,
|
|
216
|
+
hint: definition.hint,
|
|
223
217
|
};
|
|
224
218
|
},
|
|
225
|
-
|
|
219
|
+
registerAndMakeDecoder(readerOptions: ReaderOptions) {
|
|
226
220
|
const key = registerOption(readerOptions, {
|
|
227
|
-
|
|
228
|
-
|
|
221
|
+
long: definition.long,
|
|
222
|
+
short: definition.short,
|
|
223
|
+
aliasesLongs: definition.aliases?.longs,
|
|
224
|
+
aliasesShorts: definition.aliases?.shorts,
|
|
225
|
+
parsing: {
|
|
226
|
+
consumeShortGroup: true,
|
|
227
|
+
consumeNextArg: (inlined, separated) =>
|
|
228
|
+
inlined === null && separated.length === 0,
|
|
229
|
+
},
|
|
229
230
|
});
|
|
230
231
|
return {
|
|
231
|
-
|
|
232
|
-
const
|
|
233
|
-
if (
|
|
232
|
+
getAndDecodeValue() {
|
|
233
|
+
const optionResults = readerOptions.getOptionValues(key);
|
|
234
|
+
if (optionResults.length > 1) {
|
|
234
235
|
throw new TypoError(
|
|
235
236
|
new TypoText(
|
|
236
237
|
new TypoString(`--${definition.long}`, typoStyleConstants),
|
|
@@ -238,8 +239,8 @@ export function optionSingleValue<Value>(definition: {
|
|
|
238
239
|
),
|
|
239
240
|
);
|
|
240
241
|
}
|
|
241
|
-
const
|
|
242
|
-
if (
|
|
242
|
+
const optionResult = optionResults[0];
|
|
243
|
+
if (optionResult === undefined) {
|
|
243
244
|
try {
|
|
244
245
|
return definition.default();
|
|
245
246
|
} catch (error) {
|
|
@@ -252,12 +253,13 @@ export function optionSingleValue<Value>(definition: {
|
|
|
252
253
|
);
|
|
253
254
|
}
|
|
254
255
|
}
|
|
255
|
-
return decodeValue(
|
|
256
|
-
definition.long,
|
|
256
|
+
return decodeValue({
|
|
257
|
+
long: definition.long,
|
|
258
|
+
short: definition.short,
|
|
257
259
|
label,
|
|
258
|
-
definition.type,
|
|
259
|
-
|
|
260
|
-
);
|
|
260
|
+
type: definition.type,
|
|
261
|
+
input: optionResult.inlined ?? optionResult.separated[0]!,
|
|
262
|
+
});
|
|
261
263
|
},
|
|
262
264
|
};
|
|
263
265
|
},
|
|
@@ -265,30 +267,20 @@ export function optionSingleValue<Value>(definition: {
|
|
|
265
267
|
}
|
|
266
268
|
|
|
267
269
|
/**
|
|
268
|
-
* Creates an option that
|
|
269
|
-
* values into an array (e.g. `--file a.ts --file b.ts`).
|
|
270
|
-
*
|
|
271
|
-
* **Parsing rules:**
|
|
272
|
-
* - Absent → empty array `[]`.
|
|
273
|
-
* - Specified N times → array of N decoded values, in the order they appear on the
|
|
274
|
-
* command line.
|
|
275
|
-
* - Each occurrence is decoded independently with `definition.type`.
|
|
270
|
+
* Creates an option that collects every occurrence into an array (e.g. `--file a.ts --file b.ts`).
|
|
276
271
|
*
|
|
277
|
-
*
|
|
278
|
-
* `-s=value`,
|
|
272
|
+
* Parsing: absent → `[]`; N occurrences → array of N decoded values in order.
|
|
273
|
+
* Value syntax: `--long value`, `--long=value`, `-s value`, `-s=value`, `-svalue`.
|
|
279
274
|
*
|
|
280
|
-
* @typeParam Value -
|
|
281
|
-
* occurrence.
|
|
275
|
+
* @typeParam Value - Type produced by the decoder for each occurrence.
|
|
282
276
|
*
|
|
283
|
-
* @param definition -
|
|
284
|
-
* @param definition.
|
|
285
|
-
* @param definition.
|
|
286
|
-
* @param definition.
|
|
287
|
-
* @param definition.
|
|
288
|
-
* @param definition.
|
|
289
|
-
* @param definition.
|
|
290
|
-
* Defaults to the uppercased `type.content`.
|
|
291
|
-
* @param definition.type - The {@link Type} used to decode each raw string value.
|
|
277
|
+
* @param definition.long - Long-form name (without `--`).
|
|
278
|
+
* @param definition.short - Short-form name (without `-`).
|
|
279
|
+
* @param definition.description - Help text.
|
|
280
|
+
* @param definition.hint - Short note shown in parentheses.
|
|
281
|
+
* @param definition.aliases - Additional names.
|
|
282
|
+
* @param definition.label - Value placeholder in help. Defaults to uppercased `type.content`.
|
|
283
|
+
* @param definition.type - Decoder applied to each raw string value.
|
|
292
284
|
* @returns An {@link Option}`<Array<Value>>`.
|
|
293
285
|
*
|
|
294
286
|
* @example
|
|
@@ -317,23 +309,37 @@ export function optionRepeatable<Value>(definition: {
|
|
|
317
309
|
generateUsage() {
|
|
318
310
|
// TODO - showcase that it can be repeated ?
|
|
319
311
|
return {
|
|
320
|
-
description: definition.description,
|
|
321
|
-
hint: definition.hint,
|
|
322
|
-
long: definition.long,
|
|
323
312
|
short: definition.short,
|
|
313
|
+
long: definition.long,
|
|
324
314
|
label: label as Uppercase<string>,
|
|
315
|
+
annotation: " [*]",
|
|
316
|
+
description: definition.description,
|
|
317
|
+
hint: definition.hint,
|
|
325
318
|
};
|
|
326
319
|
},
|
|
327
|
-
|
|
320
|
+
registerAndMakeDecoder(readerOptions: ReaderOptions) {
|
|
328
321
|
const key = registerOption(readerOptions, {
|
|
329
|
-
|
|
330
|
-
|
|
322
|
+
long: definition.long,
|
|
323
|
+
short: definition.short,
|
|
324
|
+
aliasesLongs: definition.aliases?.longs,
|
|
325
|
+
aliasesShorts: definition.aliases?.shorts,
|
|
326
|
+
parsing: {
|
|
327
|
+
consumeShortGroup: true,
|
|
328
|
+
consumeNextArg: (inlined, separated) =>
|
|
329
|
+
inlined === null && separated.length === 0,
|
|
330
|
+
},
|
|
331
331
|
});
|
|
332
332
|
return {
|
|
333
|
-
|
|
334
|
-
const
|
|
335
|
-
return
|
|
336
|
-
decodeValue(
|
|
333
|
+
getAndDecodeValue() {
|
|
334
|
+
const optionResults = readerOptions.getOptionValues(key);
|
|
335
|
+
return optionResults.map((optionResult) =>
|
|
336
|
+
decodeValue({
|
|
337
|
+
long: definition.long,
|
|
338
|
+
short: definition.short,
|
|
339
|
+
label,
|
|
340
|
+
type: definition.type,
|
|
341
|
+
input: optionResult.inlined ?? optionResult.separated[0]!,
|
|
342
|
+
}),
|
|
337
343
|
);
|
|
338
344
|
},
|
|
339
345
|
};
|
|
@@ -341,22 +347,28 @@ export function optionRepeatable<Value>(definition: {
|
|
|
341
347
|
};
|
|
342
348
|
}
|
|
343
349
|
|
|
344
|
-
function decodeValue<Value>(
|
|
345
|
-
long: string
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
+
function decodeValue<Value>(params: {
|
|
351
|
+
long: string;
|
|
352
|
+
short: string | undefined;
|
|
353
|
+
label: string;
|
|
354
|
+
type: Type<Value>;
|
|
355
|
+
input: string;
|
|
356
|
+
}): Value {
|
|
350
357
|
return TypoError.tryWithContext(
|
|
351
|
-
() => type.decoder(
|
|
352
|
-
() =>
|
|
353
|
-
new TypoText(
|
|
354
|
-
|
|
355
|
-
new TypoString(
|
|
356
|
-
new TypoString(
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
)
|
|
358
|
+
() => params.type.decoder(params.input),
|
|
359
|
+
() => {
|
|
360
|
+
const text = new TypoText();
|
|
361
|
+
if (params.short) {
|
|
362
|
+
text.push(new TypoString(`-${params.short}`, typoStyleConstants));
|
|
363
|
+
text.push(new TypoString(`, `));
|
|
364
|
+
}
|
|
365
|
+
text.push(new TypoString(`--${params.long}`, typoStyleConstants));
|
|
366
|
+
text.push(new TypoString(`: `));
|
|
367
|
+
text.push(new TypoString(params.label, typoStyleUserInput));
|
|
368
|
+
text.push(new TypoString(`: `));
|
|
369
|
+
text.push(new TypoString(params.type.content, typoStyleLogic));
|
|
370
|
+
return text;
|
|
371
|
+
},
|
|
360
372
|
);
|
|
361
373
|
}
|
|
362
374
|
|
|
@@ -364,19 +376,20 @@ function registerOption(
|
|
|
364
376
|
readerOptions: ReaderOptions,
|
|
365
377
|
definition: {
|
|
366
378
|
long: Lowercase<string>;
|
|
367
|
-
short
|
|
368
|
-
|
|
369
|
-
|
|
379
|
+
short: undefined | string;
|
|
380
|
+
aliasesLongs: undefined | Array<Lowercase<string>>;
|
|
381
|
+
aliasesShorts: undefined | Array<string>;
|
|
382
|
+
parsing: ReaderOptionParsing;
|
|
370
383
|
},
|
|
371
384
|
) {
|
|
372
|
-
const { long, short,
|
|
385
|
+
const { long, short, aliasesLongs, aliasesShorts, parsing } = definition;
|
|
373
386
|
const longs = long ? [long] : [];
|
|
374
|
-
if (
|
|
375
|
-
longs.push(...
|
|
387
|
+
if (aliasesLongs) {
|
|
388
|
+
longs.push(...aliasesLongs);
|
|
376
389
|
}
|
|
377
390
|
const shorts = short ? [short] : [];
|
|
378
|
-
if (
|
|
379
|
-
shorts.push(...
|
|
391
|
+
if (aliasesShorts) {
|
|
392
|
+
shorts.push(...aliasesShorts);
|
|
380
393
|
}
|
|
381
|
-
return readerOptions.registerOption({ longs, shorts,
|
|
394
|
+
return readerOptions.registerOption({ longs, shorts, parsing });
|
|
382
395
|
}
|