console-toolkit 1.0.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/LICENSE +34 -0
- package/README.md +92 -0
- package/package.json +59 -0
- package/src/alphanumeric/arrows.js +31 -0
- package/src/alphanumeric/fractions.js +82 -0
- package/src/alphanumeric/number-formatters.js +131 -0
- package/src/alphanumeric/roman.js +86 -0
- package/src/alphanumeric/unicode-cultural-numbers.js +68 -0
- package/src/alphanumeric/unicode-letters.js +63 -0
- package/src/alphanumeric/unicode-numbers.js +75 -0
- package/src/alphanumeric/utils.js +44 -0
- package/src/ansi/csi.js +67 -0
- package/src/ansi/index.js +20 -0
- package/src/ansi/sgr-constants.js +99 -0
- package/src/ansi/sgr-state.js +398 -0
- package/src/ansi/sgr.js +214 -0
- package/src/box.js +253 -0
- package/src/charts/bars/block-frac-grouped.js +6 -0
- package/src/charts/bars/block-frac.js +36 -0
- package/src/charts/bars/block-grouped.js +6 -0
- package/src/charts/bars/block.js +43 -0
- package/src/charts/bars/draw-grouped.js +39 -0
- package/src/charts/bars/draw-stacked.js +24 -0
- package/src/charts/bars/frac-grouped.js +33 -0
- package/src/charts/bars/plain-grouped.js +6 -0
- package/src/charts/bars/plain.js +63 -0
- package/src/charts/columns/block-frac-grouped.js +6 -0
- package/src/charts/columns/block-frac.js +30 -0
- package/src/charts/columns/block-grouped.js +6 -0
- package/src/charts/columns/block.js +37 -0
- package/src/charts/columns/draw-grouped.js +48 -0
- package/src/charts/columns/draw-stacked.js +31 -0
- package/src/charts/columns/frac-grouped.js +27 -0
- package/src/charts/columns/plain-grouped.js +6 -0
- package/src/charts/columns/plain.js +39 -0
- package/src/charts/themes/default.js +12 -0
- package/src/charts/themes/rainbow-reversed.js +5 -0
- package/src/charts/themes/rainbow.js +8 -0
- package/src/charts/utils.js +75 -0
- package/src/draw-block-frac.js +33 -0
- package/src/draw-block.js +55 -0
- package/src/meta.js +41 -0
- package/src/output/show.js +40 -0
- package/src/output/updater.js +82 -0
- package/src/output/writer.js +131 -0
- package/src/panel.js +748 -0
- package/src/plot/bitmap.js +108 -0
- package/src/plot/draw-line.js +26 -0
- package/src/plot/draw-rect.js +216 -0
- package/src/plot/index.js +24 -0
- package/src/plot/to-quads.js +32 -0
- package/src/spinner/index.js +8 -0
- package/src/spinner/spin.js +51 -0
- package/src/spinner/spinner.js +75 -0
- package/src/spinner/spinners.js +65 -0
- package/src/strings.js +72 -0
- package/src/style.js +620 -0
- package/src/symbols.js +131 -0
- package/src/table/draw-borders.js +87 -0
- package/src/table/index.js +7 -0
- package/src/table/table.js +330 -0
- package/src/themes/blocks/unicode-half.js +9 -0
- package/src/themes/blocks/unicode-thin.js +9 -0
- package/src/themes/lines/ascii-compact.js +11 -0
- package/src/themes/lines/ascii-dots.js +9 -0
- package/src/themes/lines/ascii-girder.js +9 -0
- package/src/themes/lines/ascii-github.js +11 -0
- package/src/themes/lines/ascii-reddit.js +11 -0
- package/src/themes/lines/ascii-rounded.js +11 -0
- package/src/themes/lines/ascii.js +11 -0
- package/src/themes/lines/unicode-bold.js +15 -0
- package/src/themes/lines/unicode-rounded.js +15 -0
- package/src/themes/lines/unicode.js +15 -0
- package/src/themes/utils.js +38 -0
- package/src/turtle/draw-line-art.js +46 -0
- package/src/turtle/draw-unicode.js +33 -0
- package/src/turtle/index.js +12 -0
- package/src/turtle/turtle.js +286 -0
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import {SymbolRange, transcode as internalTranscode} from './utils.js';
|
|
2
|
+
import {minus, multiplication, superscriptPlus, superscriptMinus} from '../symbols.js';
|
|
3
|
+
|
|
4
|
+
export const transcodeTables = {
|
|
5
|
+
// Enclosed Alphanumeric
|
|
6
|
+
circled: new SymbolRange('①', 1, 20),
|
|
7
|
+
parens: new SymbolRange('⑴', 1, 20),
|
|
8
|
+
dots: new SymbolRange('⒈', 1, 20),
|
|
9
|
+
doubleCircled: new SymbolRange('⓵', 1, 10),
|
|
10
|
+
|
|
11
|
+
// Mathematical Alphanumeric Symbols
|
|
12
|
+
bold: new SymbolRange('𝟎'),
|
|
13
|
+
doubleStruck: new SymbolRange('𝟘'),
|
|
14
|
+
sansSerif: new SymbolRange('𝟢'),
|
|
15
|
+
sansSerifBold: new SymbolRange('𝟬'),
|
|
16
|
+
mono: new SymbolRange('𝟶'),
|
|
17
|
+
|
|
18
|
+
// Enclosed Alphanumeric Supplement
|
|
19
|
+
commas: new SymbolRange('🄁'),
|
|
20
|
+
|
|
21
|
+
// Number Forms
|
|
22
|
+
roman: new SymbolRange('Ⅰ', 1, 12),
|
|
23
|
+
romanLower: new SymbolRange('ⅰ', 1, 12),
|
|
24
|
+
|
|
25
|
+
// Dingbats
|
|
26
|
+
dingbatsCircledSansSerif: new SymbolRange('➀', 1, 10),
|
|
27
|
+
dingbatsNegativeCircled: new SymbolRange('❶', 1, 10),
|
|
28
|
+
dingbatsNegativeCircledSansSerif: new SymbolRange('➊', 1, 10),
|
|
29
|
+
|
|
30
|
+
// Superscripts and Subscripts
|
|
31
|
+
superscript: new SymbolRange('⁰'),
|
|
32
|
+
subscript: new SymbolRange('₀')
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
// patches
|
|
36
|
+
|
|
37
|
+
const circled_21_35 = new SymbolRange('\u{3251}', 21, 35),
|
|
38
|
+
circled_36_50 = new SymbolRange('\u{32B1}', 36, 50);
|
|
39
|
+
circled_36_50.overlay = {0: '\u{24EA}'};
|
|
40
|
+
circled_21_35.overlay = circled_36_50;
|
|
41
|
+
transcodeTables.circled.overlay = circled_21_35;
|
|
42
|
+
|
|
43
|
+
transcodeTables.dots.overlay = {0: '🄀'};
|
|
44
|
+
|
|
45
|
+
const negativeCircled_11_20 = new SymbolRange('\u{24EB}', 11, 20);
|
|
46
|
+
negativeCircled_11_20.overlay = {0: '\u{24FF}'};
|
|
47
|
+
transcodeTables.dingbatsNegativeCircled.overlay = negativeCircled_11_20;
|
|
48
|
+
|
|
49
|
+
transcodeTables.superscript.overlay = {1: '¹', 2: '²', 3: '³'};
|
|
50
|
+
|
|
51
|
+
// API
|
|
52
|
+
|
|
53
|
+
export const transcode = (s, name, options) => {
|
|
54
|
+
const table = typeof name == 'string' ? transcodeTables[name] : name;
|
|
55
|
+
if (!table) throw new Error(`There is no transcode table "${name}"`);
|
|
56
|
+
return internalTranscode(s, table, options);
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
export const numberPunctuation = (s, {addBefore = '', addAfter = ' '} = {}) =>
|
|
60
|
+
s.replace(
|
|
61
|
+
/(\d)([\,\.])/g,
|
|
62
|
+
(_, d, p) => addBefore + transcodeTables[p === '.' ? 'dots' : 'commas'].transcode(d) + addAfter
|
|
63
|
+
);
|
|
64
|
+
|
|
65
|
+
export const numberExponent = (s, {useSpecialMinus} = {}) => {
|
|
66
|
+
const r = /^([+-]?)([^e]+)e([+-]?)(.+)$/i.exec(s);
|
|
67
|
+
return r
|
|
68
|
+
? (r[1] === '-' && useSpecialMinus ? minus : r[1]) +
|
|
69
|
+
r[2] +
|
|
70
|
+
multiplication +
|
|
71
|
+
'10' +
|
|
72
|
+
(r[3] === '+' ? superscriptPlus : r[3] === '-' ? superscriptMinus : r[3]) +
|
|
73
|
+
transcode(r[4], transcodeTables.superscript)
|
|
74
|
+
: s;
|
|
75
|
+
};
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
export class SymbolRange {
|
|
2
|
+
constructor(fromSymbol, from = 0, to = 9, inputBase = '0') {
|
|
3
|
+
this.from = from;
|
|
4
|
+
this.to = to;
|
|
5
|
+
this.base = fromSymbol.codePointAt(0) - from;
|
|
6
|
+
this.inputBase = inputBase.codePointAt(0);
|
|
7
|
+
this.overlay = null;
|
|
8
|
+
}
|
|
9
|
+
get(i) {
|
|
10
|
+
if (this.overlay) {
|
|
11
|
+
const result =
|
|
12
|
+
typeof this.overlay.get == 'function'
|
|
13
|
+
? this.overlay.get(i)
|
|
14
|
+
: this.overlay[typeof i !== 'number' ? i : String.fromCodePoint(this.inputBase + i)];
|
|
15
|
+
if (result) return result;
|
|
16
|
+
}
|
|
17
|
+
if (typeof i !== 'number') {
|
|
18
|
+
i = String(i).codePointAt(0) - this.inputBase;
|
|
19
|
+
}
|
|
20
|
+
return this.from <= i && i <= this.to && String.fromCodePoint(this.base + i);
|
|
21
|
+
}
|
|
22
|
+
transcode(s, {missing} = {}) {
|
|
23
|
+
return s.replace(/./g, missing ? m => this.get(m) || missing : m => this.get(m) || m);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export const transcode = (s, tables, {missing} = {}) => {
|
|
28
|
+
let fn;
|
|
29
|
+
if (typeof tables == 'function') {
|
|
30
|
+
fn = tables;
|
|
31
|
+
} else if (!Array.isArray(tables)) {
|
|
32
|
+
if (typeof tables.transcode == 'function') return tables.transcode(s, {missing});
|
|
33
|
+
fn = m => tables[m];
|
|
34
|
+
} else {
|
|
35
|
+
fn = m => {
|
|
36
|
+
for (const table of tables) {
|
|
37
|
+
const result = typeof table.get == 'function' ? table.get(m) : table[m];
|
|
38
|
+
if (result) return result;
|
|
39
|
+
}
|
|
40
|
+
// return undefined;
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
return s.replace(/./g, missing ? m => fn(m) || missing : m => fn(m) || m);
|
|
44
|
+
};
|
package/src/ansi/csi.js
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
// CSI (Control Sequence Introducer) commands definitions and helpers.
|
|
2
|
+
// CSI is a part of Fe Escape sequences.
|
|
3
|
+
// Type Fe is supported by C1 control codes.
|
|
4
|
+
// See https://en.wikipedia.org/wiki/ANSI_escape_code for more details.
|
|
5
|
+
// SGR is in a separate file. See sgr.js.
|
|
6
|
+
|
|
7
|
+
export * from './sgr.js';
|
|
8
|
+
|
|
9
|
+
// matcher
|
|
10
|
+
export const matchCsi = /\x1B\[([\x30-\x3F]*)([\x20-\x2F]*)([\x40-\x7E])/g;
|
|
11
|
+
|
|
12
|
+
const CSI = '\x1B[';
|
|
13
|
+
|
|
14
|
+
export const CURSOR_UP1 = CSI + 'A';
|
|
15
|
+
export const CURSOR_DOWN1 = CSI + 'B';
|
|
16
|
+
export const CURSOR_FORWARD1 = CSI + 'C';
|
|
17
|
+
export const CURSOR_BACK1 = CSI + 'D';
|
|
18
|
+
export const CURSOR_NEXT_LINE1 = CSI + 'E';
|
|
19
|
+
export const CURSOR_PREV_LINE1 = CSI + 'F';
|
|
20
|
+
export const CURSOR_COLUMN1 = CSI + 'G';
|
|
21
|
+
export const CURSOR_HOME = CSI + 'H';
|
|
22
|
+
|
|
23
|
+
export const CURSOR_GET_POS = CSI + '6n';
|
|
24
|
+
export const CURSOR_SAVE_POS = CSI + 's';
|
|
25
|
+
export const CURSOR_RESTORE_POS = CSI + 'u';
|
|
26
|
+
export const CURSOR_NORMAL = CSI + '?25h';
|
|
27
|
+
export const CURSOR_INVISIBLE = CSI + '?25l';
|
|
28
|
+
|
|
29
|
+
export const cursorUp = (n = 1) => CSI + (n > 1 ? n.toFixed() : '') + 'A';
|
|
30
|
+
export const cursorDown = (n = 1) => CSI + (n > 1 ? n.toFixed() : '') + 'B';
|
|
31
|
+
export const cursorForward = (n = 1) => CSI + (n > 1 ? n.toFixed() : '') + 'C';
|
|
32
|
+
export const cursorBack = (n = 1) => CSI + (n > 1 ? n.toFixed() : '') + 'D';
|
|
33
|
+
export const cursorNextLine = (n = 1) => CSI + (n > 1 ? n.toFixed() : '') + 'E';
|
|
34
|
+
export const cursorPrevLine = (n = 1) => CSI + (n > 1 ? n.toFixed() : '') + 'F';
|
|
35
|
+
export const cursorColumn = (n = 1) => CSI + (n > 1 ? n.toFixed() : '') + 'G';
|
|
36
|
+
export const cursorSetPos = (n, m) => CSI + (n > 1 ? n.toFixed() : '') + ';' + (m > 1 ? m.toFixed() : '') + 'H';
|
|
37
|
+
export const cursorSetPosAlt = (n, m) => CSI + (n > 1 ? n.toFixed() : '') + ';' + (m > 1 ? m.toFixed() : '') + 'f'; // HVP
|
|
38
|
+
|
|
39
|
+
export const CURSOR_RIGHT1 = CURSOR_FORWARD1;
|
|
40
|
+
export const CURSOR_LEFT1 = CURSOR_BACK1;
|
|
41
|
+
export const cursorRight = cursorForward;
|
|
42
|
+
export const cursorLeft = cursorBack;
|
|
43
|
+
|
|
44
|
+
export const CLEAR_EOS = CSI + 'J';
|
|
45
|
+
export const CLEAR_BOS = CSI + '1J';
|
|
46
|
+
export const CLEAR_SCREEN = CSI + '2J';
|
|
47
|
+
export const CLEAR_SCREEN_ALL = CSI + '3J'; // includes the scrollback buffer
|
|
48
|
+
export const CLEAR_EOL = CSI + 'K';
|
|
49
|
+
export const CLEAR_BOL = CSI + '1K';
|
|
50
|
+
export const CLEAR_LINE = CSI + '2K';
|
|
51
|
+
|
|
52
|
+
export const SCREEN_SAVE = CSI + '?47h';
|
|
53
|
+
export const SCREEN_RESTORE = CSI + '?47l';
|
|
54
|
+
export const SCREEN_ALT_ON = CSI + '?1049h'; // alternative screen buffer
|
|
55
|
+
export const SCREEN_ALT_OFF = CSI + '?1049l';
|
|
56
|
+
export const SCREEN_SCROLL_UP1 = CSI + 'S'
|
|
57
|
+
export const SCREEN_SCROLL_DOWN1 = CSI + 'T'
|
|
58
|
+
export const SCREEN_REPORT_FOCUS_ON = CSI + '?1004h';
|
|
59
|
+
export const SCREEN_REPORT_FOCUS_OFF = CSI + '?1004l';
|
|
60
|
+
|
|
61
|
+
export const screenScrollUp = (n = 1) => CSI + (n > 1 ? n.toFixed() : '') + 'S';
|
|
62
|
+
export const screenScrollDown = (n = 1) => CSI + (n > 1 ? n.toFixed() : '') + 'T';
|
|
63
|
+
|
|
64
|
+
export const WRAPPING_ON = CSI + '=7h';
|
|
65
|
+
export const WRAPPING_OFF = CSI + '=7l';
|
|
66
|
+
export const BRACKETED_PASTE_ON = CSI + '?2004h';
|
|
67
|
+
export const BRACKETED_PASTE_OFF = CSI + '?2004l';
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
// ANSI escape code. See https://en.wikipedia.org/wiki/ANSI_escape_code for more details.
|
|
2
|
+
// This is a collection of escape sequences that are not part of other files (e.g., CSI, SGR).
|
|
3
|
+
|
|
4
|
+
export * from './csi.js';
|
|
5
|
+
|
|
6
|
+
export const ESC = '\x1B';
|
|
7
|
+
|
|
8
|
+
export const CURSOR_DELETE = '\x7F';
|
|
9
|
+
|
|
10
|
+
export const CURSOR_GO_UP1 = ESC + 'M';
|
|
11
|
+
|
|
12
|
+
export const CURSOR_SAVE = ESC + '7';
|
|
13
|
+
export const CURSOR_RESTORE = ESC + '8';
|
|
14
|
+
|
|
15
|
+
// matchers
|
|
16
|
+
export const matchFe = /\x1B([\x40-\x5F])/g;
|
|
17
|
+
export const matchFs = /\x1B([\x60-\x7E])/g;
|
|
18
|
+
export const matchFp = /\x1B([\x30-\x3F])/g;
|
|
19
|
+
export const matchNf = /\x1B([\x20-\x2F]+)([\x30-\x7E])/g;
|
|
20
|
+
export const matchOsc = /\x1B\]([\x20-\x7E]*)([\x07\x9C]|\x1B\x5C)/g;
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
// SGR commands as constants: some people prefer it this way
|
|
2
|
+
|
|
3
|
+
import {Commands, Colors, setCommands, getColor, getBrightColor, getBgColor, getBgBrightColor} from './sgr.js';
|
|
4
|
+
|
|
5
|
+
// Commands
|
|
6
|
+
|
|
7
|
+
export const BOLD = setCommands(Commands.BOLD);
|
|
8
|
+
export const DIM = setCommands(Commands.DIM);
|
|
9
|
+
export const ITALIC = setCommands(Commands.ITALIC);
|
|
10
|
+
export const UNDERLINE = setCommands(Commands.UNDERLINE);
|
|
11
|
+
export const BLINK = setCommands(Commands.BLINK);
|
|
12
|
+
export const RAPID_BLINK = setCommands(Commands.RAPID_BLINK);
|
|
13
|
+
export const INVERSE = setCommands(Commands.INVERSE);
|
|
14
|
+
export const HIDDEN = setCommands(Commands.HIDDEN);
|
|
15
|
+
export const STRIKETHROUGH = setCommands(Commands.STRIKETHROUGH);
|
|
16
|
+
export const OVERLINE = setCommands(Commands.OVERLINE);
|
|
17
|
+
|
|
18
|
+
// Reset commands
|
|
19
|
+
|
|
20
|
+
export const RESET_ALL = setCommands('');
|
|
21
|
+
export const RESET = RESET_ALL;
|
|
22
|
+
|
|
23
|
+
export const RESET_BOLD = setCommands(Commands.RESET_BOLD);
|
|
24
|
+
export const RESET_DIM = setCommands(Commands.RESET_DIM);
|
|
25
|
+
export const RESET_ITALIC = setCommands(Commands.RESET_ITALIC);
|
|
26
|
+
export const RESET_UNDERLINE = setCommands(Commands.RESET_UNDERLINE);
|
|
27
|
+
export const RESET_BLINK = setCommands(Commands.RESET_BLINK);
|
|
28
|
+
export const RESET_RAPID_BLINK = setCommands(Commands.RESET_RAPID_BLINK);
|
|
29
|
+
export const RESET_INVERSE = setCommands(Commands.RESET_INVERSE);
|
|
30
|
+
export const RESET_HIDDEN = setCommands(Commands.RESET_HIDDEN);
|
|
31
|
+
export const RESET_STRIKETHROUGH = setCommands(Commands.RESET_STRIKETHROUGH);
|
|
32
|
+
export const RESET_OVERLINE = setCommands(Commands.RESET_OVERLINE);
|
|
33
|
+
|
|
34
|
+
export const RESET_COLOR = setCommands(Commands.RESET_COLOR);
|
|
35
|
+
export const RESET_BG_COLOR = setCommands(Commands.RESET_BG_COLOR);
|
|
36
|
+
export const RESET_FONT = setCommands(Commands.RESET_FONT);
|
|
37
|
+
|
|
38
|
+
// Colors
|
|
39
|
+
|
|
40
|
+
export const BLACK = setCommands(getColor(Colors.BLACK));
|
|
41
|
+
export const RED = setCommands(getColor(Colors.RED));
|
|
42
|
+
export const GREEN = setCommands(getColor(Colors.GREEN));
|
|
43
|
+
export const YELLOW = setCommands(getColor(Colors.YELLOW));
|
|
44
|
+
export const BLUE = setCommands(getColor(Colors.BLUE));
|
|
45
|
+
export const MAGENTA = setCommands(getColor(Colors.MAGENTA));
|
|
46
|
+
export const CYAN = setCommands(getColor(Colors.CYAN));
|
|
47
|
+
export const WHITE = setCommands(getColor(Colors.WHITE));
|
|
48
|
+
|
|
49
|
+
export const BRIGHT_BLACK = setCommands(getBrightColor(Colors.BLACK));
|
|
50
|
+
export const BRIGHT_RED = setCommands(getBrightColor(Colors.RED));
|
|
51
|
+
export const BRIGHT_GREEN = setCommands(getBrightColor(Colors.GREEN));
|
|
52
|
+
export const BRIGHT_YELLOW = setCommands(getBrightColor(Colors.YELLOW));
|
|
53
|
+
export const BRIGHT_BLUE = setCommands(getBrightColor(Colors.BLUE));
|
|
54
|
+
export const BRIGHT_MAGENTA = setCommands(getBrightColor(Colors.MAGENTA));
|
|
55
|
+
export const BRIGHT_CYAN = setCommands(getBrightColor(Colors.CYAN));
|
|
56
|
+
export const BRIGHT_WHITE = setCommands(getBrightColor(Colors.WHITE));
|
|
57
|
+
|
|
58
|
+
export const BG_BLACK = setCommands(getBgColor(Colors.BLACK));
|
|
59
|
+
export const BG_RED = setCommands(getBgColor(Colors.RED));
|
|
60
|
+
export const BG_GREEN = setCommands(getBgColor(Colors.GREEN));
|
|
61
|
+
export const BG_YELLOW = setCommands(getBgColor(Colors.YELLOW));
|
|
62
|
+
export const BG_BLUE = setCommands(getBgColor(Colors.BLUE));
|
|
63
|
+
export const BG_MAGENTA = setCommands(getBgColor(Colors.MAGENTA));
|
|
64
|
+
export const BG_CYAN = setCommands(getBgColor(Colors.CYAN));
|
|
65
|
+
export const BG_WHITE = setCommands(getBgColor(Colors.WHITE));
|
|
66
|
+
|
|
67
|
+
export const BG_BRIGHT_BLACK = setCommands(getBgBrightColor(Colors.BLACK));
|
|
68
|
+
export const BG_BRIGHT_RED = setCommands(getBgBrightColor(Colors.RED));
|
|
69
|
+
export const BG_BRIGHT_GREEN = setCommands(getBgBrightColor(Colors.GREEN));
|
|
70
|
+
export const BG_BRIGHT_YELLOW = setCommands(getBgBrightColor(Colors.YELLOW));
|
|
71
|
+
export const BG_BRIGHT_BLUE = setCommands(getBgBrightColor(Colors.BLUE));
|
|
72
|
+
export const BG_BRIGHT_MAGENTA = setCommands(getBgBrightColor(Colors.MAGENTA));
|
|
73
|
+
export const BG_BRIGHT_CYAN = setCommands(getBgBrightColor(Colors.CYAN));
|
|
74
|
+
export const BG_BRIGHT_WHITE = setCommands(getBgBrightColor(Colors.WHITE));
|
|
75
|
+
|
|
76
|
+
export const FG_BLACK = BLACK;
|
|
77
|
+
export const FG_RED = RED;
|
|
78
|
+
export const FG_GREEN = GREEN;
|
|
79
|
+
export const FG_YELLOW = YELLOW;
|
|
80
|
+
export const FG_BLUE = BLUE;
|
|
81
|
+
export const FG_MAGENTA = MAGENTA;
|
|
82
|
+
export const FG_CYAN = CYAN;
|
|
83
|
+
export const FG_WHITE = WHITE;
|
|
84
|
+
|
|
85
|
+
export const FG_BRIGHT_BLACK = BRIGHT_BLACK;
|
|
86
|
+
export const FG_BRIGHT_RED = BRIGHT_RED;
|
|
87
|
+
export const FG_BRIGHT_GREEN = BRIGHT_GREEN;
|
|
88
|
+
export const FG_BRIGHT_YELLOW = BRIGHT_YELLOW;
|
|
89
|
+
export const FG_BRIGHT_BLUE = BRIGHT_BLUE;
|
|
90
|
+
export const FG_BRIGHT_MAGENTA = BRIGHT_MAGENTA;
|
|
91
|
+
export const FG_BRIGHT_CYAN = BRIGHT_CYAN;
|
|
92
|
+
export const FG_BRIGHT_WHITE = BRIGHT_WHITE;
|
|
93
|
+
|
|
94
|
+
export const GRAY = BRIGHT_BLACK;
|
|
95
|
+
export const GREY = GRAY;
|
|
96
|
+
export const BG_GRAY = BG_BRIGHT_BLACK;
|
|
97
|
+
export const BG_GREY = BG_GRAY;
|
|
98
|
+
export const FG_GRAY = FG_BRIGHT_BLACK;
|
|
99
|
+
export const FG_GREY = FG_GRAY;
|
|
@@ -0,0 +1,398 @@
|
|
|
1
|
+
// Support for states based on SGR commands. See https://en.wikipedia.org/wiki/ANSI_escape_code for more details.
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
Commands,
|
|
5
|
+
ColorFormatSize,
|
|
6
|
+
isFgColorCommand,
|
|
7
|
+
isBgColorCommand,
|
|
8
|
+
isFontCommand,
|
|
9
|
+
setCommands,
|
|
10
|
+
matchSgr
|
|
11
|
+
} from './sgr.js';
|
|
12
|
+
|
|
13
|
+
export const RESET_STATE = {
|
|
14
|
+
bold: null,
|
|
15
|
+
dim: null,
|
|
16
|
+
italic: null,
|
|
17
|
+
underline: null,
|
|
18
|
+
blink: null,
|
|
19
|
+
inverse: null,
|
|
20
|
+
hidden: null,
|
|
21
|
+
strikethrough: null,
|
|
22
|
+
overline: null,
|
|
23
|
+
foreground: null,
|
|
24
|
+
background: null,
|
|
25
|
+
decoration: null,
|
|
26
|
+
font: null
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
const defaultState = Symbol('defaultState');
|
|
30
|
+
|
|
31
|
+
let toState;
|
|
32
|
+
|
|
33
|
+
export const extractState = (s, initState = defaultState) => {
|
|
34
|
+
let state = toState(initState);
|
|
35
|
+
matchSgr.lastIndex = 0;
|
|
36
|
+
for (const match of s.matchAll(matchSgr)) state = addCommandsToState(state, match[1].split(';'));
|
|
37
|
+
return state;
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
toState = value => {
|
|
41
|
+
switch (typeof value) {
|
|
42
|
+
case 'object':
|
|
43
|
+
if (!value) return RESET_STATE;
|
|
44
|
+
if (typeof value.getState == 'function') return value.getState();
|
|
45
|
+
return value;
|
|
46
|
+
case 'string':
|
|
47
|
+
if (!value) break;
|
|
48
|
+
return extractState(value);
|
|
49
|
+
}
|
|
50
|
+
return {};
|
|
51
|
+
};
|
|
52
|
+
export {toState};
|
|
53
|
+
|
|
54
|
+
const TOTAL_RESETS = Array.from(Object.keys(RESET_STATE)).length;
|
|
55
|
+
|
|
56
|
+
const getStateResets = state => {
|
|
57
|
+
let resetCount = 0;
|
|
58
|
+
|
|
59
|
+
for (const name of Object.keys(RESET_STATE)) {
|
|
60
|
+
if (state[name] === null) ++resetCount;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
return resetCount;
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
export const combineStates = (...states) => {
|
|
67
|
+
let state = {};
|
|
68
|
+
for (const s of states) {
|
|
69
|
+
const currentState = toState(s);
|
|
70
|
+
for (const [name, value] of Object.entries(currentState)) {
|
|
71
|
+
if (value !== undefined) state[name] = value;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return state;
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
export const commandsToState = commands => {
|
|
78
|
+
let state = {};
|
|
79
|
+
for (let i = 0; i < commands.length; ++i) {
|
|
80
|
+
const currentCommand = commands[i];
|
|
81
|
+
switch (currentCommand) {
|
|
82
|
+
case '': // reset
|
|
83
|
+
case Commands.RESET_ALL:
|
|
84
|
+
state = RESET_STATE;
|
|
85
|
+
continue;
|
|
86
|
+
case Commands.BOLD:
|
|
87
|
+
state.bold = currentCommand;
|
|
88
|
+
continue;
|
|
89
|
+
case Commands.DIM:
|
|
90
|
+
state.dim = currentCommand;
|
|
91
|
+
continue;
|
|
92
|
+
case Commands.ITALIC:
|
|
93
|
+
state.italic = currentCommand;
|
|
94
|
+
continue;
|
|
95
|
+
case Commands.UNDERLINE:
|
|
96
|
+
case Commands.DOUBLE_UNDERLINE:
|
|
97
|
+
case Commands.CURLY_UNDERLINE:
|
|
98
|
+
state.underline = currentCommand;
|
|
99
|
+
continue;
|
|
100
|
+
case Commands.BLINK:
|
|
101
|
+
case Commands.RAPID_BLINK:
|
|
102
|
+
state.blink = currentCommand;
|
|
103
|
+
continue;
|
|
104
|
+
case Commands.INVERSE:
|
|
105
|
+
state.inverse = currentCommand;
|
|
106
|
+
continue;
|
|
107
|
+
case Commands.HIDDEN:
|
|
108
|
+
state.hidden = currentCommand;
|
|
109
|
+
continue;
|
|
110
|
+
case Commands.STRIKETHROUGH:
|
|
111
|
+
state.strikethrough = currentCommand;
|
|
112
|
+
continue;
|
|
113
|
+
case Commands.OVERLINE:
|
|
114
|
+
state.overline = currentCommand;
|
|
115
|
+
continue;
|
|
116
|
+
case Commands.RESET_BOLD:
|
|
117
|
+
// case Commands.RESET_DIM:
|
|
118
|
+
state.bold = state.dim = null;
|
|
119
|
+
continue;
|
|
120
|
+
case Commands.RESET_ITALIC:
|
|
121
|
+
state.italic = null;
|
|
122
|
+
continue;
|
|
123
|
+
case Commands.RESET_UNDERLINE:
|
|
124
|
+
// case Commands.RESET_DOUBLE_UNDERLINE:
|
|
125
|
+
// case Commands.RESET_CURLY_UNDERLINE:
|
|
126
|
+
state.underline = null;
|
|
127
|
+
continue;
|
|
128
|
+
case Commands.RESET_BLINK:
|
|
129
|
+
// case RESET_RAPID_BLINK:
|
|
130
|
+
state.blink = null;
|
|
131
|
+
continue;
|
|
132
|
+
case Commands.RESET_INVERSE:
|
|
133
|
+
state.inverse = null;
|
|
134
|
+
continue;
|
|
135
|
+
case Commands.RESET_HIDDEN:
|
|
136
|
+
state.hidden = null;
|
|
137
|
+
continue;
|
|
138
|
+
case Commands.RESET_STRIKETHROUGH:
|
|
139
|
+
state.strikethrough = null;
|
|
140
|
+
continue;
|
|
141
|
+
case Commands.RESET_OVERLINE:
|
|
142
|
+
state.overline = null;
|
|
143
|
+
continue;
|
|
144
|
+
case Commands.RESET_DECORATION_COLOR:
|
|
145
|
+
state.decoration = null;
|
|
146
|
+
continue;
|
|
147
|
+
case Commands.EXTENDED_COLOR: {
|
|
148
|
+
const next = ColorFormatSize[commands[i + 1]],
|
|
149
|
+
color = commands.slice(i, i + next);
|
|
150
|
+
i += next - 1;
|
|
151
|
+
state.foreground = color;
|
|
152
|
+
continue;
|
|
153
|
+
}
|
|
154
|
+
case Commands.BG_EXTENDED_COLOR: {
|
|
155
|
+
const next = ColorFormatSize[commands[i + 1]],
|
|
156
|
+
color = commands.slice(i, i + next);
|
|
157
|
+
i += next - 1;
|
|
158
|
+
state.background = color;
|
|
159
|
+
continue;
|
|
160
|
+
}
|
|
161
|
+
case Commands.DECORATION_COLOR: {
|
|
162
|
+
const next = ColorFormatSize[commands[i + 1]],
|
|
163
|
+
color = commands.slice(i, i + next);
|
|
164
|
+
i += next - 1;
|
|
165
|
+
state.decoration = color;
|
|
166
|
+
continue;
|
|
167
|
+
}
|
|
168
|
+
case Commands.DEFAULT_COLOR:
|
|
169
|
+
state.foreground = null;
|
|
170
|
+
continue;
|
|
171
|
+
case Commands.BG_DEFAULT_COLOR:
|
|
172
|
+
state.background = null;
|
|
173
|
+
continue;
|
|
174
|
+
case Commands.DEFAULT_FONT:
|
|
175
|
+
state.font = null;
|
|
176
|
+
continue;
|
|
177
|
+
}
|
|
178
|
+
if (isFgColorCommand(currentCommand)) {
|
|
179
|
+
state.foreground = currentCommand;
|
|
180
|
+
continue;
|
|
181
|
+
}
|
|
182
|
+
if (isBgColorCommand(currentCommand)) {
|
|
183
|
+
state.background = currentCommand;
|
|
184
|
+
continue;
|
|
185
|
+
}
|
|
186
|
+
if (isFontCommand(currentCommand)) {
|
|
187
|
+
state.font = currentCommand;
|
|
188
|
+
continue;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
return state;
|
|
192
|
+
};
|
|
193
|
+
|
|
194
|
+
export const addCommandsToState = (state, commands) => combineStates(state, commandsToState(commands));
|
|
195
|
+
|
|
196
|
+
const equalColors = (a, b) => {
|
|
197
|
+
if (a === b) return true;
|
|
198
|
+
if (Array.isArray(a) && Array.isArray(b))
|
|
199
|
+
return a.length === b.length && a.every((value, index) => value === b[index]);
|
|
200
|
+
return false;
|
|
201
|
+
};
|
|
202
|
+
|
|
203
|
+
const pushColor = (commands, color) => {
|
|
204
|
+
if (Array.isArray(color)) {
|
|
205
|
+
commands.push(...color);
|
|
206
|
+
} else {
|
|
207
|
+
commands.push(color);
|
|
208
|
+
}
|
|
209
|
+
return commands;
|
|
210
|
+
};
|
|
211
|
+
|
|
212
|
+
const resetColorProperties = {
|
|
213
|
+
foreground: Commands.RESET_COLOR,
|
|
214
|
+
background: Commands.RESET_BG_COLOR,
|
|
215
|
+
decoration: Commands.RESET_DECORATION_COLOR
|
|
216
|
+
};
|
|
217
|
+
|
|
218
|
+
const chainedStates = {bold: 1, dim: 1};
|
|
219
|
+
|
|
220
|
+
export const stateToCommands = state => {
|
|
221
|
+
state = toState(state);
|
|
222
|
+
const commands = [];
|
|
223
|
+
let resetCount = 0;
|
|
224
|
+
|
|
225
|
+
// process chained states separately
|
|
226
|
+
if (state.bold === null) {
|
|
227
|
+
commands.push(Commands.RESET_BOLD);
|
|
228
|
+
++resetCount;
|
|
229
|
+
}
|
|
230
|
+
if (state.dim === null) {
|
|
231
|
+
commands.push(Commands.RESET_DIM);
|
|
232
|
+
++resetCount;
|
|
233
|
+
}
|
|
234
|
+
state.bold && commands.push(state.bold);
|
|
235
|
+
state.dim && commands.push(state.dim);
|
|
236
|
+
|
|
237
|
+
for (const [name, value] of Object.entries(state)) {
|
|
238
|
+
if (chainedStates[name] === 1) continue; // skip chained states
|
|
239
|
+
if (resetColorProperties.hasOwnProperty(name)) {
|
|
240
|
+
// colors
|
|
241
|
+
if (value === null) {
|
|
242
|
+
commands.push(resetColorProperties[name]);
|
|
243
|
+
++resetCount;
|
|
244
|
+
continue;
|
|
245
|
+
}
|
|
246
|
+
value && pushColor(commands, value);
|
|
247
|
+
continue;
|
|
248
|
+
}
|
|
249
|
+
if (value === null) {
|
|
250
|
+
commands.push(Commands['RESET_' + name.toUpperCase()]);
|
|
251
|
+
++resetCount;
|
|
252
|
+
continue;
|
|
253
|
+
}
|
|
254
|
+
value && commands.push(value);
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
return resetCount === TOTAL_RESETS ? [''] : commands;
|
|
258
|
+
};
|
|
259
|
+
|
|
260
|
+
export const stateTransition = (prev, next) => {
|
|
261
|
+
prev = toState(prev);
|
|
262
|
+
next = toState(next);
|
|
263
|
+
const commands = [];
|
|
264
|
+
let resetCount = 0;
|
|
265
|
+
|
|
266
|
+
// process chained states separately
|
|
267
|
+
if (prev.bold !== next.bold) {
|
|
268
|
+
if (next.bold === null) {
|
|
269
|
+
commands.push(Commands.RESET_BOLD);
|
|
270
|
+
} else if (next.bold) {
|
|
271
|
+
if (next.dim === null && prev.dim !== null) commands.push(Commands.RESET_DIM);
|
|
272
|
+
commands.push(next.bold);
|
|
273
|
+
}
|
|
274
|
+
next.dim && commands.push(next.dim);
|
|
275
|
+
} else {
|
|
276
|
+
if (prev.dim !== next.dim) {
|
|
277
|
+
if (next.dim === null) {
|
|
278
|
+
commands.push(Commands.RESET_DIM);
|
|
279
|
+
next.bold && commands.push(next.bold);
|
|
280
|
+
} else {
|
|
281
|
+
next.dim && commands.push(next.dim);
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
if (next.bold === null) ++resetCount;
|
|
286
|
+
if (next.dim === null) ++resetCount;
|
|
287
|
+
|
|
288
|
+
for (const name of Object.keys(RESET_STATE)) {
|
|
289
|
+
if (chainedStates[name] === 1) continue; // skip chained states
|
|
290
|
+
const value = next[name];
|
|
291
|
+
if (resetColorProperties.hasOwnProperty(name)) {
|
|
292
|
+
// color
|
|
293
|
+
if (value === null) {
|
|
294
|
+
if (prev[name] !== null) commands.push(resetColorProperties[name]);
|
|
295
|
+
++resetCount;
|
|
296
|
+
continue;
|
|
297
|
+
}
|
|
298
|
+
if (value) {
|
|
299
|
+
if (!equalColors(prev[name], value)) pushColor(commands, value);
|
|
300
|
+
}
|
|
301
|
+
continue;
|
|
302
|
+
}
|
|
303
|
+
if (value === null) {
|
|
304
|
+
if (prev[name] !== null) commands.push(Commands['RESET_' + name.toUpperCase()]);
|
|
305
|
+
++resetCount;
|
|
306
|
+
continue;
|
|
307
|
+
}
|
|
308
|
+
if (value) {
|
|
309
|
+
if (prev[name] !== value) commands.push(value);
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
if (resetCount === TOTAL_RESETS) {
|
|
314
|
+
const prevResets = getStateResets(prev);
|
|
315
|
+
return prevResets === TOTAL_RESETS ? [] : [''];
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
return commands;
|
|
319
|
+
};
|
|
320
|
+
|
|
321
|
+
export const stateReverseTransition = (prev, next) => {
|
|
322
|
+
prev = toState(prev);
|
|
323
|
+
next = toState(next);
|
|
324
|
+
const commands = [];
|
|
325
|
+
let resetCount = 0;
|
|
326
|
+
|
|
327
|
+
// process chained states separately
|
|
328
|
+
if (next.bold !== prev.bold) {
|
|
329
|
+
if (!prev.bold) {
|
|
330
|
+
commands.push(Commands.RESET_BOLD);
|
|
331
|
+
} else {
|
|
332
|
+
if (!prev.dim && next.dim) commands.push(Commands.RESET_DIM);
|
|
333
|
+
commands.push(prev.bold);
|
|
334
|
+
}
|
|
335
|
+
prev.dim && commands.push(prev.dim);
|
|
336
|
+
} else {
|
|
337
|
+
if (next.dim !== prev.dim) {
|
|
338
|
+
if (!prev.dim) {
|
|
339
|
+
commands.push(Commands.RESET_DIM);
|
|
340
|
+
prev.bold && commands.push(prev.bold);
|
|
341
|
+
} else {
|
|
342
|
+
prev.dim && commands.push(prev.dim);
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
if (prev.bold === null) ++resetCount;
|
|
347
|
+
if (prev.dim === null) ++resetCount;
|
|
348
|
+
|
|
349
|
+
for (const name of Object.keys(RESET_STATE)) {
|
|
350
|
+
const value = prev[name];
|
|
351
|
+
if (resetColorProperties.hasOwnProperty(name)) {
|
|
352
|
+
// color
|
|
353
|
+
if (!value) {
|
|
354
|
+
if (next[name]) commands.push(resetColorProperties[name]);
|
|
355
|
+
if (value === null) ++resetCount;
|
|
356
|
+
continue;
|
|
357
|
+
}
|
|
358
|
+
if (!equalColors(next[name], value)) pushColor(commands, value);
|
|
359
|
+
continue;
|
|
360
|
+
}
|
|
361
|
+
if (!value) {
|
|
362
|
+
if (next[name]) commands.push(Commands['RESET_' + name.toUpperCase()]);
|
|
363
|
+
if (value === null) ++resetCount;
|
|
364
|
+
continue;
|
|
365
|
+
}
|
|
366
|
+
if (next[name] !== value) commands.push(value);
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
if (resetCount === TOTAL_RESETS) {
|
|
370
|
+
const nextResets = getStateResets(next);
|
|
371
|
+
return nextResets === TOTAL_RESETS ? [] : [''];
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
return commands;
|
|
375
|
+
};
|
|
376
|
+
|
|
377
|
+
export const stringifyCommands = commands => (commands?.length ? setCommands(commands) : '');
|
|
378
|
+
|
|
379
|
+
export const optimize = (s, initState = defaultState) => {
|
|
380
|
+
let state = toState(initState),
|
|
381
|
+
result = '',
|
|
382
|
+
start = 0;
|
|
383
|
+
matchSgr.lastIndex = 0;
|
|
384
|
+
for (const match of s.matchAll(matchSgr)) {
|
|
385
|
+
if (start < match.index) {
|
|
386
|
+
const commands = initState !== state ? stateTransition(initState, state) : [];
|
|
387
|
+
result += stringifyCommands(commands);
|
|
388
|
+
initState = state;
|
|
389
|
+
result += s.substring(start, match.index);
|
|
390
|
+
}
|
|
391
|
+
state = addCommandsToState(state, match[1].split(';'));
|
|
392
|
+
start = match.index + match[0].length;
|
|
393
|
+
}
|
|
394
|
+
const commands = initState !== state ? stateTransition(initState, state) : [];
|
|
395
|
+
result += stringifyCommands(commands);
|
|
396
|
+
if (start < s.length) result += s.substring(start);
|
|
397
|
+
return result;
|
|
398
|
+
};
|