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/src/lib/Usage.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { CommandUsage } from "./Command";
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
- * Converts a {@link CommandUsage} model into an array of styled lines ready to be
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 within each section is handled by {@link TypoGrid}: the widest entry
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.commandUsage - From {@link CommandDecoder.generateUsage}.
137
+ * @param params.usage - From {@link CommandDecoder.generateUsage}.
47
138
  * @param params.typoSupport - Rendering mode.
48
- * @returns One string per output line; trailing empty string for the blank line at the end.
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
- * commandUsage: commandDecoder.generateUsage(),
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: Lowercase<string>;
62
- commandUsage: CommandUsage;
152
+ cliName: string;
153
+ usage: UsageCommand;
63
154
  typoSupport: TypoSupport;
64
155
  }) {
65
- const { cliName, commandUsage, typoSupport } = params;
156
+ const { cliName, usage, typoSupport } = params;
66
157
 
67
158
  const lines = new Array<string>();
68
159
 
69
- const segments = [
70
- textUsageHero("Usage:").computeStyledString(typoSupport),
71
- textConstants(cliName).computeStyledString(typoSupport),
72
- ].concat(
73
- commandUsage.segments.map((segment) => {
74
- if ("positional" in segment) {
75
- return textUserInput(segment.positional).computeStyledString(
76
- typoSupport,
77
- );
78
- }
79
- if ("command" in segment) {
80
- return textConstants(segment.command).computeStyledString(typoSupport);
81
- }
82
- throw new Error(`Unknown segment: ${JSON.stringify(segment)}`);
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.pushString(textUsageText(commandUsage.information.description));
90
- if (commandUsage.information.hint) {
91
- introText.pushString(textDelimiter(" "));
92
- introText.pushString(textSubtleInfo(`(${commandUsage.information.hint})`));
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 commandUsage.information.details ?? []) {
183
+ for (const detail of usage.information.details ?? []) {
96
184
  const detailText = new TypoText();
97
- detailText.pushString(textSubtleInfo(detail));
185
+ detailText.push(textSubtleInfo(detail));
98
186
  lines.push(detailText.computeStyledString(typoSupport));
99
187
  }
100
188
 
101
- if (commandUsage.positionals.length > 0) {
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 commandUsage.positionals) {
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 (commandUsage.subcommands.length > 0) {
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 commandUsage.subcommands) {
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 (commandUsage.options.length > 0) {
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 commandUsage.options) {
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
- typoGridRow.push(
152
- new TypoText(
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 (commandUsage.information.examples) {
251
+ if (usage.information.examples) {
175
252
  lines.push("");
176
253
  lines.push(textBlockTitle("Examples:").computeStyledString(typoSupport));
177
- for (const example of commandUsage.information.examples) {
254
+ for (const example of usage.information.examples) {
178
255
  const exampleExplanationText = new TypoText();
179
- exampleExplanationText.pushString(textDelimiter(" "));
180
- exampleExplanationText.pushString(
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.pushString(textDelimiter(" "));
186
- commandLineText.pushString(textConstants(cliName));
260
+ commandLineText.push(textDelimiter(" "));
261
+ commandLineText.push(textConstants(cliName));
187
262
  for (const commandArg of example.commandArgs) {
188
- commandLineText.pushString(textDelimiter(" "));
263
+ commandLineText.push(textDelimiter(" "));
189
264
  if (typeof commandArg === "string") {
190
- commandLineText.pushString(commandArg);
265
+ commandLineText.push(commandArg);
191
266
  } else if ("positional" in commandArg) {
192
- commandLineText.pushString(textUserInput(commandArg.positional));
267
+ commandLineText.push(textUserInput(commandArg.positional));
193
268
  } else if ("subcommand" in commandArg) {
194
- commandLineText.pushString(textConstants(commandArg.subcommand));
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.pushString(textConstants(`-${option.short}`));
273
+ commandLineText.push(textConstants(`-${option.short}`));
199
274
  } else {
200
- commandLineText.pushString(textConstants(`--${option.long}`));
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.value !== undefined) {
203
- commandLineText.pushString(textSubtleInfo("="));
204
- commandLineText.pushString(textUserInput(option.value));
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: string | undefined;
218
- hint: string | undefined;
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
- "--flag-alias",
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
- valued: true,
21
+ parsing: optionValueFixedUniqueParsing,
22
22
  });
23
23
  const kFlag1 = readerArgs.registerOption({
24
- longs: ["flag1", "flag-alias"],
24
+ longs: ["flag1", "flag1-alias"],
25
25
  shorts: [],
26
- valued: false,
26
+ parsing: optionFlagParsing,
27
27
  });
28
28
  const kFlag2 = readerArgs.registerOption({
29
29
  longs: ["flag2"],
30
30
  shorts: ["fa2"],
31
- valued: false,
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
- valued: false,
52
+ parsing: optionFlagParsing,
41
53
  });
42
54
  const kFlagPositive = stream.registerOption({
43
55
  longs: ["flag-positive"],
44
56
  shorts: [],
45
- valued: false,
57
+ parsing: optionFlagParsing,
46
58
  });
47
59
  const kFlagNegative = stream.registerOption({
48
60
  longs: ["flag-negative"],
49
61
  shorts: [],
50
- valued: false,
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
- valued: true,
75
+ parsing: optionValueFixedUniqueParsing,
64
76
  });
65
77
  const kOptionJoin = stream.registerOption({
66
78
  longs: ["option-join"],
67
79
  shorts: [],
68
- valued: true,
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
- valued: false,
86
+ parsing: optionFlagParsing,
80
87
  });
81
88
  const kB = stream.registerOption({
82
89
  longs: [],
83
90
  shorts: ["b"],
84
- valued: true,
91
+ parsing: optionValueFixedUniqueParsing,
85
92
  });
86
93
 
87
94
  const kC = stream.registerOption({
88
95
  longs: [],
89
96
  shorts: ["c"],
90
- valued: false,
97
+ parsing: optionFlagParsing,
91
98
  });
92
99
  const kD = stream.registerOption({
93
100
  longs: [],
94
101
  shorts: ["d"],
95
- valued: true,
102
+ parsing: optionValueFixedUniqueParsing,
96
103
  });
97
104
 
98
105
  const kE = stream.registerOption({
99
106
  longs: [],
100
107
  shorts: ["e"],
101
- valued: false,
108
+ parsing: optionFlagParsing,
102
109
  });
103
110
  const kF = stream.registerOption({
104
111
  longs: [],
105
112
  shorts: ["f"],
106
- valued: true,
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
- valued: false,
121
+ parsing: optionFlagParsing,
115
122
  });
116
123
  const kH = stream.registerOption({
117
124
  longs: [],
118
125
  shorts: ["h"],
119
- valued: false,
126
+ parsing: optionFlagParsing,
120
127
  });
121
128
 
122
129
  const kI = stream.registerOption({
123
130
  longs: [],
124
131
  shorts: ["i"],
125
- valued: false,
132
+ parsing: optionFlagParsing,
126
133
  });
127
134
  const kJ = stream.registerOption({
128
135
  longs: [],
129
136
  shorts: ["j"],
130
- valued: false,
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(["1.1", "1.2"]);
148
- expect(stream.getOptionValues(kOptionJoin)).toStrictEqual(["2"]);
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(["true"]);
151
- expect(stream.getOptionValues(kB)).toStrictEqual(["3.1", "3.2"]);
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(["true"]);
154
- expect(stream.getOptionValues(kD)).toStrictEqual(["4.1", "4.2"]);
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(["true"]);
157
- expect(stream.getOptionValues(kF)).toStrictEqual(["5.1", "5.2"]);
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(["true"]);
160
- expect(stream.getOptionValues(kH)).toStrictEqual(["FALSE"]);
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(["true"]);
163
- expect(stream.getOptionValues(kJ)).toStrictEqual(["TRUE"]);
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
+ };