@bemoje/cli 1.0.5 → 1.1.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/README.md +45 -157
- package/index.d.ts +0 -3
- package/index.js +2 -5
- package/lib/Command.d.ts +108 -111
- package/lib/Command.js +92 -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,6 @@
|
|
|
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 { CommandHelpAdapter } from "./CommandHelpAdapter";
|
|
5
4
|
class Command {
|
|
6
5
|
static {
|
|
7
6
|
__name(this, "Command");
|
|
@@ -41,37 +40,6 @@ class Command {
|
|
|
41
40
|
this.helpConfiguration = { showGlobalOptions: true, sortOptions: true, sortSubcommands: true };
|
|
42
41
|
Object.defineProperty(this, "parent", { enumerable: false });
|
|
43
42
|
}
|
|
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
43
|
/** Sets the command name */
|
|
76
44
|
setName(name) {
|
|
77
45
|
this.name = name;
|
|
@@ -96,7 +64,7 @@ class Command {
|
|
|
96
64
|
this.summary = summary;
|
|
97
65
|
return this;
|
|
98
66
|
}
|
|
99
|
-
/** Sets command description, joining
|
|
67
|
+
/** Sets command description, joining variadic lines */
|
|
100
68
|
setDescription(...lines) {
|
|
101
69
|
this.description = lines.join("\n");
|
|
102
70
|
return this;
|
|
@@ -127,59 +95,56 @@ class Command {
|
|
|
127
95
|
return this;
|
|
128
96
|
}
|
|
129
97
|
/** Creates and adds a subcommand */
|
|
130
|
-
|
|
131
|
-
const sub =
|
|
98
|
+
addSubcommand(name) {
|
|
99
|
+
const sub = this.createCommand(name, this);
|
|
132
100
|
this.commands.push(sub);
|
|
133
101
|
return sub;
|
|
134
102
|
}
|
|
135
103
|
/**
|
|
136
104
|
* Adds positional argument with type inference and CLI ordering validation.
|
|
137
105
|
*/
|
|
138
|
-
|
|
106
|
+
addArgument(usage, description, options = {}) {
|
|
139
107
|
const match = usage.match(/^<(.*?)>$|^\[(.*?)\]$/);
|
|
140
108
|
if (!match) throw new Error(`Invalid argument format: ${usage}`);
|
|
141
109
|
const nameMatch = match[1] || match[2];
|
|
142
110
|
const name = nameMatch.replace(/\.\.\.$/, "");
|
|
143
111
|
this.assertArgumentNameNotInUse(name);
|
|
112
|
+
const props = { name, description };
|
|
144
113
|
if (usage.startsWith("<")) {
|
|
145
114
|
if (nameMatch.endsWith("...")) {
|
|
146
115
|
this.assertNoMultipleVariadicArguments();
|
|
147
116
|
this.arguments.push({
|
|
148
|
-
|
|
149
|
-
|
|
117
|
+
...options,
|
|
118
|
+
...props,
|
|
150
119
|
required: true,
|
|
151
|
-
|
|
152
|
-
...options
|
|
120
|
+
variadic: true
|
|
153
121
|
});
|
|
154
122
|
} else {
|
|
155
123
|
this.assertNoOptionalOrVariadicArguments();
|
|
156
124
|
this.arguments.push({
|
|
157
|
-
|
|
158
|
-
|
|
125
|
+
...options,
|
|
126
|
+
...props,
|
|
159
127
|
required: true,
|
|
160
|
-
|
|
161
|
-
...options
|
|
128
|
+
variadic: false
|
|
162
129
|
});
|
|
163
130
|
}
|
|
164
131
|
} else if (usage.startsWith("[")) {
|
|
165
132
|
if (nameMatch.endsWith("...")) {
|
|
166
133
|
this.assertNoMultipleVariadicArguments();
|
|
167
134
|
this.arguments.push({
|
|
168
|
-
|
|
169
|
-
|
|
135
|
+
...options,
|
|
136
|
+
...props,
|
|
170
137
|
required: false,
|
|
171
|
-
|
|
172
|
-
defaultValue: options.defaultValue ?? []
|
|
173
|
-
...options
|
|
138
|
+
variadic: true,
|
|
139
|
+
defaultValue: options.defaultValue ?? []
|
|
174
140
|
});
|
|
175
141
|
} else {
|
|
176
142
|
this.assertNoVariadicArgument();
|
|
177
143
|
this.arguments.push({
|
|
178
|
-
|
|
179
|
-
|
|
144
|
+
...options,
|
|
145
|
+
...props,
|
|
180
146
|
required: false,
|
|
181
|
-
|
|
182
|
-
...options
|
|
147
|
+
variadic: false
|
|
183
148
|
});
|
|
184
149
|
}
|
|
185
150
|
}
|
|
@@ -188,77 +153,97 @@ class Command {
|
|
|
188
153
|
/**
|
|
189
154
|
* Adds command-line option with type inference. Parses format: `-s, --long [<value>|[value]|<value...>|[value...]]`
|
|
190
155
|
*/
|
|
191
|
-
|
|
192
|
-
const match =
|
|
193
|
-
if (!match) throw new Error(`Invalid option format: ${
|
|
156
|
+
addOption(flags, description, opts = {}) {
|
|
157
|
+
const match = flags.match(/^-(.+?), --([a-zA-Z][\w-]*)(?:\s*(<(.+?)>|\[(.+?)\]))?$/);
|
|
158
|
+
if (!match) throw new Error(`Invalid option format: ${flags}`);
|
|
194
159
|
const short = match[1];
|
|
195
160
|
this.assertOptionShortNameIsValid(short);
|
|
196
161
|
this.assertOptionShortNameNotInUse(short);
|
|
197
162
|
const name = match[2];
|
|
198
163
|
const argName = (match[4] || match[5])?.replace(/\.\.\.$/, "");
|
|
199
164
|
this.assertOptionNameNotInUse(name);
|
|
165
|
+
const props = {
|
|
166
|
+
flags,
|
|
167
|
+
short,
|
|
168
|
+
long: name,
|
|
169
|
+
name,
|
|
170
|
+
description
|
|
171
|
+
};
|
|
200
172
|
if (!argName) {
|
|
201
|
-
this.
|
|
173
|
+
this._addOption({
|
|
202
174
|
type: "boolean",
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
175
|
+
...opts,
|
|
176
|
+
...props,
|
|
177
|
+
negate: false,
|
|
178
|
+
optional: true,
|
|
179
|
+
variadic: false,
|
|
180
|
+
get multiple() {
|
|
181
|
+
return this.variadic;
|
|
182
|
+
}
|
|
209
183
|
});
|
|
210
|
-
} else if (
|
|
211
|
-
if (
|
|
212
|
-
this.
|
|
184
|
+
} else if (flags.endsWith(">")) {
|
|
185
|
+
if (flags.endsWith("...>")) {
|
|
186
|
+
this._addOption({
|
|
213
187
|
type: "string",
|
|
214
|
-
|
|
215
|
-
|
|
188
|
+
...opts,
|
|
189
|
+
...props,
|
|
216
190
|
argName,
|
|
217
|
-
description,
|
|
218
191
|
required: true,
|
|
219
|
-
|
|
220
|
-
|
|
192
|
+
optional: false,
|
|
193
|
+
variadic: true,
|
|
194
|
+
get multiple() {
|
|
195
|
+
return this.variadic;
|
|
196
|
+
}
|
|
221
197
|
});
|
|
222
198
|
} else {
|
|
223
|
-
this.
|
|
199
|
+
this._addOption({
|
|
224
200
|
type: "string",
|
|
225
|
-
|
|
226
|
-
|
|
201
|
+
...opts,
|
|
202
|
+
...props,
|
|
227
203
|
argName,
|
|
228
|
-
description,
|
|
229
204
|
required: true,
|
|
230
|
-
|
|
231
|
-
|
|
205
|
+
optional: false,
|
|
206
|
+
variadic: false,
|
|
207
|
+
get multiple() {
|
|
208
|
+
return this.variadic;
|
|
209
|
+
}
|
|
232
210
|
});
|
|
233
211
|
}
|
|
234
|
-
} else if (
|
|
235
|
-
if (
|
|
236
|
-
this.
|
|
212
|
+
} else if (flags.endsWith("]")) {
|
|
213
|
+
if (flags.endsWith("...]")) {
|
|
214
|
+
this._addOption({
|
|
237
215
|
type: "string",
|
|
238
|
-
|
|
239
|
-
|
|
216
|
+
...opts,
|
|
217
|
+
...props,
|
|
240
218
|
argName,
|
|
241
|
-
description,
|
|
242
219
|
required: false,
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
220
|
+
optional: true,
|
|
221
|
+
variadic: true,
|
|
222
|
+
get multiple() {
|
|
223
|
+
return this.variadic;
|
|
224
|
+
},
|
|
225
|
+
defaultValue: opts.defaultValue ?? []
|
|
246
226
|
});
|
|
247
227
|
} else {
|
|
248
|
-
this.
|
|
228
|
+
this._addOption({
|
|
249
229
|
type: "string",
|
|
250
|
-
|
|
251
|
-
|
|
230
|
+
...opts,
|
|
231
|
+
...props,
|
|
252
232
|
argName,
|
|
253
|
-
description,
|
|
254
233
|
required: false,
|
|
255
|
-
|
|
256
|
-
|
|
234
|
+
optional: true,
|
|
235
|
+
variadic: false,
|
|
236
|
+
get multiple() {
|
|
237
|
+
return this.variadic;
|
|
238
|
+
}
|
|
257
239
|
});
|
|
258
240
|
}
|
|
259
241
|
}
|
|
260
242
|
return this;
|
|
261
243
|
}
|
|
244
|
+
_addOption(opt) {
|
|
245
|
+
this.options.push(opt);
|
|
246
|
+
}
|
|
262
247
|
/**
|
|
263
248
|
* Parses command-line arguments with subcommand support and type-safe validation.
|
|
264
249
|
*
|
|
@@ -268,7 +253,7 @@ class Command {
|
|
|
268
253
|
* // { arguments: ['input.txt'], options: { verbose: true, format: 'json' } }
|
|
269
254
|
* ```
|
|
270
255
|
*/
|
|
271
|
-
|
|
256
|
+
parseArgv(argv = process.argv.slice(2), globalOptions = []) {
|
|
272
257
|
const maybeSubArg = parseArgs({
|
|
273
258
|
args: argv,
|
|
274
259
|
allowPositionals: true,
|
|
@@ -278,7 +263,7 @@ class Command {
|
|
|
278
263
|
}).positionals[0];
|
|
279
264
|
const sub = this.findCommand(maybeSubArg);
|
|
280
265
|
if (sub) {
|
|
281
|
-
return sub.
|
|
266
|
+
return sub.parseArgv(
|
|
282
267
|
argv?.filter((a) => a !== maybeSubArg),
|
|
283
268
|
[...globalOptions, ...this.options]
|
|
284
269
|
);
|
|
@@ -299,7 +284,7 @@ class Command {
|
|
|
299
284
|
const token = parsed.tokens[i];
|
|
300
285
|
if (token.kind === "option") {
|
|
301
286
|
const optionDescriptor = this.options.find((o) => o.name === token.name);
|
|
302
|
-
if (optionDescriptor && optionDescriptor.
|
|
287
|
+
if (optionDescriptor && optionDescriptor.variadic && optionDescriptor.type === "string") {
|
|
303
288
|
const values = [token.value];
|
|
304
289
|
let j = i + 1;
|
|
305
290
|
while (j < parsed.tokens.length && parsed.tokens[j].kind === "positional") {
|
|
@@ -322,13 +307,13 @@ class Command {
|
|
|
322
307
|
}
|
|
323
308
|
}
|
|
324
309
|
const parsedArguments = this.arguments.map((arg, index) => {
|
|
325
|
-
if (arg.
|
|
310
|
+
if (arg.variadic) {
|
|
326
311
|
const remainingArgs = parsed.positionals.slice(index);
|
|
327
312
|
return remainingArgs.length > 0 ? remainingArgs : arg.defaultValue ?? [];
|
|
328
313
|
} else {
|
|
329
314
|
return parsed.positionals[index] ?? arg.defaultValue;
|
|
330
315
|
}
|
|
331
|
-
});
|
|
316
|
+
}).filter((arg) => arg !== void 0);
|
|
332
317
|
for (const option of this.options) {
|
|
333
318
|
if (!(option.name in parsed.values) && "defaultValue" in option) {
|
|
334
319
|
Reflect.set(parsed.values, option.name, option.defaultValue);
|
|
@@ -343,6 +328,11 @@ class Command {
|
|
|
343
328
|
options: { ...parsed.values }
|
|
344
329
|
};
|
|
345
330
|
}
|
|
331
|
+
/** Renders formatted help text using provided help definition */
|
|
332
|
+
renderHelp(help) {
|
|
333
|
+
const helper = Object.assign(help, this.helpConfiguration);
|
|
334
|
+
return helper.formatHelp(this, helper);
|
|
335
|
+
}
|
|
346
336
|
/** Validates CLI argument ordering */
|
|
347
337
|
assertNoOptionalOrVariadicArguments() {
|
|
348
338
|
if (this.arguments.some((arg) => !arg.required)) {
|
|
@@ -351,13 +341,13 @@ class Command {
|
|
|
351
341
|
}
|
|
352
342
|
/** Validates optional args don't follow variadic args */
|
|
353
343
|
assertNoVariadicArgument() {
|
|
354
|
-
if (this.arguments.some((arg) => arg.
|
|
344
|
+
if (this.arguments.some((arg) => arg.variadic)) {
|
|
355
345
|
throw new Error("Cannot add optional argument after variadic argument");
|
|
356
346
|
}
|
|
357
347
|
}
|
|
358
348
|
/** Ensures only one variadic argument per command */
|
|
359
349
|
assertNoMultipleVariadicArguments() {
|
|
360
|
-
if (this.arguments.some((arg) => arg.
|
|
350
|
+
if (this.arguments.some((arg) => arg.variadic)) {
|
|
361
351
|
throw new Error("Cannot add more than one variadic argument");
|
|
362
352
|
}
|
|
363
353
|
}
|
|
@@ -419,13 +409,9 @@ class Command {
|
|
|
419
409
|
findOption(arg) {
|
|
420
410
|
return this.options.find((option) => option.short === arg || option.name === arg);
|
|
421
411
|
}
|
|
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);
|
|
412
|
+
/** Returns a new Command instance. Override this method in subclasses. */
|
|
413
|
+
createCommand(name = "", parent = null) {
|
|
414
|
+
return new Command(name, parent);
|
|
429
415
|
}
|
|
430
416
|
}
|
|
431
417
|
export {
|
package/lib/Help.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { 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.0
|
|
3
|
+
"description": "A type-safe CLI composer that can parse argv and generate help without execution coupling.",
|
|
4
|
+
"version": "1.1.0",
|
|
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",
|