@bemoje/cli 1.0.6 → 1.1.1
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/README.md +45 -157
- package/index.d.ts +0 -3
- package/index.js +0 -3
- package/lib/Command.d.ts +109 -112
- package/lib/Command.js +93 -106
- package/lib/Help.d.ts +41 -83
- package/lib/Help.js +14 -14
- package/package.json +4 -7
- package/lib/CommandHelpAdapter.d.ts +0 -157
- package/lib/CommandHelpAdapter.js +0 -102
- package/lib/CommanderHelpAdapter.d.ts +0 -56
- package/lib/CommanderHelpAdapter.js +0 -92
- package/lib/internal/lazyProp.d.ts +0 -5
- package/lib/internal/lazyProp.js +0 -24
- package/lib/renderHelp.d.ts +0 -6
- package/lib/renderHelp.js +0 -12
package/lib/Command.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
var __defProp = Object.defineProperty;
|
|
2
2
|
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
3
3
|
import { parseArgs } from "node:util";
|
|
4
|
-
import {
|
|
4
|
+
import { Help } from "./Help.js";
|
|
5
5
|
class Command {
|
|
6
6
|
static {
|
|
7
7
|
__name(this, "Command");
|
|
@@ -41,37 +41,6 @@ class Command {
|
|
|
41
41
|
this.helpConfiguration = { showGlobalOptions: true, sortOptions: true, sortSubcommands: true };
|
|
42
42
|
Object.defineProperty(this, "parent", { enumerable: false });
|
|
43
43
|
}
|
|
44
|
-
/** Updates multiple command properties at once */
|
|
45
|
-
setState(state) {
|
|
46
|
-
Object.assign(this, state);
|
|
47
|
-
if (state.commands) {
|
|
48
|
-
state.commands = state.commands.map((cmd) => new Command(cmd.name, this).setState(cmd));
|
|
49
|
-
}
|
|
50
|
-
return this;
|
|
51
|
-
}
|
|
52
|
-
/** Serializes command to JSON, maintaining compatibility with previous state-based structure */
|
|
53
|
-
toJSON() {
|
|
54
|
-
const result = {
|
|
55
|
-
name: this.name,
|
|
56
|
-
version: this.version,
|
|
57
|
-
aliases: this.aliases,
|
|
58
|
-
summary: this.summary,
|
|
59
|
-
description: this.description,
|
|
60
|
-
hidden: this.hidden,
|
|
61
|
-
group: this.group,
|
|
62
|
-
commands: this.commands,
|
|
63
|
-
arguments: this.arguments,
|
|
64
|
-
options: this.options,
|
|
65
|
-
helpConfiguration: this.helpConfiguration
|
|
66
|
-
};
|
|
67
|
-
Object.defineProperty(result, "parent", {
|
|
68
|
-
value: this.parent,
|
|
69
|
-
writable: true,
|
|
70
|
-
enumerable: false,
|
|
71
|
-
configurable: true
|
|
72
|
-
});
|
|
73
|
-
return result;
|
|
74
|
-
}
|
|
75
44
|
/** Sets the command name */
|
|
76
45
|
setName(name) {
|
|
77
46
|
this.name = name;
|
|
@@ -96,7 +65,7 @@ class Command {
|
|
|
96
65
|
this.summary = summary;
|
|
97
66
|
return this;
|
|
98
67
|
}
|
|
99
|
-
/** Sets command description, joining
|
|
68
|
+
/** Sets command description, joining variadic lines */
|
|
100
69
|
setDescription(...lines) {
|
|
101
70
|
this.description = lines.join("\n");
|
|
102
71
|
return this;
|
|
@@ -127,59 +96,56 @@ class Command {
|
|
|
127
96
|
return this;
|
|
128
97
|
}
|
|
129
98
|
/** Creates and adds a subcommand */
|
|
130
|
-
|
|
131
|
-
const sub =
|
|
99
|
+
addSubcommand(name) {
|
|
100
|
+
const sub = this.createCommand(name, this);
|
|
132
101
|
this.commands.push(sub);
|
|
133
102
|
return sub;
|
|
134
103
|
}
|
|
135
104
|
/**
|
|
136
105
|
* Adds positional argument with type inference and CLI ordering validation.
|
|
137
106
|
*/
|
|
138
|
-
|
|
107
|
+
addArgument(usage, description, options = {}) {
|
|
139
108
|
const match = usage.match(/^<(.*?)>$|^\[(.*?)\]$/);
|
|
140
109
|
if (!match) throw new Error(`Invalid argument format: ${usage}`);
|
|
141
110
|
const nameMatch = match[1] || match[2];
|
|
142
111
|
const name = nameMatch.replace(/\.\.\.$/, "");
|
|
143
112
|
this.assertArgumentNameNotInUse(name);
|
|
113
|
+
const props = { name, description };
|
|
144
114
|
if (usage.startsWith("<")) {
|
|
145
115
|
if (nameMatch.endsWith("...")) {
|
|
146
116
|
this.assertNoMultipleVariadicArguments();
|
|
147
117
|
this.arguments.push({
|
|
148
|
-
|
|
149
|
-
|
|
118
|
+
...options,
|
|
119
|
+
...props,
|
|
150
120
|
required: true,
|
|
151
|
-
|
|
152
|
-
...options
|
|
121
|
+
variadic: true
|
|
153
122
|
});
|
|
154
123
|
} else {
|
|
155
124
|
this.assertNoOptionalOrVariadicArguments();
|
|
156
125
|
this.arguments.push({
|
|
157
|
-
|
|
158
|
-
|
|
126
|
+
...options,
|
|
127
|
+
...props,
|
|
159
128
|
required: true,
|
|
160
|
-
|
|
161
|
-
...options
|
|
129
|
+
variadic: false
|
|
162
130
|
});
|
|
163
131
|
}
|
|
164
132
|
} else if (usage.startsWith("[")) {
|
|
165
133
|
if (nameMatch.endsWith("...")) {
|
|
166
134
|
this.assertNoMultipleVariadicArguments();
|
|
167
135
|
this.arguments.push({
|
|
168
|
-
|
|
169
|
-
|
|
136
|
+
...options,
|
|
137
|
+
...props,
|
|
170
138
|
required: false,
|
|
171
|
-
|
|
172
|
-
defaultValue: options.defaultValue ?? []
|
|
173
|
-
...options
|
|
139
|
+
variadic: true,
|
|
140
|
+
defaultValue: options.defaultValue ?? []
|
|
174
141
|
});
|
|
175
142
|
} else {
|
|
176
143
|
this.assertNoVariadicArgument();
|
|
177
144
|
this.arguments.push({
|
|
178
|
-
|
|
179
|
-
|
|
145
|
+
...options,
|
|
146
|
+
...props,
|
|
180
147
|
required: false,
|
|
181
|
-
|
|
182
|
-
...options
|
|
148
|
+
variadic: false
|
|
183
149
|
});
|
|
184
150
|
}
|
|
185
151
|
}
|
|
@@ -188,77 +154,97 @@ class Command {
|
|
|
188
154
|
/**
|
|
189
155
|
* Adds command-line option with type inference. Parses format: `-s, --long [<value>|[value]|<value...>|[value...]]`
|
|
190
156
|
*/
|
|
191
|
-
|
|
192
|
-
const match =
|
|
193
|
-
if (!match) throw new Error(`Invalid option format: ${
|
|
157
|
+
addOption(flags, description, opts = {}) {
|
|
158
|
+
const match = flags.match(/^-(.+?), --([a-zA-Z][\w-]*)(?:\s*(<(.+?)>|\[(.+?)\]))?$/);
|
|
159
|
+
if (!match) throw new Error(`Invalid option format: ${flags}`);
|
|
194
160
|
const short = match[1];
|
|
195
161
|
this.assertOptionShortNameIsValid(short);
|
|
196
162
|
this.assertOptionShortNameNotInUse(short);
|
|
197
163
|
const name = match[2];
|
|
198
164
|
const argName = (match[4] || match[5])?.replace(/\.\.\.$/, "");
|
|
199
165
|
this.assertOptionNameNotInUse(name);
|
|
166
|
+
const props = {
|
|
167
|
+
flags,
|
|
168
|
+
short,
|
|
169
|
+
long: name,
|
|
170
|
+
name,
|
|
171
|
+
description
|
|
172
|
+
};
|
|
200
173
|
if (!argName) {
|
|
201
|
-
this.
|
|
174
|
+
this._addOption({
|
|
202
175
|
type: "boolean",
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
176
|
+
...opts,
|
|
177
|
+
...props,
|
|
178
|
+
negate: false,
|
|
179
|
+
optional: true,
|
|
180
|
+
variadic: false,
|
|
181
|
+
get multiple() {
|
|
182
|
+
return this.variadic;
|
|
183
|
+
}
|
|
209
184
|
});
|
|
210
|
-
} else if (
|
|
211
|
-
if (
|
|
212
|
-
this.
|
|
185
|
+
} else if (flags.endsWith(">")) {
|
|
186
|
+
if (flags.endsWith("...>")) {
|
|
187
|
+
this._addOption({
|
|
213
188
|
type: "string",
|
|
214
|
-
|
|
215
|
-
|
|
189
|
+
...opts,
|
|
190
|
+
...props,
|
|
216
191
|
argName,
|
|
217
|
-
description,
|
|
218
192
|
required: true,
|
|
219
|
-
|
|
220
|
-
|
|
193
|
+
optional: false,
|
|
194
|
+
variadic: true,
|
|
195
|
+
get multiple() {
|
|
196
|
+
return this.variadic;
|
|
197
|
+
}
|
|
221
198
|
});
|
|
222
199
|
} else {
|
|
223
|
-
this.
|
|
200
|
+
this._addOption({
|
|
224
201
|
type: "string",
|
|
225
|
-
|
|
226
|
-
|
|
202
|
+
...opts,
|
|
203
|
+
...props,
|
|
227
204
|
argName,
|
|
228
|
-
description,
|
|
229
205
|
required: true,
|
|
230
|
-
|
|
231
|
-
|
|
206
|
+
optional: false,
|
|
207
|
+
variadic: false,
|
|
208
|
+
get multiple() {
|
|
209
|
+
return this.variadic;
|
|
210
|
+
}
|
|
232
211
|
});
|
|
233
212
|
}
|
|
234
|
-
} else if (
|
|
235
|
-
if (
|
|
236
|
-
this.
|
|
213
|
+
} else if (flags.endsWith("]")) {
|
|
214
|
+
if (flags.endsWith("...]")) {
|
|
215
|
+
this._addOption({
|
|
237
216
|
type: "string",
|
|
238
|
-
|
|
239
|
-
|
|
217
|
+
...opts,
|
|
218
|
+
...props,
|
|
240
219
|
argName,
|
|
241
|
-
description,
|
|
242
220
|
required: false,
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
221
|
+
optional: true,
|
|
222
|
+
variadic: true,
|
|
223
|
+
get multiple() {
|
|
224
|
+
return this.variadic;
|
|
225
|
+
},
|
|
226
|
+
defaultValue: opts.defaultValue ?? []
|
|
246
227
|
});
|
|
247
228
|
} else {
|
|
248
|
-
this.
|
|
229
|
+
this._addOption({
|
|
249
230
|
type: "string",
|
|
250
|
-
|
|
251
|
-
|
|
231
|
+
...opts,
|
|
232
|
+
...props,
|
|
252
233
|
argName,
|
|
253
|
-
description,
|
|
254
234
|
required: false,
|
|
255
|
-
|
|
256
|
-
|
|
235
|
+
optional: true,
|
|
236
|
+
variadic: false,
|
|
237
|
+
get multiple() {
|
|
238
|
+
return this.variadic;
|
|
239
|
+
}
|
|
257
240
|
});
|
|
258
241
|
}
|
|
259
242
|
}
|
|
260
243
|
return this;
|
|
261
244
|
}
|
|
245
|
+
_addOption(opt) {
|
|
246
|
+
this.options.push(opt);
|
|
247
|
+
}
|
|
262
248
|
/**
|
|
263
249
|
* Parses command-line arguments with subcommand support and type-safe validation.
|
|
264
250
|
*
|
|
@@ -268,7 +254,7 @@ class Command {
|
|
|
268
254
|
* // { arguments: ['input.txt'], options: { verbose: true, format: 'json' } }
|
|
269
255
|
* ```
|
|
270
256
|
*/
|
|
271
|
-
|
|
257
|
+
parseArgv(argv = process.argv.slice(2), globalOptions = []) {
|
|
272
258
|
const maybeSubArg = parseArgs({
|
|
273
259
|
args: argv,
|
|
274
260
|
allowPositionals: true,
|
|
@@ -278,7 +264,7 @@ class Command {
|
|
|
278
264
|
}).positionals[0];
|
|
279
265
|
const sub = this.findCommand(maybeSubArg);
|
|
280
266
|
if (sub) {
|
|
281
|
-
return sub.
|
|
267
|
+
return sub.parseArgv(
|
|
282
268
|
argv?.filter((a) => a !== maybeSubArg),
|
|
283
269
|
[...globalOptions, ...this.options]
|
|
284
270
|
);
|
|
@@ -299,7 +285,7 @@ class Command {
|
|
|
299
285
|
const token = parsed.tokens[i];
|
|
300
286
|
if (token.kind === "option") {
|
|
301
287
|
const optionDescriptor = this.options.find((o) => o.name === token.name);
|
|
302
|
-
if (optionDescriptor && optionDescriptor.
|
|
288
|
+
if (optionDescriptor && optionDescriptor.variadic && optionDescriptor.type === "string") {
|
|
303
289
|
const values = [token.value];
|
|
304
290
|
let j = i + 1;
|
|
305
291
|
while (j < parsed.tokens.length && parsed.tokens[j].kind === "positional") {
|
|
@@ -322,13 +308,13 @@ class Command {
|
|
|
322
308
|
}
|
|
323
309
|
}
|
|
324
310
|
const parsedArguments = this.arguments.map((arg, index) => {
|
|
325
|
-
if (arg.
|
|
311
|
+
if (arg.variadic) {
|
|
326
312
|
const remainingArgs = parsed.positionals.slice(index);
|
|
327
313
|
return remainingArgs.length > 0 ? remainingArgs : arg.defaultValue ?? [];
|
|
328
314
|
} else {
|
|
329
315
|
return parsed.positionals[index] ?? arg.defaultValue;
|
|
330
316
|
}
|
|
331
|
-
});
|
|
317
|
+
}).filter((arg) => arg !== void 0);
|
|
332
318
|
for (const option of this.options) {
|
|
333
319
|
if (!(option.name in parsed.values) && "defaultValue" in option) {
|
|
334
320
|
Reflect.set(parsed.values, option.name, option.defaultValue);
|
|
@@ -343,6 +329,11 @@ class Command {
|
|
|
343
329
|
options: { ...parsed.values }
|
|
344
330
|
};
|
|
345
331
|
}
|
|
332
|
+
/** Renders formatted help text using provided help definition */
|
|
333
|
+
renderHelp(help = new Help()) {
|
|
334
|
+
const helper = Object.assign(help, this.helpConfiguration);
|
|
335
|
+
return helper.formatHelp(this, helper);
|
|
336
|
+
}
|
|
346
337
|
/** Validates CLI argument ordering */
|
|
347
338
|
assertNoOptionalOrVariadicArguments() {
|
|
348
339
|
if (this.arguments.some((arg) => !arg.required)) {
|
|
@@ -351,13 +342,13 @@ class Command {
|
|
|
351
342
|
}
|
|
352
343
|
/** Validates optional args don't follow variadic args */
|
|
353
344
|
assertNoVariadicArgument() {
|
|
354
|
-
if (this.arguments.some((arg) => arg.
|
|
345
|
+
if (this.arguments.some((arg) => arg.variadic)) {
|
|
355
346
|
throw new Error("Cannot add optional argument after variadic argument");
|
|
356
347
|
}
|
|
357
348
|
}
|
|
358
349
|
/** Ensures only one variadic argument per command */
|
|
359
350
|
assertNoMultipleVariadicArguments() {
|
|
360
|
-
if (this.arguments.some((arg) => arg.
|
|
351
|
+
if (this.arguments.some((arg) => arg.variadic)) {
|
|
361
352
|
throw new Error("Cannot add more than one variadic argument");
|
|
362
353
|
}
|
|
363
354
|
}
|
|
@@ -419,13 +410,9 @@ class Command {
|
|
|
419
410
|
findOption(arg) {
|
|
420
411
|
return this.options.find((option) => option.short === arg || option.name === arg);
|
|
421
412
|
}
|
|
422
|
-
/** Returns a
|
|
423
|
-
|
|
424
|
-
return new
|
|
425
|
-
}
|
|
426
|
-
/** Renders formatted help text using provided help definition */
|
|
427
|
-
renderHelp(help) {
|
|
428
|
-
return this.createHelpAdapter().renderHelp(help);
|
|
413
|
+
/** Returns a new Command instance. Override this method in subclasses. */
|
|
414
|
+
createCommand(name = "", parent = null) {
|
|
415
|
+
return new Command(name, parent);
|
|
429
416
|
}
|
|
430
417
|
}
|
|
431
418
|
export {
|
package/lib/Help.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { ArgumentDescriptorBase, CommandDescriptor, OptionDescriptorBase } from './Command';
|
|
1
2
|
/**
|
|
2
3
|
* Although this is a class, methods are static in style to allow override using subclass or just functions.
|
|
3
4
|
*/
|
|
@@ -11,72 +12,72 @@ export declare class Help implements IHelp {
|
|
|
11
12
|
/**
|
|
12
13
|
* Get an array of the visible subcommands. Includes a placeholder for the implicit help command, if there is one.
|
|
13
14
|
*/
|
|
14
|
-
visibleCommands(cmd:
|
|
15
|
+
visibleCommands(cmd: CommandDescriptor): CommandDescriptor[];
|
|
15
16
|
/**
|
|
16
17
|
* Compare options for sort.
|
|
17
18
|
*/
|
|
18
|
-
compareOptions(a:
|
|
19
|
+
compareOptions(a: OptionDescriptorBase, b: OptionDescriptorBase): number;
|
|
19
20
|
/**
|
|
20
21
|
* Get an array of the visible options. Includes a placeholder for the implicit help option, if there is one.
|
|
21
22
|
*/
|
|
22
|
-
visibleOptions(cmd:
|
|
23
|
+
visibleOptions(cmd: CommandDescriptor): OptionDescriptorBase[];
|
|
23
24
|
/**
|
|
24
25
|
* Get an array of the visible global options. (Not including help.)
|
|
25
26
|
*/
|
|
26
|
-
visibleGlobalOptions(cmd:
|
|
27
|
+
visibleGlobalOptions(cmd: CommandDescriptor): OptionDescriptorBase[];
|
|
27
28
|
/**
|
|
28
29
|
* Get an array of the arguments if any have a description.
|
|
29
30
|
*/
|
|
30
|
-
visibleArguments(cmd:
|
|
31
|
+
visibleArguments(cmd: CommandDescriptor): ArgumentDescriptorBase[];
|
|
31
32
|
/**
|
|
32
33
|
* Get the command term to show in the list of subcommands.
|
|
33
34
|
*/
|
|
34
|
-
subcommandTerm(cmd:
|
|
35
|
+
subcommandTerm(cmd: CommandDescriptor): string;
|
|
35
36
|
/**
|
|
36
37
|
* Get the option term to show in the list of options.
|
|
37
38
|
*/
|
|
38
|
-
optionTerm(option:
|
|
39
|
+
optionTerm(option: OptionDescriptorBase): string;
|
|
39
40
|
/**
|
|
40
41
|
* Get the argument term to show in the list of arguments.
|
|
41
42
|
*/
|
|
42
|
-
argumentTerm(argument:
|
|
43
|
+
argumentTerm(argument: ArgumentDescriptorBase): string;
|
|
43
44
|
/**
|
|
44
45
|
* Get the longest command term length.
|
|
45
46
|
*/
|
|
46
|
-
longestSubcommandTermLength(cmd:
|
|
47
|
+
longestSubcommandTermLength(cmd: CommandDescriptor, helper: Help): number;
|
|
47
48
|
/**
|
|
48
49
|
* Get the longest option term length.
|
|
49
50
|
*/
|
|
50
|
-
longestOptionTermLength(cmd:
|
|
51
|
+
longestOptionTermLength(cmd: CommandDescriptor, helper: Help): number;
|
|
51
52
|
/**
|
|
52
53
|
* Get the longest global option term length.
|
|
53
54
|
*/
|
|
54
|
-
longestGlobalOptionTermLength(cmd:
|
|
55
|
+
longestGlobalOptionTermLength(cmd: CommandDescriptor, helper: Help): number;
|
|
55
56
|
/**
|
|
56
57
|
* Get the longest argument term length.
|
|
57
58
|
*/
|
|
58
|
-
longestArgumentTermLength(cmd:
|
|
59
|
+
longestArgumentTermLength(cmd: CommandDescriptor, helper: Help): number;
|
|
59
60
|
/**
|
|
60
61
|
* Get the command usage to be displayed at the top of the built-in help.
|
|
61
62
|
*/
|
|
62
|
-
commandUsage(cmd:
|
|
63
|
+
commandUsage(cmd: CommandDescriptor): string;
|
|
63
64
|
/**
|
|
64
65
|
* Get the description for the command.
|
|
65
66
|
*/
|
|
66
|
-
commandDescription(cmd:
|
|
67
|
+
commandDescription(cmd: CommandDescriptor): string;
|
|
67
68
|
/**
|
|
68
69
|
* Get the subcommand summary to show in the list of subcommands.
|
|
69
70
|
* (Fallback to description for backwards compatibility.)
|
|
70
71
|
*/
|
|
71
|
-
subcommandDescription(cmd:
|
|
72
|
+
subcommandDescription(cmd: CommandDescriptor): string;
|
|
72
73
|
/**
|
|
73
74
|
* Get the option description to show in the list of options.
|
|
74
75
|
*/
|
|
75
|
-
optionDescription(option:
|
|
76
|
+
optionDescription(option: OptionDescriptorBase): string;
|
|
76
77
|
/**
|
|
77
78
|
* Get the argument description to show in the list of arguments.
|
|
78
79
|
*/
|
|
79
|
-
argumentDescription(argument:
|
|
80
|
+
argumentDescription(argument: ArgumentDescriptorBase): string;
|
|
80
81
|
/**
|
|
81
82
|
* Format a list of items, given a heading and an array of formatted items.
|
|
82
83
|
*/
|
|
@@ -84,11 +85,11 @@ export declare class Help implements IHelp {
|
|
|
84
85
|
/**
|
|
85
86
|
* Group items by their help group heading.
|
|
86
87
|
*/
|
|
87
|
-
groupItems<T extends
|
|
88
|
+
groupItems<T extends CommandDescriptor | OptionDescriptorBase>(unsortedItems: T[], visibleItems: T[], getGroup: (item: T) => string): Map<string, T[]>;
|
|
88
89
|
/**
|
|
89
90
|
* Generate the built-in help text.
|
|
90
91
|
*/
|
|
91
|
-
formatHelp(cmd:
|
|
92
|
+
formatHelp(cmd: CommandDescriptor, helper: IHelp): string;
|
|
92
93
|
/**
|
|
93
94
|
* Return display width of string, ignoring ANSI escape sequences. Used in padding and wrapping calculations.
|
|
94
95
|
*/
|
|
@@ -152,7 +153,7 @@ export declare class Help implements IHelp {
|
|
|
152
153
|
/**
|
|
153
154
|
* Calculate the pad width from the maximum term length.
|
|
154
155
|
*/
|
|
155
|
-
padWidth(cmd:
|
|
156
|
+
padWidth(cmd: CommandDescriptor, helper: Help): number;
|
|
156
157
|
/**
|
|
157
158
|
* Detect manually wrapped and indented strings by checking for line break followed by whitespace.
|
|
158
159
|
*/
|
|
@@ -171,71 +172,28 @@ export declare class Help implements IHelp {
|
|
|
171
172
|
*/
|
|
172
173
|
boxWrap(str: string, width: number): string;
|
|
173
174
|
}
|
|
174
|
-
/**
|
|
175
|
-
* Interface for a command object used to generate help.
|
|
176
|
-
*/
|
|
177
|
-
export interface ICommandHelp {
|
|
178
|
-
name: string;
|
|
179
|
-
aliases: string[];
|
|
180
|
-
summary?: string;
|
|
181
|
-
description: string;
|
|
182
|
-
hidden?: boolean;
|
|
183
|
-
usage: string;
|
|
184
|
-
group?: string;
|
|
185
|
-
commands: ICommandHelp[];
|
|
186
|
-
options: IOptionHelp[];
|
|
187
|
-
arguments: IArgumentHelp[];
|
|
188
|
-
parent: ICommandHelp | null;
|
|
189
|
-
helpConfiguration?: Partial<IHelp>;
|
|
190
|
-
}
|
|
191
|
-
export interface IArgumentHelp {
|
|
192
|
-
name: string;
|
|
193
|
-
description: string;
|
|
194
|
-
required: boolean;
|
|
195
|
-
variadic: boolean;
|
|
196
|
-
defaultValue?: string | string[];
|
|
197
|
-
defaultValueDescription?: string;
|
|
198
|
-
choices?: string[];
|
|
199
|
-
}
|
|
200
|
-
export interface IOptionHelp {
|
|
201
|
-
group?: string;
|
|
202
|
-
flags: string;
|
|
203
|
-
description: string;
|
|
204
|
-
short: string;
|
|
205
|
-
long: string;
|
|
206
|
-
required?: boolean;
|
|
207
|
-
optional?: boolean;
|
|
208
|
-
variadic?: boolean;
|
|
209
|
-
negate?: boolean;
|
|
210
|
-
defaultValue?: boolean | string | string[];
|
|
211
|
-
defaultValueDescription?: string;
|
|
212
|
-
env?: string;
|
|
213
|
-
choices?: string[];
|
|
214
|
-
hidden?: boolean;
|
|
215
|
-
global?: boolean;
|
|
216
|
-
}
|
|
217
175
|
export interface IHelp {
|
|
218
176
|
helpWidth: number;
|
|
219
177
|
minWidthToWrap: number;
|
|
220
178
|
sortSubcommands?: boolean;
|
|
221
179
|
sortOptions?: boolean;
|
|
222
180
|
showGlobalOptions?: boolean;
|
|
223
|
-
subcommandTerm(cmd:
|
|
224
|
-
subcommandDescription(cmd:
|
|
225
|
-
optionTerm(option:
|
|
226
|
-
optionDescription(option:
|
|
227
|
-
argumentTerm(argument:
|
|
228
|
-
argumentDescription(argument:
|
|
229
|
-
commandUsage(cmd:
|
|
230
|
-
commandDescription(cmd:
|
|
231
|
-
visibleCommands(cmd:
|
|
232
|
-
visibleOptions(cmd:
|
|
233
|
-
visibleGlobalOptions(cmd:
|
|
234
|
-
visibleArguments(cmd:
|
|
235
|
-
longestSubcommandTermLength(cmd:
|
|
236
|
-
longestOptionTermLength(cmd:
|
|
237
|
-
longestGlobalOptionTermLength(cmd:
|
|
238
|
-
longestArgumentTermLength(cmd:
|
|
181
|
+
subcommandTerm(cmd: CommandDescriptor): string;
|
|
182
|
+
subcommandDescription(cmd: CommandDescriptor): string;
|
|
183
|
+
optionTerm(option: OptionDescriptorBase): string;
|
|
184
|
+
optionDescription(option: OptionDescriptorBase): string;
|
|
185
|
+
argumentTerm(argument: ArgumentDescriptorBase): string;
|
|
186
|
+
argumentDescription(argument: ArgumentDescriptorBase): string;
|
|
187
|
+
commandUsage(cmd: CommandDescriptor): string;
|
|
188
|
+
commandDescription(cmd: CommandDescriptor): string;
|
|
189
|
+
visibleCommands(cmd: CommandDescriptor): CommandDescriptor[];
|
|
190
|
+
visibleOptions(cmd: CommandDescriptor): OptionDescriptorBase[];
|
|
191
|
+
visibleGlobalOptions(cmd: CommandDescriptor): OptionDescriptorBase[];
|
|
192
|
+
visibleArguments(cmd: CommandDescriptor): ArgumentDescriptorBase[];
|
|
193
|
+
longestSubcommandTermLength(cmd: CommandDescriptor, helper: IHelp): number;
|
|
194
|
+
longestOptionTermLength(cmd: CommandDescriptor, helper: IHelp): number;
|
|
195
|
+
longestGlobalOptionTermLength(cmd: CommandDescriptor, helper: IHelp): number;
|
|
196
|
+
longestArgumentTermLength(cmd: CommandDescriptor, helper: IHelp): number;
|
|
239
197
|
displayWidth(str: string): number;
|
|
240
198
|
styleTitle(title: string): string;
|
|
241
199
|
styleUsage(str: string): string;
|
|
@@ -251,13 +209,13 @@ export interface IHelp {
|
|
|
251
209
|
styleOptionText(str: string): string;
|
|
252
210
|
styleSubcommandText(str: string): string;
|
|
253
211
|
styleArgumentText(str: string): string;
|
|
254
|
-
compareOptions(a:
|
|
255
|
-
padWidth(cmd:
|
|
212
|
+
compareOptions(a: OptionDescriptorBase, b: OptionDescriptorBase): number;
|
|
213
|
+
padWidth(cmd: CommandDescriptor, helper: IHelp): number;
|
|
256
214
|
boxWrap(str: string, width: number): string;
|
|
257
215
|
preformatted(str: string): boolean;
|
|
258
216
|
formatItem(term: string, termWidth: number, description: string, helper: IHelp): string;
|
|
259
217
|
formatItemList(heading: string, items: string[], helper: IHelp): string[];
|
|
260
|
-
groupItems<T extends
|
|
261
|
-
formatHelp(cmd:
|
|
218
|
+
groupItems<T extends CommandDescriptor | OptionDescriptorBase>(unsortedItems: T[], visibleItems: T[], getGroup: (item: T) => string): Map<string, T[]>;
|
|
219
|
+
formatHelp(cmd: CommandDescriptor, helper: IHelp): string;
|
|
262
220
|
}
|
|
263
221
|
//# sourceMappingURL=Help.d.ts.map
|
package/lib/Help.js
CHANGED
|
@@ -69,7 +69,10 @@ class Help {
|
|
|
69
69
|
* Get the command term to show in the list of subcommands.
|
|
70
70
|
*/
|
|
71
71
|
subcommandTerm(cmd) {
|
|
72
|
-
const args = cmd.arguments.map((arg) =>
|
|
72
|
+
const args = cmd.arguments.map((arg) => {
|
|
73
|
+
const nameOutput = arg.name + (arg.variadic === true ? "..." : "");
|
|
74
|
+
return arg.required ? "<" + nameOutput + ">" : "[" + nameOutput + "]";
|
|
75
|
+
}).join(" ");
|
|
73
76
|
return cmd.name + (cmd.aliases[0] ? "|" + cmd.aliases[0] : "") + (cmd.options.length ? " [options]" : "") + // simplistic check for non-help option
|
|
74
77
|
(args ? " " + args : "");
|
|
75
78
|
}
|
|
@@ -129,7 +132,13 @@ class Help {
|
|
|
129
132
|
for (let ancestorCmd = cmd.parent; ancestorCmd; ancestorCmd = ancestorCmd.parent) {
|
|
130
133
|
ancestorCmdNames = ancestorCmd.name + " " + ancestorCmdNames;
|
|
131
134
|
}
|
|
132
|
-
return ancestorCmdNames + cmdName + " " +
|
|
135
|
+
return ancestorCmdNames + cmdName + " " + [
|
|
136
|
+
...cmd.options.length ? ["[options]"] : [],
|
|
137
|
+
...cmd.commands.length ? ["[command]"] : [],
|
|
138
|
+
...cmd.arguments.map((arg) => {
|
|
139
|
+
return arg.required ? arg.variadic ? `<${arg.name}...>` : `<${arg.name}>` : arg.variadic ? `[${arg.name}...]` : `[${arg.name}]`;
|
|
140
|
+
})
|
|
141
|
+
].join(" ");
|
|
133
142
|
}
|
|
134
143
|
/**
|
|
135
144
|
* Get the description for the command.
|
|
@@ -142,7 +151,7 @@ class Help {
|
|
|
142
151
|
* (Fallback to description for backwards compatibility.)
|
|
143
152
|
*/
|
|
144
153
|
subcommandDescription(cmd) {
|
|
145
|
-
return cmd.summary || cmd.description;
|
|
154
|
+
return cmd.summary || (cmd.description.includes("\n") ? cmd.description.split("\n")[0] : "");
|
|
146
155
|
}
|
|
147
156
|
/**
|
|
148
157
|
* Get the option description to show in the list of options.
|
|
@@ -287,7 +296,8 @@ class Help {
|
|
|
287
296
|
* Return display width of string, ignoring ANSI escape sequences. Used in padding and wrapping calculations.
|
|
288
297
|
*/
|
|
289
298
|
displayWidth(str) {
|
|
290
|
-
|
|
299
|
+
const sgrPattern = /\x1b\[\d*(;\d*)*m/g;
|
|
300
|
+
return str.replace(sgrPattern, "").length;
|
|
291
301
|
}
|
|
292
302
|
/**
|
|
293
303
|
* Style the title for displaying in the help. Called with 'Usage:', 'Options:', etc.
|
|
@@ -458,16 +468,6 @@ ${itemIndentStr}`);
|
|
|
458
468
|
return wrappedLines.join("\n");
|
|
459
469
|
}
|
|
460
470
|
}
|
|
461
|
-
function stripColor(str) {
|
|
462
|
-
const sgrPattern = /\x1b\[\d*(;\d*)*m/g;
|
|
463
|
-
return str.replace(sgrPattern, "");
|
|
464
|
-
}
|
|
465
|
-
__name(stripColor, "stripColor");
|
|
466
|
-
function humanReadableArgName(arg) {
|
|
467
|
-
const nameOutput = arg.name + (arg.variadic === true ? "..." : "");
|
|
468
|
-
return arg.required ? "<" + nameOutput + ">" : "[" + nameOutput + "]";
|
|
469
|
-
}
|
|
470
|
-
__name(humanReadableArgName, "humanReadableArgName");
|
|
471
471
|
export {
|
|
472
472
|
Help
|
|
473
473
|
};
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bemoje/cli",
|
|
3
|
-
"description": "A type-safe CLI
|
|
4
|
-
"version": "1.
|
|
3
|
+
"description": "A type-safe CLI composer that can parse argv and generate help without execution coupling.",
|
|
4
|
+
"version": "1.1.1",
|
|
5
5
|
"private": false,
|
|
6
6
|
"sideEffects": false,
|
|
7
7
|
"type": "module",
|
|
@@ -16,7 +16,8 @@
|
|
|
16
16
|
"typings": "./index.d.ts",
|
|
17
17
|
"dependencies": {},
|
|
18
18
|
"devDependencies": {
|
|
19
|
-
"commander": "^14.0.0"
|
|
19
|
+
"commander": "^14.0.0",
|
|
20
|
+
"type-fest": "4.41.0"
|
|
20
21
|
},
|
|
21
22
|
"license": "MIT",
|
|
22
23
|
"repository": {
|
|
@@ -26,11 +27,8 @@
|
|
|
26
27
|
"keywords": [
|
|
27
28
|
"cli",
|
|
28
29
|
"command-line",
|
|
29
|
-
"argument-parser",
|
|
30
|
-
"options-parser",
|
|
31
30
|
"typescript",
|
|
32
31
|
"type-safe",
|
|
33
|
-
"fluent-api",
|
|
34
32
|
"help-generation",
|
|
35
33
|
"commander",
|
|
36
34
|
"commander.js",
|
|
@@ -38,7 +36,6 @@
|
|
|
38
36
|
"validation",
|
|
39
37
|
"parsing",
|
|
40
38
|
"composition",
|
|
41
|
-
"adapter",
|
|
42
39
|
"terminal",
|
|
43
40
|
"console",
|
|
44
41
|
"args",
|