@clerc/plugin-help 0.19.0 → 0.21.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/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
- import { definePlugin, resolveCommand, NoSuchCommandError, SingleCommand } from '@clerc/core';
2
- import { toArray, gracefulFlagName, kebabCase } from '@clerc/utils';
1
+ import { definePlugin, SingleCommand, resolveCommand, NoSuchCommandError } from '@clerc/core';
2
+ import { toArray, gracefulFlagName } from '@clerc/utils';
3
3
  import pc from 'picocolors';
4
4
  import getFuncName from 'get-func-name';
5
5
  import { Table } from '@clerc/toolkit';
@@ -39,7 +39,7 @@ const render = (sections) => {
39
39
  const rendered = [];
40
40
  for (const section of sections) {
41
41
  if (section.type === "block" || !section.type) {
42
- const indent = " ".repeat(4);
42
+ const indent = " ";
43
43
  const formattedBody = section.body.map((line) => indent + line);
44
44
  formattedBody.unshift("");
45
45
  const body = formattedBody.join("\n");
@@ -55,22 +55,36 @@ const render = (sections) => {
55
55
  };
56
56
 
57
57
  const DELIMITER = pc.yellow("-");
58
- const formatCommandName = (name) => Array.isArray(name) ? name.join(" ") : typeof name === "string" ? name : "<Single Command>";
58
+ const NO_DESCRIPTION = "(No description)";
59
+ const SINGLE_COMMAND = "<Single Command>";
60
+ const NAME = "Name:";
61
+ const VERSION = "Version:";
62
+ const COMMANDS = "Commands:";
63
+ const SUBCOMMAND = "Subcommand:";
64
+ const FLAGS = "Flags:";
65
+ const DESCRIPTION = "Description:";
66
+ const USAGE = "Usage:";
67
+ const EXAMPLES = "Examples:";
68
+ const NOTES = "Notes:";
69
+ const print = (s) => {
70
+ process.stdout.write(s);
71
+ };
72
+ const formatCommandName = (name) => Array.isArray(name) ? name.join(" ") : typeof name === "string" ? name : SINGLE_COMMAND;
59
73
  const generateCliDetail = (sections, cli, subcommand) => {
60
74
  const items = [
61
75
  {
62
- title: "Name:",
76
+ title: NAME,
63
77
  body: pc.red(cli._name)
64
78
  },
65
79
  {
66
- title: "Version:",
80
+ title: VERSION,
67
81
  body: pc.yellow(cli._version)
68
82
  }
69
83
  ];
70
84
  if (subcommand) {
71
85
  items.push({
72
- title: "Subcommand:",
73
- body: pc.green(formatCommandName(subcommand.name))
86
+ title: SUBCOMMAND,
87
+ body: pc.green(`${cli._name} ${formatCommandName(subcommand.name)}`)
74
88
  });
75
89
  }
76
90
  sections.push({
@@ -78,53 +92,55 @@ const generateCliDetail = (sections, cli, subcommand) => {
78
92
  items
79
93
  });
80
94
  sections.push({
81
- title: "Description:",
95
+ title: DESCRIPTION,
82
96
  body: [(subcommand == null ? void 0 : subcommand.description) || cli._description]
83
97
  });
84
98
  };
85
99
  const generateExamples = (sections, examples) => {
86
100
  const examplesFormatted = examples.map(([command, description]) => [command, DELIMITER, description]);
87
101
  sections.push({
88
- title: "Examples:",
102
+ title: EXAMPLES,
89
103
  body: splitTable(...examplesFormatted)
90
104
  });
91
105
  };
92
- const showHelp = (ctx, notes, examples) => {
106
+ const generateHelp = (ctx, notes, examples) => {
93
107
  const { cli } = ctx;
94
108
  const sections = [];
95
109
  generateCliDetail(sections, cli);
96
- if (ctx.isSingleCommand) {
97
- sections.push({
98
- title: "Usage:",
99
- body: [pc.magenta(`$ ${cli._name} [flags]`)]
100
- });
101
- } else {
102
- sections.push({
103
- title: "Usage:",
104
- body: [pc.magenta(`$ ${cli._name} [command] [flags]`)]
105
- });
106
- }
107
- if (!ctx.isSingleCommand) {
108
- sections.push({
109
- title: "Commands:",
110
- body: splitTable(...Object.values(cli._commands).map((command) => {
111
- const commandNameWithAlias = [command.name, ...toArray(command.alias || [])].join(", ");
112
- return [pc.cyan(commandNameWithAlias), DELIMITER, command.description];
113
- }))
114
- });
115
- }
110
+ sections.push({
111
+ title: USAGE,
112
+ body: [pc.magenta(`$ ${cli._name} [command] [flags]`)]
113
+ });
114
+ const commands = [...ctx.hasSingleCommand ? [cli._commands[SingleCommand]] : [], ...Object.values(cli._commands)].map((command) => {
115
+ const commandNameWithAlias = [typeof command.name === "symbol" ? "" : command.name, ...toArray(command.alias || [])].sort((a, b) => {
116
+ if (a === SingleCommand) {
117
+ return -1;
118
+ }
119
+ if (b === SingleCommand) {
120
+ return 1;
121
+ }
122
+ return a.length - b.length;
123
+ }).map((n) => {
124
+ return n === "" || typeof n === "symbol" ? `${cli._name}` : `${cli._name} ${n}`;
125
+ }).join(", ");
126
+ return [pc.cyan(commandNameWithAlias), DELIMITER, command.description];
127
+ });
128
+ sections.push({
129
+ title: COMMANDS,
130
+ body: splitTable(...commands)
131
+ });
116
132
  if (notes) {
117
133
  sections.push({
118
- title: "Notes:",
134
+ title: NOTES,
119
135
  body: notes
120
136
  });
121
137
  }
122
138
  if (examples) {
123
139
  generateExamples(sections, examples);
124
140
  }
125
- process.stdout.write(render(sections));
141
+ return render(sections);
126
142
  };
127
- const showSubcommandHelp = (ctx, command) => {
143
+ const generateSubcommandHelp = (ctx, command) => {
128
144
  var _a;
129
145
  const { cli } = ctx;
130
146
  const subcommand = resolveCommand(cli._commands, command);
@@ -132,25 +148,26 @@ const showSubcommandHelp = (ctx, command) => {
132
148
  throw new NoSuchCommandError(formatCommandName(command));
133
149
  }
134
150
  const sections = [];
135
- generateCliDetail(sections, cli, ctx.isSingleCommand ? void 0 : subcommand);
151
+ generateCliDetail(sections, cli, subcommand);
136
152
  const parameters = ((_a = subcommand.parameters) == null ? void 0 : _a.join(" ")) || void 0;
153
+ const commandName = ctx.name === SingleCommand ? "" : ` ${formatCommandName(subcommand.name)}`;
154
+ const parametersString = parameters ? ` ${parameters}` : "";
155
+ const flagsString = subcommand.flags ? " [flags]" : "";
137
156
  sections.push({
138
- title: "Usage:",
139
- body: [pc.magenta(`$ ${cli._name}${ctx.isSingleCommand ? "" : ` ${formatCommandName(subcommand.name)}`}${parameters ? ` ${parameters}` : ""} [flags]`)]
157
+ title: USAGE,
158
+ body: [pc.magenta(`$ ${cli._name}${commandName}${parametersString}${flagsString}`)]
140
159
  });
141
160
  if (subcommand.flags) {
142
161
  sections.push({
143
- title: "Flags:",
162
+ title: FLAGS,
144
163
  body: splitTable(
145
164
  ...Object.entries(subcommand.flags).map(([name, flag]) => {
146
165
  const flagNameWithAlias = [gracefulFlagName(name)];
147
166
  if (flag.alias) {
148
167
  flagNameWithAlias.push(gracefulFlagName(flag.alias));
149
168
  }
150
- const items = [pc.blue(flagNameWithAlias.map(kebabCase).join(", "))];
151
- if (flag.description) {
152
- items.push(DELIMITER, flag.description);
153
- }
169
+ const items = [pc.blue(flagNameWithAlias.join(", "))];
170
+ items.push(DELIMITER, flag.description || NO_DESCRIPTION);
154
171
  if (flag.type) {
155
172
  const type = stringifyType(flag.type);
156
173
  items.push(pc.gray(`(${type})`));
@@ -162,14 +179,14 @@ const showSubcommandHelp = (ctx, command) => {
162
179
  }
163
180
  if (subcommand.notes) {
164
181
  sections.push({
165
- title: "Notes:",
182
+ title: NOTES,
166
183
  body: subcommand.notes
167
184
  });
168
185
  }
169
186
  if (subcommand.examples) {
170
187
  generateExamples(sections, subcommand.examples);
171
188
  }
172
- process.stdout.write(render(sections));
189
+ return render(sections);
173
190
  };
174
191
  const helpPlugin = ({
175
192
  command = true,
@@ -195,24 +212,31 @@ const helpPlugin = ({
195
212
  ]
196
213
  }).on("help", (ctx) => {
197
214
  if (ctx.parameters.command.length) {
198
- showSubcommandHelp(ctx, ctx.parameters.command);
215
+ print(generateSubcommandHelp(ctx, ctx.parameters.command));
199
216
  } else {
200
- showHelp(ctx, notes, examples);
217
+ print(generateHelp(ctx, notes, examples));
201
218
  }
202
219
  });
203
220
  }
204
221
  cli.inspector((ctx, next) => {
205
- if (!ctx.isSingleCommand && !ctx.raw._.length && showHelpWhenNoCommand) {
206
- showHelp(ctx, notes, examples);
207
- } else if (ctx.raw.mergedFlags.h || ctx.raw.mergedFlags.help) {
222
+ const hasHelpFlag = ctx.raw.mergedFlags.h || ctx.raw.mergedFlags.help;
223
+ if (!ctx.hasSingleCommandOrAlias && !ctx.raw._.length && showHelpWhenNoCommand && !hasHelpFlag) {
224
+ let str = "No command supplied.\n\n";
225
+ str += generateHelp(ctx, notes, examples);
226
+ str += "\n";
227
+ print(str);
228
+ process.exit(1);
229
+ } else if (hasHelpFlag) {
208
230
  if (ctx.raw._.length) {
209
- showSubcommandHelp(ctx, ctx.raw._);
210
- } else {
211
- if (!ctx.isSingleCommand) {
212
- showHelp(ctx, notes, examples);
213
- } else {
214
- showSubcommandHelp(ctx, SingleCommand);
231
+ if (ctx.called !== SingleCommand) {
232
+ if (ctx.name === SingleCommand) {
233
+ print(generateHelp(ctx, notes, examples));
234
+ } else {
235
+ print(generateSubcommandHelp(ctx, ctx.raw._));
236
+ }
215
237
  }
238
+ } else {
239
+ print(generateHelp(ctx, notes, examples));
216
240
  }
217
241
  } else {
218
242
  next();
package/dist/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
- import { definePlugin, resolveCommand, NoSuchCommandError, SingleCommand } from '@clerc/core';
2
- import { toArray, gracefulFlagName, kebabCase } from '@clerc/utils';
1
+ import { definePlugin, SingleCommand, resolveCommand, NoSuchCommandError } from '@clerc/core';
2
+ import { toArray, gracefulFlagName } from '@clerc/utils';
3
3
  import pc from 'picocolors';
4
4
  import getFuncName from 'get-func-name';
5
5
  import { Table } from '@clerc/toolkit';
@@ -39,7 +39,7 @@ const render = (sections) => {
39
39
  const rendered = [];
40
40
  for (const section of sections) {
41
41
  if (section.type === "block" || !section.type) {
42
- const indent = " ".repeat(4);
42
+ const indent = " ";
43
43
  const formattedBody = section.body.map((line) => indent + line);
44
44
  formattedBody.unshift("");
45
45
  const body = formattedBody.join("\n");
@@ -55,22 +55,36 @@ const render = (sections) => {
55
55
  };
56
56
 
57
57
  const DELIMITER = pc.yellow("-");
58
- const formatCommandName = (name) => Array.isArray(name) ? name.join(" ") : typeof name === "string" ? name : "<Single Command>";
58
+ const NO_DESCRIPTION = "(No description)";
59
+ const SINGLE_COMMAND = "<Single Command>";
60
+ const NAME = "Name:";
61
+ const VERSION = "Version:";
62
+ const COMMANDS = "Commands:";
63
+ const SUBCOMMAND = "Subcommand:";
64
+ const FLAGS = "Flags:";
65
+ const DESCRIPTION = "Description:";
66
+ const USAGE = "Usage:";
67
+ const EXAMPLES = "Examples:";
68
+ const NOTES = "Notes:";
69
+ const print = (s) => {
70
+ process.stdout.write(s);
71
+ };
72
+ const formatCommandName = (name) => Array.isArray(name) ? name.join(" ") : typeof name === "string" ? name : SINGLE_COMMAND;
59
73
  const generateCliDetail = (sections, cli, subcommand) => {
60
74
  const items = [
61
75
  {
62
- title: "Name:",
76
+ title: NAME,
63
77
  body: pc.red(cli._name)
64
78
  },
65
79
  {
66
- title: "Version:",
80
+ title: VERSION,
67
81
  body: pc.yellow(cli._version)
68
82
  }
69
83
  ];
70
84
  if (subcommand) {
71
85
  items.push({
72
- title: "Subcommand:",
73
- body: pc.green(formatCommandName(subcommand.name))
86
+ title: SUBCOMMAND,
87
+ body: pc.green(`${cli._name} ${formatCommandName(subcommand.name)}`)
74
88
  });
75
89
  }
76
90
  sections.push({
@@ -78,53 +92,55 @@ const generateCliDetail = (sections, cli, subcommand) => {
78
92
  items
79
93
  });
80
94
  sections.push({
81
- title: "Description:",
95
+ title: DESCRIPTION,
82
96
  body: [(subcommand == null ? void 0 : subcommand.description) || cli._description]
83
97
  });
84
98
  };
85
99
  const generateExamples = (sections, examples) => {
86
100
  const examplesFormatted = examples.map(([command, description]) => [command, DELIMITER, description]);
87
101
  sections.push({
88
- title: "Examples:",
102
+ title: EXAMPLES,
89
103
  body: splitTable(...examplesFormatted)
90
104
  });
91
105
  };
92
- const showHelp = (ctx, notes, examples) => {
106
+ const generateHelp = (ctx, notes, examples) => {
93
107
  const { cli } = ctx;
94
108
  const sections = [];
95
109
  generateCliDetail(sections, cli);
96
- if (ctx.isSingleCommand) {
97
- sections.push({
98
- title: "Usage:",
99
- body: [pc.magenta(`$ ${cli._name} [flags]`)]
100
- });
101
- } else {
102
- sections.push({
103
- title: "Usage:",
104
- body: [pc.magenta(`$ ${cli._name} [command] [flags]`)]
105
- });
106
- }
107
- if (!ctx.isSingleCommand) {
108
- sections.push({
109
- title: "Commands:",
110
- body: splitTable(...Object.values(cli._commands).map((command) => {
111
- const commandNameWithAlias = [command.name, ...toArray(command.alias || [])].join(", ");
112
- return [pc.cyan(commandNameWithAlias), DELIMITER, command.description];
113
- }))
114
- });
115
- }
110
+ sections.push({
111
+ title: USAGE,
112
+ body: [pc.magenta(`$ ${cli._name} [command] [flags]`)]
113
+ });
114
+ const commands = [...ctx.hasSingleCommand ? [cli._commands[SingleCommand]] : [], ...Object.values(cli._commands)].map((command) => {
115
+ const commandNameWithAlias = [typeof command.name === "symbol" ? "" : command.name, ...toArray(command.alias || [])].sort((a, b) => {
116
+ if (a === SingleCommand) {
117
+ return -1;
118
+ }
119
+ if (b === SingleCommand) {
120
+ return 1;
121
+ }
122
+ return a.length - b.length;
123
+ }).map((n) => {
124
+ return n === "" || typeof n === "symbol" ? `${cli._name}` : `${cli._name} ${n}`;
125
+ }).join(", ");
126
+ return [pc.cyan(commandNameWithAlias), DELIMITER, command.description];
127
+ });
128
+ sections.push({
129
+ title: COMMANDS,
130
+ body: splitTable(...commands)
131
+ });
116
132
  if (notes) {
117
133
  sections.push({
118
- title: "Notes:",
134
+ title: NOTES,
119
135
  body: notes
120
136
  });
121
137
  }
122
138
  if (examples) {
123
139
  generateExamples(sections, examples);
124
140
  }
125
- process.stdout.write(render(sections));
141
+ return render(sections);
126
142
  };
127
- const showSubcommandHelp = (ctx, command) => {
143
+ const generateSubcommandHelp = (ctx, command) => {
128
144
  var _a;
129
145
  const { cli } = ctx;
130
146
  const subcommand = resolveCommand(cli._commands, command);
@@ -132,25 +148,26 @@ const showSubcommandHelp = (ctx, command) => {
132
148
  throw new NoSuchCommandError(formatCommandName(command));
133
149
  }
134
150
  const sections = [];
135
- generateCliDetail(sections, cli, ctx.isSingleCommand ? void 0 : subcommand);
151
+ generateCliDetail(sections, cli, subcommand);
136
152
  const parameters = ((_a = subcommand.parameters) == null ? void 0 : _a.join(" ")) || void 0;
153
+ const commandName = ctx.name === SingleCommand ? "" : ` ${formatCommandName(subcommand.name)}`;
154
+ const parametersString = parameters ? ` ${parameters}` : "";
155
+ const flagsString = subcommand.flags ? " [flags]" : "";
137
156
  sections.push({
138
- title: "Usage:",
139
- body: [pc.magenta(`$ ${cli._name}${ctx.isSingleCommand ? "" : ` ${formatCommandName(subcommand.name)}`}${parameters ? ` ${parameters}` : ""} [flags]`)]
157
+ title: USAGE,
158
+ body: [pc.magenta(`$ ${cli._name}${commandName}${parametersString}${flagsString}`)]
140
159
  });
141
160
  if (subcommand.flags) {
142
161
  sections.push({
143
- title: "Flags:",
162
+ title: FLAGS,
144
163
  body: splitTable(
145
164
  ...Object.entries(subcommand.flags).map(([name, flag]) => {
146
165
  const flagNameWithAlias = [gracefulFlagName(name)];
147
166
  if (flag.alias) {
148
167
  flagNameWithAlias.push(gracefulFlagName(flag.alias));
149
168
  }
150
- const items = [pc.blue(flagNameWithAlias.map(kebabCase).join(", "))];
151
- if (flag.description) {
152
- items.push(DELIMITER, flag.description);
153
- }
169
+ const items = [pc.blue(flagNameWithAlias.join(", "))];
170
+ items.push(DELIMITER, flag.description || NO_DESCRIPTION);
154
171
  if (flag.type) {
155
172
  const type = stringifyType(flag.type);
156
173
  items.push(pc.gray(`(${type})`));
@@ -162,14 +179,14 @@ const showSubcommandHelp = (ctx, command) => {
162
179
  }
163
180
  if (subcommand.notes) {
164
181
  sections.push({
165
- title: "Notes:",
182
+ title: NOTES,
166
183
  body: subcommand.notes
167
184
  });
168
185
  }
169
186
  if (subcommand.examples) {
170
187
  generateExamples(sections, subcommand.examples);
171
188
  }
172
- process.stdout.write(render(sections));
189
+ return render(sections);
173
190
  };
174
191
  const helpPlugin = ({
175
192
  command = true,
@@ -195,24 +212,31 @@ const helpPlugin = ({
195
212
  ]
196
213
  }).on("help", (ctx) => {
197
214
  if (ctx.parameters.command.length) {
198
- showSubcommandHelp(ctx, ctx.parameters.command);
215
+ print(generateSubcommandHelp(ctx, ctx.parameters.command));
199
216
  } else {
200
- showHelp(ctx, notes, examples);
217
+ print(generateHelp(ctx, notes, examples));
201
218
  }
202
219
  });
203
220
  }
204
221
  cli.inspector((ctx, next) => {
205
- if (!ctx.isSingleCommand && !ctx.raw._.length && showHelpWhenNoCommand) {
206
- showHelp(ctx, notes, examples);
207
- } else if (ctx.raw.mergedFlags.h || ctx.raw.mergedFlags.help) {
222
+ const hasHelpFlag = ctx.raw.mergedFlags.h || ctx.raw.mergedFlags.help;
223
+ if (!ctx.hasSingleCommandOrAlias && !ctx.raw._.length && showHelpWhenNoCommand && !hasHelpFlag) {
224
+ let str = "No command supplied.\n\n";
225
+ str += generateHelp(ctx, notes, examples);
226
+ str += "\n";
227
+ print(str);
228
+ process.exit(1);
229
+ } else if (hasHelpFlag) {
208
230
  if (ctx.raw._.length) {
209
- showSubcommandHelp(ctx, ctx.raw._);
210
- } else {
211
- if (!ctx.isSingleCommand) {
212
- showHelp(ctx, notes, examples);
213
- } else {
214
- showSubcommandHelp(ctx, SingleCommand);
231
+ if (ctx.called !== SingleCommand) {
232
+ if (ctx.name === SingleCommand) {
233
+ print(generateHelp(ctx, notes, examples));
234
+ } else {
235
+ print(generateSubcommandHelp(ctx, ctx.raw._));
236
+ }
215
237
  }
238
+ } else {
239
+ print(generateHelp(ctx, notes, examples));
216
240
  }
217
241
  } else {
218
242
  next();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@clerc/plugin-help",
3
- "version": "0.19.0",
3
+ "version": "0.21.0",
4
4
  "author": "Ray <nn_201312@163.com> (https://github.com/so1ve)",
5
5
  "description": "Clerc plugin help",
6
6
  "keywords": [
@@ -53,11 +53,11 @@
53
53
  "dependencies": {
54
54
  "get-func-name": "^2.0.0",
55
55
  "picocolors": "^1.0.0",
56
- "@clerc/toolkit": "0.19.0",
57
- "@clerc/utils": "0.19.0"
56
+ "@clerc/toolkit": "0.21.0",
57
+ "@clerc/utils": "0.21.0"
58
58
  },
59
59
  "devDependencies": {
60
- "@clerc/core": "0.19.0"
60
+ "@clerc/core": "0.21.0"
61
61
  },
62
62
  "scripts": {
63
63
  "build": "puild",