@clerc/plugin-help 1.0.0-beta.19 → 1.0.0-beta.20

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/dist/index.d.ts CHANGED
@@ -11,7 +11,7 @@ type FlagDefaultValue<T = unknown> = T | FlagDefaultValueFunction<T>;
11
11
  *
12
12
  * @template T The target type.
13
13
  */
14
- interface FlagTypeFunction<T = unknown> {
14
+ interface TypeFunction<T = unknown> {
15
15
  (value: string): T;
16
16
  /**
17
17
  * Optional display name for the type, useful in help output.
@@ -19,7 +19,7 @@ interface FlagTypeFunction<T = unknown> {
19
19
  */
20
20
  display?: string;
21
21
  }
22
- type FlagType<T = unknown> = FlagTypeFunction<T> | readonly [FlagTypeFunction<T>];
22
+ type FlagType<T = unknown> = TypeFunction<T> | readonly [TypeFunction<T>];
23
23
  //#endregion
24
24
  //#region src/types.d.ts
25
25
  interface Formatters {
package/dist/index.js CHANGED
@@ -51,35 +51,50 @@ function validateGroup(group, groupMap, itemType, itemName) {
51
51
  if (group && group !== DEFAULT_GROUP_KEY && !groupMap.has(group)) throw new Error(`Unknown ${itemType} group "${group}" for "${itemName}". Available groups: ${[...groupMap.keys()].join(", ") || "(none)"}`);
52
52
  }
53
53
  var HelpRenderer = class {
54
- _commandGroups;
55
- _flagGroups;
56
- _globalFlagGroups;
57
- constructor(_formatters, _cli, _globalFlags, _command, _notes, _examples, groups) {
54
+ _command;
55
+ get _commandGroups() {
56
+ return groupDefinitionsToMap(this._getGroups().commands);
57
+ }
58
+ get _flagGroups() {
59
+ return groupDefinitionsToMap(this._getGroups().flags);
60
+ }
61
+ get _globalFlagGroups() {
62
+ return groupDefinitionsToMap(this._getGroups().globalFlags);
63
+ }
64
+ constructor(_formatters, _cli, _globalFlags, _getGroups, _examples, _notes) {
58
65
  this._formatters = _formatters;
59
66
  this._cli = _cli;
60
67
  this._globalFlags = _globalFlags;
61
- this._command = _command;
62
- this._notes = _notes;
68
+ this._getGroups = _getGroups;
63
69
  this._examples = _examples;
64
- this._commandGroups = groupDefinitionsToMap(groups?.commands);
65
- this._flagGroups = groupDefinitionsToMap(groups?.flags);
66
- this._globalFlagGroups = groupDefinitionsToMap(groups?.globalFlags);
70
+ this._notes = _notes;
71
+ }
72
+ setCommand(command) {
73
+ if (command) {
74
+ this._command = command;
75
+ this._examples = command?.help?.examples;
76
+ this._notes = command?.help?.notes;
77
+ }
78
+ }
79
+ renderSections(sections) {
80
+ return sections.filter(isTruthy).map((section) => {
81
+ const body = Array.isArray(section.body) ? section.body.filter((s) => s !== void 0).join("\n") : section.body;
82
+ if (!section.title) return body;
83
+ return `${yc.bold(section.title)}\n${body.split("\n").map(withIndent).join("\n")}`;
84
+ }).join("\n\n");
67
85
  }
68
86
  render() {
69
- return [
87
+ const sections = [
70
88
  this.renderHeader(),
71
89
  this.renderUsage(),
72
90
  this.renderParameters(),
73
- this.renderCommands(),
74
- this.renderGlobalFlags(),
75
91
  this.renderCommandFlags(),
76
- this.renderNotes(),
77
- this.renderExamples()
78
- ].filter(isTruthy).filter((section) => section.body.length > 0).map((section) => {
79
- const body = Array.isArray(section.body) ? section.body.filter((s) => s !== void 0).join("\n") : section.body;
80
- if (!section.title) return body;
81
- return `${yc.bold(section.title)}\n${body.split("\n").map(withIndent).join("\n")}`;
82
- }).join("\n\n");
92
+ this.renderGlobalFlags(),
93
+ this.renderCommands(),
94
+ this.renderExamples(),
95
+ this.renderNotes()
96
+ ];
97
+ return this.renderSections(sections);
83
98
  }
84
99
  renderHeader() {
85
100
  const { _name, _version, _description } = this._cli;
@@ -123,26 +138,15 @@ var HelpRenderer = class {
123
138
  }
124
139
  getSubcommands(parentCommandName) {
125
140
  const subcommands = /* @__PURE__ */ new Map();
126
- if (!parentCommandName) return subcommands;
141
+ if (parentCommandName === "") return subcommands;
127
142
  const prefix = `${parentCommandName} `;
128
- for (const [name, command] of this._cli._commands) if (name.startsWith(prefix) && name !== parentCommandName) {
143
+ for (const [name, command] of this._cli._commands) if (name.startsWith(prefix)) {
129
144
  const subcommandName = name.slice(prefix.length);
130
145
  subcommands.set(subcommandName, command);
131
146
  }
132
147
  return subcommands;
133
148
  }
134
- renderCommands() {
135
- const commands = this._cli._commands;
136
- let commandsToShow;
137
- let title = "Commands";
138
- let prefix = "";
139
- if (this._command) {
140
- prefix = this._command.name ? `${this._command.name} ` : "";
141
- title = "Subcommands";
142
- commandsToShow = this.getSubcommands(this._command.name);
143
- if (commandsToShow.size === 0) return;
144
- } else commandsToShow = commands;
145
- if (commandsToShow.size === 0) return;
149
+ buildGroupedCommandsBody(commandsToShow, prefix) {
146
150
  const groupedCommands = /* @__PURE__ */ new Map();
147
151
  const defaultCommands = [];
148
152
  let rootCommand = [];
@@ -171,6 +175,33 @@ var HelpRenderer = class {
171
175
  body.push(...splitTable(items).map(withIndent));
172
176
  }
173
177
  }
178
+ return body;
179
+ }
180
+ renderAvailableSubcommands(parentCommandName) {
181
+ const subcommands = this.getSubcommands(parentCommandName);
182
+ if (subcommands.size === 0) return "";
183
+ const prefix = `${parentCommandName} `;
184
+ const body = this.buildGroupedCommandsBody(subcommands, prefix);
185
+ if (body.length === 0) return "";
186
+ const sections = [{ body: `${yc.green(this._cli._name)} ${yc.cyan(parentCommandName)} not found` }, {
187
+ title: "Available Subcommands",
188
+ body
189
+ }];
190
+ return this.renderSections(sections);
191
+ }
192
+ renderCommands() {
193
+ const commands = this._cli._commands;
194
+ let commandsToShow;
195
+ let title = "Commands";
196
+ let prefix = "";
197
+ if (this._command) {
198
+ prefix = this._command.name ? `${this._command.name} ` : "";
199
+ title = "Subcommands";
200
+ commandsToShow = this.getSubcommands(this._command.name);
201
+ if (commandsToShow.size === 0) return;
202
+ } else commandsToShow = commands;
203
+ if (commandsToShow.size === 0) return;
204
+ const body = this.buildGroupedCommandsBody(commandsToShow, prefix);
174
205
  return {
175
206
  title,
176
207
  body
@@ -284,6 +315,15 @@ const helpPlugin = ({ command = true, flag = true, showHelpWhenNoCommandSpecifie
284
315
  if (banner) console.log(banner);
285
316
  console.log(s);
286
317
  }
318
+ const renderer = new HelpRenderer(mergedFormatters, cli, cli._globalFlags, () => groups, effectiveExamples, effectiveNotes);
319
+ function tryPrintSubcommandsHelp(commandName) {
320
+ const subcommandsOutput = renderer.renderAvailableSubcommands(commandName);
321
+ if (subcommandsOutput) {
322
+ printHelp(subcommandsOutput);
323
+ return true;
324
+ }
325
+ return false;
326
+ }
287
327
  if (command) cli.command("help", "Show help", {
288
328
  parameters: ["[command...]"],
289
329
  help: {
@@ -295,9 +335,14 @@ const helpPlugin = ({ command = true, flag = true, showHelpWhenNoCommandSpecifie
295
335
  let command$1;
296
336
  if (commandName.length > 0) {
297
337
  [command$1] = resolveCommand(cli._commands, commandName);
298
- if (!command$1) throw new NoSuchCommandError(commandName.join(" "));
338
+ if (!command$1) {
339
+ const parentCommandName = commandName.join(" ");
340
+ if (tryPrintSubcommandsHelp(parentCommandName)) return;
341
+ throw new NoSuchCommandError(parentCommandName);
342
+ }
299
343
  }
300
- printHelp(new HelpRenderer(mergedFormatters, cli, cli._globalFlags, command$1, command$1 ? command$1.help?.notes : effectiveNotes, command$1 ? command$1.help?.examples : effectiveExamples, groups).render());
344
+ renderer.setCommand(command$1);
345
+ printHelp(renderer.render());
301
346
  });
302
347
  if (flag) cli.globalFlag("help", "Show help", {
303
348
  alias: "h",
@@ -309,9 +354,13 @@ const helpPlugin = ({ command = true, flag = true, showHelpWhenNoCommandSpecifie
309
354
  handler: async (ctx, next) => {
310
355
  if (ctx.flags.help) {
311
356
  const command$1 = ctx.command;
312
- if (!command$1 && ctx.rawParsed.parameters.length > 0) await next();
313
- printHelp(new HelpRenderer(mergedFormatters, cli, cli._globalFlags, command$1, command$1 ? command$1.help?.notes : effectiveNotes, command$1 ? command$1.help?.examples : effectiveExamples, groups).render());
314
- } else if (showHelpWhenNoCommandSpecified && !ctx.command && ctx.rawParsed.parameters.length === 0) printHelp(new HelpRenderer(mergedFormatters, cli, cli._globalFlags, void 0, effectiveNotes, effectiveExamples, groups).render());
357
+ if (!command$1 && ctx.rawParsed.parameters.length > 0) {
358
+ if (tryPrintSubcommandsHelp(ctx.rawParsed.parameters.join(" "))) return;
359
+ await next();
360
+ }
361
+ renderer.setCommand(command$1);
362
+ printHelp(renderer.render());
363
+ } else if (showHelpWhenNoCommandSpecified && !ctx.command && ctx.rawParsed.parameters.length === 0) printHelp(renderer.render());
315
364
  else await next();
316
365
  }
317
366
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@clerc/plugin-help",
3
- "version": "1.0.0-beta.19",
3
+ "version": "1.0.0-beta.20",
4
4
  "author": "Ray <i@mk1.io> (https://github.com/so1ve)",
5
5
  "type": "module",
6
6
  "description": "Clerc plugin help",
@@ -52,9 +52,9 @@
52
52
  },
53
53
  "devDependencies": {
54
54
  "kons": "^0.7.1",
55
- "@clerc/core": "1.0.0-beta.19",
56
- "@clerc/parser": "1.0.0-beta.19",
57
- "@clerc/utils": "1.0.0-beta.19"
55
+ "@clerc/parser": "1.0.0-beta.20",
56
+ "@clerc/core": "1.0.0-beta.20",
57
+ "@clerc/utils": "1.0.0-beta.20"
58
58
  },
59
59
  "peerDependencies": {
60
60
  "@clerc/core": "*"