cli-kiss 0.2.3 → 0.2.5
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 +696 -734
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/docs/.vitepress/config.mts +2 -3
- package/docs/.vitepress/theme/index.ts +4 -0
- package/docs/.vitepress/theme/style.css +4 -0
- package/docs/guide/01_getting_started.md +12 -13
- package/docs/guide/02_commands.md +71 -52
- package/docs/guide/03_options.md +25 -33
- package/docs/guide/04_positionals.md +45 -55
- package/docs/guide/05_types.md +66 -66
- package/docs/guide/06_run.md +28 -40
- package/docs/index.md +8 -3
- package/docs/public/favicon.ico +0 -0
- package/docs/public/hero.png +0 -0
- package/package.json +1 -1
- package/src/index.ts +0 -2
- package/src/lib/Command.ts +45 -123
- package/src/lib/Operation.ts +23 -32
- package/src/lib/Option.ts +150 -170
- package/src/lib/Positional.ts +44 -94
- package/src/lib/Reader.ts +123 -99
- package/src/lib/Run.ts +86 -45
- package/src/lib/Type.ts +246 -156
- package/src/lib/Typo.ts +98 -107
- package/src/lib/Usage.ts +163 -82
- package/tests/unit.Reader.aliases.ts +31 -15
- package/tests/unit.Reader.commons.ts +99 -43
- package/tests/unit.Reader.parsings.ts +50 -0
- package/tests/unit.Reader.shortBig.ts +75 -31
- package/tests/unit.command.execute.ts +86 -43
- package/tests/unit.command.usage.ts +88 -82
- package/tests/unit.runner.colors.ts +197 -0
- package/tests/unit.runner.cycle.ts +77 -63
- package/tests/unit.runner.errors.ts +23 -15
package/src/lib/Usage.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { CommandInformation } from "./Command";
|
|
2
2
|
import {
|
|
3
3
|
TypoGrid,
|
|
4
4
|
TypoString,
|
|
@@ -13,7 +13,99 @@ import {
|
|
|
13
13
|
} from "./Typo";
|
|
14
14
|
|
|
15
15
|
/**
|
|
16
|
-
*
|
|
16
|
+
* Usage model. Produced by {@link CommandDecoder.generateUsage}, consumed by {@link usageToStyledLines}.
|
|
17
|
+
*/
|
|
18
|
+
export type UsageCommand = {
|
|
19
|
+
/**
|
|
20
|
+
* Segments of the usage line
|
|
21
|
+
*/
|
|
22
|
+
segments: Array<{ positional: string } | { subcommand: string }>;
|
|
23
|
+
/**
|
|
24
|
+
* Command metadata.
|
|
25
|
+
*/
|
|
26
|
+
information: CommandInformation;
|
|
27
|
+
/**
|
|
28
|
+
* Positionals in declaration order.
|
|
29
|
+
*/
|
|
30
|
+
positionals: Array<UsagePositional>;
|
|
31
|
+
/**
|
|
32
|
+
* Subcommands, populated when none was selected.
|
|
33
|
+
*/
|
|
34
|
+
subcommands: Array<UsageSubcommand>;
|
|
35
|
+
/**
|
|
36
|
+
* Options in registration order.
|
|
37
|
+
*/
|
|
38
|
+
options: Array<UsageOption>;
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Positional metadata for the `Positionals:` section of help.
|
|
43
|
+
*/
|
|
44
|
+
export type UsagePositional = {
|
|
45
|
+
/**
|
|
46
|
+
* Help text.
|
|
47
|
+
*/
|
|
48
|
+
description?: string | undefined;
|
|
49
|
+
/**
|
|
50
|
+
* Short note shown in parentheses.
|
|
51
|
+
*/
|
|
52
|
+
hint?: string | undefined;
|
|
53
|
+
/**
|
|
54
|
+
* Placeholder label shown in the usage line and the `Positionals:` section.
|
|
55
|
+
*/
|
|
56
|
+
label: string;
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Entry in the `Subcommands:` section.
|
|
61
|
+
*/
|
|
62
|
+
export type UsageSubcommand = {
|
|
63
|
+
/**
|
|
64
|
+
* Token the user types (e.g. `"deploy"`).
|
|
65
|
+
*/
|
|
66
|
+
name: string;
|
|
67
|
+
/**
|
|
68
|
+
* From {@link CommandInformation.description}.
|
|
69
|
+
*/
|
|
70
|
+
description?: string | undefined;
|
|
71
|
+
/**
|
|
72
|
+
* From {@link CommandInformation.hint}.
|
|
73
|
+
*/
|
|
74
|
+
hint?: string | undefined;
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Option metadata for the `Options:` section of help.
|
|
79
|
+
*/
|
|
80
|
+
export type UsageOption = {
|
|
81
|
+
/**
|
|
82
|
+
* Short-form name without `-` (e.g. `"v"`).
|
|
83
|
+
*/
|
|
84
|
+
short?: string | undefined;
|
|
85
|
+
/**
|
|
86
|
+
* Long-form name without `--` (e.g. `"verbose"`).
|
|
87
|
+
*/
|
|
88
|
+
long: string;
|
|
89
|
+
/**
|
|
90
|
+
* Value placeholder in help (e.g. `"<FILE>"`).
|
|
91
|
+
*/
|
|
92
|
+
label?: string | undefined;
|
|
93
|
+
/**
|
|
94
|
+
* Extra annotation appended to the option label in help.
|
|
95
|
+
*/
|
|
96
|
+
annotation?: string | undefined;
|
|
97
|
+
/**
|
|
98
|
+
* Help text.
|
|
99
|
+
*/
|
|
100
|
+
description?: string | undefined;
|
|
101
|
+
/**
|
|
102
|
+
* Short note shown in parentheses.
|
|
103
|
+
*/
|
|
104
|
+
hint?: string | undefined;
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Converts a {@link UsageCommand} model into an array of styled lines ready to be
|
|
17
109
|
* joined with `"\n"` and printed to the terminal.
|
|
18
110
|
*
|
|
19
111
|
* The output format is:
|
|
@@ -30,7 +122,7 @@ import {
|
|
|
30
122
|
* <name> <description> (<hint>)
|
|
31
123
|
*
|
|
32
124
|
* Options:
|
|
33
|
-
* -s, --long <LABEL> <description> (<hint>)
|
|
125
|
+
* -s, --long <LABEL><annotation> <description> (<hint>)
|
|
34
126
|
*
|
|
35
127
|
* Examples:
|
|
36
128
|
* <description>
|
|
@@ -39,102 +131,94 @@ import {
|
|
|
39
131
|
* ```
|
|
40
132
|
* Sections that have no entries are omitted. The trailing empty line is always included.
|
|
41
133
|
*
|
|
42
|
-
* Column alignment
|
|
43
|
-
* in each column sets the width for the entire section.
|
|
134
|
+
* Column alignment per section via {@link TypoGrid}.
|
|
44
135
|
*
|
|
45
136
|
* @param params.cliName - Program name for the usage line.
|
|
46
|
-
* @param params.
|
|
137
|
+
* @param params.usage - From {@link CommandDecoder.generateUsage}.
|
|
47
138
|
* @param params.typoSupport - Rendering mode.
|
|
48
|
-
* @returns
|
|
139
|
+
* @returns Styled lines; includes a trailing empty string.
|
|
49
140
|
*
|
|
50
141
|
* @example
|
|
51
142
|
* ```ts
|
|
52
143
|
* const lines = usageToStyledLines({
|
|
53
144
|
* cliName: "my-cli",
|
|
54
|
-
*
|
|
145
|
+
* usage: commandDecoder.generateUsage(),
|
|
55
146
|
* typoSupport: TypoSupport.tty(),
|
|
56
147
|
* });
|
|
57
148
|
* process.stdout.write(lines.join("\n"));
|
|
58
149
|
* ```
|
|
59
150
|
*/
|
|
60
151
|
export function usageToStyledLines(params: {
|
|
61
|
-
cliName:
|
|
62
|
-
|
|
152
|
+
cliName: string;
|
|
153
|
+
usage: UsageCommand;
|
|
63
154
|
typoSupport: TypoSupport;
|
|
64
155
|
}) {
|
|
65
|
-
const { cliName,
|
|
156
|
+
const { cliName, usage, typoSupport } = params;
|
|
66
157
|
|
|
67
158
|
const lines = new Array<string>();
|
|
68
159
|
|
|
69
|
-
const
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
}),
|
|
84
|
-
);
|
|
85
|
-
lines.push(segments.join(" "));
|
|
160
|
+
const segmentsText = new TypoText();
|
|
161
|
+
segmentsText.push(textUsageHero("Usage:"));
|
|
162
|
+
segmentsText.push(textDelimiter(" "));
|
|
163
|
+
segmentsText.push(textConstants(cliName));
|
|
164
|
+
for (const segment of usage.segments) {
|
|
165
|
+
segmentsText.push(textDelimiter(" "));
|
|
166
|
+
if ("positional" in segment) {
|
|
167
|
+
segmentsText.push(textUserInput(segment.positional));
|
|
168
|
+
}
|
|
169
|
+
if ("subcommand" in segment) {
|
|
170
|
+
segmentsText.push(textConstants(segment.subcommand));
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
lines.push(segmentsText.computeStyledString(typoSupport));
|
|
86
174
|
|
|
87
175
|
lines.push("");
|
|
88
176
|
const introText = new TypoText();
|
|
89
|
-
introText.
|
|
90
|
-
if (
|
|
91
|
-
introText.
|
|
92
|
-
introText.
|
|
177
|
+
introText.push(textUsageText(usage.information.description));
|
|
178
|
+
if (usage.information.hint) {
|
|
179
|
+
introText.push(textDelimiter(" "));
|
|
180
|
+
introText.push(textSubtleInfo(`(${usage.information.hint})`));
|
|
93
181
|
}
|
|
94
182
|
lines.push(introText.computeStyledString(typoSupport));
|
|
95
|
-
for (const detail of
|
|
183
|
+
for (const detail of usage.information.details ?? []) {
|
|
96
184
|
const detailText = new TypoText();
|
|
97
|
-
detailText.
|
|
185
|
+
detailText.push(textSubtleInfo(detail));
|
|
98
186
|
lines.push(detailText.computeStyledString(typoSupport));
|
|
99
187
|
}
|
|
100
188
|
|
|
101
|
-
if (
|
|
189
|
+
if (usage.positionals.length > 0) {
|
|
102
190
|
lines.push("");
|
|
103
191
|
lines.push(textBlockTitle("Positionals:").computeStyledString(typoSupport));
|
|
104
192
|
const typoGrid = new TypoGrid();
|
|
105
|
-
for (const positionalUsage of
|
|
193
|
+
for (const positionalUsage of usage.positionals) {
|
|
106
194
|
const typoGridRow = new Array<TypoText>();
|
|
107
195
|
typoGridRow.push(new TypoText(textDelimiter(" ")));
|
|
108
196
|
typoGridRow.push(new TypoText(textUserInput(positionalUsage.label)));
|
|
109
197
|
typoGridRow.push(...createInformationals(positionalUsage));
|
|
110
198
|
typoGrid.pushRow(typoGridRow);
|
|
111
199
|
}
|
|
112
|
-
lines.push(
|
|
113
|
-
...typoGrid.computeStyledGrid(typoSupport).map((row) => row.join("")),
|
|
114
|
-
);
|
|
200
|
+
lines.push(...typoGrid.computeStyledLines(typoSupport));
|
|
115
201
|
}
|
|
116
202
|
|
|
117
|
-
if (
|
|
203
|
+
if (usage.subcommands.length > 0) {
|
|
118
204
|
lines.push("");
|
|
119
205
|
lines.push(textBlockTitle("Subcommands:").computeStyledString(typoSupport));
|
|
120
206
|
const typoGrid = new TypoGrid();
|
|
121
|
-
for (const subcommandUsage of
|
|
207
|
+
for (const subcommandUsage of usage.subcommands) {
|
|
122
208
|
const typoGridRow = new Array<TypoText>();
|
|
123
209
|
typoGridRow.push(new TypoText(textDelimiter(" ")));
|
|
124
210
|
typoGridRow.push(new TypoText(textConstants(subcommandUsage.name)));
|
|
125
211
|
typoGridRow.push(...createInformationals(subcommandUsage));
|
|
126
212
|
typoGrid.pushRow(typoGridRow);
|
|
127
213
|
}
|
|
128
|
-
lines.push(
|
|
129
|
-
...typoGrid.computeStyledGrid(typoSupport).map((row) => row.join("")),
|
|
130
|
-
);
|
|
214
|
+
lines.push(...typoGrid.computeStyledLines(typoSupport));
|
|
131
215
|
}
|
|
132
216
|
|
|
133
|
-
if (
|
|
217
|
+
if (usage.options.length > 0) {
|
|
134
218
|
lines.push("");
|
|
135
219
|
lines.push(textBlockTitle("Options:").computeStyledString(typoSupport));
|
|
136
220
|
const typoGrid = new TypoGrid();
|
|
137
|
-
for (const optionUsage of
|
|
221
|
+
for (const optionUsage of usage.options) {
|
|
138
222
|
const typoGridRow = new Array<TypoText>();
|
|
139
223
|
typoGridRow.push(new TypoText(textDelimiter(" ")));
|
|
140
224
|
if (optionUsage.short) {
|
|
@@ -147,61 +231,58 @@ export function usageToStyledLines(params: {
|
|
|
147
231
|
} else {
|
|
148
232
|
typoGridRow.push(new TypoText());
|
|
149
233
|
}
|
|
234
|
+
const longOptionText = new TypoText(
|
|
235
|
+
textConstants(`--${optionUsage.long}`),
|
|
236
|
+
);
|
|
150
237
|
if (optionUsage.label) {
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
textConstants(`--${optionUsage.long}`),
|
|
154
|
-
textDelimiter(" "),
|
|
155
|
-
textUserInput(optionUsage.label),
|
|
156
|
-
),
|
|
157
|
-
);
|
|
158
|
-
} else {
|
|
159
|
-
typoGridRow.push(
|
|
160
|
-
new TypoText(
|
|
161
|
-
textConstants(`--${optionUsage.long}`),
|
|
162
|
-
textSubtleInfo("[=no]"),
|
|
163
|
-
),
|
|
164
|
-
);
|
|
238
|
+
longOptionText.push(textDelimiter(" "));
|
|
239
|
+
longOptionText.push(textUserInput(optionUsage.label));
|
|
165
240
|
}
|
|
241
|
+
if (optionUsage.annotation) {
|
|
242
|
+
longOptionText.push(textSubtleInfo(optionUsage.annotation));
|
|
243
|
+
}
|
|
244
|
+
typoGridRow.push(longOptionText);
|
|
166
245
|
typoGridRow.push(...createInformationals(optionUsage));
|
|
167
246
|
typoGrid.pushRow(typoGridRow);
|
|
168
247
|
}
|
|
169
|
-
lines.push(
|
|
170
|
-
...typoGrid.computeStyledGrid(typoSupport).map((row) => row.join("")),
|
|
171
|
-
);
|
|
248
|
+
lines.push(...typoGrid.computeStyledLines(typoSupport));
|
|
172
249
|
}
|
|
173
250
|
|
|
174
|
-
if (
|
|
251
|
+
if (usage.information.examples) {
|
|
175
252
|
lines.push("");
|
|
176
253
|
lines.push(textBlockTitle("Examples:").computeStyledString(typoSupport));
|
|
177
|
-
for (const example of
|
|
254
|
+
for (const example of usage.information.examples) {
|
|
178
255
|
const exampleExplanationText = new TypoText();
|
|
179
|
-
exampleExplanationText.
|
|
180
|
-
exampleExplanationText.
|
|
181
|
-
textSubtleInfo(`# ${example.explanation}`),
|
|
182
|
-
);
|
|
256
|
+
exampleExplanationText.push(textDelimiter(" "));
|
|
257
|
+
exampleExplanationText.push(textSubtleInfo(`# ${example.explanation}`));
|
|
183
258
|
lines.push(exampleExplanationText.computeStyledString(typoSupport));
|
|
184
259
|
const commandLineText = new TypoText();
|
|
185
|
-
commandLineText.
|
|
186
|
-
commandLineText.
|
|
260
|
+
commandLineText.push(textDelimiter(" "));
|
|
261
|
+
commandLineText.push(textConstants(cliName));
|
|
187
262
|
for (const commandArg of example.commandArgs) {
|
|
188
|
-
commandLineText.
|
|
263
|
+
commandLineText.push(textDelimiter(" "));
|
|
189
264
|
if (typeof commandArg === "string") {
|
|
190
|
-
commandLineText.
|
|
265
|
+
commandLineText.push(commandArg);
|
|
191
266
|
} else if ("positional" in commandArg) {
|
|
192
|
-
commandLineText.
|
|
267
|
+
commandLineText.push(textUserInput(commandArg.positional));
|
|
193
268
|
} else if ("subcommand" in commandArg) {
|
|
194
|
-
commandLineText.
|
|
269
|
+
commandLineText.push(textConstants(commandArg.subcommand));
|
|
195
270
|
} else if ("option" in commandArg) {
|
|
196
271
|
const option = commandArg.option;
|
|
197
272
|
if ("short" in option) {
|
|
198
|
-
commandLineText.
|
|
273
|
+
commandLineText.push(textConstants(`-${option.short}`));
|
|
199
274
|
} else {
|
|
200
|
-
commandLineText.
|
|
275
|
+
commandLineText.push(textConstants(`--${option.long}`));
|
|
276
|
+
}
|
|
277
|
+
if (option.inlined !== undefined) {
|
|
278
|
+
commandLineText.push(textSubtleInfo("="));
|
|
279
|
+
commandLineText.push(textUserInput(option.inlined));
|
|
201
280
|
}
|
|
202
|
-
if (option.
|
|
203
|
-
|
|
204
|
-
|
|
281
|
+
if (option.separated !== undefined) {
|
|
282
|
+
for (const separatedValue of option.separated) {
|
|
283
|
+
commandLineText.push(textDelimiter(" "));
|
|
284
|
+
commandLineText.push(textUserInput(separatedValue));
|
|
285
|
+
}
|
|
205
286
|
}
|
|
206
287
|
}
|
|
207
288
|
}
|
|
@@ -214,8 +295,8 @@ export function usageToStyledLines(params: {
|
|
|
214
295
|
}
|
|
215
296
|
|
|
216
297
|
function createInformationals(usage: {
|
|
217
|
-
description
|
|
218
|
-
hint
|
|
298
|
+
description?: string | undefined;
|
|
299
|
+
hint?: string | undefined;
|
|
219
300
|
}): Array<TypoText> {
|
|
220
301
|
const informationals = [];
|
|
221
302
|
if (usage.description) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { expect, it } from "@jest/globals";
|
|
2
|
-
import { ReaderArgs } from "../src";
|
|
2
|
+
import { ReaderArgs, ReaderOptionParsing } from "../src";
|
|
3
3
|
|
|
4
|
-
it("run", async ()
|
|
4
|
+
it("run", async function () {
|
|
5
5
|
const readerArgs = new ReaderArgs([
|
|
6
6
|
"--option=1.1",
|
|
7
7
|
"--option-alias1=1.2",
|
|
@@ -10,7 +10,7 @@ it("run", async () => {
|
|
|
10
10
|
"-pts=1.4",
|
|
11
11
|
"-o",
|
|
12
12
|
"1.5",
|
|
13
|
-
"--
|
|
13
|
+
"--flag1-alias",
|
|
14
14
|
"-fa2=woops",
|
|
15
15
|
"-fa2o=1.6",
|
|
16
16
|
]);
|
|
@@ -18,29 +18,45 @@ it("run", async () => {
|
|
|
18
18
|
const kOption = readerArgs.registerOption({
|
|
19
19
|
longs: ["option", "option-alias1", "option-alias2"],
|
|
20
20
|
shorts: ["pts", "o"],
|
|
21
|
-
|
|
21
|
+
parsing: optionValueFixedUniqueParsing,
|
|
22
22
|
});
|
|
23
23
|
const kFlag1 = readerArgs.registerOption({
|
|
24
|
-
longs: ["flag1", "
|
|
24
|
+
longs: ["flag1", "flag1-alias"],
|
|
25
25
|
shorts: [],
|
|
26
|
-
|
|
26
|
+
parsing: optionFlagParsing,
|
|
27
27
|
});
|
|
28
28
|
const kFlag2 = readerArgs.registerOption({
|
|
29
29
|
longs: ["flag2"],
|
|
30
30
|
shorts: ["fa2"],
|
|
31
|
-
|
|
31
|
+
parsing: optionFlagParsing,
|
|
32
32
|
});
|
|
33
33
|
|
|
34
34
|
expect(readerArgs.consumePositional()).toStrictEqual(undefined);
|
|
35
35
|
|
|
36
36
|
expect(readerArgs.getOptionValues(kOption)).toStrictEqual([
|
|
37
|
-
"1.1",
|
|
38
|
-
"1.2",
|
|
39
|
-
"1.3",
|
|
40
|
-
"1.4",
|
|
41
|
-
"1.5",
|
|
42
|
-
"1.6",
|
|
37
|
+
{ inlined: "1.1", separated: [] },
|
|
38
|
+
{ inlined: "1.2", separated: [] },
|
|
39
|
+
{ inlined: null, separated: ["1.3"] },
|
|
40
|
+
{ inlined: "1.4", separated: [] },
|
|
41
|
+
{ inlined: null, separated: ["1.5"] },
|
|
42
|
+
{ inlined: "1.6", separated: [] },
|
|
43
|
+
]);
|
|
44
|
+
expect(readerArgs.getOptionValues(kFlag1)).toStrictEqual([
|
|
45
|
+
{ inlined: null, separated: [] },
|
|
46
|
+
]);
|
|
47
|
+
expect(readerArgs.getOptionValues(kFlag2)).toStrictEqual([
|
|
48
|
+
{ inlined: "woops", separated: [] },
|
|
49
|
+
{ inlined: null, separated: [] },
|
|
43
50
|
]);
|
|
44
|
-
expect(readerArgs.getOptionValues(kFlag1)).toStrictEqual(["true"]);
|
|
45
|
-
expect(readerArgs.getOptionValues(kFlag2)).toStrictEqual(["woops", "true"]);
|
|
46
51
|
});
|
|
52
|
+
|
|
53
|
+
const optionFlagParsing: ReaderOptionParsing = {
|
|
54
|
+
consumeShortGroup: false,
|
|
55
|
+
consumeNextArg: () => false,
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
const optionValueFixedUniqueParsing: ReaderOptionParsing = {
|
|
59
|
+
consumeShortGroup: true,
|
|
60
|
+
consumeNextArg: (inlined, separated) =>
|
|
61
|
+
inlined === null && separated.length === 0,
|
|
62
|
+
};
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { expect, it } from "@jest/globals";
|
|
2
|
-
import { ReaderArgs } from "../src";
|
|
2
|
+
import { ReaderArgs, ReaderOptionParsing } from "../src";
|
|
3
3
|
|
|
4
|
-
it("run", async ()
|
|
4
|
+
it("run", async function () {
|
|
5
5
|
const stream = new ReaderArgs([
|
|
6
6
|
"positional-0",
|
|
7
|
+
"--no-flag-no",
|
|
7
8
|
"--flag-normal",
|
|
8
9
|
"--flag-positive=true",
|
|
9
10
|
"--flag-negative=false",
|
|
@@ -12,7 +13,8 @@ it("run", async () => {
|
|
|
12
13
|
"1.1",
|
|
13
14
|
"--option-split",
|
|
14
15
|
"1.2",
|
|
15
|
-
"--option-join=2",
|
|
16
|
+
"--option-join=2.1",
|
|
17
|
+
"--option-join=2.2",
|
|
16
18
|
"-ab",
|
|
17
19
|
"3.1",
|
|
18
20
|
"-cd=4.1",
|
|
@@ -34,76 +36,81 @@ it("run", async () => {
|
|
|
34
36
|
|
|
35
37
|
expect(stream.consumePositional()).toStrictEqual("positional-0");
|
|
36
38
|
|
|
39
|
+
const kFlagUnset = stream.registerOption({
|
|
40
|
+
longs: ["flag-unset"],
|
|
41
|
+
shorts: [],
|
|
42
|
+
parsing: optionFlagParsing,
|
|
43
|
+
});
|
|
44
|
+
const kFlagNo = stream.registerOption({
|
|
45
|
+
longs: ["no-flag-no"],
|
|
46
|
+
shorts: [],
|
|
47
|
+
parsing: optionFlagParsing,
|
|
48
|
+
});
|
|
37
49
|
const kFlagNormal = stream.registerOption({
|
|
38
50
|
longs: ["flag-normal"],
|
|
39
51
|
shorts: [],
|
|
40
|
-
|
|
52
|
+
parsing: optionFlagParsing,
|
|
41
53
|
});
|
|
42
54
|
const kFlagPositive = stream.registerOption({
|
|
43
55
|
longs: ["flag-positive"],
|
|
44
56
|
shorts: [],
|
|
45
|
-
|
|
57
|
+
parsing: optionFlagParsing,
|
|
46
58
|
});
|
|
47
59
|
const kFlagNegative = stream.registerOption({
|
|
48
60
|
longs: ["flag-negative"],
|
|
49
61
|
shorts: [],
|
|
50
|
-
|
|
51
|
-
});
|
|
52
|
-
const kFlagUnset = stream.registerOption({
|
|
53
|
-
longs: ["flag-unset"],
|
|
54
|
-
shorts: [],
|
|
55
|
-
valued: false,
|
|
62
|
+
parsing: optionFlagParsing,
|
|
56
63
|
});
|
|
57
64
|
|
|
58
65
|
expect(stream.consumePositional()).toStrictEqual("positional-1");
|
|
59
66
|
|
|
67
|
+
const kOptionUnset = stream.registerOption({
|
|
68
|
+
longs: ["option-unset"],
|
|
69
|
+
shorts: [],
|
|
70
|
+
parsing: optionValueFixedUniqueParsing,
|
|
71
|
+
});
|
|
60
72
|
const kOptionSplit = stream.registerOption({
|
|
61
73
|
longs: ["option-split"],
|
|
62
74
|
shorts: [],
|
|
63
|
-
|
|
75
|
+
parsing: optionValueFixedUniqueParsing,
|
|
64
76
|
});
|
|
65
77
|
const kOptionJoin = stream.registerOption({
|
|
66
78
|
longs: ["option-join"],
|
|
67
79
|
shorts: [],
|
|
68
|
-
|
|
69
|
-
});
|
|
70
|
-
const kOptionUnset = stream.registerOption({
|
|
71
|
-
longs: ["option-unset"],
|
|
72
|
-
shorts: [],
|
|
73
|
-
valued: true,
|
|
80
|
+
parsing: optionValueFixedUniqueParsing,
|
|
74
81
|
});
|
|
75
82
|
|
|
76
83
|
const kA = stream.registerOption({
|
|
77
84
|
longs: [],
|
|
78
85
|
shorts: ["a"],
|
|
79
|
-
|
|
86
|
+
parsing: optionFlagParsing,
|
|
80
87
|
});
|
|
81
88
|
const kB = stream.registerOption({
|
|
82
89
|
longs: [],
|
|
83
90
|
shorts: ["b"],
|
|
84
|
-
|
|
91
|
+
parsing: optionValueFixedUniqueParsing,
|
|
85
92
|
});
|
|
86
93
|
|
|
87
94
|
const kC = stream.registerOption({
|
|
88
95
|
longs: [],
|
|
89
96
|
shorts: ["c"],
|
|
90
|
-
|
|
97
|
+
parsing: optionFlagParsing,
|
|
91
98
|
});
|
|
92
99
|
const kD = stream.registerOption({
|
|
93
100
|
longs: [],
|
|
94
101
|
shorts: ["d"],
|
|
95
|
-
|
|
102
|
+
parsing: optionValueFixedUniqueParsing,
|
|
96
103
|
});
|
|
97
104
|
|
|
98
105
|
const kE = stream.registerOption({
|
|
99
106
|
longs: [],
|
|
100
107
|
shorts: ["e"],
|
|
101
|
-
|
|
108
|
+
parsing: optionFlagParsing,
|
|
102
109
|
});
|
|
103
110
|
const kF = stream.registerOption({
|
|
104
111
|
longs: [],
|
|
105
112
|
shorts: ["f"],
|
|
106
|
-
|
|
113
|
+
parsing: optionValueFixedUniqueParsing,
|
|
107
114
|
});
|
|
108
115
|
|
|
109
116
|
expect(stream.consumePositional()).toStrictEqual("positional-2");
|
|
@@ -111,23 +118,23 @@ it("run", async () => {
|
|
|
111
118
|
const kG = stream.registerOption({
|
|
112
119
|
longs: [],
|
|
113
120
|
shorts: ["g"],
|
|
114
|
-
|
|
121
|
+
parsing: optionFlagParsing,
|
|
115
122
|
});
|
|
116
123
|
const kH = stream.registerOption({
|
|
117
124
|
longs: [],
|
|
118
125
|
shorts: ["h"],
|
|
119
|
-
|
|
126
|
+
parsing: optionFlagParsing,
|
|
120
127
|
});
|
|
121
128
|
|
|
122
129
|
const kI = stream.registerOption({
|
|
123
130
|
longs: [],
|
|
124
131
|
shorts: ["i"],
|
|
125
|
-
|
|
132
|
+
parsing: optionFlagParsing,
|
|
126
133
|
});
|
|
127
134
|
const kJ = stream.registerOption({
|
|
128
135
|
longs: [],
|
|
129
136
|
shorts: ["j"],
|
|
130
|
-
|
|
137
|
+
parsing: optionFlagParsing,
|
|
131
138
|
});
|
|
132
139
|
|
|
133
140
|
expect(stream.consumePositional()).toStrictEqual("positional-3");
|
|
@@ -138,27 +145,76 @@ it("run", async () => {
|
|
|
138
145
|
expect(stream.consumePositional()).toStrictEqual("positional-4");
|
|
139
146
|
expect(stream.consumePositional()).toStrictEqual(undefined);
|
|
140
147
|
|
|
141
|
-
expect(stream.getOptionValues(kFlagNormal)).toStrictEqual(["true"]);
|
|
142
|
-
expect(stream.getOptionValues(kFlagPositive)).toStrictEqual(["true"]);
|
|
143
|
-
expect(stream.getOptionValues(kFlagNegative)).toStrictEqual(["false"]);
|
|
144
148
|
expect(stream.getOptionValues(kFlagUnset)).toStrictEqual([]);
|
|
149
|
+
expect(stream.getOptionValues(kFlagNo)).toStrictEqual([
|
|
150
|
+
{ inlined: null, separated: [] },
|
|
151
|
+
]);
|
|
152
|
+
expect(stream.getOptionValues(kFlagNormal)).toStrictEqual([
|
|
153
|
+
{ inlined: null, separated: [] },
|
|
154
|
+
]);
|
|
155
|
+
expect(stream.getOptionValues(kFlagPositive)).toStrictEqual([
|
|
156
|
+
{ inlined: "true", separated: [] },
|
|
157
|
+
]);
|
|
158
|
+
expect(stream.getOptionValues(kFlagNegative)).toStrictEqual([
|
|
159
|
+
{ inlined: "false", separated: [] },
|
|
160
|
+
]);
|
|
145
161
|
|
|
146
162
|
expect(stream.getOptionValues(kOptionUnset)).toStrictEqual([]);
|
|
147
|
-
expect(stream.getOptionValues(kOptionSplit)).toStrictEqual([
|
|
148
|
-
|
|
163
|
+
expect(stream.getOptionValues(kOptionSplit)).toStrictEqual([
|
|
164
|
+
{ inlined: null, separated: ["1.1"] },
|
|
165
|
+
{ inlined: null, separated: ["1.2"] },
|
|
166
|
+
]);
|
|
167
|
+
expect(stream.getOptionValues(kOptionJoin)).toStrictEqual([
|
|
168
|
+
{ inlined: "2.1", separated: [] },
|
|
169
|
+
{ inlined: "2.2", separated: [] },
|
|
170
|
+
]);
|
|
149
171
|
|
|
150
|
-
expect(stream.getOptionValues(kA)).toStrictEqual([
|
|
151
|
-
|
|
172
|
+
expect(stream.getOptionValues(kA)).toStrictEqual([
|
|
173
|
+
{ inlined: null, separated: [] },
|
|
174
|
+
]);
|
|
175
|
+
expect(stream.getOptionValues(kB)).toStrictEqual([
|
|
176
|
+
{ inlined: null, separated: ["3.1"] },
|
|
177
|
+
{ inlined: null, separated: ["3.2"] },
|
|
178
|
+
]);
|
|
152
179
|
|
|
153
|
-
expect(stream.getOptionValues(kC)).toStrictEqual([
|
|
154
|
-
|
|
180
|
+
expect(stream.getOptionValues(kC)).toStrictEqual([
|
|
181
|
+
{ inlined: null, separated: [] },
|
|
182
|
+
]);
|
|
183
|
+
expect(stream.getOptionValues(kD)).toStrictEqual([
|
|
184
|
+
{ inlined: "4.1", separated: [] },
|
|
185
|
+
{ inlined: "4.2", separated: [] },
|
|
186
|
+
]);
|
|
155
187
|
|
|
156
|
-
expect(stream.getOptionValues(kE)).toStrictEqual([
|
|
157
|
-
|
|
188
|
+
expect(stream.getOptionValues(kE)).toStrictEqual([
|
|
189
|
+
{ inlined: null, separated: [] },
|
|
190
|
+
]);
|
|
191
|
+
expect(stream.getOptionValues(kF)).toStrictEqual([
|
|
192
|
+
{ inlined: "5.1", separated: [] },
|
|
193
|
+
{ inlined: "5.2", separated: [] },
|
|
194
|
+
]);
|
|
158
195
|
|
|
159
|
-
expect(stream.getOptionValues(kG)).toStrictEqual([
|
|
160
|
-
|
|
196
|
+
expect(stream.getOptionValues(kG)).toStrictEqual([
|
|
197
|
+
{ inlined: null, separated: [] },
|
|
198
|
+
]);
|
|
199
|
+
expect(stream.getOptionValues(kH)).toStrictEqual([
|
|
200
|
+
{ inlined: "FALSE", separated: [] },
|
|
201
|
+
]);
|
|
161
202
|
|
|
162
|
-
expect(stream.getOptionValues(kI)).toStrictEqual([
|
|
163
|
-
|
|
203
|
+
expect(stream.getOptionValues(kI)).toStrictEqual([
|
|
204
|
+
{ inlined: null, separated: [] },
|
|
205
|
+
]);
|
|
206
|
+
expect(stream.getOptionValues(kJ)).toStrictEqual([
|
|
207
|
+
{ inlined: "TRUE", separated: [] },
|
|
208
|
+
]);
|
|
164
209
|
});
|
|
210
|
+
|
|
211
|
+
const optionFlagParsing: ReaderOptionParsing = {
|
|
212
|
+
consumeShortGroup: false,
|
|
213
|
+
consumeNextArg: () => false,
|
|
214
|
+
};
|
|
215
|
+
|
|
216
|
+
const optionValueFixedUniqueParsing: ReaderOptionParsing = {
|
|
217
|
+
consumeShortGroup: true,
|
|
218
|
+
consumeNextArg: (inlined, separated) =>
|
|
219
|
+
inlined === null && separated.length === 0,
|
|
220
|
+
};
|