1 | const rpad = require('pad-right');
|
2 |
|
3 | const GAP = 4;
|
4 | const __ = ' ';
|
5 | const ALL = '__all__';
|
6 | const DEF = '__default__';
|
7 | const NL = '\n';
|
8 |
|
9 | function format(arr) {
|
10 | if (!arr.length) return '';
|
11 | let len = maxLen( arr.map(x => x[0]) ) + GAP;
|
12 | let join = a => rpad(a[0], len, ' ') + a[1] + (a[2] == null ? '' : ` (default ${a[2]})`);
|
13 | return arr.map(join);
|
14 | }
|
15 |
|
16 | function maxLen(arr) {
|
17 | let c=0, d=0, l=0, i=arr.length;
|
18 | if (i) while (i--) {
|
19 | d = arr[i].length;
|
20 | if (d > c) {
|
21 | l = i; c = d;
|
22 | }
|
23 | }
|
24 | return arr[l].length;
|
25 | }
|
26 |
|
27 | function noop(s) {
|
28 | return s;
|
29 | }
|
30 |
|
31 | function section(str, arr, fn) {
|
32 | if (!arr || !arr.length) return '';
|
33 | let i=0, out='';
|
34 | out += (NL + __ + str);
|
35 | for (; i < arr.length; i++) {
|
36 | out += (NL + __ + __ + fn(arr[i]));
|
37 | }
|
38 | return out + NL;
|
39 | }
|
40 |
|
41 | exports.help = function (bin, tree, key) {
|
42 | let out='', cmd=tree[key], pfx=`$ ${bin}`, all=tree[ALL];
|
43 | let prefix = s => `${pfx} ${s}`;
|
44 |
|
45 |
|
46 | all.options.push(['-h, --help', 'Displays this message']);
|
47 | cmd.options = (cmd.options || []).concat(all.options);
|
48 |
|
49 |
|
50 | (cmd.options.length > 0) && (cmd.usage += ' [options]');
|
51 |
|
52 |
|
53 | out += section('Description', cmd.describe, noop);
|
54 | out += section('Usage', [cmd.usage], prefix);
|
55 |
|
56 | if (key === DEF) {
|
57 |
|
58 | let cmds = Object.keys(tree).filter(k => !/__/.test(k));
|
59 | let text = cmds.map(k => [k, (tree[k].describe || [''])[0]]);
|
60 | out += section('Available Commands', format(text), noop);
|
61 |
|
62 | out += (NL + __ + 'For more info, run any command with the `--help` flag');
|
63 | cmds.slice(0, 2).forEach(k => {
|
64 | out += (NL + __ + __ + `${pfx} ${k} --help`);
|
65 | });
|
66 | out += NL;
|
67 | }
|
68 |
|
69 | out += section('Options', format(cmd.options), noop);
|
70 | out += section('Examples', cmd.examples.map(prefix), noop);
|
71 |
|
72 | return out;
|
73 | }
|
74 |
|
75 | exports.error = function (bin, str, num=1) {
|
76 | let out = section('ERROR', [str], noop);
|
77 | out += (NL + __ + `Run \`$ ${bin} --help\` for more info.` + NL);
|
78 | console.error(out);
|
79 | process.exit(num);
|
80 | }
|
81 |
|
82 |
|
83 | exports.parse = function (str) {
|
84 | return (str || '').split(/^-{1,2}|,|\s+-{1,2}|\s+/).filter(Boolean);
|
85 | }
|
86 |
|
87 |
|
88 | exports.sentences = function (str) {
|
89 | return (str || '').replace(/([.?!])\s*(?=[A-Z])/g, '$1|').split('|');
|
90 | }
|