cli-kiss 0.2.6 → 0.2.7

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.
@@ -0,0 +1,34 @@
1
+ import { it } from "@jest/globals";
2
+ import { similaritySort } from "../src/lib/Similarity";
3
+
4
+ it("run", async function () {
5
+ expect(
6
+ orderBySimilarity("--inst", ["--flag", "--blah", "--install"]),
7
+ ).toStrictEqual(["--install", "--flag", "--blah"]);
8
+
9
+ expect(
10
+ orderBySimilarity("instlal", ["install", "dudu", "--blah"]),
11
+ ).toStrictEqual(["install", "--blah", "dudu"]);
12
+
13
+ expect(
14
+ orderBySimilarity("cat", ["cats", "catz", "cut", "kat", "hello", "world"]),
15
+ ).toStrictEqual(["cats", "catz", "cut", "kat", "hello", "world"]);
16
+
17
+ expect(orderBySimilarity("cat", ["cut", "kat"])).toStrictEqual([
18
+ "cut",
19
+ "kat",
20
+ ]);
21
+
22
+ expect(orderBySimilarity("acb", ["abc", "ac", "ab"])).toStrictEqual([
23
+ "abc",
24
+ "ac",
25
+ "ab",
26
+ ]);
27
+ });
28
+
29
+ function orderBySimilarity(reference: string, candidates: Array<string>) {
30
+ return similaritySort(
31
+ reference,
32
+ candidates.map((key) => ({ key, value: key })),
33
+ );
34
+ }
@@ -32,9 +32,10 @@ const usageTty = usageToStyledLines({
32
32
  typoSupport: TypoSupport.tty(),
33
33
  }).join("\n");
34
34
 
35
- const unexpectedNone = "Error: Unexpected unknown option: --color";
36
- const unexpectedMock =
37
- "{{Error:}@darkRed}+ Unexpected unknown option: {{--color}@darkYellow}+";
35
+ const unknownOptionNone =
36
+ 'Error: Unknown option: "--color": did you mean: --help, --version ?';
37
+ const unknownOptionMock =
38
+ '{{Error:}@darkRed}+ Unknown option: {{"--color"}@darkYellow}+: did you mean: {{--help}@darkCyan}+, {{--version}@darkCyan}+ ?';
38
39
 
39
40
  it("run", async function () {
40
41
  await withEnv("FORCE_COLOR", "false", async () => {
@@ -82,21 +83,21 @@ it("run", async function () {
82
83
  [],
83
84
  [
84
85
  usageMock,
85
- '{{Error:}@darkRed}+ {{--color}@darkCyan}+: {{<color-mode>}@darkBlue}+: Invalid value: {{"42"}@darkYellow}+ (expected one of: {{"auto"}@darkYellow}+ | {{"always"}@darkYellow}+ | {{"never"}@darkYellow}+...)',
86
+ '{{Error:}@darkRed}+ {{--color}@darkCyan}+: {{<color-mode>}@darkBlue}+: Unknown value: {{"42"}@darkYellow}+: did you mean: {{"auto"}@darkYellow}+, {{"always"}@darkYellow}+, {{"never"}@darkYellow}+ ?',
86
87
  ],
87
88
  1,
88
89
  );
89
90
  });
90
91
 
91
92
  await withEnv("MOCK_COLOR", "1", async () => {
92
- await testAllFlagsFailures("env", usageMock, unexpectedMock);
93
+ await testAllFlagsFailures("env", usageMock, unknownOptionMock);
93
94
  });
94
95
  await withEnv("FORCE_COLOR", "0", async () => {
95
- await testAllFlagsFailures("env", usageNone, unexpectedNone);
96
+ await testAllFlagsFailures("env", usageNone, unknownOptionNone);
96
97
  });
97
98
 
98
- await testAllFlagsFailures("mock", usageMock, unexpectedMock);
99
- await testAllFlagsFailures("never", usageNone, unexpectedNone);
99
+ await testAllFlagsFailures("mock", usageMock, unknownOptionMock);
100
+ await testAllFlagsFailures("never", usageNone, unknownOptionNone);
100
101
  });
101
102
  });
102
103
 
@@ -29,9 +29,9 @@ it("run", async function () {
29
29
  " subcommand Subcommand Description",
30
30
  "",
31
31
  "Options:",
32
- " --flag[=no] Option flag description",
33
- " --repeatable <string> [*] Option repeatable description",
34
- " --single-value <enum(number)> Option single value description",
32
+ " -ff, --flag[=no] Option flag description",
33
+ " -r, --repeatable <string> [*] Option repeatable description",
34
+ " -s, --single-value <enum(number)> Option single value description",
35
35
  "",
36
36
  ].join("\n");
37
37
  const subcommandUsage = [
@@ -46,10 +46,10 @@ it("run", async function () {
46
46
  " [variadic]... Variadics positional description",
47
47
  "",
48
48
  "Options:",
49
- " --flag[=no] Option flag description",
50
- " --repeatable <string> [*] Option repeatable description",
51
- " --single-value <enum(number)> Option single value description",
52
- " --url <url> [*] Option url description",
49
+ " -ff, --flag[=no] Option flag description",
50
+ " -r, --repeatable <string> [*] Option repeatable description",
51
+ " -s, --single-value <enum(number)> Option single value description",
52
+ " -u, --url <url> [*] Option url description",
53
53
  "",
54
54
  ].join("\n");
55
55
 
@@ -115,13 +115,19 @@ it("run", async function () {
115
115
  await testCase(
116
116
  ["--invalid1", "--invalid2", "required1", "--invalid3"],
117
117
  [],
118
- [rootUsage, "Error: Unexpected unknown option: --invalid1"],
118
+ [
119
+ rootUsage,
120
+ 'Error: Unknown option: "--invalid1": did you mean: --single-value, --help, --version ?',
121
+ ],
119
122
  1,
120
123
  );
121
124
  await testCase(
122
125
  ["required1", "unknown", "-wut", "--flag", "--single-value"],
123
126
  [],
124
- [rootUsage, 'Error: <subcommand>: Invalid value: "unknown"'],
127
+ [
128
+ rootUsage,
129
+ 'Error: <subcommand>: Unknown name: "unknown": did you mean: subcommand ?',
130
+ ],
125
131
  1,
126
132
  );
127
133
 
@@ -149,13 +155,19 @@ it("run", async function () {
149
155
  await testCase(
150
156
  ["--url", "https://example.com"],
151
157
  [],
152
- [rootUsage, "Error: Unexpected unknown option: --url"],
158
+ [
159
+ rootUsage,
160
+ 'Error: Unknown option: "--url": did you mean: --help, -r, --version ?',
161
+ ],
153
162
  1,
154
163
  );
155
164
  await testCase(
156
165
  ["required1", "--url", "https://example.com"],
157
166
  [],
158
- [rootUsage, "Error: Unexpected unknown option: --url"],
167
+ [
168
+ rootUsage,
169
+ 'Error: Unknown option: "--url": did you mean: --help, -r, --version ?',
170
+ ],
159
171
  1,
160
172
  );
161
173
  await testCase(
@@ -207,13 +219,19 @@ it("run", async function () {
207
219
  await testCase(
208
220
  ["--invalid", "required1", "subcommand", "required2"],
209
221
  [],
210
- [rootUsage, "Error: Unexpected unknown option: --invalid"],
222
+ [
223
+ rootUsage,
224
+ 'Error: Unknown option: "--invalid": did you mean: --single-value, --help, --flag ?',
225
+ ],
211
226
  1,
212
227
  );
213
228
  await testCase(
214
229
  ["required1", "subcommand", "required2", "--nope"],
215
230
  [],
216
- [subcommandUsage, "Error: Unexpected unknown option: --nope"],
231
+ [
232
+ subcommandUsage,
233
+ 'Error: Unknown option: "--nope": did you mean: --help, --flag, --repeatable ?',
234
+ ],
217
235
  1,
218
236
  );
219
237
  await testCase(
@@ -247,7 +265,7 @@ it("run", async function () {
247
265
  [],
248
266
  [
249
267
  subcommandUsage,
250
- 'Error: <required1>: Invalid value: "invalid" (expected one of: "required1" | "required1-bis")',
268
+ 'Error: <required1>: Unknown value: "invalid": did you mean: "required1-bis", "required1" ?',
251
269
  ],
252
270
  1,
253
271
  );
@@ -256,7 +274,7 @@ it("run", async function () {
256
274
  [],
257
275
  [
258
276
  subcommandUsage,
259
- 'Error: <required1>: Invalid value: "invalid" (expected one of: "required1" | "required1-bis")',
277
+ 'Error: <required1>: Unknown value: "invalid": did you mean: "required1-bis", "required1" ?',
260
278
  ],
261
279
  1,
262
280
  );
@@ -265,7 +283,7 @@ it("run", async function () {
265
283
  [],
266
284
  [
267
285
  subcommandUsage,
268
- 'Error: <required2>: Invalid value: "invalid" (expected one of: "required2" | "required2-bis")',
286
+ 'Error: <required2>: Unknown value: "invalid": did you mean: "required2-bis", "required2" ?',
269
287
  ],
270
288
  1,
271
289
  );
@@ -274,7 +292,7 @@ it("run", async function () {
274
292
  [],
275
293
  [
276
294
  subcommandUsage,
277
- 'Error: <required1>: Invalid value: "invalid" (expected one of: "required1" | "required1-bis")',
295
+ 'Error: <required1>: Unknown value: "invalid": did you mean: "required1-bis", "required1" ?',
278
296
  ],
279
297
  1,
280
298
  );
@@ -285,7 +303,7 @@ it("run", async function () {
285
303
  [],
286
304
  [
287
305
  subcommandUsage,
288
- 'Error: --single-value: <enum(number)>: from: enum(string): Invalid value: "dodo" (expected one of: "42" | "43")',
306
+ 'Error: --single-value: <enum(number)>: from: enum(string): Unknown value: "dodo": did you mean: "42", "43" ?',
289
307
  ],
290
308
  1,
291
309
  );
@@ -294,7 +312,7 @@ it("run", async function () {
294
312
  [],
295
313
  [
296
314
  subcommandUsage,
297
- 'Error: --single-value: <enum(number)>: from: enum(string): Invalid value: "44" (expected one of: "42" | "43")',
315
+ 'Error: --single-value: <enum(number)>: from: enum(string): Unknown value: "44": did you mean: "42", "43" ?',
298
316
  ],
299
317
  1,
300
318
  );
@@ -303,7 +321,10 @@ it("run", async function () {
303
321
  await testCase(
304
322
  ["--url", "not-a-url", "required1", "subcommand", "required2"],
305
323
  [],
306
- [rootUsage, "Error: Unexpected unknown option: --url"],
324
+ [
325
+ rootUsage,
326
+ 'Error: Unknown option: "--url": did you mean: --help, -r, --version ?',
327
+ ],
307
328
  1,
308
329
  );
309
330
  await testCase(
@@ -340,6 +361,62 @@ it("run", async function () {
340
361
  [subcommandUsage, "Error: --single-value: Must not be set multiple times"],
341
362
  1,
342
363
  );
364
+
365
+ // Test suggestions
366
+ await testCase(
367
+ ["required1", "subcommand", "required2", "-f"],
368
+ [],
369
+ [
370
+ subcommandUsage,
371
+ 'Error: Unknown option: "-f": did you mean: -ff, -r, -s ?',
372
+ ],
373
+ 1,
374
+ );
375
+ await testCase(
376
+ ["required1", "subcommand", "required2", "-flag"],
377
+ [],
378
+ [
379
+ subcommandUsage,
380
+ 'Error: Unknown option: "-flag": did you mean: --flag, -ff, --single-value ?',
381
+ ],
382
+ 1,
383
+ );
384
+ await testCase(
385
+ ["required1", "subcommand", "required2", "--uri"],
386
+ [],
387
+ [
388
+ subcommandUsage,
389
+ 'Error: Unknown option: "--uri": did you mean: --url, --version, -r ?',
390
+ ],
391
+ 1,
392
+ );
393
+ await testCase(
394
+ ["required1", "subcommand", "required2", "--single-"],
395
+ [],
396
+ [
397
+ subcommandUsage,
398
+ 'Error: Unknown option: "--single-": did you mean: --single-value, --help, --flag ?',
399
+ ],
400
+ 1,
401
+ );
402
+ await testCase(
403
+ ["required-bis1", "subcommand", "required2"],
404
+ [],
405
+ [
406
+ subcommandUsage,
407
+ 'Error: <required1>: Unknown value: "required-bis1": did you mean: "required1-bis", "required1" ?',
408
+ ],
409
+ 1,
410
+ );
411
+ await testCase(
412
+ ["required1", "subcomm"],
413
+ [],
414
+ [
415
+ rootUsage,
416
+ 'Error: <subcommand>: Unknown name: "subcomm": did you mean: subcommand ?',
417
+ ],
418
+ 1,
419
+ );
343
420
  });
344
421
 
345
422
  async function testCase(
@@ -364,22 +441,25 @@ async function testCase(
364
441
  options: {
365
442
  optionFlag: optionFlag({
366
443
  long: "flag",
444
+ short: "ff",
367
445
  description: "Option flag description",
368
446
  }),
369
447
  optionRepeatable: optionRepeatable({
370
448
  long: "repeatable",
449
+ short: "r",
371
450
  type: type(),
372
451
  description: "Option repeatable description",
373
452
  }),
374
453
  optionSingleValue: optionSingleValue({
375
454
  long: "single-value",
455
+ short: "s",
376
456
  type: typeConverted(
377
457
  "enum(number)",
378
458
  typeChoice("enum(string)", ["42", "43"]),
379
459
  (value) => Number(value),
380
460
  ),
381
461
  description: "Option single value description",
382
- defaultWhenNotDefined: () => 42,
462
+ defaultIfNotSpecified: () => 42,
383
463
  }),
384
464
  },
385
465
  positionals: [
@@ -401,8 +481,9 @@ async function testCase(
401
481
  options: {
402
482
  optionExtra: optionRepeatable({
403
483
  long: "url",
484
+ short: "u",
404
485
  description: "Option url description",
405
- type: typeUrl("url"),
486
+ type: typeUrl(),
406
487
  }),
407
488
  },
408
489
  positionals: [
@@ -17,7 +17,11 @@ it("run", async function () {
17
17
  );
18
18
  await testCase(
19
19
  ["--nope"],
20
- "{{Error:}@darkRed}+ Unexpected unknown option: {{--nope}@darkYellow}+",
20
+ '{{Error:}@darkRed}+ Unknown option: {{"--nope"}@darkYellow}+: did you mean: {{--help}@darkCyan}+, {{--flag}@darkCyan}+, {{--repeatable}@darkCyan}+ ?',
21
+ );
22
+ await testCase(
23
+ ["--repeat"],
24
+ '{{Error:}@darkRed}+ Unknown option: {{"--repeat"}@darkYellow}+: did you mean: {{--repeatable}@darkCyan}+, {{--help}@darkCyan}+, {{--flag}@darkCyan}+ ?',
21
25
  );
22
26
  await testCase(
23
27
  ["--flag", "--flag"],
@@ -58,7 +62,7 @@ async function testCase(args: Array<string>, error: string) {
58
62
  optionSingleValue: optionSingleValue({
59
63
  long: "single-value",
60
64
  type: typeUrl("location"),
61
- defaultWhenNotDefined: () => undefined,
65
+ defaultIfNotSpecified: () => undefined,
62
66
  }),
63
67
  optionRepeatable: optionRepeatable({
64
68
  long: "repeatable",