breadc 0.1.1 → 0.4.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 +18 -13
- package/dist/index.cjs +453 -63
- package/dist/index.d.ts +298 -35
- package/dist/index.mjs +453 -62
- package/package.json +7 -9
package/dist/index.cjs
CHANGED
|
@@ -3,38 +3,289 @@
|
|
|
3
3
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
4
|
|
|
5
5
|
const kolorist = require('kolorist');
|
|
6
|
-
const minimist = require('minimist');
|
|
7
|
-
const createDebug = require('debug');
|
|
8
6
|
|
|
9
7
|
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e["default"] : e; }
|
|
10
8
|
|
|
11
9
|
const kolorist__default = /*#__PURE__*/_interopDefaultLegacy(kolorist);
|
|
12
|
-
const minimist__default = /*#__PURE__*/_interopDefaultLegacy(minimist);
|
|
13
|
-
const createDebug__default = /*#__PURE__*/_interopDefaultLegacy(createDebug);
|
|
14
10
|
|
|
15
|
-
function
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
11
|
+
var minimist = function (args, opts) {
|
|
12
|
+
if (!opts) opts = {};
|
|
13
|
+
|
|
14
|
+
var flags = { bools : {}, strings : {}, unknownFn: null };
|
|
15
|
+
|
|
16
|
+
if (typeof opts['unknown'] === 'function') {
|
|
17
|
+
flags.unknownFn = opts['unknown'];
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
if (typeof opts['boolean'] === 'boolean' && opts['boolean']) {
|
|
21
|
+
flags.allBools = true;
|
|
22
|
+
} else {
|
|
23
|
+
[].concat(opts['boolean']).filter(Boolean).forEach(function (key) {
|
|
24
|
+
flags.bools[key] = true;
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
var aliases = {};
|
|
29
|
+
Object.keys(opts.alias || {}).forEach(function (key) {
|
|
30
|
+
aliases[key] = [].concat(opts.alias[key]);
|
|
31
|
+
aliases[key].forEach(function (x) {
|
|
32
|
+
aliases[x] = [key].concat(aliases[key].filter(function (y) {
|
|
33
|
+
return x !== y;
|
|
34
|
+
}));
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
[].concat(opts.string).filter(Boolean).forEach(function (key) {
|
|
39
|
+
flags.strings[key] = true;
|
|
40
|
+
if (aliases[key]) {
|
|
41
|
+
flags.strings[aliases[key]] = true;
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
var defaults = opts['default'] || {};
|
|
46
|
+
|
|
47
|
+
var argv = { _ : [] };
|
|
48
|
+
Object.keys(flags.bools).forEach(function (key) {
|
|
49
|
+
setArg(key, defaults[key] === undefined ? false : defaults[key]);
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
var notFlags = [];
|
|
53
|
+
|
|
54
|
+
if (args.indexOf('--') !== -1) {
|
|
55
|
+
notFlags = args.slice(args.indexOf('--')+1);
|
|
56
|
+
args = args.slice(0, args.indexOf('--'));
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function argDefined(key, arg) {
|
|
60
|
+
return (flags.allBools && /^--[^=]+$/.test(arg)) ||
|
|
61
|
+
flags.strings[key] || flags.bools[key] || aliases[key];
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function setArg (key, val, arg) {
|
|
65
|
+
if (arg && flags.unknownFn && !argDefined(key, arg)) {
|
|
66
|
+
if (flags.unknownFn(arg) === false) return;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
var value = !flags.strings[key] && isNumber(val)
|
|
70
|
+
? Number(val) : val
|
|
71
|
+
;
|
|
72
|
+
setKey(argv, key.split('.'), value);
|
|
73
|
+
|
|
74
|
+
(aliases[key] || []).forEach(function (x) {
|
|
75
|
+
setKey(argv, x.split('.'), value);
|
|
76
|
+
});
|
|
32
77
|
}
|
|
78
|
+
|
|
79
|
+
function setKey (obj, keys, value) {
|
|
80
|
+
var o = obj;
|
|
81
|
+
for (var i = 0; i < keys.length-1; i++) {
|
|
82
|
+
var key = keys[i];
|
|
83
|
+
if (isConstructorOrProto(o, key)) return;
|
|
84
|
+
if (o[key] === undefined) o[key] = {};
|
|
85
|
+
if (o[key] === Object.prototype || o[key] === Number.prototype
|
|
86
|
+
|| o[key] === String.prototype) o[key] = {};
|
|
87
|
+
if (o[key] === Array.prototype) o[key] = [];
|
|
88
|
+
o = o[key];
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
var key = keys[keys.length - 1];
|
|
92
|
+
if (isConstructorOrProto(o, key)) return;
|
|
93
|
+
if (o === Object.prototype || o === Number.prototype
|
|
94
|
+
|| o === String.prototype) o = {};
|
|
95
|
+
if (o === Array.prototype) o = [];
|
|
96
|
+
if (o[key] === undefined || flags.bools[key] || typeof o[key] === 'boolean') {
|
|
97
|
+
o[key] = value;
|
|
98
|
+
}
|
|
99
|
+
else if (Array.isArray(o[key])) {
|
|
100
|
+
o[key].push(value);
|
|
101
|
+
}
|
|
102
|
+
else {
|
|
103
|
+
o[key] = [ o[key], value ];
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
function aliasIsBoolean(key) {
|
|
108
|
+
return aliases[key].some(function (x) {
|
|
109
|
+
return flags.bools[x];
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
for (var i = 0; i < args.length; i++) {
|
|
114
|
+
var arg = args[i];
|
|
115
|
+
|
|
116
|
+
if (/^--.+=/.test(arg)) {
|
|
117
|
+
// Using [\s\S] instead of . because js doesn't support the
|
|
118
|
+
// 'dotall' regex modifier. See:
|
|
119
|
+
// http://stackoverflow.com/a/1068308/13216
|
|
120
|
+
var m = arg.match(/^--([^=]+)=([\s\S]*)$/);
|
|
121
|
+
var key = m[1];
|
|
122
|
+
var value = m[2];
|
|
123
|
+
if (flags.bools[key]) {
|
|
124
|
+
value = value !== 'false';
|
|
125
|
+
}
|
|
126
|
+
setArg(key, value, arg);
|
|
127
|
+
}
|
|
128
|
+
else if (/^--no-.+/.test(arg)) {
|
|
129
|
+
var key = arg.match(/^--no-(.+)/)[1];
|
|
130
|
+
setArg(key, false, arg);
|
|
131
|
+
}
|
|
132
|
+
else if (/^--.+/.test(arg)) {
|
|
133
|
+
var key = arg.match(/^--(.+)/)[1];
|
|
134
|
+
var next = args[i + 1];
|
|
135
|
+
if (next !== undefined && !/^-/.test(next)
|
|
136
|
+
&& !flags.bools[key]
|
|
137
|
+
&& !flags.allBools
|
|
138
|
+
&& (aliases[key] ? !aliasIsBoolean(key) : true)) {
|
|
139
|
+
setArg(key, next, arg);
|
|
140
|
+
i++;
|
|
141
|
+
}
|
|
142
|
+
else if (/^(true|false)$/.test(next)) {
|
|
143
|
+
setArg(key, next === 'true', arg);
|
|
144
|
+
i++;
|
|
145
|
+
}
|
|
146
|
+
else {
|
|
147
|
+
setArg(key, flags.strings[key] ? '' : true, arg);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
else if (/^-[^-]+/.test(arg)) {
|
|
151
|
+
var letters = arg.slice(1,-1).split('');
|
|
152
|
+
|
|
153
|
+
var broken = false;
|
|
154
|
+
for (var j = 0; j < letters.length; j++) {
|
|
155
|
+
var next = arg.slice(j+2);
|
|
156
|
+
|
|
157
|
+
if (next === '-') {
|
|
158
|
+
setArg(letters[j], next, arg);
|
|
159
|
+
continue;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
if (/[A-Za-z]/.test(letters[j]) && /=/.test(next)) {
|
|
163
|
+
setArg(letters[j], next.split('=')[1], arg);
|
|
164
|
+
broken = true;
|
|
165
|
+
break;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
if (/[A-Za-z]/.test(letters[j])
|
|
169
|
+
&& /-?\d+(\.\d*)?(e-?\d+)?$/.test(next)) {
|
|
170
|
+
setArg(letters[j], next, arg);
|
|
171
|
+
broken = true;
|
|
172
|
+
break;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
if (letters[j+1] && letters[j+1].match(/\W/)) {
|
|
176
|
+
setArg(letters[j], arg.slice(j+2), arg);
|
|
177
|
+
broken = true;
|
|
178
|
+
break;
|
|
179
|
+
}
|
|
180
|
+
else {
|
|
181
|
+
setArg(letters[j], flags.strings[letters[j]] ? '' : true, arg);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
var key = arg.slice(-1)[0];
|
|
186
|
+
if (!broken && key !== '-') {
|
|
187
|
+
if (args[i+1] && !/^(-|--)[^-]/.test(args[i+1])
|
|
188
|
+
&& !flags.bools[key]
|
|
189
|
+
&& (aliases[key] ? !aliasIsBoolean(key) : true)) {
|
|
190
|
+
setArg(key, args[i+1], arg);
|
|
191
|
+
i++;
|
|
192
|
+
}
|
|
193
|
+
else if (args[i+1] && /^(true|false)$/.test(args[i+1])) {
|
|
194
|
+
setArg(key, args[i+1] === 'true', arg);
|
|
195
|
+
i++;
|
|
196
|
+
}
|
|
197
|
+
else {
|
|
198
|
+
setArg(key, flags.strings[key] ? '' : true, arg);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
else {
|
|
203
|
+
if (!flags.unknownFn || flags.unknownFn(arg) !== false) {
|
|
204
|
+
argv._.push(
|
|
205
|
+
flags.strings['_'] || !isNumber(arg) ? arg : Number(arg)
|
|
206
|
+
);
|
|
207
|
+
}
|
|
208
|
+
if (opts.stopEarly) {
|
|
209
|
+
argv._.push.apply(argv._, args.slice(i + 1));
|
|
210
|
+
break;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
Object.keys(defaults).forEach(function (key) {
|
|
216
|
+
if (!hasKey(argv, key.split('.'))) {
|
|
217
|
+
setKey(argv, key.split('.'), defaults[key]);
|
|
218
|
+
|
|
219
|
+
(aliases[key] || []).forEach(function (x) {
|
|
220
|
+
setKey(argv, x.split('.'), defaults[key]);
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
if (opts['--']) {
|
|
226
|
+
argv['--'] = new Array();
|
|
227
|
+
notFlags.forEach(function(key) {
|
|
228
|
+
argv['--'].push(key);
|
|
229
|
+
});
|
|
230
|
+
}
|
|
231
|
+
else {
|
|
232
|
+
notFlags.forEach(function(key) {
|
|
233
|
+
argv._.push(key);
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
return argv;
|
|
238
|
+
};
|
|
239
|
+
|
|
240
|
+
function hasKey (obj, keys) {
|
|
241
|
+
var o = obj;
|
|
242
|
+
keys.slice(0,-1).forEach(function (key) {
|
|
243
|
+
o = (o[key] || {});
|
|
244
|
+
});
|
|
245
|
+
|
|
246
|
+
var key = keys[keys.length - 1];
|
|
247
|
+
return key in o;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
function isNumber (x) {
|
|
251
|
+
if (typeof x === 'number') return true;
|
|
252
|
+
if (/^0x[0-9a-f]+$/i.test(x)) return true;
|
|
253
|
+
return /^[-+]?(?:\d+(?:\.\d*)?|\.\d+)(e[-+]?\d+)?$/.test(x);
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
|
|
257
|
+
function isConstructorOrProto (obj, key) {
|
|
258
|
+
return key === 'constructor' && typeof obj[key] === 'function' || key === '__proto__';
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
function createDefaultLogger(name, logger) {
|
|
262
|
+
const println = !!logger && typeof logger === "function" ? logger : logger?.println ?? ((message, ...args) => {
|
|
263
|
+
console.log(message, ...args);
|
|
264
|
+
});
|
|
265
|
+
const info = typeof logger === "object" && logger?.info ? logger.info : (message, ...args) => {
|
|
266
|
+
println(`${kolorist.blue("INFO")} ${message}`, ...args);
|
|
267
|
+
};
|
|
268
|
+
const warn = typeof logger === "object" && logger?.warn ? logger.warn : (message, ...args) => {
|
|
269
|
+
println(`${kolorist.yellow("WARN")} ${message}`, ...args);
|
|
270
|
+
};
|
|
271
|
+
const error = typeof logger === "object" && logger?.error ? logger.error : (message, ...args) => {
|
|
272
|
+
println(`${kolorist.red("ERROR")} ${message}`, ...args);
|
|
273
|
+
};
|
|
274
|
+
const debug = typeof logger === "object" && logger?.debug ? logger.debug : (message, ...args) => {
|
|
275
|
+
println(`${kolorist.gray(name)} ${message}`, ...args);
|
|
276
|
+
};
|
|
277
|
+
return {
|
|
278
|
+
println,
|
|
279
|
+
info,
|
|
280
|
+
warn,
|
|
281
|
+
error,
|
|
282
|
+
debug
|
|
33
283
|
};
|
|
34
284
|
}
|
|
35
285
|
|
|
36
286
|
const _Option = class {
|
|
37
287
|
constructor(format, config = {}) {
|
|
288
|
+
this.format = format;
|
|
38
289
|
const match = _Option.OptionRE.exec(format);
|
|
39
290
|
if (match) {
|
|
40
291
|
if (match[3]) {
|
|
@@ -50,25 +301,28 @@ const _Option = class {
|
|
|
50
301
|
throw new Error(`Can not parse option format from "${format}"`);
|
|
51
302
|
}
|
|
52
303
|
this.description = config.description ?? "";
|
|
53
|
-
this.
|
|
304
|
+
this.required = format.indexOf("<") !== -1;
|
|
305
|
+
this.default = config.default;
|
|
306
|
+
this.construct = config.construct;
|
|
54
307
|
}
|
|
55
308
|
};
|
|
56
309
|
let Option = _Option;
|
|
57
310
|
Option.OptionRE = /^(-[a-zA-Z], )?--([a-zA-Z.]+)( \[[a-zA-Z]+\]| <[a-zA-Z]+>)?$/;
|
|
58
311
|
|
|
59
|
-
class
|
|
312
|
+
const _Command = class {
|
|
60
313
|
constructor(format, config) {
|
|
61
314
|
this.options = [];
|
|
62
315
|
this.format = config.condition ? [format] : format.split(" ").map((t) => t.trim()).filter(Boolean);
|
|
316
|
+
this.default = this.format.length === 0 || this.format[0][0] === "[" || this.format[0][0] === "<";
|
|
63
317
|
this.description = config.description ?? "";
|
|
64
318
|
this.conditionFn = config.condition;
|
|
65
319
|
this.logger = config.logger;
|
|
320
|
+
if (this.format.length > _Command.MaxDep) {
|
|
321
|
+
this.logger.warn(`Command format string "${format}" is too long`);
|
|
322
|
+
}
|
|
66
323
|
}
|
|
67
324
|
option(format, configOrDescription = "", otherConfig = {}) {
|
|
68
|
-
const config = otherConfig;
|
|
69
|
-
if (typeof configOrDescription === "string") {
|
|
70
|
-
config.description = configOrDescription;
|
|
71
|
-
}
|
|
325
|
+
const config = typeof configOrDescription === "object" ? configOrDescription : { ...otherConfig, description: configOrDescription };
|
|
72
326
|
try {
|
|
73
327
|
const option = new Option(format, config);
|
|
74
328
|
this.options.push(option);
|
|
@@ -77,13 +331,18 @@ class Command {
|
|
|
77
331
|
}
|
|
78
332
|
return this;
|
|
79
333
|
}
|
|
334
|
+
get hasConditionFn() {
|
|
335
|
+
return !!this.conditionFn;
|
|
336
|
+
}
|
|
80
337
|
shouldRun(args) {
|
|
81
338
|
if (this.conditionFn) {
|
|
82
339
|
return this.conditionFn(args);
|
|
83
340
|
} else {
|
|
84
|
-
|
|
341
|
+
if (this.default)
|
|
342
|
+
return true;
|
|
343
|
+
const isCmd = (t) => t[0] !== "[" && t[0] !== "<";
|
|
85
344
|
for (let i = 0; i < this.format.length; i++) {
|
|
86
|
-
if (
|
|
345
|
+
if (!isCmd(this.format[i])) {
|
|
87
346
|
return true;
|
|
88
347
|
}
|
|
89
348
|
if (i >= args["_"].length || this.format[i] !== args["_"][i]) {
|
|
@@ -93,7 +352,7 @@ class Command {
|
|
|
93
352
|
return true;
|
|
94
353
|
}
|
|
95
354
|
}
|
|
96
|
-
parseArgs(args) {
|
|
355
|
+
parseArgs(args, globalOptions) {
|
|
97
356
|
if (this.conditionFn) {
|
|
98
357
|
const argumentss2 = args["_"];
|
|
99
358
|
const options2 = args;
|
|
@@ -104,33 +363,62 @@ class Command {
|
|
|
104
363
|
options: args
|
|
105
364
|
};
|
|
106
365
|
}
|
|
107
|
-
const
|
|
366
|
+
const isCmd = (t) => t[0] !== "[" && t[0] !== "<";
|
|
108
367
|
const argumentss = [];
|
|
109
368
|
for (let i = 0; i < this.format.length; i++) {
|
|
110
|
-
if (
|
|
369
|
+
if (isCmd(this.format[i]))
|
|
111
370
|
continue;
|
|
112
371
|
if (i < args["_"].length) {
|
|
113
372
|
if (this.format[i].startsWith("[...")) {
|
|
114
|
-
argumentss.push(args["_"].slice(i));
|
|
373
|
+
argumentss.push(args["_"].slice(i).map(String));
|
|
115
374
|
} else {
|
|
116
|
-
argumentss.push(args["_"][i]);
|
|
375
|
+
argumentss.push(String(args["_"][i]));
|
|
117
376
|
}
|
|
118
377
|
} else {
|
|
119
378
|
if (this.format[i].startsWith("<")) {
|
|
379
|
+
this.logger.warn(`You should provide the argument "${this.format[i]}"`);
|
|
120
380
|
argumentss.push(void 0);
|
|
121
381
|
} else if (this.format[i].startsWith("[...")) {
|
|
122
382
|
argumentss.push([]);
|
|
123
383
|
} else if (this.format[i].startsWith("[")) {
|
|
124
384
|
argumentss.push(void 0);
|
|
125
|
-
} else
|
|
385
|
+
} else {
|
|
386
|
+
this.logger.warn(`unknown format string ("${this.format[i]}")`);
|
|
387
|
+
}
|
|
126
388
|
}
|
|
127
389
|
}
|
|
390
|
+
const fullOptions = globalOptions.concat(this.options).reduce((map, o) => {
|
|
391
|
+
map.set(o.name, o);
|
|
392
|
+
return map;
|
|
393
|
+
}, /* @__PURE__ */ new Map());
|
|
128
394
|
const options = args;
|
|
129
395
|
delete options["_"];
|
|
396
|
+
for (const [name, rawOption] of fullOptions) {
|
|
397
|
+
if (rawOption.required) {
|
|
398
|
+
if (options[name] === void 0) {
|
|
399
|
+
options[name] = false;
|
|
400
|
+
} else if (options[name] === "") {
|
|
401
|
+
options[name] = true;
|
|
402
|
+
}
|
|
403
|
+
} else {
|
|
404
|
+
if (options[name] === false) {
|
|
405
|
+
options[name] = void 0;
|
|
406
|
+
} else if (!(name in options)) {
|
|
407
|
+
options[name] = void 0;
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
if (rawOption.construct) {
|
|
411
|
+
options[name] = rawOption.construct(options[name]);
|
|
412
|
+
} else if (rawOption.default) {
|
|
413
|
+
if (!options[name]) {
|
|
414
|
+
options[name] = rawOption.default;
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
}
|
|
130
418
|
return {
|
|
131
419
|
command: this,
|
|
132
420
|
arguments: argumentss,
|
|
133
|
-
options
|
|
421
|
+
options
|
|
134
422
|
};
|
|
135
423
|
}
|
|
136
424
|
action(fn) {
|
|
@@ -138,17 +426,29 @@ class Command {
|
|
|
138
426
|
return this;
|
|
139
427
|
}
|
|
140
428
|
async run(...args) {
|
|
141
|
-
|
|
429
|
+
if (this.actionFn) {
|
|
430
|
+
this.actionFn(...args);
|
|
431
|
+
} else {
|
|
432
|
+
this.logger.warn(`You may miss action function in "${this.format}"`);
|
|
433
|
+
}
|
|
142
434
|
}
|
|
143
|
-
}
|
|
144
|
-
Command
|
|
145
|
-
|
|
435
|
+
};
|
|
436
|
+
let Command = _Command;
|
|
437
|
+
Command.MaxDep = 5;
|
|
438
|
+
function createHelpCommand(breadc) {
|
|
439
|
+
let helpCommand = void 0;
|
|
146
440
|
return new Command("-h, --help", {
|
|
147
441
|
condition(args) {
|
|
148
|
-
const isEmpty = !args["
|
|
149
|
-
if (args.help && isEmpty) {
|
|
150
|
-
|
|
151
|
-
|
|
442
|
+
const isEmpty = !args["--"]?.length;
|
|
443
|
+
if ((args.help || args.h) && isEmpty) {
|
|
444
|
+
if (args["_"].length > 0) {
|
|
445
|
+
for (const cmd of breadc.commands) {
|
|
446
|
+
if (!cmd.hasConditionFn && !cmd.default && cmd.shouldRun(args)) {
|
|
447
|
+
helpCommand = cmd;
|
|
448
|
+
return true;
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
}
|
|
152
452
|
return true;
|
|
153
453
|
} else {
|
|
154
454
|
return false;
|
|
@@ -156,10 +456,12 @@ function createVersionCommand(breadc) {
|
|
|
156
456
|
},
|
|
157
457
|
logger: breadc.logger
|
|
158
458
|
}).action(() => {
|
|
159
|
-
breadc.
|
|
459
|
+
for (const line of breadc.help(helpCommand)) {
|
|
460
|
+
breadc.logger.println(line);
|
|
461
|
+
}
|
|
160
462
|
});
|
|
161
463
|
}
|
|
162
|
-
function
|
|
464
|
+
function createVersionCommand(breadc) {
|
|
163
465
|
return new Command("-v, --version", {
|
|
164
466
|
condition(args) {
|
|
165
467
|
const isEmpty = !args["_"].length && !args["--"]?.length;
|
|
@@ -173,7 +475,7 @@ function createHelpCommand(breadc) {
|
|
|
173
475
|
},
|
|
174
476
|
logger: breadc.logger
|
|
175
477
|
}).action(() => {
|
|
176
|
-
breadc.logger.println(
|
|
478
|
+
breadc.logger.println(breadc.version());
|
|
177
479
|
});
|
|
178
480
|
}
|
|
179
481
|
|
|
@@ -182,22 +484,78 @@ class Breadc {
|
|
|
182
484
|
this.options = [];
|
|
183
485
|
this.commands = [];
|
|
184
486
|
this.name = name;
|
|
185
|
-
this.
|
|
186
|
-
this.
|
|
487
|
+
this._version = option.version ?? "unknown";
|
|
488
|
+
this.description = option.description;
|
|
489
|
+
this.logger = createDefaultLogger(name, option.logger);
|
|
187
490
|
const breadc = {
|
|
188
491
|
name: this.name,
|
|
189
|
-
version: this.version,
|
|
492
|
+
version: () => this.version.call(this),
|
|
493
|
+
help: (command) => this.help.call(this, command),
|
|
190
494
|
logger: this.logger,
|
|
191
495
|
options: this.options,
|
|
192
496
|
commands: this.commands
|
|
193
497
|
};
|
|
194
|
-
this.commands
|
|
498
|
+
this.commands.push(createVersionCommand(breadc), createHelpCommand(breadc));
|
|
195
499
|
}
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
500
|
+
version() {
|
|
501
|
+
return `${this.name}/${this._version}`;
|
|
502
|
+
}
|
|
503
|
+
help(command) {
|
|
504
|
+
const output = [];
|
|
505
|
+
const println = (msg) => output.push(msg);
|
|
506
|
+
println(this.version());
|
|
507
|
+
if (!command) {
|
|
508
|
+
if (this.description) {
|
|
509
|
+
println("");
|
|
510
|
+
if (Array.isArray(this.description)) {
|
|
511
|
+
for (const line of this.description) {
|
|
512
|
+
println(line);
|
|
513
|
+
}
|
|
514
|
+
} else {
|
|
515
|
+
println(this.description);
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
} else {
|
|
519
|
+
if (command.description) {
|
|
520
|
+
println("");
|
|
521
|
+
println(command.description);
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
if (!command) {
|
|
525
|
+
if (this.defaultCommand) {
|
|
526
|
+
println(``);
|
|
527
|
+
println(`Usage:`);
|
|
528
|
+
println(` $ ${this.name} ${this.defaultCommand.format.join(" ")}`);
|
|
529
|
+
}
|
|
530
|
+
} else {
|
|
531
|
+
println(``);
|
|
532
|
+
println(`Usage:`);
|
|
533
|
+
println(` $ ${this.name} ${command.format.join(" ")}`);
|
|
200
534
|
}
|
|
535
|
+
if (!command && this.commands.length > 2) {
|
|
536
|
+
println(``);
|
|
537
|
+
println(`Commands:`);
|
|
538
|
+
const commandHelps = this.commands.filter((c) => !c.hasConditionFn).map((c) => [` $ ${this.name} ${c.format.join(" ")}`, c.description]);
|
|
539
|
+
for (const line of twoColumn(commandHelps)) {
|
|
540
|
+
println(line);
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
println(``);
|
|
544
|
+
println(`Options:`);
|
|
545
|
+
const optionHelps = [].concat([
|
|
546
|
+
...command ? command.options.map((o) => [` ${o.format}`, o.description]) : [],
|
|
547
|
+
...this.options.map((o) => [` ${o.format}`, o.description]),
|
|
548
|
+
[` -h, --help`, `Display this message`],
|
|
549
|
+
[` -v, --version`, `Display version number`]
|
|
550
|
+
]);
|
|
551
|
+
for (const line of twoColumn(optionHelps)) {
|
|
552
|
+
println(line);
|
|
553
|
+
}
|
|
554
|
+
println(``);
|
|
555
|
+
return output;
|
|
556
|
+
}
|
|
557
|
+
option(format, configOrDescription = "", otherConfig = {}) {
|
|
558
|
+
const config = typeof configOrDescription === "object" ? configOrDescription : { ...otherConfig, description: configOrDescription };
|
|
201
559
|
try {
|
|
202
560
|
const option = new Option(format, config);
|
|
203
561
|
this.options.push(option);
|
|
@@ -206,32 +564,57 @@ class Breadc {
|
|
|
206
564
|
}
|
|
207
565
|
return this;
|
|
208
566
|
}
|
|
209
|
-
command(format,
|
|
567
|
+
command(format, configOrDescription = "", otherConfig = {}) {
|
|
568
|
+
const config = typeof configOrDescription === "object" ? configOrDescription : { ...otherConfig, description: configOrDescription };
|
|
210
569
|
const command = new Command(format, { ...config, logger: this.logger });
|
|
570
|
+
if (command.default) {
|
|
571
|
+
if (this.defaultCommand) {
|
|
572
|
+
this.logger.warn("You can not have two default commands.");
|
|
573
|
+
}
|
|
574
|
+
this.defaultCommand = command;
|
|
575
|
+
}
|
|
211
576
|
this.commands.push(command);
|
|
212
577
|
return command;
|
|
213
578
|
}
|
|
214
579
|
parse(args) {
|
|
215
|
-
const allowOptions = [
|
|
580
|
+
const allowOptions = [
|
|
581
|
+
...this.options,
|
|
582
|
+
...this.commands.flatMap((c) => c.options)
|
|
583
|
+
];
|
|
216
584
|
const alias = allowOptions.reduce((map, o) => {
|
|
217
585
|
if (o.shortcut) {
|
|
218
586
|
map[o.shortcut] = o.name;
|
|
219
587
|
}
|
|
220
588
|
return map;
|
|
221
589
|
}, {});
|
|
222
|
-
const argv =
|
|
590
|
+
const argv = minimist(args, {
|
|
223
591
|
string: allowOptions.filter((o) => o.type === "string").map((o) => o.name),
|
|
224
592
|
boolean: allowOptions.filter((o) => o.type === "boolean").map((o) => o.name),
|
|
225
|
-
alias
|
|
593
|
+
alias,
|
|
594
|
+
unknown: (t) => {
|
|
595
|
+
if (t[0] !== "-")
|
|
596
|
+
return true;
|
|
597
|
+
else {
|
|
598
|
+
if (["--help", "-h", "--version", "-v"].includes(t)) {
|
|
599
|
+
return true;
|
|
600
|
+
} else {
|
|
601
|
+
this.logger.warn(`Find unknown flag "${t}"`);
|
|
602
|
+
return false;
|
|
603
|
+
}
|
|
604
|
+
}
|
|
605
|
+
}
|
|
226
606
|
});
|
|
227
607
|
for (const shortcut of Object.keys(alias)) {
|
|
228
608
|
delete argv[shortcut];
|
|
229
609
|
}
|
|
230
610
|
for (const command of this.commands) {
|
|
231
|
-
if (command.shouldRun(argv)) {
|
|
232
|
-
return command.parseArgs(argv);
|
|
611
|
+
if (!command.default && command.shouldRun(argv)) {
|
|
612
|
+
return command.parseArgs(argv, this.options);
|
|
233
613
|
}
|
|
234
614
|
}
|
|
615
|
+
if (this.defaultCommand) {
|
|
616
|
+
return this.defaultCommand.parseArgs(argv, this.options);
|
|
617
|
+
}
|
|
235
618
|
const argumentss = argv["_"];
|
|
236
619
|
const options = argv;
|
|
237
620
|
delete options["_"];
|
|
@@ -248,12 +631,19 @@ class Breadc {
|
|
|
248
631
|
}
|
|
249
632
|
}
|
|
250
633
|
}
|
|
634
|
+
function twoColumn(texts, split = " ") {
|
|
635
|
+
const left = padRight(texts.map((t) => t[0]));
|
|
636
|
+
return left.map((l, idx) => l + split + texts[idx][1]);
|
|
637
|
+
}
|
|
638
|
+
function padRight(texts, fill = " ") {
|
|
639
|
+
const length = texts.map((t) => t.length).reduce((max, l) => Math.max(max, l), 0);
|
|
640
|
+
return texts.map((t) => t + fill.repeat(length - t.length));
|
|
641
|
+
}
|
|
251
642
|
|
|
252
643
|
function breadc(name, option = {}) {
|
|
253
644
|
return new Breadc(name, option);
|
|
254
645
|
}
|
|
255
646
|
|
|
256
647
|
exports.kolorist = kolorist__default;
|
|
257
|
-
exports.minimist = minimist__default;
|
|
258
|
-
exports.createDebug = createDebug__default;
|
|
259
648
|
exports["default"] = breadc;
|
|
649
|
+
exports.minimist = minimist;
|