Skip to content

Commit a50384a

Browse files
authored
Merge pull request microsoft#49763 from danielfrankcom/microsoft#47457/rewrite
Rewrite of ANSI code handling method
2 parents 19f2507 + c166624 commit a50384a

4 files changed

Lines changed: 426 additions & 144 deletions

File tree

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
/*---------------------------------------------------------------------------------------------
2+
* Copyright (c) Microsoft Corporation. All rights reserved.
3+
* Licensed under the MIT License. See License.txt in the project root for license information.
4+
*--------------------------------------------------------------------------------------------*/
5+
6+
import { LinkDetector } from 'vs/workbench/parts/debug/browser/linkDetector';
7+
8+
/**
9+
* @param text The content to stylize.
10+
* @returns An {@link HTMLSpanElement} that contains the potentially stylized text.
11+
*/
12+
export function handleANSIOutput(text: string, linkDetector: LinkDetector): HTMLSpanElement {
13+
14+
const root: HTMLSpanElement = document.createElement('span');
15+
const textLength: number = text.length;
16+
17+
let styleNames: string[] = [];
18+
let currentPos: number = 0;
19+
let buffer: string = '';
20+
21+
while (currentPos < textLength) {
22+
23+
let sequenceFound: boolean = false;
24+
25+
// Potentially an ANSI escape sequence.
26+
// See http://ascii-table.com/ansi-escape-sequences.php & https://en.wikipedia.org/wiki/ANSI_escape_code
27+
if (text.charCodeAt(currentPos) === 27 && text.charAt(currentPos + 1) === '[') {
28+
29+
const startPos: number = currentPos;
30+
currentPos += 2; // Ignore 'Esc[' as it's in every sequence.
31+
32+
let ansiSequence: string = '';
33+
34+
while (currentPos < textLength) {
35+
const char: string = text.charAt(currentPos);
36+
ansiSequence += char;
37+
38+
currentPos++;
39+
40+
// Look for a known sequence terminating character.
41+
if (char.match(/^[ABCDHIJKfhmpsu]$/)) {
42+
sequenceFound = true;
43+
break;
44+
}
45+
46+
}
47+
48+
if (sequenceFound) {
49+
50+
// Flush buffer with previous styles.
51+
appendStylizedStringToContainer(root, buffer, styleNames, linkDetector);
52+
53+
buffer = '';
54+
55+
/*
56+
* Certain ranges that are matched here do not contain real graphics rendition sequences. For
57+
* the sake of having a simpler expression, they have been included anyway.
58+
*/
59+
if (ansiSequence.match(/^(?:[39][0-7]|[0-8]|39)(?:;(?:[39][0-7]|[0-8]|39))*;?m$/)) {
60+
61+
const styleCodes: number[] = ansiSequence.slice(0, -1) // Remove final 'm' character.
62+
.split(';') // Separate style codes.
63+
.filter(elem => elem !== '') // Filter empty elems as '34;m' -> ['34', ''].
64+
.map(elem => parseInt(elem, 10)); // Convert to numbers.
65+
66+
for (let code of styleCodes) {
67+
if (code === 0) {
68+
styleNames = [];
69+
} else if (code === 1) {
70+
styleNames.push('code-bold');
71+
} else if (code === 4) {
72+
styleNames.push('code-underline');
73+
} else if ((code >= 30 && code <= 37) || (code >= 90 && code <= 97)) {
74+
styleNames.push('code-foreground-' + code);
75+
} else if (code === 39) {
76+
// Remove all foreground colour codes
77+
styleNames = styleNames.filter(style => !style.match(/^code-foreground-\d+$/));
78+
}
79+
}
80+
81+
} else {
82+
// Unsupported sequence so simply hide it.
83+
}
84+
85+
} else {
86+
currentPos = startPos;
87+
}
88+
89+
}
90+
91+
if (sequenceFound === false) {
92+
buffer += text.charAt(currentPos);
93+
currentPos++;
94+
}
95+
96+
}
97+
98+
// Flush remaining text buffer if not empty.
99+
if (buffer) {
100+
appendStylizedStringToContainer(root, buffer, styleNames, linkDetector);
101+
}
102+
103+
return root;
104+
105+
}
106+
107+
/**
108+
* @param root The {@link HTMLElement} to append the content to.
109+
* @param stringContent The text content to be appended.
110+
* @param cssClasses The list of CSS styles to apply to the text content.
111+
* @param linkDetector The {@link LinkDetector} responsible for generating links from {@param stringContent}.
112+
*/
113+
export function appendStylizedStringToContainer(root: HTMLElement, stringContent: string, cssClasses: string[], linkDetector: LinkDetector): void {
114+
if (!root || !stringContent) {
115+
return;
116+
}
117+
118+
const content = linkDetector.handleLinks(stringContent);
119+
let container: HTMLElement;
120+
121+
if (typeof content === 'string') {
122+
container = document.createElement('span');
123+
container.textContent = content;
124+
} else {
125+
container = content;
126+
}
127+
128+
container.className = cssClasses.join(' ');
129+
root.appendChild(container);
130+
}

src/vs/workbench/parts/debug/browser/media/repl.css

Lines changed: 27 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -165,32 +165,33 @@
165165
.monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code-bold { font-weight: bold; }
166166
.monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code-underline { text-decoration: underline; }
167167

168-
.monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code30, .monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code90 { color: gray; }
169-
.monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code31, .monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code91 { color: #BE1717; }
170-
.monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code32, .monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code92 { color: #338A2F; }
171-
.monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code33, .monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code93 { color: #BEB817; }
172-
.monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code34, .monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code94 { color: darkblue; }
173-
.monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code35, .monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code95 { color: darkmagenta; }
174-
.monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code36, .monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code96 { color: darkcyan; }
175-
.monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code37, .monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code97 { color: #BDBDBD; }
176-
177-
.vs-dark .monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code30, .vs-dark .monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code90 { color: #A0A0A0; }
178-
.vs-dark .monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code31, .vs-dark .monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code91 { color: #A74747; }
179-
.vs-dark .monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code32, .vs-dark .monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code92 { color: #348F34; }
180-
.vs-dark .monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code33, .vs-dark .monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code93 { color: #5F4C29; }
181-
.vs-dark .monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code34, .vs-dark .monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code94 { color: #6286BB; }
182-
.vs-dark .monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code35, .vs-dark .monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code95 { color: #914191; }
183-
.vs-dark .monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code36, .vs-dark .monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code96 { color: #218D8D; }
184-
.vs-dark .monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code37, .vs-dark .monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code97 { color: #707070; }
185-
186-
.hc-black .monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code30, .hc-black .monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code90 { color: gray; }
187-
.hc-black .monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code31, .hc-black .monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code91 { color: #A74747; }
188-
.hc-black .monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code32, .hc-black .monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code92 { color: #348F34; }
189-
.hc-black .monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code33, .hc-black .monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code93 { color: #5F4C29; }
190-
.hc-black .monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code34, .hc-black .monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code94 { color: #6286BB; }
191-
.hc-black .monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code35, .hc-black .monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code95 { color: #914191; }
192-
.hc-black .monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code36, .hc-black .monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code96 { color: #218D8D; }
193-
.hc-black .monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code37, .hc-black .monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code97 { color: #707070; }
168+
/* Regular and bright color codes are currently treated the same. */
169+
.monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code-foreground-30, .monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code-foreground-90 { color: gray; }
170+
.monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code-foreground-31, .monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code-foreground-91 { color: #BE1717; }
171+
.monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code-foreground-32, .monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code-foreground-92 { color: #338A2F; }
172+
.monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code-foreground-33, .monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code-foreground-93 { color: #BEB817; }
173+
.monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code-foreground-34, .monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code-foreground-94 { color: darkblue; }
174+
.monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code-foreground-35, .monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code-foreground-95 { color: darkmagenta; }
175+
.monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code-foreground-36, .monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code-foreground-96 { color: darkcyan; }
176+
.monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code-foreground-37, .monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code-foreground-97 { color: #BDBDBD; }
177+
178+
.vs-dark .monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code-foreground-30, .vs-dark .monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code-foreground-90 { color: #A0A0A0; }
179+
.vs-dark .monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code-foreground-31, .vs-dark .monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code-foreground-91 { color: #A74747; }
180+
.vs-dark .monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code-foreground-32, .vs-dark .monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code-foreground-92 { color: #348F34; }
181+
.vs-dark .monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code-foreground-33, .vs-dark .monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code-foreground-93 { color: #5F4C29; }
182+
.vs-dark .monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code-foreground-34, .vs-dark .monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code-foreground-94 { color: #6286BB; }
183+
.vs-dark .monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code-foreground-35, .vs-dark .monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code-foreground-95 { color: #914191; }
184+
.vs-dark .monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code-foreground-36, .vs-dark .monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code-foreground-96 { color: #218D8D; }
185+
.vs-dark .monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code-foreground-37, .vs-dark .monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code-foreground-97 { color: #707070; }
186+
187+
.hc-black .monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code-foreground-30, .hc-black .monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code-foreground-90 { color: gray; }
188+
.hc-black .monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code-foreground-31, .hc-black .monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code-foreground-91 { color: #A74747; }
189+
.hc-black .monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code-foreground-32, .hc-black .monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code-foreground-92 { color: #348F34; }
190+
.hc-black .monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code-foreground-33, .hc-black .monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code-foreground-93 { color: #5F4C29; }
191+
.hc-black .monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code-foreground-34, .hc-black .monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code-foreground-94 { color: #6286BB; }
192+
.hc-black .monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code-foreground-35, .hc-black .monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code-foreground-95 { color: #914191; }
193+
.hc-black .monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code-foreground-36, .hc-black .monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code-foreground-96 { color: #218D8D; }
194+
.hc-black .monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code-foreground-37, .hc-black .monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression .code-foreground-97 { color: #707070; }
194195

195196
/* Links */
196197
.monaco-workbench .repl .repl-tree .monaco-tree .monaco-tree-row > .content > .output.expression a {

0 commit comments

Comments
 (0)