breadc 0.8.8 → 0.9.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 +2 -3
- package/dist/index.cjs +275 -263
- package/dist/index.d.ts +205 -147
- package/dist/index.mjs +276 -261
- package/package.json +15 -5
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
|
};
|
|
@@ -597,66 +613,66 @@ function makeHelpCommand(name, config, allCommands) {
|
|
|
597
613
|
}
|
|
598
614
|
}
|
|
599
615
|
}
|
|
600
|
-
|
|
616
|
+
const alias = /* @__PURE__ */ new Map();
|
|
617
|
+
for (const cmd of commands) {
|
|
618
|
+
if (!alias.has(cmd.format)) {
|
|
619
|
+
alias.set(cmd.format, cmd);
|
|
620
|
+
}
|
|
621
|
+
}
|
|
622
|
+
return [...alias.values()];
|
|
623
|
+
}
|
|
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
|
+
}
|
|
601
629
|
}
|
|
602
|
-
const command = {
|
|
603
|
-
async callback(parsed) {
|
|
604
|
-
const context = parsed.options.__context__;
|
|
605
|
-
const cursor = parsed.options.__cursor__;
|
|
606
|
-
const usage = allCommands.length === 0 ? `[OPTIONS]` : allCommands.length === 1 ? `[OPTIONS] ${allCommands[0].format}` : allCommands.some((c) => c._default) ? `[OPTIONS] [COMMAND]` : `[OPTIONS] <COMMAND>`;
|
|
607
|
-
const output = [
|
|
608
|
-
`${name}/${config.version ? config.version : "unknown"}`,
|
|
609
|
-
() => {
|
|
610
|
-
if (config.description) {
|
|
611
|
-
return ["", config.description];
|
|
612
|
-
} else {
|
|
613
|
-
return void 0;
|
|
614
|
-
}
|
|
615
|
-
},
|
|
616
|
-
"",
|
|
617
|
-
`${color.bold(color.underline("Usage:"))} ${color.bold(name)} ${usage}`,
|
|
618
|
-
() => {
|
|
619
|
-
const cmds = expandCommands(cursor);
|
|
620
|
-
if (cmds.length > 0) {
|
|
621
|
-
return [
|
|
622
|
-
"",
|
|
623
|
-
color.bold(color.underline("Commands:")),
|
|
624
|
-
cmds.map((cmd) => [
|
|
625
|
-
` ${color.bold(name)} ${color.bold(cmd.format)}`,
|
|
626
|
-
cmd.description
|
|
627
|
-
])
|
|
628
|
-
];
|
|
629
|
-
} else {
|
|
630
|
-
return void 0;
|
|
631
|
-
}
|
|
632
|
-
},
|
|
633
|
-
"",
|
|
634
|
-
color.bold(color.underline("Options:")),
|
|
635
|
-
[...context.options.entries()].filter(([key, op]) => key === op.name).sort((lhs, rhs) => lhs[1].order - rhs[1].order).map(([_key, op]) => [
|
|
636
|
-
" " + (!op.short ? " " : "") + color.bold(op.format),
|
|
637
|
-
op.description
|
|
638
|
-
]),
|
|
639
|
-
""
|
|
640
|
-
];
|
|
641
|
-
const text = expandMessage(output).join("\n");
|
|
642
|
-
console.log(text);
|
|
643
|
-
return text;
|
|
644
|
-
},
|
|
645
|
-
format: "-h, --help",
|
|
646
|
-
description: "Print help",
|
|
647
|
-
_arguments: [],
|
|
648
|
-
_options: [],
|
|
649
|
-
// @ts-ignore
|
|
650
|
-
option: void 0,
|
|
651
|
-
// @ts-ignore
|
|
652
|
-
alias: void 0,
|
|
653
|
-
// @ts-ignore
|
|
654
|
-
action: void 0
|
|
655
|
-
};
|
|
656
630
|
const node = makeTreeNode({
|
|
657
|
-
command,
|
|
658
631
|
next() {
|
|
659
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
|
+
};
|
|
660
676
|
}
|
|
661
677
|
});
|
|
662
678
|
const option = {
|
|
@@ -665,11 +681,10 @@ function makeHelpCommand(name, config, allCommands) {
|
|
|
665
681
|
short: "h",
|
|
666
682
|
type: "boolean",
|
|
667
683
|
initial: void 0,
|
|
668
|
-
description
|
|
684
|
+
description,
|
|
669
685
|
order: 999999999,
|
|
670
|
-
|
|
671
|
-
context.
|
|
672
|
-
context.result.options.__context__ = context;
|
|
686
|
+
parse(cursor, _token, context) {
|
|
687
|
+
context.meta.__cursor__ = cursor;
|
|
673
688
|
return node;
|
|
674
689
|
}
|
|
675
690
|
};
|
|
@@ -679,10 +694,13 @@ function makeHelpCommand(name, config, allCommands) {
|
|
|
679
694
|
function breadc(name, config = {}) {
|
|
680
695
|
let defaultCommand = void 0;
|
|
681
696
|
const allCommands = [];
|
|
682
|
-
const globalOptions = [
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
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
|
+
}
|
|
686
704
|
const container = makePluginContainer(config.plugins);
|
|
687
705
|
const root = makeTreeNode({
|
|
688
706
|
init(context) {
|
|
@@ -690,8 +708,6 @@ function breadc(name, config = {}) {
|
|
|
690
708
|
if (defaultCommand) {
|
|
691
709
|
initContextOptions(defaultCommand._options, context);
|
|
692
710
|
}
|
|
693
|
-
},
|
|
694
|
-
finish() {
|
|
695
711
|
}
|
|
696
712
|
});
|
|
697
713
|
const breadc2 = {
|
|
@@ -703,8 +719,8 @@ function breadc(name, config = {}) {
|
|
|
703
719
|
globalOptions.push(option);
|
|
704
720
|
return breadc2;
|
|
705
721
|
},
|
|
706
|
-
command(text, _config = {}) {
|
|
707
|
-
const config2 = typeof _config === "string" ? { description: _config } : _config;
|
|
722
|
+
command(text, _config = {}, _config2 = {}) {
|
|
723
|
+
const config2 = typeof _config === "string" ? { description: _config, ..._config2 } : _config;
|
|
708
724
|
const command = makeCommand(text, config2, root, container);
|
|
709
725
|
if (command._default) {
|
|
710
726
|
defaultCommand = command;
|
|
@@ -713,19 +729,16 @@ function breadc(name, config = {}) {
|
|
|
713
729
|
return command;
|
|
714
730
|
},
|
|
715
731
|
parse(args) {
|
|
716
|
-
|
|
717
|
-
return result;
|
|
732
|
+
return parse(root, args);
|
|
718
733
|
},
|
|
719
734
|
async run(args) {
|
|
720
735
|
const result = breadc2.parse(args);
|
|
721
|
-
const
|
|
722
|
-
if (
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
return r;
|
|
728
|
-
}
|
|
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;
|
|
729
742
|
}
|
|
730
743
|
return void 0;
|
|
731
744
|
}
|
|
@@ -737,6 +750,5 @@ function breadc(name, config = {}) {
|
|
|
737
750
|
exports.BreadcError = BreadcError;
|
|
738
751
|
exports.ParseError = ParseError;
|
|
739
752
|
exports.breadc = breadc;
|
|
740
|
-
exports.default = breadc;
|
|
741
753
|
exports.definePlugin = definePlugin;
|
|
742
754
|
exports.makeTreeNode = makeTreeNode;
|