padrone 1.4.0 → 1.6.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/CHANGELOG.md +115 -0
- package/README.md +108 -283
- package/dist/args-Cnq0nwSM.mjs +272 -0
- package/dist/args-Cnq0nwSM.mjs.map +1 -0
- package/dist/codegen/index.d.mts +28 -3
- package/dist/codegen/index.d.mts.map +1 -1
- package/dist/codegen/index.mjs +169 -19
- package/dist/codegen/index.mjs.map +1 -1
- package/dist/commands-B_gufyR9.mjs +514 -0
- package/dist/commands-B_gufyR9.mjs.map +1 -0
- package/dist/{completion.mjs → completion-BEuflbDO.mjs} +86 -108
- package/dist/completion-BEuflbDO.mjs.map +1 -0
- package/dist/docs/index.d.mts +22 -2
- package/dist/docs/index.d.mts.map +1 -1
- package/dist/docs/index.mjs +92 -7
- package/dist/docs/index.mjs.map +1 -1
- package/dist/errors-CL63UOzt.mjs +137 -0
- package/dist/errors-CL63UOzt.mjs.map +1 -0
- package/dist/{formatter-ClUK5hcQ.d.mts → formatter-DrvhDMrq.d.mts} +35 -6
- package/dist/formatter-DrvhDMrq.d.mts.map +1 -0
- package/dist/help-B5Kk83of.mjs +849 -0
- package/dist/help-B5Kk83of.mjs.map +1 -0
- package/dist/index-BaU3X6dY.d.mts +1178 -0
- package/dist/index-BaU3X6dY.d.mts.map +1 -0
- package/dist/index.d.mts +763 -36
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +3608 -1534
- package/dist/index.mjs.map +1 -1
- package/dist/mcp-BM-d0nZi.mjs +377 -0
- package/dist/mcp-BM-d0nZi.mjs.map +1 -0
- package/dist/serve-Bk0JUlCj.mjs +402 -0
- package/dist/serve-Bk0JUlCj.mjs.map +1 -0
- package/dist/stream-DC4H8YTx.mjs +77 -0
- package/dist/stream-DC4H8YTx.mjs.map +1 -0
- package/dist/test.d.mts +5 -8
- package/dist/test.d.mts.map +1 -1
- package/dist/test.mjs +5 -27
- package/dist/test.mjs.map +1 -1
- package/dist/{update-check-EbNDkzyV.mjs → update-check-CZ2VqjnV.mjs} +16 -17
- package/dist/update-check-CZ2VqjnV.mjs.map +1 -0
- package/dist/zod.d.mts +32 -0
- package/dist/zod.d.mts.map +1 -0
- package/dist/zod.mjs +50 -0
- package/dist/zod.mjs.map +1 -0
- package/package.json +20 -9
- package/src/cli/completions.ts +14 -11
- package/src/cli/docs.ts +13 -16
- package/src/cli/doctor.ts +213 -24
- package/src/cli/index.ts +28 -82
- package/src/cli/init.ts +12 -10
- package/src/cli/link.ts +22 -18
- package/src/cli/wrap.ts +14 -11
- package/src/codegen/discovery.ts +80 -28
- package/src/codegen/index.ts +2 -1
- package/src/codegen/parsers/bash.ts +179 -0
- package/src/codegen/schema-to-code.ts +2 -1
- package/src/core/args.ts +296 -0
- package/src/core/commands.ts +373 -0
- package/src/core/create.ts +268 -0
- package/src/{runtime.ts → core/default-runtime.ts} +70 -135
- package/src/{errors.ts → core/errors.ts} +22 -0
- package/src/core/exec.ts +259 -0
- package/src/core/interceptors.ts +302 -0
- package/src/{parse.ts → core/parse.ts} +36 -89
- package/src/core/program-methods.ts +301 -0
- package/src/core/results.ts +229 -0
- package/src/core/runtime.ts +246 -0
- package/src/core/validate.ts +247 -0
- package/src/docs/index.ts +124 -11
- package/src/extension/auto-output.ts +95 -0
- package/src/extension/color.ts +38 -0
- package/src/extension/completion.ts +49 -0
- package/src/extension/config.ts +262 -0
- package/src/extension/env.ts +101 -0
- package/src/extension/help.ts +192 -0
- package/src/extension/index.ts +43 -0
- package/src/extension/ink.ts +93 -0
- package/src/extension/interactive.ts +106 -0
- package/src/extension/logger.ts +214 -0
- package/src/extension/man.ts +51 -0
- package/src/extension/mcp.ts +52 -0
- package/src/extension/progress-renderer.ts +338 -0
- package/src/extension/progress.ts +299 -0
- package/src/extension/repl.ts +94 -0
- package/src/extension/serve.ts +48 -0
- package/src/extension/signal.ts +87 -0
- package/src/extension/stdin.ts +62 -0
- package/src/extension/suggestions.ts +114 -0
- package/src/extension/timing.ts +81 -0
- package/src/extension/tracing.ts +175 -0
- package/src/extension/update-check.ts +77 -0
- package/src/extension/utils.ts +51 -0
- package/src/extension/version.ts +63 -0
- package/src/{completion.ts → feature/completion.ts} +130 -57
- package/src/{interactive.ts → feature/interactive.ts} +47 -6
- package/src/feature/mcp.ts +387 -0
- package/src/{repl-loop.ts → feature/repl-loop.ts} +26 -16
- package/src/feature/serve.ts +438 -0
- package/src/feature/test.ts +262 -0
- package/src/{update-check.ts → feature/update-check.ts} +16 -16
- package/src/{wrap.ts → feature/wrap.ts} +27 -27
- package/src/index.ts +120 -11
- package/src/output/colorizer.ts +154 -0
- package/src/{formatter.ts → output/formatter.ts} +281 -135
- package/src/{help.ts → output/help.ts} +62 -15
- package/src/{zod.d.ts → schema/zod.d.ts} +1 -1
- package/src/schema/zod.ts +50 -0
- package/src/test.ts +2 -285
- package/src/types/args-meta.ts +151 -0
- package/src/types/builder.ts +697 -0
- package/src/types/command.ts +157 -0
- package/src/types/index.ts +59 -0
- package/src/types/interceptor.ts +296 -0
- package/src/types/preferences.ts +83 -0
- package/src/types/result.ts +71 -0
- package/src/types/schema.ts +19 -0
- package/src/util/dotenv.ts +244 -0
- package/src/{shell-utils.ts → util/shell-utils.ts} +26 -9
- package/src/util/stream.ts +101 -0
- package/src/{type-helpers.ts → util/type-helpers.ts} +23 -16
- package/src/{type-utils.ts → util/type-utils.ts} +99 -37
- package/src/util/utils.ts +51 -0
- package/src/zod.ts +1 -0
- package/dist/args-CVDbyyzG.mjs +0 -199
- package/dist/args-CVDbyyzG.mjs.map +0 -1
- package/dist/chunk-y_GBKt04.mjs +0 -5
- package/dist/completion.d.mts +0 -64
- package/dist/completion.d.mts.map +0 -1
- package/dist/completion.mjs.map +0 -1
- package/dist/formatter-ClUK5hcQ.d.mts.map +0 -1
- package/dist/help-CcBe91bV.mjs +0 -1254
- package/dist/help-CcBe91bV.mjs.map +0 -1
- package/dist/types-DjIdJN5G.d.mts +0 -1059
- package/dist/types-DjIdJN5G.d.mts.map +0 -1
- package/dist/update-check-EbNDkzyV.mjs.map +0 -1
- package/src/args.ts +0 -461
- package/src/colorizer.ts +0 -41
- package/src/command-utils.ts +0 -532
- package/src/create.ts +0 -1477
- package/src/types.ts +0 -1109
- package/src/utils.ts +0 -140
|
@@ -0,0 +1,849 @@
|
|
|
1
|
+
import { o as findCommandByName } from "./commands-B_gufyR9.mjs";
|
|
2
|
+
import { a as getJsonSchema, c as parsePositionalConfig, i as extractSchemaMetadata, u as camelToKebab } from "./args-Cnq0nwSM.mjs";
|
|
3
|
+
//#region src/util/utils.ts
|
|
4
|
+
function getRootCommand(cmd) {
|
|
5
|
+
let current = cmd;
|
|
6
|
+
while (current.parent) current = current.parent;
|
|
7
|
+
return current;
|
|
8
|
+
}
|
|
9
|
+
async function readVersionFromPackageJson() {
|
|
10
|
+
try {
|
|
11
|
+
const fs = await import("node:fs");
|
|
12
|
+
const path = await import("node:path");
|
|
13
|
+
let dir = process.cwd();
|
|
14
|
+
for (let i = 0; i < 10; i++) {
|
|
15
|
+
const pkgPath = path.join(dir, "package.json");
|
|
16
|
+
if (fs.existsSync(pkgPath)) {
|
|
17
|
+
const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf-8"));
|
|
18
|
+
if (pkg.version) return pkg.version;
|
|
19
|
+
}
|
|
20
|
+
const parentDir = path.dirname(dir);
|
|
21
|
+
if (parentDir === dir) break;
|
|
22
|
+
dir = parentDir;
|
|
23
|
+
}
|
|
24
|
+
} catch {}
|
|
25
|
+
return "0.0.0";
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Attempts to get the version from various sources:
|
|
29
|
+
* 1. Explicit version set on the command
|
|
30
|
+
* 2. npm_package_version environment variable (set by npm/yarn/pnpm when running scripts)
|
|
31
|
+
* 3. package.json in current or parent directories
|
|
32
|
+
*
|
|
33
|
+
* Returns synchronously when an explicit version or env var is available.
|
|
34
|
+
* Falls back to async package.json discovery otherwise.
|
|
35
|
+
*/
|
|
36
|
+
function getVersion(explicitVersion) {
|
|
37
|
+
if (explicitVersion) return explicitVersion;
|
|
38
|
+
if (typeof process !== "undefined" && process.env?.npm_package_version) return process.env.npm_package_version;
|
|
39
|
+
if (typeof process !== "undefined") return readVersionFromPackageJson();
|
|
40
|
+
return "0.0.0";
|
|
41
|
+
}
|
|
42
|
+
//#endregion
|
|
43
|
+
//#region src/output/colorizer.ts
|
|
44
|
+
const ansiCodes = {
|
|
45
|
+
reset: "\x1B[0m",
|
|
46
|
+
bold: "\x1B[1m",
|
|
47
|
+
dim: "\x1B[2m",
|
|
48
|
+
italic: "\x1B[3m",
|
|
49
|
+
underline: "\x1B[4m",
|
|
50
|
+
strikethrough: "\x1B[9m",
|
|
51
|
+
red: "\x1B[31m",
|
|
52
|
+
green: "\x1B[32m",
|
|
53
|
+
yellow: "\x1B[33m",
|
|
54
|
+
blue: "\x1B[34m",
|
|
55
|
+
magenta: "\x1B[35m",
|
|
56
|
+
cyan: "\x1B[36m",
|
|
57
|
+
white: "\x1B[37m",
|
|
58
|
+
gray: "\x1B[90m"
|
|
59
|
+
};
|
|
60
|
+
const defaultTheme = {
|
|
61
|
+
command: ["cyan", "bold"],
|
|
62
|
+
arg: ["green"],
|
|
63
|
+
type: ["yellow"],
|
|
64
|
+
description: ["dim"],
|
|
65
|
+
label: ["bold"],
|
|
66
|
+
meta: ["gray"],
|
|
67
|
+
example: ["underline"],
|
|
68
|
+
exampleValue: ["italic"],
|
|
69
|
+
deprecated: ["strikethrough", "gray"]
|
|
70
|
+
};
|
|
71
|
+
const colorThemes = {
|
|
72
|
+
default: defaultTheme,
|
|
73
|
+
ocean: {
|
|
74
|
+
command: ["blue", "bold"],
|
|
75
|
+
arg: ["cyan"],
|
|
76
|
+
type: ["green"],
|
|
77
|
+
description: ["dim"],
|
|
78
|
+
label: ["bold"],
|
|
79
|
+
meta: ["gray"],
|
|
80
|
+
example: ["underline", "cyan"],
|
|
81
|
+
exampleValue: ["italic"],
|
|
82
|
+
deprecated: ["strikethrough", "gray"]
|
|
83
|
+
},
|
|
84
|
+
warm: {
|
|
85
|
+
command: ["yellow", "bold"],
|
|
86
|
+
arg: ["red"],
|
|
87
|
+
type: ["magenta"],
|
|
88
|
+
description: ["dim"],
|
|
89
|
+
label: ["bold"],
|
|
90
|
+
meta: ["gray"],
|
|
91
|
+
example: ["underline", "yellow"],
|
|
92
|
+
exampleValue: ["italic"],
|
|
93
|
+
deprecated: ["strikethrough", "gray"]
|
|
94
|
+
},
|
|
95
|
+
monochrome: {
|
|
96
|
+
command: ["bold"],
|
|
97
|
+
arg: ["underline"],
|
|
98
|
+
type: ["dim"],
|
|
99
|
+
description: ["dim"],
|
|
100
|
+
label: ["bold"],
|
|
101
|
+
meta: ["dim"],
|
|
102
|
+
example: ["underline"],
|
|
103
|
+
exampleValue: ["italic"],
|
|
104
|
+
deprecated: ["strikethrough", "dim"]
|
|
105
|
+
}
|
|
106
|
+
};
|
|
107
|
+
function makeStyleFn(styles) {
|
|
108
|
+
const prefix = styles.map((s) => ansiCodes[s]).join("");
|
|
109
|
+
return (text) => `${prefix}${text}${ansiCodes.reset}`;
|
|
110
|
+
}
|
|
111
|
+
function resolveConfig(config) {
|
|
112
|
+
if (!config) return defaultTheme;
|
|
113
|
+
if (typeof config === "string") return colorThemes[config] ?? defaultTheme;
|
|
114
|
+
return {
|
|
115
|
+
...defaultTheme,
|
|
116
|
+
...config
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
function createColorizer(config) {
|
|
120
|
+
const resolved = resolveConfig(config);
|
|
121
|
+
return {
|
|
122
|
+
command: makeStyleFn(resolved.command),
|
|
123
|
+
arg: makeStyleFn(resolved.arg),
|
|
124
|
+
type: makeStyleFn(resolved.type),
|
|
125
|
+
description: makeStyleFn(resolved.description),
|
|
126
|
+
label: makeStyleFn(resolved.label),
|
|
127
|
+
meta: makeStyleFn(resolved.meta),
|
|
128
|
+
example: makeStyleFn(resolved.example),
|
|
129
|
+
exampleValue: makeStyleFn(resolved.exampleValue),
|
|
130
|
+
deprecated: makeStyleFn(resolved.deprecated)
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
//#endregion
|
|
134
|
+
//#region src/output/formatter.ts
|
|
135
|
+
const DEFAULT_TERMINAL_WIDTH = 80;
|
|
136
|
+
function wrapText(text, maxWidth) {
|
|
137
|
+
if (maxWidth <= 0 || text.length <= maxWidth) return [text];
|
|
138
|
+
const words = text.split(" ");
|
|
139
|
+
const lines = [];
|
|
140
|
+
let current = "";
|
|
141
|
+
for (const word of words) if (current && current.length + 1 + word.length > maxWidth) {
|
|
142
|
+
lines.push(current);
|
|
143
|
+
current = word;
|
|
144
|
+
} else current = current ? `${current} ${word}` : word;
|
|
145
|
+
if (current) lines.push(current);
|
|
146
|
+
return lines.length > 0 ? lines : [text];
|
|
147
|
+
}
|
|
148
|
+
function createTextStyler() {
|
|
149
|
+
return {
|
|
150
|
+
command: (text) => text,
|
|
151
|
+
arg: (text) => text,
|
|
152
|
+
type: (text) => text,
|
|
153
|
+
description: (text) => text,
|
|
154
|
+
label: (text) => text,
|
|
155
|
+
section: (text) => text,
|
|
156
|
+
meta: (text) => text,
|
|
157
|
+
example: (text) => text,
|
|
158
|
+
exampleValue: (text) => text,
|
|
159
|
+
deprecated: (text) => text
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
function createAnsiStyler(theme) {
|
|
163
|
+
const colorizer = createColorizer(theme);
|
|
164
|
+
return {
|
|
165
|
+
command: colorizer.command,
|
|
166
|
+
arg: colorizer.arg,
|
|
167
|
+
type: colorizer.type,
|
|
168
|
+
description: colorizer.description,
|
|
169
|
+
label: colorizer.label,
|
|
170
|
+
section: colorizer.label,
|
|
171
|
+
meta: colorizer.meta,
|
|
172
|
+
example: colorizer.example,
|
|
173
|
+
exampleValue: colorizer.exampleValue,
|
|
174
|
+
deprecated: colorizer.deprecated
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
function createConsoleStyler(theme) {
|
|
178
|
+
return createAnsiStyler(theme);
|
|
179
|
+
}
|
|
180
|
+
function createMarkdownStyler() {
|
|
181
|
+
return {
|
|
182
|
+
command: (text) => `**${text}**`,
|
|
183
|
+
arg: (text) => `\`${text}\``,
|
|
184
|
+
type: (text) => `\`${text}\``,
|
|
185
|
+
description: (text) => text,
|
|
186
|
+
label: (text) => `**${text}**`,
|
|
187
|
+
section: (text) => `### ${text}`,
|
|
188
|
+
meta: (text) => `*${text}*`,
|
|
189
|
+
example: (text) => `**${text}**`,
|
|
190
|
+
exampleValue: (text) => `\`${text}\``,
|
|
191
|
+
deprecated: (text) => `~~${text}~~`
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
function escapeHtml(text) {
|
|
195
|
+
return text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
196
|
+
}
|
|
197
|
+
function createHtmlStyler() {
|
|
198
|
+
return {
|
|
199
|
+
command: (text) => `<strong style="color: #00bcd4;">${escapeHtml(text)}</strong>`,
|
|
200
|
+
arg: (text) => `<code style="color: #4caf50;">${escapeHtml(text)}</code>`,
|
|
201
|
+
type: (text) => `<code style="color: #ff9800;">${escapeHtml(text)}</code>`,
|
|
202
|
+
description: (text) => `<span style="color: #666;">${escapeHtml(text)}</span>`,
|
|
203
|
+
label: (text) => `<strong>${escapeHtml(text)}</strong>`,
|
|
204
|
+
section: (text) => `<h3>${escapeHtml(text)}</h3>`,
|
|
205
|
+
meta: (text) => `<span style="color: #999;">${escapeHtml(text)}</span>`,
|
|
206
|
+
example: (text) => `<strong style="text-decoration: underline;">${escapeHtml(text)}</strong>`,
|
|
207
|
+
exampleValue: (text) => `<em>${escapeHtml(text)}</em>`,
|
|
208
|
+
deprecated: (text) => `<del style="color: #999;">${escapeHtml(text)}</del>`
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
function createTextLayout() {
|
|
212
|
+
return {
|
|
213
|
+
newline: "\n",
|
|
214
|
+
indent: (level) => " ".repeat(level),
|
|
215
|
+
join: (parts) => parts.filter(Boolean).join(" ")
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
function createMarkdownLayout() {
|
|
219
|
+
return {
|
|
220
|
+
newline: "\n\n",
|
|
221
|
+
indent: (level) => {
|
|
222
|
+
if (level === 0) return "";
|
|
223
|
+
if (level === 1) return " ";
|
|
224
|
+
return " ";
|
|
225
|
+
},
|
|
226
|
+
join: (parts) => parts.filter(Boolean).join(" ")
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
function createHtmlLayout() {
|
|
230
|
+
return {
|
|
231
|
+
newline: "<br>",
|
|
232
|
+
indent: (level) => " ".repeat(level),
|
|
233
|
+
join: (parts) => parts.filter(Boolean).join(" "),
|
|
234
|
+
wrapDocument: (content) => `<div style="font-family: monospace; line-height: 1.6;">${content}</div>`
|
|
235
|
+
};
|
|
236
|
+
}
|
|
237
|
+
/**
|
|
238
|
+
* Creates a formatter that uses the given styler and layout configuration.
|
|
239
|
+
*/
|
|
240
|
+
function createGenericFormatter(styler, layout, showAllBuiltins, terminalWidth) {
|
|
241
|
+
const { newline, indent, join, wrapDocument } = layout;
|
|
242
|
+
function formatUsageSection(info) {
|
|
243
|
+
const usageParts = [styler.command(info.usage.command), info.usage.hasSubcommands ? styler.meta("[command]") : ""];
|
|
244
|
+
if (info.positionals && info.positionals.length > 0) for (const arg of info.positionals) {
|
|
245
|
+
const name = arg.name.startsWith("...") ? `${arg.name}` : arg.name;
|
|
246
|
+
usageParts.push(styler.meta(arg.optional ? `[${name}]` : `<${name}>`));
|
|
247
|
+
}
|
|
248
|
+
if (info.usage.hasArguments) usageParts.push(styler.meta("[options]"));
|
|
249
|
+
return [`${styler.label("Usage:")} ${join(usageParts)}`];
|
|
250
|
+
}
|
|
251
|
+
function formatSubcommandsSection(info) {
|
|
252
|
+
const lines = [];
|
|
253
|
+
const subcommands = info.subcommands;
|
|
254
|
+
const subcommandSuffix = (c) => c.hasSubcommands ? " <subcommand>" : "";
|
|
255
|
+
const formatAliasParts = (c) => {
|
|
256
|
+
if (!c.aliases?.length) return {
|
|
257
|
+
plain: "",
|
|
258
|
+
styled: ""
|
|
259
|
+
};
|
|
260
|
+
const realAliases = c.aliases.filter((a) => a !== "[default]");
|
|
261
|
+
const hasDefault = c.aliases.some((a) => a === "[default]");
|
|
262
|
+
const parts = [];
|
|
263
|
+
const styledParts = [];
|
|
264
|
+
if (realAliases.length) {
|
|
265
|
+
parts.push(`(${realAliases.join(", ")})`);
|
|
266
|
+
styledParts.push(`(${realAliases.join(", ")})`);
|
|
267
|
+
}
|
|
268
|
+
if (hasDefault) {
|
|
269
|
+
parts.push("[default]");
|
|
270
|
+
styledParts.push(styler.meta("[default]"));
|
|
271
|
+
}
|
|
272
|
+
return {
|
|
273
|
+
plain: parts.length ? ` ${parts.join(" ")}` : "",
|
|
274
|
+
styled: styledParts.length ? ` ${styledParts.join(" ")}` : ""
|
|
275
|
+
};
|
|
276
|
+
};
|
|
277
|
+
const maxNameLength = Math.max(...subcommands.map((c) => {
|
|
278
|
+
return (c.name + subcommandSuffix(c) + formatAliasParts(c).plain).length;
|
|
279
|
+
}));
|
|
280
|
+
const grouped = Object.groupBy(subcommands, (c) => c.group ?? "");
|
|
281
|
+
const renderSubcommands = (cmds) => {
|
|
282
|
+
for (const subCmd of cmds) {
|
|
283
|
+
const aliasParts = formatAliasParts(subCmd);
|
|
284
|
+
const suffix = subcommandSuffix(subCmd);
|
|
285
|
+
const commandDisplay = subCmd.name + suffix + aliasParts.plain;
|
|
286
|
+
const padding = " ".repeat(Math.max(0, maxNameLength - commandDisplay.length + 2));
|
|
287
|
+
const isDeprecated = !!subCmd.deprecated;
|
|
288
|
+
const isDefaultEntry = subCmd.name === "[default]";
|
|
289
|
+
const lineParts = [isDeprecated ? styler.deprecated(commandDisplay) : (isDefaultEntry ? styler.meta(subCmd.name) : styler.command(subCmd.name)) + (suffix ? styler.meta(suffix) : "") + aliasParts.styled, padding];
|
|
290
|
+
const displayText = subCmd.title ?? subCmd.description;
|
|
291
|
+
if (displayText) lineParts.push(isDeprecated ? styler.deprecated(displayText) : styler.description(displayText));
|
|
292
|
+
if (isDeprecated) {
|
|
293
|
+
const deprecatedMeta = typeof subCmd.deprecated === "string" ? styler.meta(` (deprecated: ${subCmd.deprecated})`) : styler.meta(" (deprecated)");
|
|
294
|
+
lineParts.push(deprecatedMeta);
|
|
295
|
+
}
|
|
296
|
+
lines.push(indent(1) + lineParts.join(""));
|
|
297
|
+
}
|
|
298
|
+
};
|
|
299
|
+
for (const [key, items] of Object.entries(grouped)) {
|
|
300
|
+
if (lines.length > 0) lines.push("");
|
|
301
|
+
lines.push(styler.section(key ? `${key}:` : "Commands:"));
|
|
302
|
+
renderSubcommands(items);
|
|
303
|
+
}
|
|
304
|
+
if (!info.builtins?.length) {
|
|
305
|
+
lines.push("");
|
|
306
|
+
lines.push(styler.meta(`Run "${info.name} [command] --help" for more information on a command.`));
|
|
307
|
+
}
|
|
308
|
+
return lines;
|
|
309
|
+
}
|
|
310
|
+
function formatPositionalsSection(info) {
|
|
311
|
+
const lines = [];
|
|
312
|
+
const args = info.positionals;
|
|
313
|
+
lines.push(styler.section("Arguments:"));
|
|
314
|
+
const maxNameLength = Math.min(32, Math.max(...args.map((a) => a.name.length)));
|
|
315
|
+
const descCol = 2 + maxNameLength + 2;
|
|
316
|
+
const posAvailWidth = terminalWidth ? terminalWidth - descCol : void 0;
|
|
317
|
+
const descColPad = " ".repeat(descCol);
|
|
318
|
+
for (const arg of args) {
|
|
319
|
+
const padding = " ".repeat(Math.max(2, maxNameLength - arg.name.length + 2));
|
|
320
|
+
const prefix = indent(1) + styler.arg(arg.name) + padding;
|
|
321
|
+
const descPlain = arg.description ?? "";
|
|
322
|
+
const styledDesc = descPlain ? styler.description(descPlain) : "";
|
|
323
|
+
const metaParts = [];
|
|
324
|
+
const styledMetaParts = [];
|
|
325
|
+
if (info.usage.stdinField === arg.name) {
|
|
326
|
+
metaParts.push("(stdin)");
|
|
327
|
+
styledMetaParts.push(styler.meta("(stdin)"));
|
|
328
|
+
}
|
|
329
|
+
if (arg.enum) {
|
|
330
|
+
const text = `(choices: ${arg.enum.join(", ")})`;
|
|
331
|
+
metaParts.push(text);
|
|
332
|
+
styledMetaParts.push(styler.meta(text));
|
|
333
|
+
}
|
|
334
|
+
if (arg.default !== void 0) {
|
|
335
|
+
const text = `(default: ${String(arg.default)})`;
|
|
336
|
+
metaParts.push(text);
|
|
337
|
+
styledMetaParts.push(styler.meta(text));
|
|
338
|
+
}
|
|
339
|
+
const metaStyled = join(styledMetaParts);
|
|
340
|
+
if (posAvailWidth && posAvailWidth > 0) if ([descPlain, metaParts.join(" ")].filter(Boolean).join(" ").length <= posAvailWidth) lines.push(prefix + [styledDesc, metaStyled].filter(Boolean).join(" "));
|
|
341
|
+
else if (!descPlain || descPlain.length <= posAvailWidth) {
|
|
342
|
+
lines.push(prefix + styledDesc);
|
|
343
|
+
if (metaStyled) lines.push(descColPad + metaStyled);
|
|
344
|
+
} else {
|
|
345
|
+
const wrapped = wrapText(descPlain, posAvailWidth);
|
|
346
|
+
lines.push(prefix + styler.description(wrapped[0]));
|
|
347
|
+
for (const wline of wrapped.slice(1)) lines.push(descColPad + styler.description(wline));
|
|
348
|
+
if (metaStyled) lines.push(descColPad + metaStyled);
|
|
349
|
+
}
|
|
350
|
+
else lines.push(prefix + join([styledDesc, metaStyled]));
|
|
351
|
+
}
|
|
352
|
+
return lines;
|
|
353
|
+
}
|
|
354
|
+
function formatArgumentsSection(info) {
|
|
355
|
+
const lines = [];
|
|
356
|
+
const argList = info.arguments || [];
|
|
357
|
+
const hasDefault = (value) => {
|
|
358
|
+
if (value === void 0) return false;
|
|
359
|
+
if (value === "") return false;
|
|
360
|
+
if (Array.isArray(value) && value.length === 0) return false;
|
|
361
|
+
return true;
|
|
362
|
+
};
|
|
363
|
+
const argColumns = argList.map((arg) => {
|
|
364
|
+
const kebab = camelToKebab(arg.name);
|
|
365
|
+
const primaryName = kebab && arg.aliases?.includes(kebab) ? kebab : arg.name;
|
|
366
|
+
const remainingAliases = arg.aliases?.filter((a) => a !== primaryName);
|
|
367
|
+
return {
|
|
368
|
+
flagsPlain: arg.flags?.length ? arg.flags.map((f) => `-${f}`).join(", ") : "",
|
|
369
|
+
namesPlain: [`--${primaryName}`, ...remainingAliases?.map((a) => `--${a}`) || []].join(", "),
|
|
370
|
+
typePlain: arg.type && arg.type !== "boolean" ? arg.optional ? `[${arg.type}]` : `<${arg.type}>` : "",
|
|
371
|
+
isDeprecated: !!arg.deprecated,
|
|
372
|
+
arg
|
|
373
|
+
};
|
|
374
|
+
});
|
|
375
|
+
const maxFlagsWidth = Math.min(12, Math.max(0, ...argColumns.map((c) => c.flagsPlain.length)));
|
|
376
|
+
const maxNamesWidth = Math.min(32, Math.max(0, ...argColumns.map((c) => c.namesPlain.length)));
|
|
377
|
+
const maxTypeWidth = Math.min(16, Math.max(0, ...argColumns.map((c) => c.typePlain.length)));
|
|
378
|
+
const hasAnyFlags = maxFlagsWidth > 0;
|
|
379
|
+
const descCol = 2 + (hasAnyFlags ? maxFlagsWidth + 2 : 0) + maxNamesWidth + 2 + (maxTypeWidth > 0 ? maxTypeWidth + 2 : 0);
|
|
380
|
+
const argAvailWidth = terminalWidth ? terminalWidth - descCol : void 0;
|
|
381
|
+
const descColPad = " ".repeat(descCol);
|
|
382
|
+
const grouped = Object.groupBy(argColumns, (c) => c.arg.group ?? "");
|
|
383
|
+
const renderArgColumns = (columns) => {
|
|
384
|
+
for (const { flagsPlain, namesPlain, typePlain, isDeprecated, arg } of columns) {
|
|
385
|
+
const parts = [];
|
|
386
|
+
if (hasAnyFlags) {
|
|
387
|
+
const styledFlags = isDeprecated ? flagsPlain ? styler.deprecated(flagsPlain) : "" : flagsPlain ? styler.arg(flagsPlain) : "";
|
|
388
|
+
const flagsPadding = " ".repeat(Math.max(0, maxFlagsWidth - flagsPlain.length));
|
|
389
|
+
const separator = flagsPlain ? ", " : " ";
|
|
390
|
+
parts.push(styledFlags + flagsPadding + separator);
|
|
391
|
+
}
|
|
392
|
+
const styledNames = isDeprecated ? styler.deprecated(namesPlain) : styler.arg(namesPlain);
|
|
393
|
+
const namesPadding = " ".repeat(Math.max(2, maxNamesWidth - namesPlain.length + 2));
|
|
394
|
+
parts.push(styledNames + namesPadding);
|
|
395
|
+
if (maxTypeWidth > 0) {
|
|
396
|
+
const styledType = typePlain ? styler.type(typePlain) : "";
|
|
397
|
+
const typePadding = " ".repeat(Math.max(2, maxTypeWidth - typePlain.length + 2));
|
|
398
|
+
parts.push(styledType + typePadding);
|
|
399
|
+
}
|
|
400
|
+
const prefix = indent(1) + parts.join("");
|
|
401
|
+
const contPad = argAvailWidth ? descColPad : indent(3);
|
|
402
|
+
const inlineMeta = [];
|
|
403
|
+
const styledInlineMeta = [];
|
|
404
|
+
if (isDeprecated && typeof arg.deprecated !== "string") {
|
|
405
|
+
inlineMeta.push("(deprecated)");
|
|
406
|
+
styledInlineMeta.push(styler.meta("(deprecated)"));
|
|
407
|
+
}
|
|
408
|
+
if (hasDefault(arg.default)) {
|
|
409
|
+
const text = `(default: ${String(arg.default)})`;
|
|
410
|
+
inlineMeta.push(text);
|
|
411
|
+
styledInlineMeta.push(styler.meta(text));
|
|
412
|
+
}
|
|
413
|
+
if (arg.enum) {
|
|
414
|
+
const text = `(choices: ${arg.enum.join(", ")})`;
|
|
415
|
+
inlineMeta.push(text);
|
|
416
|
+
styledInlineMeta.push(styler.meta(text));
|
|
417
|
+
}
|
|
418
|
+
const descPlain = arg.description ?? "";
|
|
419
|
+
const styledDesc = descPlain ? isDeprecated ? styler.deprecated(descPlain) : styler.description(descPlain) : "";
|
|
420
|
+
const metaStyled = join(styledInlineMeta);
|
|
421
|
+
if (argAvailWidth && argAvailWidth > 0) if ([descPlain, inlineMeta.join(" ")].filter(Boolean).join(" ").length <= argAvailWidth) lines.push(prefix + [styledDesc, metaStyled].filter(Boolean).join(" "));
|
|
422
|
+
else if (!descPlain || descPlain.length <= argAvailWidth) {
|
|
423
|
+
lines.push(prefix + styledDesc);
|
|
424
|
+
if (metaStyled) lines.push(descColPad + metaStyled);
|
|
425
|
+
} else {
|
|
426
|
+
const wrapped = wrapText(descPlain, argAvailWidth);
|
|
427
|
+
const styleFn = isDeprecated ? styler.deprecated : styler.description;
|
|
428
|
+
lines.push(prefix + styleFn(wrapped[0]));
|
|
429
|
+
for (const wline of wrapped.slice(1)) lines.push(descColPad + styleFn(wline));
|
|
430
|
+
if (metaStyled) lines.push(descColPad + metaStyled);
|
|
431
|
+
}
|
|
432
|
+
else {
|
|
433
|
+
const descParts = [];
|
|
434
|
+
if (styledDesc) descParts.push(styledDesc);
|
|
435
|
+
lines.push(prefix + join(descParts));
|
|
436
|
+
if (styledInlineMeta.length > 0) lines.push(indent(3) + metaStyled);
|
|
437
|
+
}
|
|
438
|
+
const line3Parts = [];
|
|
439
|
+
if (isDeprecated && typeof arg.deprecated === "string") line3Parts.push(styler.meta(`(deprecated: ${arg.deprecated})`));
|
|
440
|
+
if (arg.examples && arg.examples.length > 0) {
|
|
441
|
+
const exampleValues = arg.examples.map((example) => typeof example === "string" ? example : JSON.stringify(example)).join(", ");
|
|
442
|
+
line3Parts.push(styler.example("Example:"), styler.exampleValue(exampleValues));
|
|
443
|
+
}
|
|
444
|
+
if (line3Parts.length > 0) lines.push(contPad + join(line3Parts));
|
|
445
|
+
const line4Parts = [];
|
|
446
|
+
if (info.usage.stdinField === arg.name) line4Parts.push(styler.meta("(stdin)"));
|
|
447
|
+
if (arg.env) {
|
|
448
|
+
const envVars = typeof arg.env === "string" ? [arg.env] : arg.env;
|
|
449
|
+
line4Parts.push(styler.example("Env:"), styler.exampleValue(envVars.join(", ")));
|
|
450
|
+
}
|
|
451
|
+
if (arg.configKey) line4Parts.push(styler.example("Config:"), styler.exampleValue(arg.configKey));
|
|
452
|
+
if (line4Parts.length > 0) lines.push(contPad + join(line4Parts));
|
|
453
|
+
}
|
|
454
|
+
};
|
|
455
|
+
for (const [key, items] of Object.entries(grouped)) {
|
|
456
|
+
if (lines.length > 0) lines.push("");
|
|
457
|
+
lines.push(styler.section(key ? `${key}:` : "Options:"));
|
|
458
|
+
renderArgColumns(items);
|
|
459
|
+
}
|
|
460
|
+
return lines;
|
|
461
|
+
}
|
|
462
|
+
function formatBuiltinsSection(info) {
|
|
463
|
+
const lines = [];
|
|
464
|
+
const builtins = info.builtins;
|
|
465
|
+
if (!showAllBuiltins) {
|
|
466
|
+
lines.push(`${styler.label("Global:")} ${styler.meta([
|
|
467
|
+
"help [command]",
|
|
468
|
+
"version",
|
|
469
|
+
"[command] --repl"
|
|
470
|
+
].join(", "))}`);
|
|
471
|
+
const hint = info.usage.hasSubcommands ? `Run "${info.name} [command] --help" for more information. Use "--all" for all global commands.` : `Use "${info.name} help --all" for more information on global commands.`;
|
|
472
|
+
lines.push(styler.meta(hint));
|
|
473
|
+
return lines;
|
|
474
|
+
}
|
|
475
|
+
lines.push(styler.section("Global:"));
|
|
476
|
+
const allLengths = [];
|
|
477
|
+
for (const entry of builtins) {
|
|
478
|
+
allLengths.push(entry.name.length);
|
|
479
|
+
if (entry.sub) for (const sub of entry.sub) allLengths.push(sub.name.length + 2);
|
|
480
|
+
}
|
|
481
|
+
const maxLen = Math.max(...allLengths);
|
|
482
|
+
for (const entry of builtins) {
|
|
483
|
+
const padding = " ".repeat(Math.max(2, maxLen - entry.name.length + 2));
|
|
484
|
+
const parts = [styler.command(entry.name)];
|
|
485
|
+
if (entry.description) parts.push(padding + styler.description(entry.description));
|
|
486
|
+
lines.push(indent(1) + parts.join(""));
|
|
487
|
+
if (entry.sub) for (const sub of entry.sub) {
|
|
488
|
+
const subPadding = " ".repeat(Math.max(2, maxLen - sub.name.length));
|
|
489
|
+
const subParts = [styler.arg(sub.name)];
|
|
490
|
+
if (sub.description) subParts.push(subPadding + styler.description(sub.description));
|
|
491
|
+
lines.push(indent(2) + subParts.join(""));
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
return lines;
|
|
495
|
+
}
|
|
496
|
+
return { format(info) {
|
|
497
|
+
const lines = [];
|
|
498
|
+
if (info.deprecated) {
|
|
499
|
+
const deprecationMessage = typeof info.deprecated === "string" ? `⚠️ This command is deprecated: ${info.deprecated}` : "⚠️ This command is deprecated";
|
|
500
|
+
lines.push(styler.deprecated(deprecationMessage));
|
|
501
|
+
lines.push("");
|
|
502
|
+
}
|
|
503
|
+
lines.push(...formatUsageSection(info));
|
|
504
|
+
lines.push("");
|
|
505
|
+
if (info.title) {
|
|
506
|
+
lines.push(styler.label(info.title));
|
|
507
|
+
lines.push("");
|
|
508
|
+
}
|
|
509
|
+
if (info.aliases && info.aliases.length > 0) {
|
|
510
|
+
lines.push(styler.meta(`Aliases: ${info.aliases.join(", ")}`));
|
|
511
|
+
lines.push("");
|
|
512
|
+
}
|
|
513
|
+
if (info.description) {
|
|
514
|
+
lines.push(styler.description(info.description));
|
|
515
|
+
lines.push("");
|
|
516
|
+
}
|
|
517
|
+
if (info.examples && info.examples.length > 0) {
|
|
518
|
+
lines.push(styler.section("Examples:"));
|
|
519
|
+
for (const ex of info.examples) lines.push(indent(1) + styler.meta("$ ") + styler.exampleValue(ex));
|
|
520
|
+
lines.push("");
|
|
521
|
+
}
|
|
522
|
+
if (info.subcommands && info.subcommands.length > 0) {
|
|
523
|
+
lines.push(...formatSubcommandsSection(info));
|
|
524
|
+
lines.push("");
|
|
525
|
+
}
|
|
526
|
+
if (info.positionals && info.positionals.length > 0) {
|
|
527
|
+
lines.push(...formatPositionalsSection(info));
|
|
528
|
+
lines.push("");
|
|
529
|
+
}
|
|
530
|
+
if (info.arguments && info.arguments.length > 0) {
|
|
531
|
+
lines.push(...formatArgumentsSection(info));
|
|
532
|
+
lines.push("");
|
|
533
|
+
}
|
|
534
|
+
if (info.builtins && info.builtins.length > 0) {
|
|
535
|
+
lines.push(...formatBuiltinsSection(info));
|
|
536
|
+
lines.push("");
|
|
537
|
+
}
|
|
538
|
+
if (info.arguments?.some((arg) => arg.negatable && arg.default === true)) {
|
|
539
|
+
lines.push(styler.meta("Boolean options can be negated with --no-<option>."));
|
|
540
|
+
lines.push("");
|
|
541
|
+
}
|
|
542
|
+
if (info.nestedCommands?.length) {
|
|
543
|
+
lines.push(styler.section("Subcommand Details:"));
|
|
544
|
+
lines.push("");
|
|
545
|
+
for (const nestedCmd of info.nestedCommands) {
|
|
546
|
+
lines.push(styler.meta("─".repeat(60)));
|
|
547
|
+
lines.push(this.format(nestedCmd));
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
const result = lines.join(newline);
|
|
551
|
+
return wrapDocument ? wrapDocument(result) : result;
|
|
552
|
+
} };
|
|
553
|
+
}
|
|
554
|
+
function createJsonFormatter() {
|
|
555
|
+
return { format(info) {
|
|
556
|
+
return JSON.stringify(info, null, 2);
|
|
557
|
+
} };
|
|
558
|
+
}
|
|
559
|
+
function shouldUseAnsi(env, isTTY) {
|
|
560
|
+
if (env?.NO_COLOR) return false;
|
|
561
|
+
if (env?.CI) return false;
|
|
562
|
+
if (typeof isTTY === "boolean") return isTTY;
|
|
563
|
+
return false;
|
|
564
|
+
}
|
|
565
|
+
/**
|
|
566
|
+
* Creates a minimal formatter that outputs just a single-line usage string.
|
|
567
|
+
*/
|
|
568
|
+
function createMinimalFormatter() {
|
|
569
|
+
return { format(info) {
|
|
570
|
+
const parts = [info.usage.command];
|
|
571
|
+
if (info.usage.hasSubcommands) parts.push("[command]");
|
|
572
|
+
if (info.positionals && info.positionals.length > 0) for (const arg of info.positionals) {
|
|
573
|
+
const name = arg.name.startsWith("...") ? `${arg.name}` : arg.name;
|
|
574
|
+
parts.push(arg.optional ? `[${name}]` : `<${name}>`);
|
|
575
|
+
}
|
|
576
|
+
if (info.usage.hasArguments) parts.push("[options]");
|
|
577
|
+
return parts.join(" ");
|
|
578
|
+
} };
|
|
579
|
+
}
|
|
580
|
+
function createFormatter(format, detail = "standard", theme, all, width, terminal, env) {
|
|
581
|
+
if (detail === "minimal") return createMinimalFormatter();
|
|
582
|
+
if (format === "json") return createJsonFormatter();
|
|
583
|
+
const tw = format === "markdown" || format === "html" ? void 0 : width ?? terminal?.columns ?? DEFAULT_TERMINAL_WIDTH;
|
|
584
|
+
if (format === "ansi" || format === "auto" && shouldUseAnsi(env, terminal?.isTTY)) return createGenericFormatter(createAnsiStyler(theme), createTextLayout(), all, tw);
|
|
585
|
+
if (format === "console") return createGenericFormatter(createConsoleStyler(theme), createTextLayout(), all, tw);
|
|
586
|
+
if (format === "markdown") return createGenericFormatter(createMarkdownStyler(), createMarkdownLayout(), all);
|
|
587
|
+
if (format === "html") return createGenericFormatter(createHtmlStyler(), createHtmlLayout(), all);
|
|
588
|
+
return createGenericFormatter(createTextStyler(), createTextLayout(), all, tw);
|
|
589
|
+
}
|
|
590
|
+
//#endregion
|
|
591
|
+
//#region src/output/help.ts
|
|
592
|
+
/**
|
|
593
|
+
* Extract positional arguments info from schema based on meta.positional config.
|
|
594
|
+
*/
|
|
595
|
+
function extractPositionalArgsInfo(schema, meta) {
|
|
596
|
+
const args = [];
|
|
597
|
+
const positionalNames = /* @__PURE__ */ new Set();
|
|
598
|
+
if (!schema || !meta?.positional || meta.positional.length === 0) return {
|
|
599
|
+
args,
|
|
600
|
+
positionalNames
|
|
601
|
+
};
|
|
602
|
+
const positionalConfig = parsePositionalConfig(meta.positional);
|
|
603
|
+
try {
|
|
604
|
+
const jsonSchema = getJsonSchema(schema);
|
|
605
|
+
if (jsonSchema.type === "object" && jsonSchema.properties) {
|
|
606
|
+
const properties = jsonSchema.properties;
|
|
607
|
+
const required = jsonSchema.required || [];
|
|
608
|
+
for (const { name, variadic } of positionalConfig) {
|
|
609
|
+
const prop = properties[name];
|
|
610
|
+
if (!prop) continue;
|
|
611
|
+
positionalNames.add(name);
|
|
612
|
+
const optMeta = meta.fields?.[name];
|
|
613
|
+
args.push({
|
|
614
|
+
name: variadic ? `...${name}` : name,
|
|
615
|
+
description: optMeta?.description ?? prop.description,
|
|
616
|
+
optional: !required.includes(name),
|
|
617
|
+
default: prop.default,
|
|
618
|
+
type: variadic ? `array<${prop.items?.type || "string"}>` : prop.type,
|
|
619
|
+
enum: prop.enum ?? prop.items?.enum
|
|
620
|
+
});
|
|
621
|
+
}
|
|
622
|
+
}
|
|
623
|
+
} catch {}
|
|
624
|
+
return {
|
|
625
|
+
args,
|
|
626
|
+
positionalNames
|
|
627
|
+
};
|
|
628
|
+
}
|
|
629
|
+
function extractArgsInfo(schema, meta, positionalNames) {
|
|
630
|
+
const result = [];
|
|
631
|
+
if (!schema) return result;
|
|
632
|
+
if (!schema["~standard"].vendor.includes("zod")) return result;
|
|
633
|
+
const argsMeta = meta?.fields;
|
|
634
|
+
try {
|
|
635
|
+
const jsonSchema = getJsonSchema(schema);
|
|
636
|
+
if (jsonSchema.type === "object" && jsonSchema.properties) {
|
|
637
|
+
const properties = jsonSchema.properties;
|
|
638
|
+
const required = jsonSchema.required || [];
|
|
639
|
+
const propertyNames = new Set(Object.keys(properties));
|
|
640
|
+
const hasExplicitNegation = (key) => {
|
|
641
|
+
const camelNegated = `no${key.charAt(0).toUpperCase()}${key.slice(1)}`;
|
|
642
|
+
if (propertyNames.has(camelNegated)) return true;
|
|
643
|
+
const kebabNegated = `no-${key}`;
|
|
644
|
+
if (propertyNames.has(kebabNegated)) return true;
|
|
645
|
+
return false;
|
|
646
|
+
};
|
|
647
|
+
const isNegationOf = (key) => {
|
|
648
|
+
if (key.startsWith("no") && key.length > 2 && key[2] === key[2]?.toUpperCase()) {
|
|
649
|
+
const positiveKey = key.charAt(2).toLowerCase() + key.slice(3);
|
|
650
|
+
if (propertyNames.has(positiveKey)) return true;
|
|
651
|
+
}
|
|
652
|
+
if (key.startsWith("no-")) {
|
|
653
|
+
const positiveKey = key.slice(3);
|
|
654
|
+
if (propertyNames.has(positiveKey)) return true;
|
|
655
|
+
}
|
|
656
|
+
return false;
|
|
657
|
+
};
|
|
658
|
+
for (const [key, prop] of Object.entries(properties)) {
|
|
659
|
+
if (positionalNames?.has(key)) continue;
|
|
660
|
+
const isOptional = !required.includes(key);
|
|
661
|
+
const enumValues = prop.enum ?? prop.items?.enum;
|
|
662
|
+
const optMeta = argsMeta?.[key];
|
|
663
|
+
const propType = prop.type;
|
|
664
|
+
const isNegatable = propType === "boolean" && !hasExplicitNegation(key) && !isNegationOf(key);
|
|
665
|
+
result.push({
|
|
666
|
+
name: key,
|
|
667
|
+
description: optMeta?.description ?? prop.description,
|
|
668
|
+
optional: isOptional,
|
|
669
|
+
default: prop.default,
|
|
670
|
+
type: propType === "array" ? `${prop.items?.type || "string"}[]` : propType,
|
|
671
|
+
enum: enumValues,
|
|
672
|
+
deprecated: optMeta?.deprecated ?? prop?.deprecated,
|
|
673
|
+
hidden: optMeta?.hidden ?? prop?.hidden,
|
|
674
|
+
examples: optMeta?.examples ?? prop?.examples,
|
|
675
|
+
variadic: propType === "array",
|
|
676
|
+
negatable: isNegatable,
|
|
677
|
+
group: optMeta?.group
|
|
678
|
+
});
|
|
679
|
+
}
|
|
680
|
+
}
|
|
681
|
+
} catch {}
|
|
682
|
+
return result;
|
|
683
|
+
}
|
|
684
|
+
/**
|
|
685
|
+
* Builds a comprehensive HelpInfo structure from a command.
|
|
686
|
+
* This is the single source of truth that all formatters use.
|
|
687
|
+
* @param cmd - The command to build help info for
|
|
688
|
+
* @param detail - The level of detail ('minimal', 'standard', or 'full')
|
|
689
|
+
*/
|
|
690
|
+
function getHelpInfo(cmd, detail = "standard", all) {
|
|
691
|
+
const rootCmd = getRootCommand(cmd);
|
|
692
|
+
const isDefaultCommand = cmd.parent && (!cmd.name || cmd.aliases?.includes(""));
|
|
693
|
+
const nonEmptyAliases = cmd.aliases?.filter(Boolean);
|
|
694
|
+
const commandName = cmd.path || cmd.name || nonEmptyAliases?.[0] || (cmd.parent ? "[default]" : "program");
|
|
695
|
+
const remainingAliases = !cmd.name && nonEmptyAliases?.length ? nonEmptyAliases.slice(1) : nonEmptyAliases ?? [];
|
|
696
|
+
const displayAliases = isDefaultCommand ? [...remainingAliases, "[default]"] : nonEmptyAliases;
|
|
697
|
+
const { args: positionalArgs, positionalNames } = cmd.argsSchema ? extractPositionalArgsInfo(cmd.argsSchema, cmd.meta) : {
|
|
698
|
+
args: [],
|
|
699
|
+
positionalNames: /* @__PURE__ */ new Set()
|
|
700
|
+
};
|
|
701
|
+
const hasPositionals = positionalArgs.length > 0;
|
|
702
|
+
const helpInfo = {
|
|
703
|
+
name: commandName,
|
|
704
|
+
title: cmd.title,
|
|
705
|
+
description: cmd.description,
|
|
706
|
+
examples: cmd.examples,
|
|
707
|
+
aliases: displayAliases,
|
|
708
|
+
deprecated: cmd.deprecated,
|
|
709
|
+
hidden: cmd.hidden,
|
|
710
|
+
usage: {
|
|
711
|
+
command: rootCmd === cmd ? commandName : `${rootCmd.name} ${commandName}`,
|
|
712
|
+
hasSubcommands: !!(cmd.commands && cmd.commands.length > 0),
|
|
713
|
+
hasPositionals,
|
|
714
|
+
hasArguments: false,
|
|
715
|
+
stdinField: cmd.meta?.stdin
|
|
716
|
+
}
|
|
717
|
+
};
|
|
718
|
+
if (cmd.commands && cmd.commands.length > 0) {
|
|
719
|
+
const visibleCommands = detail === "full" ? cmd.commands : cmd.commands.filter((c) => !c.hidden);
|
|
720
|
+
helpInfo.subcommands = [...cmd.action ? [{
|
|
721
|
+
name: "[default]",
|
|
722
|
+
title: cmd.title,
|
|
723
|
+
description: cmd.description
|
|
724
|
+
}] : [], ...visibleCommands.flatMap((c) => {
|
|
725
|
+
const isDefault = !c.name || c.aliases?.includes("");
|
|
726
|
+
const nonEmptyAliases = c.aliases?.filter(Boolean);
|
|
727
|
+
const displayName = c.name || nonEmptyAliases?.[0] || "[default]";
|
|
728
|
+
const remainingAliases = !c.name && nonEmptyAliases?.length ? nonEmptyAliases.slice(1) : nonEmptyAliases ?? [];
|
|
729
|
+
const displayAliases = isDefault && displayName !== "[default]" ? [...remainingAliases, "[default]"] : isDefault ? remainingAliases : nonEmptyAliases;
|
|
730
|
+
const hasSubcommands = !!(c.commands && c.commands.length > 0);
|
|
731
|
+
const hasDefaultHandler = c.action || c.commands?.some((sub) => !sub.name || sub.aliases?.includes(""));
|
|
732
|
+
if (hasSubcommands && hasDefaultHandler) {
|
|
733
|
+
const defaultSub = !c.action ? c.commands?.find((sub) => !sub.name || sub.aliases?.includes("")) : void 0;
|
|
734
|
+
const hasDefaultSubInfo = defaultSub && (defaultSub.title || defaultSub.description);
|
|
735
|
+
return [{
|
|
736
|
+
name: displayName,
|
|
737
|
+
title: hasDefaultSubInfo ? defaultSub.title : c.title,
|
|
738
|
+
description: hasDefaultSubInfo ? defaultSub.description : c.description,
|
|
739
|
+
aliases: displayAliases?.length ? displayAliases : void 0,
|
|
740
|
+
deprecated: c.deprecated,
|
|
741
|
+
hidden: c.hidden,
|
|
742
|
+
group: c.group
|
|
743
|
+
}, {
|
|
744
|
+
name: displayName,
|
|
745
|
+
title: c.title,
|
|
746
|
+
description: c.description,
|
|
747
|
+
deprecated: c.deprecated,
|
|
748
|
+
hidden: c.hidden,
|
|
749
|
+
hasSubcommands: true,
|
|
750
|
+
group: c.group
|
|
751
|
+
}];
|
|
752
|
+
}
|
|
753
|
+
return [{
|
|
754
|
+
name: displayName,
|
|
755
|
+
title: c.title,
|
|
756
|
+
description: c.description,
|
|
757
|
+
aliases: displayAliases?.length ? displayAliases : void 0,
|
|
758
|
+
deprecated: c.deprecated,
|
|
759
|
+
hidden: c.hidden,
|
|
760
|
+
hasSubcommands,
|
|
761
|
+
group: c.group
|
|
762
|
+
}];
|
|
763
|
+
})];
|
|
764
|
+
if (detail === "full") helpInfo.nestedCommands = visibleCommands.map((c) => getHelpInfo(c, "full"));
|
|
765
|
+
}
|
|
766
|
+
if (hasPositionals) helpInfo.positionals = positionalArgs;
|
|
767
|
+
if (cmd.argsSchema) {
|
|
768
|
+
const argsInfo = extractArgsInfo(cmd.argsSchema, cmd.meta, positionalNames);
|
|
769
|
+
const argMap = Object.fromEntries(argsInfo.map((arg) => [arg.name, arg]));
|
|
770
|
+
const { flags, aliases } = extractSchemaMetadata(cmd.argsSchema, cmd.meta?.fields, cmd.meta?.autoAlias);
|
|
771
|
+
for (const [flag, name] of Object.entries(flags)) {
|
|
772
|
+
const arg = argMap[name];
|
|
773
|
+
if (!arg) continue;
|
|
774
|
+
arg.flags = [...arg.flags || [], flag];
|
|
775
|
+
}
|
|
776
|
+
for (const [alias, name] of Object.entries(aliases)) {
|
|
777
|
+
const arg = argMap[name];
|
|
778
|
+
if (!arg) continue;
|
|
779
|
+
arg.aliases = [...arg.aliases || [], alias];
|
|
780
|
+
}
|
|
781
|
+
const visibleArgs = argsInfo.filter((arg) => !arg.hidden);
|
|
782
|
+
if (visibleArgs.length > 0) {
|
|
783
|
+
helpInfo.arguments = visibleArgs;
|
|
784
|
+
helpInfo.usage.hasArguments = true;
|
|
785
|
+
}
|
|
786
|
+
}
|
|
787
|
+
if (!cmd.parent || all) {
|
|
788
|
+
const builtins = [];
|
|
789
|
+
if (!findCommandByName("help", rootCmd.commands)) builtins.push({
|
|
790
|
+
name: "help [command], -h, --help",
|
|
791
|
+
description: "Show help for a command",
|
|
792
|
+
sub: [
|
|
793
|
+
{
|
|
794
|
+
name: "--all",
|
|
795
|
+
description: "Show all global commands and flags"
|
|
796
|
+
},
|
|
797
|
+
{
|
|
798
|
+
name: "--detail <level>",
|
|
799
|
+
description: "Detail level (minimal, standard, full)"
|
|
800
|
+
},
|
|
801
|
+
{
|
|
802
|
+
name: "--format <format>",
|
|
803
|
+
description: "Output format (text, ansi, json, markdown, html)"
|
|
804
|
+
}
|
|
805
|
+
]
|
|
806
|
+
});
|
|
807
|
+
if (!findCommandByName("version", rootCmd.commands)) builtins.push({
|
|
808
|
+
name: "version, -v, --version",
|
|
809
|
+
description: "Show version information"
|
|
810
|
+
});
|
|
811
|
+
if (!findCommandByName("completion", rootCmd.commands)) builtins.push({
|
|
812
|
+
name: "completion [shell]",
|
|
813
|
+
description: "Generate shell completions (bash, zsh, fish, powershell)"
|
|
814
|
+
});
|
|
815
|
+
if (!findCommandByName("man", rootCmd.commands)) builtins.push({
|
|
816
|
+
name: "man",
|
|
817
|
+
description: "Show or install man pages (--setup to install, --remove to uninstall) (experimental)"
|
|
818
|
+
});
|
|
819
|
+
builtins.push({
|
|
820
|
+
name: "[command] --repl",
|
|
821
|
+
description: "Start interactive REPL scoped to a command"
|
|
822
|
+
});
|
|
823
|
+
if (!findCommandByName("mcp", rootCmd.commands)) builtins.push({
|
|
824
|
+
name: "mcp [http|stdio]",
|
|
825
|
+
description: "Start a Model Context Protocol server to expose commands as AI tools (experimental)",
|
|
826
|
+
sub: [{
|
|
827
|
+
name: "--port <port>",
|
|
828
|
+
description: "HTTP port (default: 3000)"
|
|
829
|
+
}, {
|
|
830
|
+
name: "--host <host>",
|
|
831
|
+
description: "HTTP host (default: 127.0.0.1)"
|
|
832
|
+
}]
|
|
833
|
+
});
|
|
834
|
+
builtins.push({
|
|
835
|
+
name: "--color [theme], --no-color",
|
|
836
|
+
description: "Set color theme (default, ocean, warm, monochrome) or disable colors"
|
|
837
|
+
});
|
|
838
|
+
if (builtins.length > 0) helpInfo.builtins = builtins;
|
|
839
|
+
}
|
|
840
|
+
return helpInfo;
|
|
841
|
+
}
|
|
842
|
+
function generateHelp(rootCommand, commandObj = rootCommand, prefs) {
|
|
843
|
+
const helpInfo = getHelpInfo(commandObj, prefs?.detail, prefs?.all);
|
|
844
|
+
return createFormatter(prefs?.format ?? "auto", prefs?.detail, prefs?.theme, prefs?.all, prefs?.width, prefs?.terminal, prefs?.env).format(helpInfo);
|
|
845
|
+
}
|
|
846
|
+
//#endregion
|
|
847
|
+
export { getVersion as a, getRootCommand as i, getHelpInfo as n, colorThemes as r, generateHelp as t };
|
|
848
|
+
|
|
849
|
+
//# sourceMappingURL=help-B5Kk83of.mjs.map
|