mirror of
https://github.com/Microsoft/vscode
synced 2024-10-05 19:02:54 +00:00
strings: use more comprehensive ansi escape code regex (#173362)
* strings: use more comprehensive ansi escape code regex The ansi escape remover only recognized a few codes, and only a subset of their syntax. Be more comprehensive, and add tests. Fixes #153648 * address pr comment
This commit is contained in:
parent
06c5eb5ead
commit
dc6fd239e6
|
@ -21,11 +21,8 @@ interface ServerReadyAction {
|
|||
killOnServerStop?: boolean;
|
||||
}
|
||||
|
||||
// Escape codes
|
||||
// http://en.wikipedia.org/wiki/ANSI_escape_code
|
||||
const EL = /\x1B\x5B[12]?K/g; // Erase in line
|
||||
const COLOR_START = /\x1b\[\d+m/g; // Color
|
||||
const COLOR_END = /\x1b\[0?m/g; // Color
|
||||
// Escape codes, compiled from https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h3-Functions-using-CSI-_-ordered-by-the-final-character_s_
|
||||
const CSI_SEQUENCE = /(:?\x1b\[|\x9B)[=?>!]?[\d;:]*["$#'* ]?[a-zA-Z@^`{}|~]/g;
|
||||
|
||||
/**
|
||||
* Froms vs/base/common/strings.ts in core
|
||||
|
@ -33,9 +30,7 @@ const COLOR_END = /\x1b\[0?m/g; // Color
|
|||
*/
|
||||
function removeAnsiEscapeCodes(str: string): string {
|
||||
if (str) {
|
||||
str = str.replace(EL, '');
|
||||
str = str.replace(COLOR_START, '');
|
||||
str = str.replace(COLOR_END, '');
|
||||
str = str.replace(CSI_SEQUENCE, '');
|
||||
}
|
||||
|
||||
return str;
|
||||
|
|
|
@ -727,17 +727,12 @@ export function lcut(text: string, n: number) {
|
|||
return text.substring(i).replace(/^\s/, '');
|
||||
}
|
||||
|
||||
// Escape codes
|
||||
// http://en.wikipedia.org/wiki/ANSI_escape_code
|
||||
const EL = /\x1B\x5B[12]?K/g; // Erase in line
|
||||
const COLOR_START = /\x1b\[\d+m/g; // Color
|
||||
const COLOR_END = /\x1b\[0?m/g; // Color
|
||||
// Escape codes, compiled from https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h3-Functions-using-CSI-_-ordered-by-the-final-character_s_
|
||||
const CSI_SEQUENCE = /(:?\x1b\[|\x9B)[=?>!]?[\d;:]*["$#'* ]?[a-zA-Z@^`{}|~]/g;
|
||||
|
||||
export function removeAnsiEscapeCodes(str: string): string {
|
||||
if (str) {
|
||||
str = str.replace(EL, '');
|
||||
str = str.replace(COLOR_START, '');
|
||||
str = str.replace(COLOR_END, '');
|
||||
str = str.replace(CSI_SEQUENCE, '');
|
||||
}
|
||||
|
||||
return str;
|
||||
|
|
|
@ -395,4 +395,126 @@ suite('Strings', () => {
|
|||
return `${i++}${after}`;
|
||||
}), 'a0ca1ca2ca3c');
|
||||
});
|
||||
|
||||
test('removeAnsiEscapeCodes', () => {
|
||||
const CSI = '\x1b\[';
|
||||
const sequences = [
|
||||
// Base cases from https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h3-Functions-using-CSI-_-ordered-by-the-final-character_s_
|
||||
`${CSI}42@`,
|
||||
`${CSI}42 @`,
|
||||
`${CSI}42A`,
|
||||
`${CSI}42 A`,
|
||||
`${CSI}42B`,
|
||||
`${CSI}42C`,
|
||||
`${CSI}42D`,
|
||||
`${CSI}42E`,
|
||||
`${CSI}42F`,
|
||||
`${CSI}42G`,
|
||||
`${CSI}42;42H`,
|
||||
`${CSI}42I`,
|
||||
`${CSI}42J`,
|
||||
`${CSI}?42J`,
|
||||
`${CSI}42K`,
|
||||
`${CSI}?42K`,
|
||||
`${CSI}42L`,
|
||||
`${CSI}42M`,
|
||||
`${CSI}42P`,
|
||||
`${CSI}#P`,
|
||||
`${CSI}3#P`,
|
||||
`${CSI}#Q`,
|
||||
`${CSI}3#Q`,
|
||||
`${CSI}#R`,
|
||||
`${CSI}42S`,
|
||||
`${CSI}?1;2;3S`,
|
||||
`${CSI}42T`,
|
||||
`${CSI}42;42;42;42;42T`,
|
||||
`${CSI}>3T`,
|
||||
`${CSI}42X`,
|
||||
`${CSI}42Z`,
|
||||
`${CSI}42^`,
|
||||
`${CSI}42\``,
|
||||
`${CSI}42a`,
|
||||
`${CSI}42b`,
|
||||
`${CSI}42c`,
|
||||
`${CSI}=42c`,
|
||||
`${CSI}>42c`,
|
||||
`${CSI}42d`,
|
||||
`${CSI}42e`,
|
||||
`${CSI}42;42f`,
|
||||
`${CSI}42g`,
|
||||
`${CSI}3h`,
|
||||
`${CSI}?3h`,
|
||||
`${CSI}42i`,
|
||||
`${CSI}?42i`,
|
||||
`${CSI}3l`,
|
||||
`${CSI}?3l`,
|
||||
`${CSI}3m`,
|
||||
`${CSI}>0;0m`,
|
||||
`${CSI}>0m`,
|
||||
`${CSI}?0m`,
|
||||
`${CSI}42n`,
|
||||
`${CSI}>42n`,
|
||||
`${CSI}?42n`,
|
||||
`${CSI}>42p`,
|
||||
`${CSI}!p`,
|
||||
`${CSI}0;0"p`,
|
||||
`${CSI}42$p`,
|
||||
`${CSI}?42$p`,
|
||||
`${CSI}#p`,
|
||||
`${CSI}3#p`,
|
||||
`${CSI}>42q`,
|
||||
`${CSI}42q`,
|
||||
`${CSI}42 q`,
|
||||
`${CSI}42"q`,
|
||||
`${CSI}#q`,
|
||||
`${CSI}42;42r`,
|
||||
`${CSI}?3r`,
|
||||
`${CSI}0;0;0;0;3$r`,
|
||||
`${CSI}s`,
|
||||
`${CSI}0;0s`,
|
||||
`${CSI}>42s`,
|
||||
`${CSI}?3s`,
|
||||
`${CSI}42;42;42t`,
|
||||
`${CSI}>3t`,
|
||||
`${CSI}42 t`,
|
||||
`${CSI}0;0;0;0;3$t`,
|
||||
`${CSI}u`,
|
||||
`${CSI}42 u`,
|
||||
`${CSI}0;0;0;0;0;0;0;0$v`,
|
||||
`${CSI}42$w`,
|
||||
`${CSI}0;0;0;0'w`,
|
||||
`${CSI}42x`,
|
||||
`${CSI}42*x`,
|
||||
`${CSI}0;0;0;0;0$x`,
|
||||
`${CSI}42#y`,
|
||||
`${CSI}0;0;0;0;0;0*y`,
|
||||
`${CSI}42;0'z`,
|
||||
`${CSI}0;1;2;4$z`,
|
||||
`${CSI}3'{`,
|
||||
`${CSI}#{`,
|
||||
`${CSI}3#{`,
|
||||
`${CSI}0;0;0;0\${`,
|
||||
`${CSI}0;0;0;0#|`,
|
||||
`${CSI}42$|`,
|
||||
`${CSI}42'|`,
|
||||
`${CSI}42*|`,
|
||||
`${CSI}#}`,
|
||||
`${CSI}42'}`,
|
||||
`${CSI}42$}`,
|
||||
`${CSI}42'~`,
|
||||
`${CSI}42$~`,
|
||||
|
||||
// Common SGR cases:
|
||||
`${CSI}1;31m`, // multiple attrs
|
||||
`${CSI}105m`, // bright background
|
||||
`${CSI}48:5:128m`, // 256 indexed color
|
||||
`${CSI}48;5;128m`, // 256 indexed color alt
|
||||
`${CSI}38:2:0:255:255:255m`, // truecolor
|
||||
`${CSI}38;2;255;255;255m`, // truecolor alt
|
||||
];
|
||||
|
||||
for (const sequence of sequences) {
|
||||
assert.strictEqual(strings.removeAnsiEscapeCodes(`hello${sequence}world`), 'helloworld', `expect to remove ${JSON.stringify(sequence)}`);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Reference in a new issue