-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathutils.ts
97 lines (82 loc) · 2.8 KB
/
utils.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
type FormatFn = (s?: string) => string;
function fmt(value: number): FormatFn {
return (s = '%s'): string => `\x1b[${value}m${s}\x1b[0m`;
}
function map<T extends Record<keyof T, number>, S = Record<keyof T, FormatFn>>(o: T, v: number): S {
return Object
.keys(o)
.reduce((a, b) => ({
...a,
[b]: fmt(o[b as keyof T] + v)
}), {}) as S;
}
const styles = {reset: 0, bold: 1, dim: 2, underline: 4, blink: 5, reverse: 7, hide: 8};
const colors = {black: 0, red: 1, green: 2, yellow: 3, blue: 4, magenta: 5, cyan: 6, white: 7};
export const format = {
style: map(styles, 0),
fg: {
...map(colors, 30),
bright: map(colors, 90)
},
bg: {
...map(colors, 40),
bright: map(colors, 100)
}
};
export enum InsertionMode {
Before = -1,
Replace = 0,
After = 1
}
/**
* Inserts a value into a string at the correct position adhering to linebreaks and indentation
*
* @param text The text to insert the value into
* @param find String to search for
* @param value Value to insert
* @param mode Insertion mode
* @returns Modified text
*/
export function stringInsertion(text: string, find: string, value: string, mode: InsertionMode): string {
let idx = text.indexOf(find);
// value could not be found within the text
if (idx === -1) {
return text;
}
// replace the value at the correct position
if (mode === InsertionMode.Replace) {
return text.slice(0, idx) + value + text.slice(idx + find.length);
}
// move the index to the end of the search string
if (mode === InsertionMode.After) {
idx += find.length;
}
// find linebreak in the correct direction
const findIdx = mode === InsertionMode.After
? text.indexOf.bind(text)
: text.lastIndexOf.bind(text);
let linebreak = findIdx('\n', idx);
// continue finding linebreaks until a non-empty line is found
let hasNewLine = false;
while (text.slice(Math.min(linebreak, idx), Math.max(linebreak, idx)).trim() === '') {
linebreak = findIdx('\n', linebreak + mode);
hasNewLine = true;
}
if (mode === InsertionMode.After) {
linebreak = text.lastIndexOf('\n', linebreak - 1);
}
linebreak++;
// count the number of whitespace characters at the start of the line
let indentCount = 0;
if (hasNewLine) {
while ([' ', '\t'].includes(text[linebreak + indentCount])) {
indentCount++;
}
}
// return the text with the new value inserted at the correct position
return text.slice(0, idx)
+ (mode === InsertionMode.After && hasNewLine ? '\n' : '')
+ text.slice(linebreak, linebreak + indentCount) + value
+ (mode === InsertionMode.Before && hasNewLine ? '\n' : '')
+ text.slice(idx);
}