breadc 0.8.9 → 0.9.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 +2 -3
- package/dist/index.cjs +268 -262
- package/dist/index.d.ts +205 -147
- package/dist/index.mjs +269 -260
- package/package.json +18 -8
package/dist/index.cjs
CHANGED
|
@@ -1,94 +1,86 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
-
|
|
5
3
|
const color = require('@breadc/color');
|
|
6
4
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
5
|
+
class BreadcError extends Error {
|
|
6
|
+
}
|
|
7
|
+
class ParseError extends Error {
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
function camelCase(text) {
|
|
11
|
+
return text.split("-").map((t, idx) => idx === 0 ? t : t[0].toUpperCase() + t.slice(1)).join("");
|
|
12
|
+
}
|
|
13
|
+
function twoColumn(texts, split = " ") {
|
|
14
|
+
const left = padRight(texts.map((t) => t[0]));
|
|
15
|
+
return left.map((l, idx) => l + split + texts[idx][1]);
|
|
16
|
+
}
|
|
17
|
+
function padRight(texts, fill = " ") {
|
|
18
|
+
const length = texts.map((t) => t.length).reduce((max, l) => Math.max(max, l), 0);
|
|
19
|
+
return texts.map((t) => t + fill.repeat(length - t.length));
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const OptionRE = /^(-[a-zA-Z], )?--([a-zA-Z0-9\-]+)( <[a-zA-Z0-9\-]+>)?$/;
|
|
23
|
+
function makeOption(format, config = { default: void 0 }) {
|
|
24
|
+
let name = "";
|
|
25
|
+
let short = void 0;
|
|
26
|
+
const match = OptionRE.exec(format);
|
|
27
|
+
if (match) {
|
|
28
|
+
name = match[2];
|
|
29
|
+
if (match[1]) {
|
|
30
|
+
short = match[1][1];
|
|
24
31
|
}
|
|
25
|
-
if (
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
onPostCommand[key] = [];
|
|
32
|
+
if (match[3]) {
|
|
33
|
+
if (name.startsWith("no-")) {
|
|
34
|
+
throw new BreadcError(`Can not parse option format (${format})`);
|
|
29
35
|
}
|
|
30
|
-
|
|
36
|
+
const initial = config.default ?? void 0;
|
|
37
|
+
return {
|
|
38
|
+
format,
|
|
39
|
+
type: "string",
|
|
40
|
+
name,
|
|
41
|
+
short,
|
|
42
|
+
description: config.description ?? "",
|
|
43
|
+
order: 0,
|
|
44
|
+
// @ts-ignore
|
|
45
|
+
initial: config.cast ? config.cast(initial) : initial,
|
|
46
|
+
cast: config.cast
|
|
47
|
+
};
|
|
31
48
|
} else {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
}
|
|
36
|
-
onPostCommand[key].push(fn);
|
|
49
|
+
if (name.startsWith("no-")) {
|
|
50
|
+
name = name.slice(3);
|
|
51
|
+
config.default = true;
|
|
37
52
|
}
|
|
53
|
+
const initial = config.default === void 0 || config.default === null ? false : config.default;
|
|
54
|
+
return {
|
|
55
|
+
format,
|
|
56
|
+
type: "boolean",
|
|
57
|
+
name,
|
|
58
|
+
short,
|
|
59
|
+
description: config.description ?? "",
|
|
60
|
+
order: 0,
|
|
61
|
+
// @ts-ignore
|
|
62
|
+
initial: config.cast ? config.cast(initial) : initial,
|
|
63
|
+
cast: config.cast
|
|
64
|
+
};
|
|
38
65
|
}
|
|
66
|
+
} else {
|
|
67
|
+
throw new BreadcError(`Can not parse option format (${format})`);
|
|
39
68
|
}
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
69
|
+
}
|
|
70
|
+
const initContextOptions = (options, context) => {
|
|
71
|
+
for (const option of options) {
|
|
72
|
+
context.options.set(option.name, option);
|
|
73
|
+
if (option.short) {
|
|
74
|
+
context.options.set(option.short, option);
|
|
44
75
|
}
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
(t, idx) => idx === 0 ? t : t[0].toUpperCase() + t.slice(1)
|
|
48
|
-
).join("");
|
|
49
|
-
const fns = container[key];
|
|
50
|
-
if (fns && fns.length > 0) {
|
|
51
|
-
await Promise.all(fns.map((fn) => fn(result)));
|
|
52
|
-
}
|
|
76
|
+
if (option.type === "boolean") {
|
|
77
|
+
context.options.set("no-" + option.name, option);
|
|
53
78
|
}
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
init(breadc, allCommands, globalOptions) {
|
|
57
|
-
if (plugins.length === 0)
|
|
58
|
-
return;
|
|
59
|
-
for (const p of plugins) {
|
|
60
|
-
p.onInit?.(breadc, allCommands, globalOptions);
|
|
61
|
-
}
|
|
62
|
-
},
|
|
63
|
-
async preRun(breadc) {
|
|
64
|
-
if (plugins.length === 0)
|
|
65
|
-
return;
|
|
66
|
-
for (const p of plugins) {
|
|
67
|
-
await p.onPreRun?.(breadc);
|
|
68
|
-
}
|
|
69
|
-
},
|
|
70
|
-
async preCommand(command, result) {
|
|
71
|
-
if (plugins.length === 0)
|
|
72
|
-
return;
|
|
73
|
-
await run(onPreCommand, command, result);
|
|
74
|
-
},
|
|
75
|
-
async postCommand(command, result) {
|
|
76
|
-
if (plugins.length === 0)
|
|
77
|
-
return;
|
|
78
|
-
await run(onPostCommand, command, result);
|
|
79
|
-
},
|
|
80
|
-
async postRun(breadc) {
|
|
81
|
-
if (plugins.length === 0)
|
|
82
|
-
return;
|
|
83
|
-
for (const p of plugins) {
|
|
84
|
-
await p.onPostRun?.(breadc);
|
|
85
|
-
}
|
|
79
|
+
if (option.initial !== void 0) {
|
|
80
|
+
context.result.options[camelCase(option.name)] = option.initial;
|
|
86
81
|
}
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
function definePlugin(plugin) {
|
|
90
|
-
return plugin;
|
|
91
|
-
}
|
|
82
|
+
}
|
|
83
|
+
};
|
|
92
84
|
|
|
93
85
|
class Token {
|
|
94
86
|
constructor(text) {
|
|
@@ -169,23 +161,6 @@ class Lexer {
|
|
|
169
161
|
}
|
|
170
162
|
}
|
|
171
163
|
|
|
172
|
-
function camelCase(text) {
|
|
173
|
-
return text.split("-").map((t, idx) => idx === 0 ? t : t[0].toUpperCase() + t.slice(1)).join("");
|
|
174
|
-
}
|
|
175
|
-
function twoColumn(texts, split = " ") {
|
|
176
|
-
const left = padRight(texts.map((t) => t[0]));
|
|
177
|
-
return left.map((l, idx) => l + split + texts[idx][1]);
|
|
178
|
-
}
|
|
179
|
-
function padRight(texts, fill = " ") {
|
|
180
|
-
const length = texts.map((t) => t.length).reduce((max, l) => Math.max(max, l), 0);
|
|
181
|
-
return texts.map((t) => t + fill.repeat(length - t.length));
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
class BreadcError extends Error {
|
|
185
|
-
}
|
|
186
|
-
class ParseError extends Error {
|
|
187
|
-
}
|
|
188
|
-
|
|
189
164
|
function makeTreeNode(pnode) {
|
|
190
165
|
const node = {
|
|
191
166
|
children: /* @__PURE__ */ new Map(),
|
|
@@ -203,6 +178,7 @@ function makeTreeNode(pnode) {
|
|
|
203
178
|
}
|
|
204
179
|
},
|
|
205
180
|
finish() {
|
|
181
|
+
return pnode.command?.callback;
|
|
206
182
|
},
|
|
207
183
|
...pnode
|
|
208
184
|
};
|
|
@@ -214,8 +190,8 @@ function parseOption(cursor, token, context) {
|
|
|
214
190
|
if (context.options.has(key)) {
|
|
215
191
|
const option = context.options.get(key);
|
|
216
192
|
const name = camelCase(option.name);
|
|
217
|
-
if (option.
|
|
218
|
-
return option.
|
|
193
|
+
if (option.parse) {
|
|
194
|
+
return option.parse(cursor, token, context);
|
|
219
195
|
} else if (option.type === "boolean") {
|
|
220
196
|
context.result.options[name] = !key.startsWith("no-") ? true : false;
|
|
221
197
|
} else if (option.type === "string") {
|
|
@@ -238,7 +214,15 @@ function parseOption(cursor, token, context) {
|
|
|
238
214
|
context.result.options[name] = option.cast(context.result.options[name]);
|
|
239
215
|
}
|
|
240
216
|
} else {
|
|
241
|
-
|
|
217
|
+
switch (context.config.allowUnknownOption) {
|
|
218
|
+
case "rest":
|
|
219
|
+
context.result["--"].push(token.raw());
|
|
220
|
+
case "skip":
|
|
221
|
+
break;
|
|
222
|
+
case "error":
|
|
223
|
+
default:
|
|
224
|
+
throw new ParseError(`Unknown option ${token.raw()}`);
|
|
225
|
+
}
|
|
242
226
|
}
|
|
243
227
|
return cursor;
|
|
244
228
|
}
|
|
@@ -251,7 +235,12 @@ function parse(root, args) {
|
|
|
251
235
|
arguments: [],
|
|
252
236
|
options: {},
|
|
253
237
|
"--": []
|
|
254
|
-
}
|
|
238
|
+
},
|
|
239
|
+
meta: {},
|
|
240
|
+
config: {
|
|
241
|
+
allowUnknownOption: "error"
|
|
242
|
+
},
|
|
243
|
+
parseOption
|
|
255
244
|
};
|
|
256
245
|
let cursor = root;
|
|
257
246
|
root.init(context);
|
|
@@ -259,7 +248,7 @@ function parse(root, args) {
|
|
|
259
248
|
if (token.type() === "--") {
|
|
260
249
|
break;
|
|
261
250
|
} else if (token.isOption()) {
|
|
262
|
-
const res = parseOption(cursor, token, context);
|
|
251
|
+
const res = context.parseOption(cursor, token, context);
|
|
263
252
|
if (res === false) {
|
|
264
253
|
break;
|
|
265
254
|
} else {
|
|
@@ -276,81 +265,24 @@ function parse(root, args) {
|
|
|
276
265
|
throw new ParseError("unreachable");
|
|
277
266
|
}
|
|
278
267
|
}
|
|
279
|
-
cursor.finish(context);
|
|
268
|
+
const callback = cursor.finish(context);
|
|
280
269
|
for (const token of lexer) {
|
|
281
270
|
context.result["--"].push(token.raw());
|
|
282
271
|
}
|
|
283
272
|
return {
|
|
284
|
-
|
|
273
|
+
callback,
|
|
274
|
+
matched: {
|
|
275
|
+
node: cursor,
|
|
276
|
+
command: cursor.command,
|
|
277
|
+
option: cursor.option
|
|
278
|
+
},
|
|
279
|
+
meta: context.meta,
|
|
285
280
|
arguments: context.result.arguments,
|
|
286
281
|
options: context.result.options,
|
|
287
282
|
"--": context.result["--"]
|
|
288
283
|
};
|
|
289
284
|
}
|
|
290
285
|
|
|
291
|
-
const OptionRE = /^(-[a-zA-Z], )?--([a-zA-Z0-9\-]+)( <[a-zA-Z0-9\-]+>)?$/;
|
|
292
|
-
function makeOption(format, config = {}) {
|
|
293
|
-
let name = "";
|
|
294
|
-
let short = void 0;
|
|
295
|
-
const match = OptionRE.exec(format);
|
|
296
|
-
if (match) {
|
|
297
|
-
name = match[2];
|
|
298
|
-
if (match[1]) {
|
|
299
|
-
short = match[1][1];
|
|
300
|
-
}
|
|
301
|
-
if (match[3]) {
|
|
302
|
-
if (name.startsWith("no-")) {
|
|
303
|
-
throw new BreadcError(`Can not parse option format (${format})`);
|
|
304
|
-
}
|
|
305
|
-
const initial = config.default ?? "";
|
|
306
|
-
return {
|
|
307
|
-
format,
|
|
308
|
-
type: "string",
|
|
309
|
-
name,
|
|
310
|
-
short,
|
|
311
|
-
description: config.description ?? "",
|
|
312
|
-
order: 0,
|
|
313
|
-
// @ts-ignore
|
|
314
|
-
initial: config.cast ? config.cast(initial) : initial,
|
|
315
|
-
cast: config.cast
|
|
316
|
-
};
|
|
317
|
-
} else {
|
|
318
|
-
if (name.startsWith("no-")) {
|
|
319
|
-
name = name.slice(3);
|
|
320
|
-
config.default = true;
|
|
321
|
-
}
|
|
322
|
-
const initial = config.default === void 0 || config.default === null ? false : config.default;
|
|
323
|
-
return {
|
|
324
|
-
format,
|
|
325
|
-
type: "boolean",
|
|
326
|
-
name,
|
|
327
|
-
short,
|
|
328
|
-
description: config.description ?? "",
|
|
329
|
-
order: 0,
|
|
330
|
-
// @ts-ignore
|
|
331
|
-
initial: config.cast ? config.cast(initial) : initial,
|
|
332
|
-
cast: config.cast
|
|
333
|
-
};
|
|
334
|
-
}
|
|
335
|
-
} else {
|
|
336
|
-
throw new BreadcError(`Can not parse option format (${format})`);
|
|
337
|
-
}
|
|
338
|
-
}
|
|
339
|
-
const initContextOptions = (options, context) => {
|
|
340
|
-
for (const option of options) {
|
|
341
|
-
context.options.set(option.name, option);
|
|
342
|
-
if (option.short) {
|
|
343
|
-
context.options.set(option.short, option);
|
|
344
|
-
}
|
|
345
|
-
if (option.type === "boolean") {
|
|
346
|
-
context.options.set("no-" + option.name, option);
|
|
347
|
-
}
|
|
348
|
-
if (option.initial !== void 0) {
|
|
349
|
-
context.result.options[camelCase(option.name)] = option.initial;
|
|
350
|
-
}
|
|
351
|
-
}
|
|
352
|
-
};
|
|
353
|
-
|
|
354
286
|
function makeCommand(format, config, root, container) {
|
|
355
287
|
const args = [];
|
|
356
288
|
const options = [];
|
|
@@ -401,6 +333,7 @@ function makeCommand(format, config, root, container) {
|
|
|
401
333
|
return makeTreeNode({
|
|
402
334
|
command,
|
|
403
335
|
init(context) {
|
|
336
|
+
context.config.allowUnknownOption = config.allowUnknownOption ?? "error";
|
|
404
337
|
initContextOptions(options, context);
|
|
405
338
|
},
|
|
406
339
|
finish(context) {
|
|
@@ -424,6 +357,7 @@ function makeCommand(format, config, root, container) {
|
|
|
424
357
|
}
|
|
425
358
|
}
|
|
426
359
|
context.result["--"] = rest.splice(args2.length);
|
|
360
|
+
return command.callback;
|
|
427
361
|
}
|
|
428
362
|
});
|
|
429
363
|
}
|
|
@@ -520,28 +454,110 @@ function* parseCommandFormat(format) {
|
|
|
520
454
|
}
|
|
521
455
|
return void 0;
|
|
522
456
|
}
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
457
|
+
|
|
458
|
+
function makePluginContainer(plugins = []) {
|
|
459
|
+
const onPreCommand = {};
|
|
460
|
+
const onPostCommand = {};
|
|
461
|
+
for (const plugin of plugins) {
|
|
462
|
+
if (typeof plugin.onPreCommand === "function") {
|
|
463
|
+
const key = "*";
|
|
464
|
+
if (!(key in onPreCommand)) {
|
|
465
|
+
onPreCommand[key] = [];
|
|
466
|
+
}
|
|
467
|
+
onPreCommand[key].push(plugin.onPreCommand);
|
|
468
|
+
} else {
|
|
469
|
+
for (const [key, fn] of Object.entries(plugin.onPreCommand ?? {})) {
|
|
470
|
+
if (!(key in onPreCommand)) {
|
|
471
|
+
onPreCommand[key] = [];
|
|
472
|
+
}
|
|
473
|
+
onPreCommand[key].push(fn);
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
if (typeof plugin.onPostCommand === "function") {
|
|
477
|
+
const key = "*";
|
|
478
|
+
if (!(key in onPostCommand)) {
|
|
479
|
+
onPostCommand[key] = [];
|
|
480
|
+
}
|
|
481
|
+
onPostCommand[key].push(plugin.onPostCommand);
|
|
482
|
+
} else {
|
|
483
|
+
for (const [key, fn] of Object.entries(plugin.onPostCommand ?? {})) {
|
|
484
|
+
if (!(key in onPostCommand)) {
|
|
485
|
+
onPostCommand[key] = [];
|
|
486
|
+
}
|
|
487
|
+
onPostCommand[key].push(fn);
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
const run = async (container, command, result) => {
|
|
492
|
+
const prefix = command._arguments.filter((a) => a.type === "const").map((a) => a.name);
|
|
493
|
+
if (prefix.length === 0) {
|
|
494
|
+
prefix.push("_");
|
|
495
|
+
}
|
|
496
|
+
for (let i = 0; i <= prefix.length; i++) {
|
|
497
|
+
const key = i === 0 ? "*" : prefix.slice(0, i).map(
|
|
498
|
+
(t, idx) => idx === 0 ? t : t[0].toUpperCase() + t.slice(1)
|
|
499
|
+
).join("");
|
|
500
|
+
const fns = container[key];
|
|
501
|
+
if (fns && fns.length > 0) {
|
|
502
|
+
await Promise.all(fns.map((fn) => fn(result)));
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
};
|
|
506
|
+
return {
|
|
507
|
+
init(breadc, allCommands, globalOptions) {
|
|
508
|
+
if (plugins.length === 0)
|
|
509
|
+
return;
|
|
510
|
+
for (const p of plugins) {
|
|
511
|
+
p.onInit?.(breadc, allCommands, globalOptions);
|
|
512
|
+
}
|
|
529
513
|
},
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
514
|
+
async preRun(breadc) {
|
|
515
|
+
if (plugins.length === 0)
|
|
516
|
+
return;
|
|
517
|
+
for (const p of plugins) {
|
|
518
|
+
await p.onPreRun?.(breadc);
|
|
519
|
+
}
|
|
520
|
+
},
|
|
521
|
+
async preCommand(command, result) {
|
|
522
|
+
if (plugins.length === 0)
|
|
523
|
+
return;
|
|
524
|
+
await run(onPreCommand, command, result);
|
|
525
|
+
},
|
|
526
|
+
async postCommand(command, result) {
|
|
527
|
+
if (plugins.length === 0)
|
|
528
|
+
return;
|
|
529
|
+
await run(onPostCommand, command, result);
|
|
530
|
+
},
|
|
531
|
+
async postRun(breadc) {
|
|
532
|
+
if (plugins.length === 0)
|
|
533
|
+
return;
|
|
534
|
+
for (const p of plugins) {
|
|
535
|
+
await p.onPostRun?.(breadc);
|
|
536
|
+
}
|
|
537
|
+
}
|
|
540
538
|
};
|
|
539
|
+
}
|
|
540
|
+
function definePlugin(plugin) {
|
|
541
|
+
return plugin;
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
function makeVersionCommand(name, config) {
|
|
545
|
+
let description = "Print version";
|
|
546
|
+
if (typeof config.builtin?.version === "object") {
|
|
547
|
+
if (config.builtin.version.description) {
|
|
548
|
+
description = config.builtin.version.description;
|
|
549
|
+
}
|
|
550
|
+
}
|
|
541
551
|
const node = makeTreeNode({
|
|
542
|
-
command,
|
|
543
552
|
next() {
|
|
544
553
|
return false;
|
|
554
|
+
},
|
|
555
|
+
finish() {
|
|
556
|
+
return () => {
|
|
557
|
+
const text = typeof config.builtin?.version === "object" && config.builtin.version.content ? config.builtin.version.content : `${name}/${config.version ? config.version : "unknown"}`;
|
|
558
|
+
console.log(text);
|
|
559
|
+
return text;
|
|
560
|
+
};
|
|
545
561
|
}
|
|
546
562
|
});
|
|
547
563
|
const option = {
|
|
@@ -551,8 +567,8 @@ function makeVersionCommand(name, config) {
|
|
|
551
567
|
type: "boolean",
|
|
552
568
|
initial: void 0,
|
|
553
569
|
order: 999999999 + 1,
|
|
554
|
-
description
|
|
555
|
-
|
|
570
|
+
description,
|
|
571
|
+
parse() {
|
|
556
572
|
return node;
|
|
557
573
|
}
|
|
558
574
|
};
|
|
@@ -605,64 +621,58 @@ function makeHelpCommand(name, config, allCommands) {
|
|
|
605
621
|
}
|
|
606
622
|
return [...alias.values()];
|
|
607
623
|
}
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
`${name}/${config.version ? config.version : "unknown"}`,
|
|
615
|
-
() => {
|
|
616
|
-
if (config.description) {
|
|
617
|
-
return ["", config.description];
|
|
618
|
-
} else {
|
|
619
|
-
return void 0;
|
|
620
|
-
}
|
|
621
|
-
},
|
|
622
|
-
"",
|
|
623
|
-
`${color.bold(color.underline("Usage:"))} ${color.bold(name)} ${usage}`,
|
|
624
|
-
() => {
|
|
625
|
-
const cmds = expandCommands(cursor);
|
|
626
|
-
if (cmds.length > 0) {
|
|
627
|
-
return [
|
|
628
|
-
"",
|
|
629
|
-
color.bold(color.underline("Commands:")),
|
|
630
|
-
cmds.map((cmd) => [
|
|
631
|
-
` ${color.bold(name)} ${color.bold(cmd.format)}`,
|
|
632
|
-
cmd.description
|
|
633
|
-
])
|
|
634
|
-
];
|
|
635
|
-
} else {
|
|
636
|
-
return void 0;
|
|
637
|
-
}
|
|
638
|
-
},
|
|
639
|
-
"",
|
|
640
|
-
color.bold(color.underline("Options:")),
|
|
641
|
-
[...context.options.entries()].filter(([key, op]) => key === op.name).sort((lhs, rhs) => lhs[1].order - rhs[1].order).map(([_key, op]) => [
|
|
642
|
-
" " + (!op.short ? " " : "") + color.bold(op.format),
|
|
643
|
-
op.description
|
|
644
|
-
]),
|
|
645
|
-
""
|
|
646
|
-
];
|
|
647
|
-
const text = expandMessage(output).join("\n");
|
|
648
|
-
console.log(text);
|
|
649
|
-
return text;
|
|
650
|
-
},
|
|
651
|
-
format: "-h, --help",
|
|
652
|
-
description: "Print help",
|
|
653
|
-
_arguments: [],
|
|
654
|
-
_options: [],
|
|
655
|
-
// @ts-ignore
|
|
656
|
-
option: void 0,
|
|
657
|
-
// @ts-ignore
|
|
658
|
-
alias: void 0,
|
|
659
|
-
// @ts-ignore
|
|
660
|
-
action: void 0
|
|
661
|
-
};
|
|
624
|
+
let description = "Print help";
|
|
625
|
+
if (typeof config.builtin?.help === "object") {
|
|
626
|
+
if (config.builtin.help.description) {
|
|
627
|
+
description = config.builtin.help.description;
|
|
628
|
+
}
|
|
629
|
+
}
|
|
662
630
|
const node = makeTreeNode({
|
|
663
|
-
command,
|
|
664
631
|
next() {
|
|
665
632
|
return false;
|
|
633
|
+
},
|
|
634
|
+
finish(context) {
|
|
635
|
+
return () => {
|
|
636
|
+
const cursor = context.meta.__cursor__;
|
|
637
|
+
const usage = allCommands.length === 0 ? `[OPTIONS]` : allCommands.length === 1 ? `[OPTIONS] ${allCommands[0].format}` : allCommands.some((c) => c._default) ? `[OPTIONS] [COMMAND]` : `[OPTIONS] <COMMAND>`;
|
|
638
|
+
const output = [
|
|
639
|
+
`${name}/${config.version ? config.version : "unknown"}`,
|
|
640
|
+
() => {
|
|
641
|
+
if (config.description) {
|
|
642
|
+
return ["", config.description];
|
|
643
|
+
} else {
|
|
644
|
+
return void 0;
|
|
645
|
+
}
|
|
646
|
+
},
|
|
647
|
+
"",
|
|
648
|
+
`${color.bold(color.underline("Usage:"))} ${color.bold(name)} ${usage}`,
|
|
649
|
+
() => {
|
|
650
|
+
const cmds = expandCommands(cursor);
|
|
651
|
+
if (cmds.length > 0) {
|
|
652
|
+
return [
|
|
653
|
+
"",
|
|
654
|
+
color.bold(color.underline("Commands:")),
|
|
655
|
+
cmds.map((cmd) => [
|
|
656
|
+
` ${color.bold(name)} ${color.bold(cmd.format)}`,
|
|
657
|
+
cmd.description
|
|
658
|
+
])
|
|
659
|
+
];
|
|
660
|
+
} else {
|
|
661
|
+
return void 0;
|
|
662
|
+
}
|
|
663
|
+
},
|
|
664
|
+
"",
|
|
665
|
+
color.bold(color.underline("Options:")),
|
|
666
|
+
[...context.options.entries()].filter(([key, op]) => key === op.name).sort((lhs, rhs) => lhs[1].order - rhs[1].order).map(([_key, op]) => [
|
|
667
|
+
" " + (!op.short ? " " : "") + color.bold(op.format),
|
|
668
|
+
op.description
|
|
669
|
+
]),
|
|
670
|
+
""
|
|
671
|
+
];
|
|
672
|
+
const text = expandMessage(output).join("\n");
|
|
673
|
+
console.log(text);
|
|
674
|
+
return text;
|
|
675
|
+
};
|
|
666
676
|
}
|
|
667
677
|
});
|
|
668
678
|
const option = {
|
|
@@ -671,11 +681,10 @@ function makeHelpCommand(name, config, allCommands) {
|
|
|
671
681
|
short: "h",
|
|
672
682
|
type: "boolean",
|
|
673
683
|
initial: void 0,
|
|
674
|
-
description
|
|
684
|
+
description,
|
|
675
685
|
order: 999999999,
|
|
676
|
-
|
|
677
|
-
context.
|
|
678
|
-
context.result.options.__context__ = context;
|
|
686
|
+
parse(cursor, _token, context) {
|
|
687
|
+
context.meta.__cursor__ = cursor;
|
|
679
688
|
return node;
|
|
680
689
|
}
|
|
681
690
|
};
|
|
@@ -685,10 +694,13 @@ function makeHelpCommand(name, config, allCommands) {
|
|
|
685
694
|
function breadc(name, config = {}) {
|
|
686
695
|
let defaultCommand = void 0;
|
|
687
696
|
const allCommands = [];
|
|
688
|
-
const globalOptions = [
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
697
|
+
const globalOptions = [];
|
|
698
|
+
if (config.builtin?.help !== false) {
|
|
699
|
+
globalOptions.push(makeHelpCommand(name, config, allCommands));
|
|
700
|
+
}
|
|
701
|
+
if (config.builtin?.version !== false) {
|
|
702
|
+
globalOptions.push(makeVersionCommand(name, config));
|
|
703
|
+
}
|
|
692
704
|
const container = makePluginContainer(config.plugins);
|
|
693
705
|
const root = makeTreeNode({
|
|
694
706
|
init(context) {
|
|
@@ -696,8 +708,6 @@ function breadc(name, config = {}) {
|
|
|
696
708
|
if (defaultCommand) {
|
|
697
709
|
initContextOptions(defaultCommand._options, context);
|
|
698
710
|
}
|
|
699
|
-
},
|
|
700
|
-
finish() {
|
|
701
711
|
}
|
|
702
712
|
});
|
|
703
713
|
const breadc2 = {
|
|
@@ -709,8 +719,8 @@ function breadc(name, config = {}) {
|
|
|
709
719
|
globalOptions.push(option);
|
|
710
720
|
return breadc2;
|
|
711
721
|
},
|
|
712
|
-
command(text, _config = {}) {
|
|
713
|
-
const config2 = typeof _config === "string" ? { description: _config } : _config;
|
|
722
|
+
command(text, _config = {}, _config2 = {}) {
|
|
723
|
+
const config2 = typeof _config === "string" ? { description: _config, ..._config2 } : _config;
|
|
714
724
|
const command = makeCommand(text, config2, root, container);
|
|
715
725
|
if (command._default) {
|
|
716
726
|
defaultCommand = command;
|
|
@@ -719,19 +729,16 @@ function breadc(name, config = {}) {
|
|
|
719
729
|
return command;
|
|
720
730
|
},
|
|
721
731
|
parse(args) {
|
|
722
|
-
|
|
723
|
-
return result;
|
|
732
|
+
return parse(root, args);
|
|
724
733
|
},
|
|
725
734
|
async run(args) {
|
|
726
735
|
const result = breadc2.parse(args);
|
|
727
|
-
const
|
|
728
|
-
if (
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
return r;
|
|
734
|
-
}
|
|
736
|
+
const callback = result.callback;
|
|
737
|
+
if (callback) {
|
|
738
|
+
await container.preRun(breadc2);
|
|
739
|
+
const r = await callback(result);
|
|
740
|
+
await container.postRun(breadc2);
|
|
741
|
+
return r;
|
|
735
742
|
}
|
|
736
743
|
return void 0;
|
|
737
744
|
}
|
|
@@ -743,6 +750,5 @@ function breadc(name, config = {}) {
|
|
|
743
750
|
exports.BreadcError = BreadcError;
|
|
744
751
|
exports.ParseError = ParseError;
|
|
745
752
|
exports.breadc = breadc;
|
|
746
|
-
exports.default = breadc;
|
|
747
753
|
exports.definePlugin = definePlugin;
|
|
748
754
|
exports.makeTreeNode = makeTreeNode;
|