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
@@ -47,7 +47,7 @@ const rootCommand = commandChained(
47
47
  string: optionSingleValue({
48
48
  long: "string-option",
49
49
  type: type(),
50
- defaultIfNotSpecified: () => undefined,
50
+ fallbackValueIfAbsent: () => undefined,
51
51
  }),
52
52
  number: optionRepeatable({
53
53
  long: "number-option",
@@ -1,4 +1,4 @@
1
- import { it } from "@jest/globals";
1
+ import { expect, it } from "@jest/globals";
2
2
  import {
3
3
  command,
4
4
  Command,
@@ -37,10 +37,9 @@ const rootCommand = commandChained<any, any, any>(
37
37
  options: {
38
38
  choiceOption: optionSingleValue({
39
39
  long: "choice-option",
40
- type: typeChoice("choice", ["unset", "empty", "choice1", "choice2"]),
40
+ type: typeChoice("choice", ["unset", "choice1", "choice2"]),
41
41
  description: "choice-option description",
42
- valueIfNothingInlined: () => "empty",
43
- defaultIfNotSpecified: () => "unset",
42
+ fallbackValueIfAbsent: () => "unset",
44
43
  }),
45
44
  booleanFlag: optionFlag({
46
45
  short: "b",
@@ -81,7 +80,7 @@ const rootCommand = commandChained<any, any, any>(
81
80
  short: "s",
82
81
  long: "string-option",
83
82
  type: type("cool-stuff"),
84
- defaultIfNotSpecified: () => undefined,
83
+ fallbackValueIfAbsent: () => undefined,
85
84
  description: "string-option description",
86
85
  }),
87
86
  complexOption: optionRepeatable({
@@ -174,10 +173,16 @@ const rootCommand = commandChained<any, any, any>(
174
173
  duduValue: optionSingleValue({
175
174
  long: "dudu",
176
175
  type: type("dudu-value"),
177
- defaultIfNotSpecified: () => "duduDefault",
176
+ fallbackValueIfAbsent: () => "duduDefault",
178
177
  hint: "Dudu option hint",
179
178
  description: "Dudu option description",
180
179
  }),
180
+ impliable: optionSingleValue({
181
+ long: "impliable",
182
+ type: type("text"),
183
+ impliedValueIfNotInlined: () => "implied",
184
+ fallbackValueIfAbsent: () => "absent",
185
+ }),
181
186
  },
182
187
  positionals: [
183
188
  positionalRequired({
@@ -308,6 +313,7 @@ it("run", async function () {
308
313
  " {{-s}@darkCyan}+, {{--string-option}@darkCyan}+ {{<cool-stuff>}@darkBlue}+ string-option description",
309
314
  " {{--complex-option}@darkCyan}+ {{<number,string[,string]...>}@darkBlue}+{{ [*]}-}* complex-option description",
310
315
  " {{--dudu}@darkCyan}+ {{<dudu-value>}@darkBlue}+ Dudu option description {{(Dudu option hint)}-}*",
316
+ " {{--impliable}@darkCyan}+{{[=text]}-}*",
311
317
  "",
312
318
  "{{Examples:}@darkGreen}+",
313
319
  " {{# Example usage of subcommand 2}-}*",
@@ -1,34 +1,43 @@
1
- import { it } from "@jest/globals";
2
- import { similaritySort } from "../src/lib/Similarity";
1
+ import { expect, it } from "@jest/globals";
2
+ import { TypoString, TypoText } from "../src";
3
+ import { suggestTextPushMessage } from "../src/lib/Suggest";
3
4
 
4
5
  it("run", async function () {
5
- expect(
6
- orderBySimilarity("--inst", ["--flag", "--blah", "--install"]),
7
- ).toStrictEqual(["--install", "--flag", "--blah"]);
6
+ expectReasonables(["--flag", "--blah", "--install"], "--inst", ["--install"]);
7
+ expectReasonables(["install", "dudu", "--blah"], "instlal", ["install"]);
8
+ expectReasonables(["hello", "kat", "cats"], "cat", ["cats", "kat"]);
9
+ expectReasonables(["cut", "kat"], "cat", ["cut", "kat"]);
10
+ expectReasonables(["abc", "ac", "ab"], "acb", ["abc", "ac", "ab"]);
8
11
 
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",
12
+ const library = [
13
+ "install",
14
+ "install-package",
15
+ "install-package-latest",
16
+ "uninstall",
17
+ "update",
18
+ "list",
19
+ ];
20
+ expectReasonables(library, "instal", ["install", "uninstall"]);
21
+ expectReasonables(library, "insta-package", ["install-package"]);
22
+ expectReasonables(library, "insta-package-lates", ["install-package-latest"]);
23
+ expectReasonables(library, "install-package-lat", [
24
+ "install-package-latest",
25
+ "install-package",
26
26
  ]);
27
27
  });
28
28
 
29
- function orderBySimilarity(reference: string, candidates: Array<string>) {
30
- return similaritySort(
31
- reference,
32
- candidates.map((key) => ({ key, value: key })),
29
+ function expectReasonables(
30
+ references: Array<string>,
31
+ query: string,
32
+ reasonables: Array<string>,
33
+ ) {
34
+ const text = new TypoText();
35
+ suggestTextPushMessage(
36
+ text,
37
+ query,
38
+ references.map((key) => ({ reference: key, hint: new TypoString(key) })),
39
+ );
40
+ expect(text.computeRawString()).toStrictEqual(
41
+ " Did you mean: " + reasonables.join(", ") + " ?",
33
42
  );
34
43
  }
@@ -1,4 +1,4 @@
1
- import { it } from "@jest/globals";
1
+ import { expect, it } from "@jest/globals";
2
2
  import {
3
3
  command,
4
4
  operation,
@@ -33,12 +33,12 @@ const usageTty = usageToStyledLines({
33
33
  }).join("\n");
34
34
 
35
35
  const unknownOptionNone =
36
- 'Error: Unknown option: "--color": did you mean: --help, --version ?';
36
+ 'Error: Unknown option: "--color". Did you mean: --help, --version ?';
37
37
  const unknownOptionMock =
38
- '{{Error:}@darkRed}+ Unknown option: {{"--color"}@darkYellow}+: did you mean: {{--help}@darkCyan}+, {{--version}@darkCyan}+ ?';
38
+ '{{Error:}@darkRed}+ Unknown option: {{"--color"}@darkYellow}+. Did you mean: {{--help}@darkCyan}+, {{--version}@darkCyan}+ ?';
39
39
 
40
40
  it("run", async function () {
41
- await withEnv("FORCE_COLOR", "false", async () => {
41
+ await withEnv("FORCE_COLOR", "", async () => {
42
42
  if (process.stdout.isTTY) {
43
43
  await testAllHelpsSuccesses(usageTty);
44
44
  } else {
@@ -55,9 +55,6 @@ it("run", async function () {
55
55
  await withEnv("NO_COLOR", "", async () => {
56
56
  await testAllHelpsSuccesses(usageTty);
57
57
  });
58
- await withEnv("MOCK_COLOR", "", async () => {
59
- await testAllHelpsSuccesses(usageTty);
60
- });
61
58
  await withEnv("TERM", "dumb", async () => {
62
59
  await testAllHelpsSuccesses(usageTty);
63
60
  });
@@ -72,32 +69,12 @@ it("run", async function () {
72
69
  await withEnv("FORCE_COLOR", "0", async () => {
73
70
  await testAllHelpsSuccesses(usageNone);
74
71
  });
75
- await withEnv("MOCK_COLOR", "true", async () => {
76
- await testAllHelpsSuccesses(usageMock);
77
- });
78
-
79
- await withEnv("MOCK_COLOR", "1", async () => {
80
- await testCase(
81
- "flag",
82
- ["--color=42"],
83
- [],
84
- [
85
- usageMock,
86
- '{{Error:}@darkRed}+ {{--color}@darkCyan}+: {{<color-mode>}@darkBlue}+: Unknown value: {{"42"}@darkYellow}+: did you mean: {{"auto"}@darkYellow}+, {{"always"}@darkYellow}+, {{"never"}@darkYellow}+ ?',
87
- ],
88
- 1,
89
- );
90
- });
91
72
 
92
- await withEnv("MOCK_COLOR", "1", async () => {
93
- await testAllFlagsFailures("env", usageMock, unknownOptionMock);
94
- });
73
+ await testAllFlagsFailures("mock", usageMock, unknownOptionMock);
74
+ await testAllFlagsFailures("never", usageNone, unknownOptionNone);
95
75
  await withEnv("FORCE_COLOR", "0", async () => {
96
76
  await testAllFlagsFailures("env", usageNone, unknownOptionNone);
97
77
  });
98
-
99
- await testAllFlagsFailures("mock", usageMock, unknownOptionMock);
100
- await testAllFlagsFailures("never", usageNone, unknownOptionNone);
101
78
  });
102
79
  });
103
80
 
@@ -106,24 +83,22 @@ async function testAllFlagsFailures(
106
83
  usageErr: string,
107
84
  message: string,
108
85
  ) {
86
+ await testCase(colorSetup, ["--color"], [], [usageErr, message], 1);
109
87
  await testCase(colorSetup, ["--color=auto"], [], [usageErr, message], 1);
110
88
  await testCase(colorSetup, ["--color=always"], [], [usageErr, message], 1);
111
89
  await testCase(colorSetup, ["--color=never"], [], [usageErr, message], 1);
112
- await testCase(colorSetup, ["--color=mock"], [], [usageErr, message], 1);
113
- await testCase(colorSetup, ["--color"], [], [usageErr, message], 1);
114
90
  }
115
91
 
116
92
  async function testAllHelpsSuccesses(usageFromEnv: string) {
117
93
  await testCase("flag", ["--color=auto", "--help"], [usageFromEnv], [], 0);
118
94
  await testCase("flag", ["--color=always", "--help"], [usageTty], [], 0);
119
95
  await testCase("flag", ["--color=never", "--help"], [usageNone], [], 0);
120
- await testCase("flag", ["--color=mock", "--help"], [usageMock], [], 0);
121
96
  await testCase("flag", ["--color", "--help"], [usageTty], [], 0);
122
97
  await testCase("flag", ["--help"], [usageFromEnv], [], 0);
123
- await testCase("env", ["--help"], [usageFromEnv], [], 0);
124
98
  await testCase("always", ["--help"], [usageTty], [], 0);
125
99
  await testCase("never", ["--help"], [usageNone], [], 0);
126
100
  await testCase("mock", ["--help"], [usageMock], [], 0);
101
+ await testCase("env", ["--help"], [usageFromEnv], [], 0);
127
102
  }
128
103
 
129
104
  async function testCase(