cli-kiss 0.1.8 → 0.2.0

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
@@ -12,6 +12,48 @@ import {
12
12
  TypoText,
13
13
  } from "./Typo";
14
14
 
15
+ /**
16
+ * Converts a {@link CommandUsage} model into an array of styled lines ready to be
17
+ * joined with `"\n"` and printed to the terminal.
18
+ *
19
+ * The output format is:
20
+ * ```
21
+ * Usage: <cliName> [breadcrumbs...]
22
+ *
23
+ * <description> (<hint>)
24
+ * <detail lines...>
25
+ *
26
+ * Positionals:
27
+ * <LABEL> <description> (<hint>)
28
+ *
29
+ * Subcommands:
30
+ * <name> <description> (<hint>)
31
+ *
32
+ * Options:
33
+ * -s, --long <LABEL> <description> (<hint>)
34
+ *
35
+ * ```
36
+ * Sections that have no entries are omitted. The trailing empty line is always included.
37
+ *
38
+ * Column alignment within each section is handled by {@link TypoGrid}: the widest entry
39
+ * in each column sets the width for the entire section.
40
+ *
41
+ * @param params.cliName - The CLI program name shown at the start of the usage line.
42
+ * @param params.commandUsage - The usage model produced by {@link CommandFactory.generateUsage}.
43
+ * @param params.typoSupport - Controls color/styling of the output.
44
+ * @returns An ordered array of strings, one per output line (including a trailing
45
+ * empty string for the blank line at the end).
46
+ *
47
+ * @example
48
+ * ```ts
49
+ * const lines = usageToStyledLines({
50
+ * cliName: "my-cli",
51
+ * commandUsage: commandFactory.generateUsage(),
52
+ * typoSupport: TypoSupport.tty(),
53
+ * });
54
+ * process.stdout.write(lines.join("\n"));
55
+ * ```
56
+ */
15
57
  export function usageToStyledLines(params: {
16
58
  cliName: Lowercase<string>;
17
59
  commandUsage: CommandUsage;
@@ -9,7 +9,7 @@ import {
9
9
  positionalOptional,
10
10
  positionalRequired,
11
11
  positionalVariadics,
12
- runAsCliAndExit,
12
+ runAndExit,
13
13
  typeConverted,
14
14
  typeOneOf,
15
15
  typeString,
@@ -324,7 +324,7 @@ async function testCase(
324
324
  ],
325
325
  },
326
326
  async () => {
327
- onLogStdOut.call("Has executed root command");
327
+ console.log("Has executed root command");
328
328
  },
329
329
  ),
330
330
  {
@@ -359,17 +359,17 @@ async function testCase(
359
359
  ],
360
360
  },
361
361
  async () => {
362
- onLogStdOut.call("Has executed subcommand");
362
+ console.log("Has executed subcommand");
363
363
  },
364
364
  ),
365
365
  ),
366
366
  },
367
367
  );
368
- await runAsCliAndExit("my-cli", args, null, cmd, {
368
+ console.log = onLogStdOut.call;
369
+ console.error = onLogStdErr.call;
370
+ await runAndExit("my-cli", args, null, cmd, {
369
371
  buildVersion: "1.0.0",
370
372
  useTtyColors: false,
371
- onLogStdOut: onLogStdOut.call,
372
- onLogStdErr: onLogStdErr.call,
373
373
  onExit: onExit.call,
374
374
  });
375
375
  expect({
@@ -5,7 +5,7 @@ import {
5
5
  optionFlag,
6
6
  optionRepeatable,
7
7
  optionSingleValue,
8
- runAsCliAndExit,
8
+ runAndExit,
9
9
  typeNumber,
10
10
  typeUrl,
11
11
  } from "../src";
@@ -34,43 +34,43 @@ it("run", async () => {
34
34
  });
35
35
 
36
36
  async function testCase(args: Array<string>, error: string) {
37
+ const onLogStdOut = makeMocked<string, void>([]);
37
38
  const onLogStdErr = makeMocked<string, void>([null as unknown as void]);
38
39
  const onExit = makeMocked<number, never>([null as never]);
39
- await runAsCliAndExit(
40
- "my-cli",
41
- args,
42
- null,
43
- command<void, void>(
44
- { description: "" },
45
- operation(
46
- {
47
- options: {
48
- optionFlag: optionFlag({ long: "flag" }),
49
- optionSingleValue: optionSingleValue({
50
- label: "LOCATION",
51
- long: "single-value",
52
- type: typeUrl,
53
- default: () => undefined,
54
- }),
55
- optionRepeatable: optionRepeatable({
56
- label: "INDEX",
57
- long: "repeatable",
58
- type: typeNumber,
59
- }),
60
- },
61
- positionals: [],
40
+ const rootCommand = command<void, void>(
41
+ { description: "" },
42
+ operation(
43
+ {
44
+ options: {
45
+ optionFlag: optionFlag({
46
+ long: "flag",
47
+ }),
48
+ optionSingleValue: optionSingleValue({
49
+ label: "LOCATION",
50
+ long: "single-value",
51
+ type: typeUrl,
52
+ default: () => undefined,
53
+ }),
54
+ optionRepeatable: optionRepeatable({
55
+ label: "INDEX",
56
+ long: "repeatable",
57
+ type: typeNumber,
58
+ }),
62
59
  },
63
- async (_, _inputs) => {},
64
- ),
60
+ positionals: [],
61
+ },
62
+ async () => {},
65
63
  ),
66
- {
67
- buildVersion: "1.0.0",
68
- usageOnError: false,
69
- useTtyColors: "mock",
70
- onLogStdErr: onLogStdErr.call,
71
- onExit: onExit.call,
72
- },
73
64
  );
65
+ console.log = onLogStdOut.call;
66
+ console.error = onLogStdErr.call;
67
+ await runAndExit("my-cli", args, null, rootCommand, {
68
+ buildVersion: "1.0.0",
69
+ usageOnError: false,
70
+ useTtyColors: "mock",
71
+ onExit: onExit.call,
72
+ });
73
+ expect(onLogStdOut.history).toEqual([]);
74
74
  expect(onLogStdErr.history).toEqual([error]);
75
75
  expect(onExit.history).toEqual([1]);
76
76
  }