@silvery/commander 0.6.1 → 0.7.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/package.json +2 -3
- package/src/colorize.ts +43 -88
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@silvery/commander",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"description": "Colorized Commander.js help output using ANSI escape codes",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ansi",
|
|
@@ -29,8 +29,7 @@
|
|
|
29
29
|
"access": "public"
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"@silvery/ansi": ">=
|
|
33
|
-
"@silvery/style": ">=0.1.0",
|
|
32
|
+
"@silvery/ansi": ">=1.0.0",
|
|
34
33
|
"commander": ">=12.0.0"
|
|
35
34
|
},
|
|
36
35
|
"peerDependencies": {
|
package/src/colorize.ts
CHANGED
|
@@ -1,57 +1,38 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Commander.js help colorization using
|
|
2
|
+
* Commander.js help colorization using @silvery/ansi.
|
|
3
3
|
*
|
|
4
4
|
* Uses Commander's built-in style hooks (styleTitle, styleOptionText, etc.)
|
|
5
|
-
* rather than regex post-processing.
|
|
6
|
-
* or plain commander — accepts a minimal CommandLike interface so Commander
|
|
7
|
-
* is a peer dependency, not a hard one.
|
|
5
|
+
* rather than regex post-processing.
|
|
8
6
|
*
|
|
9
7
|
* @example
|
|
10
8
|
* ```ts
|
|
11
9
|
* import { Command } from "@silvery/commander"
|
|
10
|
+
* // Command auto-colorizes in its constructor — no manual call needed.
|
|
11
|
+
* // For plain Commander:
|
|
12
12
|
* import { colorizeHelp } from "@silvery/commander"
|
|
13
|
-
*
|
|
14
|
-
* const program = new Command("myapp").description("My CLI tool")
|
|
15
13
|
* colorizeHelp(program)
|
|
16
14
|
* ```
|
|
17
15
|
*/
|
|
18
16
|
|
|
19
|
-
import {
|
|
20
|
-
import { detectColor } from "@silvery/ansi"
|
|
17
|
+
import { createStyle } from "@silvery/ansi"
|
|
21
18
|
|
|
22
|
-
//
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
const
|
|
26
|
-
const CYAN = `\x1b[${FG_COLORS.cyan}m`
|
|
27
|
-
const GREEN = `\x1b[${FG_COLORS.green}m`
|
|
28
|
-
const YELLOW = `\x1b[${FG_COLORS.yellow}m`
|
|
19
|
+
// Auto-detect terminal color level. The Style instance handles the full
|
|
20
|
+
// degradation chain: truecolor → 256 → basic (ANSI 16) → null (no color).
|
|
21
|
+
// When level is null (NO_COLOR), style methods return plain text.
|
|
22
|
+
const s = createStyle()
|
|
29
23
|
|
|
30
24
|
/**
|
|
31
25
|
* Check if color output should be enabled.
|
|
32
|
-
*
|
|
33
|
-
* FORCE_COLOR, TERM, etc.).
|
|
26
|
+
* Delegates to @silvery/ansi's auto-detection (NO_COLOR, FORCE_COLOR, TERM).
|
|
34
27
|
*/
|
|
35
|
-
let _shouldColorize: boolean | undefined
|
|
36
|
-
|
|
37
28
|
export function shouldColorize(): boolean {
|
|
38
|
-
|
|
39
|
-
_shouldColorize = detectColor(process.stdout) !== null
|
|
40
|
-
return _shouldColorize
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
/** Wrap a string with ANSI codes, handling nested resets. */
|
|
44
|
-
function ansi(text: string, code: string): string {
|
|
45
|
-
return `${code}${text}${RESET}`
|
|
29
|
+
return s.level > 0
|
|
46
30
|
}
|
|
47
31
|
|
|
48
32
|
/**
|
|
49
33
|
* Minimal interface for Commander's Command — avoids requiring Commander
|
|
50
34
|
* as a direct dependency. Works with both `commander` and
|
|
51
35
|
* `@silvery/commander`.
|
|
52
|
-
*
|
|
53
|
-
* Uses permissive types to ensure structural compatibility with all
|
|
54
|
-
* Commander versions, overloads, and generic instantiations.
|
|
55
36
|
*/
|
|
56
37
|
export interface CommandLike {
|
|
57
38
|
// biome-ignore lint: permissive to match Commander's overloaded signatures
|
|
@@ -62,82 +43,56 @@ export interface CommandLike {
|
|
|
62
43
|
readonly commands: readonly any[]
|
|
63
44
|
}
|
|
64
45
|
|
|
65
|
-
/** Color scheme for help output.
|
|
46
|
+
/** Color scheme for help output. Each value is a styling function (text → styled text). */
|
|
66
47
|
export interface ColorizeHelpOptions {
|
|
67
|
-
/**
|
|
68
|
-
commands?: string
|
|
69
|
-
/**
|
|
70
|
-
flags?: string
|
|
71
|
-
/**
|
|
72
|
-
description?: string
|
|
73
|
-
/**
|
|
74
|
-
heading?: string
|
|
75
|
-
/**
|
|
76
|
-
brackets?: string
|
|
48
|
+
/** Style for command/subcommand names. Default: cyan */
|
|
49
|
+
commands?: (text: string) => string
|
|
50
|
+
/** Style for --flags and -short options. Default: green */
|
|
51
|
+
flags?: (text: string) => string
|
|
52
|
+
/** Style for description text. Default: dim */
|
|
53
|
+
description?: (text: string) => string
|
|
54
|
+
/** Style for section headings (Usage:, Options:, etc.). Default: bold */
|
|
55
|
+
heading?: (text: string) => string
|
|
56
|
+
/** Style for <required> and [optional] argument brackets. Default: yellow */
|
|
57
|
+
brackets?: (text: string) => string
|
|
77
58
|
}
|
|
78
59
|
|
|
79
60
|
/**
|
|
80
61
|
* Apply colorized help output to a Commander.js program and all its subcommands.
|
|
81
62
|
*
|
|
82
63
|
* Uses Commander's built-in `configureHelp()` style hooks rather than
|
|
83
|
-
* post-processing the formatted string.
|
|
84
|
-
* formatting changes in Commander and handles wrapping correctly.
|
|
64
|
+
* post-processing the formatted string.
|
|
85
65
|
*
|
|
86
66
|
* @param program - A Commander Command instance (or compatible object)
|
|
87
|
-
* @param options - Override default
|
|
67
|
+
* @param options - Override default style functions for each element
|
|
88
68
|
*/
|
|
89
69
|
export function colorizeHelp(program: CommandLike, options?: ColorizeHelpOptions): void {
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
70
|
+
// Ensure style generates codes — at minimum basic (ANSI 16).
|
|
71
|
+
// Auto-detected level may be higher (256/truecolor) for richer output.
|
|
72
|
+
// May be 0 if NO_COLOR is set; in that case, force basic since Commander
|
|
73
|
+
// handles the final strip via configureOutput.
|
|
74
|
+
if (s.level === 0) s.level = 1
|
|
75
|
+
|
|
76
|
+
const cmds = options?.commands ?? ((t: string) => s.cyan(t))
|
|
77
|
+
const flags = options?.flags ?? ((t: string) => s.green(t))
|
|
78
|
+
const desc = options?.description ?? ((t: string) => s.dim(t))
|
|
79
|
+
const heading = options?.heading ?? ((t: string) => s.bold(t))
|
|
80
|
+
const brackets = options?.brackets ?? ((t: string) => s.yellow(t))
|
|
95
81
|
|
|
96
82
|
const helpConfig: Record<string, unknown> = {
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
return ansi(str, cmds)
|
|
105
|
-
},
|
|
106
|
-
|
|
107
|
-
// Option terms: "-v, --verbose", "--repo <path>", "[options]"
|
|
108
|
-
styleOptionText(str: string): string {
|
|
109
|
-
return ansi(str, flags)
|
|
110
|
-
},
|
|
111
|
-
|
|
112
|
-
// Subcommand names in the commands list
|
|
113
|
-
styleSubcommandText(str: string): string {
|
|
114
|
-
return ansi(str, cmds)
|
|
115
|
-
},
|
|
116
|
-
|
|
117
|
-
// Argument terms: "<file>", "[dir]"
|
|
118
|
-
styleArgumentText(str: string): string {
|
|
119
|
-
return ansi(str, brackets)
|
|
120
|
-
},
|
|
121
|
-
|
|
122
|
-
// Description text for options, subcommands, arguments
|
|
123
|
-
styleDescriptionText(str: string): string {
|
|
124
|
-
return ansi(str, desc)
|
|
125
|
-
},
|
|
126
|
-
|
|
127
|
-
// Command description (the main program description line) — keep normal
|
|
128
|
-
styleCommandDescription(str: string): string {
|
|
129
|
-
return str
|
|
130
|
-
},
|
|
83
|
+
styleTitle: (str: string) => heading(str),
|
|
84
|
+
styleCommandText: (str: string) => cmds(str),
|
|
85
|
+
styleOptionText: (str: string) => flags(str),
|
|
86
|
+
styleSubcommandText: (str: string) => cmds(str),
|
|
87
|
+
styleArgumentText: (str: string) => brackets(str),
|
|
88
|
+
styleDescriptionText: (str: string) => desc(str),
|
|
89
|
+
styleCommandDescription: (str: string) => str,
|
|
131
90
|
}
|
|
132
91
|
|
|
133
92
|
program.configureHelp(helpConfig)
|
|
134
93
|
|
|
135
94
|
// Tell Commander that color output is supported, even when stdout is not
|
|
136
|
-
// a TTY
|
|
137
|
-
// all ANSI codes from helpInformation() output.
|
|
138
|
-
//
|
|
139
|
-
// Callers who want to respect NO_COLOR/FORCE_COLOR should check
|
|
140
|
-
// shouldColorize() before calling colorizeHelp().
|
|
95
|
+
// a TTY. Without this, Commander strips ANSI codes from helpInformation().
|
|
141
96
|
program.configureOutput({
|
|
142
97
|
getOutHasColors: () => true,
|
|
143
98
|
getErrHasColors: () => true,
|