1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2025-01-18 03:44:05 -05:00

perf(cli/console): Don't add redundant ANSI codes (#7823)

This commit is contained in:
Nayeem Rahman 2020-10-05 10:50:49 +01:00 committed by GitHub
parent f632b3b6e7
commit 72425810b8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 104 additions and 66 deletions

View file

@ -1097,8 +1097,8 @@
return null; return null;
} }
function parseCss(cssString) { function getDefaultCss() {
const css = { return {
backgroundColor: null, backgroundColor: null,
color: null, color: null,
fontWeight: null, fontWeight: null,
@ -1106,6 +1106,10 @@
textDecorationColor: null, textDecorationColor: null,
textDecorationLine: [], textDecorationLine: [],
}; };
}
function parseCss(cssString) {
const css = getDefaultCss();
const rawEntries = []; const rawEntries = [];
let inValue = false; let inValue = false;
@ -1160,12 +1164,12 @@
css.color = color; css.color = color;
} }
} else if (key == "font-weight") { } else if (key == "font-weight") {
if (["normal", "bold"].includes(value)) { if (value == "bold") {
css.fontWeight = value; css.fontWeight = value;
} }
} else if (key == "font-style") { } else if (key == "font-style") {
if (["normal", "italic", "oblique", "oblique 14deg"].includes(value)) { if (["italic", "oblique", "oblique 14deg"].includes(value)) {
css.fontStyle = value; css.fontStyle = "italic";
} }
} else if (key == "text-decoration-line") { } else if (key == "text-decoration-line") {
css.textDecorationLine = []; css.textDecorationLine = [];
@ -1196,51 +1200,82 @@
return css; return css;
} }
function cssToAnsi(css) { function colorEquals(color1, color2) {
return color1?.[0] == color2?.[0] && color1?.[1] == color2?.[1] &&
color1?.[2] == color2?.[2];
}
function cssToAnsi(css, prevCss = null) {
prevCss = prevCss ?? getDefaultCss();
let ansi = ""; let ansi = "";
if (!colorEquals(css.backgroundColor, prevCss.backgroundColor)) {
if (css.backgroundColor != null) { if (css.backgroundColor != null) {
const [r, g, b] = css.backgroundColor; const [r, g, b] = css.backgroundColor;
ansi += `\x1b[48;2;${r};${g};${b}m`; ansi += `\x1b[48;2;${r};${g};${b}m`;
} else { } else {
ansi += "\x1b[49m"; ansi += "\x1b[49m";
} }
}
if (!colorEquals(css.color, prevCss.color)) {
if (css.color != null) { if (css.color != null) {
const [r, g, b] = css.color; const [r, g, b] = css.color;
ansi += `\x1b[38;2;${r};${g};${b}m`; ansi += `\x1b[38;2;${r};${g};${b}m`;
} else { } else {
ansi += "\x1b[39m"; ansi += "\x1b[39m";
} }
}
if (css.fontWeight != prevCss.fontWeight) {
if (css.fontWeight == "bold") { if (css.fontWeight == "bold") {
ansi += `\x1b[1m`; ansi += `\x1b[1m`;
} else { } else {
ansi += "\x1b[22m"; ansi += "\x1b[22m";
} }
if (["italic", "oblique"].includes(css.fontStyle)) { }
if (css.fontStyle != prevCss.fontStyle) {
if (css.fontStyle == "italic") {
ansi += `\x1b[3m`; ansi += `\x1b[3m`;
} else { } else {
ansi += "\x1b[23m"; ansi += "\x1b[23m";
} }
}
if (!colorEquals(css.textDecorationColor, prevCss.textDecorationColor)) {
if (css.textDecorationColor != null) { if (css.textDecorationColor != null) {
const [r, g, b] = css.textDecorationColor; const [r, g, b] = css.textDecorationColor;
ansi += `\x1b[58;2;${r};${g};${b}m`; ansi += `\x1b[58;2;${r};${g};${b}m`;
} else { } else {
ansi += "\x1b[59m"; ansi += "\x1b[59m";
} }
}
if (
css.textDecorationLine.includes("line-through") !=
prevCss.textDecorationLine.includes("line-through")
) {
if (css.textDecorationLine.includes("line-through")) { if (css.textDecorationLine.includes("line-through")) {
ansi += "\x1b[9m"; ansi += "\x1b[9m";
} else { } else {
ansi += "\x1b[29m"; ansi += "\x1b[29m";
} }
}
if (
css.textDecorationLine.includes("overline") !=
prevCss.textDecorationLine.includes("overline")
) {
if (css.textDecorationLine.includes("overline")) { if (css.textDecorationLine.includes("overline")) {
ansi += "\x1b[53m"; ansi += "\x1b[53m";
} else { } else {
ansi += "\x1b[55m"; ansi += "\x1b[55m";
} }
}
if (
css.textDecorationLine.includes("underline") !=
prevCss.textDecorationLine.includes("underline")
) {
if (css.textDecorationLine.includes("underline")) { if (css.textDecorationLine.includes("underline")) {
ansi += "\x1b[4m"; ansi += "\x1b[4m";
} else { } else {
ansi += "\x1b[24m"; ansi += "\x1b[24m";
} }
}
return ansi; return ansi;
} }
@ -1257,6 +1292,7 @@
// have to append to `string` when a substitution occurs / at the end. // have to append to `string` when a substitution occurs / at the end.
let appendedChars = 0; let appendedChars = 0;
let usedStyle = false; let usedStyle = false;
let prevCss = null;
for (let i = 0; i < first.length - 1; i++) { for (let i = 0; i < first.length - 1; i++) {
if (first[i] == "%") { if (first[i] == "%") {
const char = first[++i]; const char = first[++i];
@ -1293,9 +1329,15 @@
); );
} else if (char == "c") { } else if (char == "c") {
const value = args[a++]; const value = args[a++];
formattedArg = noColor ? "" : cssToAnsi(parseCss(value)); if (!noColor) {
const css = parseCss(value);
formattedArg = cssToAnsi(css, prevCss);
if (formattedArg != "") { if (formattedArg != "") {
usedStyle = true; usedStyle = true;
prevCss = css;
}
} else {
formattedArg = "";
} }
} }

View file

@ -57,8 +57,8 @@ function parseCssColor(colorString: string): Css {
} }
/** ANSI-fy the CSS, replace "\x1b" with "_". */ /** ANSI-fy the CSS, replace "\x1b" with "_". */
function cssToAnsiEsc(css: Css): string { function cssToAnsiEsc(css: Css, prevCss: Css | null = null): string {
return cssToAnsi_(css).replaceAll("\x1b", "_"); return cssToAnsi_(css, prevCss).replaceAll("\x1b", "_");
} }
// test cases from web-platform-tests // test cases from web-platform-tests
@ -944,7 +944,7 @@ unitTest(function consoleParseCss(): void {
); );
assertEquals( assertEquals(
parseCss("font-style: oblique"), parseCss("font-style: oblique"),
{ ...DEFAULT_CSS, fontStyle: "oblique" }, { ...DEFAULT_CSS, fontStyle: "italic" },
); );
assertEquals( assertEquals(
parseCss("text-decoration-color: green"), parseCss("text-decoration-color: green"),
@ -983,46 +983,42 @@ unitTest(function consoleParseCss(): void {
}); });
unitTest(function consoleCssToAnsi(): void { unitTest(function consoleCssToAnsi(): void {
// TODO(nayeemrmn): Optimize these by accounting for the previous CSS.
assertEquals( assertEquals(
cssToAnsiEsc({ ...DEFAULT_CSS, backgroundColor: [200, 201, 202] }), cssToAnsiEsc({ ...DEFAULT_CSS, backgroundColor: [200, 201, 202] }),
"_[48;2;200;201;202m_[39m_[22m_[23m_[59m_[29m_[55m_[24m", "_[48;2;200;201;202m",
); );
assertEquals( assertEquals(
cssToAnsiEsc({ ...DEFAULT_CSS, color: [203, 204, 205] }), cssToAnsiEsc({ ...DEFAULT_CSS, color: [203, 204, 205] }),
"_[49m_[38;2;203;204;205m_[22m_[23m_[59m_[29m_[55m_[24m", "_[38;2;203;204;205m",
);
assertEquals(
cssToAnsiEsc({ ...DEFAULT_CSS, fontWeight: "bold" }),
"_[49m_[39m_[1m_[23m_[59m_[29m_[55m_[24m",
);
assertEquals(
cssToAnsiEsc({ ...DEFAULT_CSS, fontStyle: "italic" }),
"_[49m_[39m_[22m_[3m_[59m_[29m_[55m_[24m",
);
assertEquals(
cssToAnsiEsc({ ...DEFAULT_CSS, fontStyle: "oblique" }),
"_[49m_[39m_[22m_[3m_[59m_[29m_[55m_[24m",
); );
assertEquals(cssToAnsiEsc({ ...DEFAULT_CSS, fontWeight: "bold" }), "_[1m");
assertEquals(cssToAnsiEsc({ ...DEFAULT_CSS, fontStyle: "italic" }), "_[3m");
assertEquals( assertEquals(
cssToAnsiEsc({ ...DEFAULT_CSS, textDecorationColor: [206, 207, 208] }), cssToAnsiEsc({ ...DEFAULT_CSS, textDecorationColor: [206, 207, 208] }),
"_[49m_[39m_[22m_[23m_[58;2;206;207;208m_[29m_[55m_[24m", "_[58;2;206;207;208m",
); );
assertEquals( assertEquals(
cssToAnsiEsc({ ...DEFAULT_CSS, textDecorationLine: ["underline"] }), cssToAnsiEsc({ ...DEFAULT_CSS, textDecorationLine: ["underline"] }),
"_[49m_[39m_[22m_[23m_[59m_[29m_[55m_[4m", "_[4m",
); );
assertEquals( assertEquals(
cssToAnsiEsc( cssToAnsiEsc(
{ ...DEFAULT_CSS, textDecorationLine: ["overline", "line-through"] }, { ...DEFAULT_CSS, textDecorationLine: ["overline", "line-through"] },
), ),
"_[49m_[39m_[22m_[23m_[59m_[9m_[53m_[24m", "_[9m_[53m",
); );
assertEquals( assertEquals(
cssToAnsiEsc( cssToAnsiEsc(
{ ...DEFAULT_CSS, color: [203, 204, 205], fontWeight: "bold" }, { ...DEFAULT_CSS, color: [203, 204, 205], fontWeight: "bold" },
), ),
"_[49m_[38;2;203;204;205m_[1m_[23m_[59m_[29m_[55m_[24m", "_[38;2;203;204;205m_[1m",
);
assertEquals(
cssToAnsiEsc(
{ ...DEFAULT_CSS, color: [0, 0, 0], fontWeight: "bold" },
{ ...DEFAULT_CSS, color: [203, 204, 205], fontStyle: "italic" },
),
"_[38;2;0;0;0m_[1m_[23m",
); );
}); });