UNPKG

3.85 kBPlain TextView Raw
1import Option from "./Option.ts";
2export const removeBrackets = (v: string) => v.replace(/[<[].+/, '').trim();
3export const findAllBrackets = (v: string) => {
4 const ANGLED_BRACKET_RE_GLOBAL = /<([^>]+)>/g;
5 const SQUARE_BRACKET_RE_GLOBAL = /\[([^\]]+)\]/g;
6 const res = [];
7
8 const parse = (match: string[]) => {
9 let variadic = false;
10 let value = match[1];
11
12 if (value.startsWith('...')) {
13 value = value.slice(3);
14 variadic = true;
15 }
16
17 return {
18 required: match[0].startsWith('<'),
19 value,
20 variadic
21 };
22 };
23
24 let angledMatch;
25
26 while (angledMatch = ANGLED_BRACKET_RE_GLOBAL.exec(v)) {
27 res.push(parse(angledMatch));
28 }
29
30 let squareMatch;
31
32 while (squareMatch = SQUARE_BRACKET_RE_GLOBAL.exec(v)) {
33 res.push(parse(squareMatch));
34 }
35
36 return res;
37};
38interface MriOptions {
39 alias: {
40 [k: string]: string[];
41 };
42 boolean: string[];
43}
44export const getMriOptions = (options: Option[]) => {
45 const result: MriOptions = {
46 alias: {},
47 boolean: []
48 };
49
50 for (const [index, option] of options.entries()) {
51 // We do not set default values in mri options
52 // Since its type (typeof) will be used to cast parsed arguments.
53 // Which mean `--foo foo` will be parsed as `{foo: true}` if we have `{default:{foo: true}}`
54 // Set alias
55 if (option.names.length > 1) {
56 result.alias[option.names[0]] = option.names.slice(1);
57 } // Set boolean
58
59
60 if (option.isBoolean) {
61 if (option.negated) {
62 // For negated option
63 // We only set it to `boolean` type when there's no string-type option with the same name
64 const hasStringTypeOption = options.some((o, i) => {
65 return i !== index && o.names.some(name => option.names.includes(name)) && typeof o.required === 'boolean';
66 });
67
68 if (!hasStringTypeOption) {
69 result.boolean.push(option.names[0]);
70 }
71 } else {
72 result.boolean.push(option.names[0]);
73 }
74 }
75 }
76
77 return result;
78};
79export const findLongest = (arr: string[]) => {
80 return arr.sort((a, b) => {
81 return a.length > b.length ? -1 : 1;
82 })[0];
83};
84export const padRight = (str: string, length: number) => {
85 return str.length >= length ? str : `${str}${' '.repeat(length - str.length)}`;
86};
87export const camelcase = (input: string) => {
88 return input.replace(/([a-z])-([a-z])/g, (_, p1, p2) => {
89 return p1 + p2.toUpperCase();
90 });
91};
92export const setDotProp = (obj: {
93 [k: string]: any;
94}, keys: string[], val: any) => {
95 let i = 0;
96 let length = keys.length;
97 let t = obj;
98 let x;
99
100 for (; i < length; ++i) {
101 x = t[keys[i]];
102 t = t[keys[i]] = i === length - 1 ? val : x != null ? x : !!~keys[i + 1].indexOf('.') || !(+keys[i + 1] > -1) ? {} : [];
103 }
104};
105export const setByType = (obj: {
106 [k: string]: any;
107}, transforms: {
108 [k: string]: any;
109}) => {
110 for (const key of Object.keys(transforms)) {
111 const transform = transforms[key];
112
113 if (transform.shouldTransform) {
114 obj[key] = Array.prototype.concat.call([], obj[key]);
115
116 if (typeof transform.transformFunction === 'function') {
117 obj[key] = obj[key].map(transform.transformFunction);
118 }
119 }
120 }
121};
122export const getFileName = (input: string) => {
123 const m = /([^\\\/]+)$/.exec(input);
124 return m ? m[1] : '';
125};
126export const camelcaseOptionName = (name: string) => {
127 // Camelcase the option name
128 // Don't camelcase anything after the dot `.`
129 return name.split('.').map((v, i) => {
130 return i === 0 ? camelcase(v) : v;
131 }).join('.');
132};
133export class CACError extends Error {
134 constructor(message: string) {
135 super(message);
136 this.name = this.constructor.name;
137
138 if (typeof Error.captureStackTrace === 'function') {
139 Error.captureStackTrace(this, this.constructor);
140 } else {
141 this.stack = new Error(message).stack;
142 }
143 }
144
145}
\No newline at end of file