From eb5d8d0dd73ef1847d09cee8354f74e494b59168 Mon Sep 17 00:00:00 2001 From: Josh Goldberg Date: Sat, 2 Dec 2017 20:56:35 -0800 Subject: [PATCH] Prettified timestamps and error reports in --pretty Timestamps look like Gulp's, with grey times inside white brackets. Files have cyan filenames, yellow line and column numbers, and grey TS{####} errors. I wonder if those are actually useful for folks using the --pretty CLI: are they used for anything outside Visual Studio... Can we just get rid of them? Re-uses compiler/program's color logic in compiler/watch. The relevant variables are now exported and marked `@internal`. Is there a preferred way of re-using this code in both those files? --- src/compiler/program.ts | 41 ++++++++++++++++++++++++++--------------- src/compiler/watch.ts | 10 +++++++++- 2 files changed, 35 insertions(+), 16 deletions(-) diff --git a/src/compiler/program.ts b/src/compiler/program.ts index 4088a6951a1..4c743ce89d0 100755 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -241,22 +241,27 @@ namespace ts { return errorMessage; } - const redForegroundEscapeSequence = "\u001b[91m"; - const yellowForegroundEscapeSequence = "\u001b[93m"; - const blueForegroundEscapeSequence = "\u001b[93m"; + /** @internal */ + export const foregroundColorEscapeSequences = { + grey: "\u001b[90m", + red: "\u001b[91m", + yellow: "\u001b[93m", + cyan: "\u001b[96m" + }; const gutterStyleSequence = "\u001b[30;47m"; const gutterSeparator = " "; const resetEscapeSequence = "\u001b[0m"; const ellipsis = "..."; function getCategoryFormat(category: DiagnosticCategory): string { switch (category) { - case DiagnosticCategory.Warning: return yellowForegroundEscapeSequence; - case DiagnosticCategory.Error: return redForegroundEscapeSequence; - case DiagnosticCategory.Message: return blueForegroundEscapeSequence; + case DiagnosticCategory.Warning: return foregroundColorEscapeSequences.yellow; + case DiagnosticCategory.Error: return foregroundColorEscapeSequences.red; + case DiagnosticCategory.Message: return foregroundColorEscapeSequences.yellow; } } - function formatAndReset(text: string, formatStyle: string) { + /** @internal */ + export function formatColorAndReset(text: string, formatStyle: string) { return formatStyle + text + resetEscapeSequence; } @@ -289,7 +294,7 @@ namespace ts { // If the error spans over 5 lines, we'll only show the first 2 and last 2 lines, // so we'll skip ahead to the second-to-last line. if (hasMoreThanFiveLines && firstLine + 1 < i && i < lastLine - 1) { - context += formatAndReset(padLeft(ellipsis, gutterWidth), gutterStyleSequence) + gutterSeparator + host.getNewLine(); + context += formatColorAndReset(padLeft(ellipsis, gutterWidth), gutterStyleSequence) + gutterSeparator + host.getNewLine(); i = lastLine - 1; } @@ -300,12 +305,12 @@ namespace ts { lineContent = lineContent.replace("\t", " "); // convert tabs to single spaces // Output the gutter and the actual contents of the line. - context += formatAndReset(padLeft(i + 1 + "", gutterWidth), gutterStyleSequence) + gutterSeparator; + context += formatColorAndReset(padLeft(i + 1 + "", gutterWidth), gutterStyleSequence) + gutterSeparator; context += lineContent + host.getNewLine(); // Output the gutter and the error span for the line using tildes. - context += formatAndReset(padLeft("", gutterWidth), gutterStyleSequence) + gutterSeparator; - context += redForegroundEscapeSequence; + context += formatColorAndReset(padLeft("", gutterWidth), gutterStyleSequence) + gutterSeparator; + context += foregroundColorEscapeSequences.red; if (i === firstLine) { // If we're on the last line, then limit it to the last character of the last line. // Otherwise, we'll just squiggle the rest of the line, giving 'slice' no end position. @@ -324,13 +329,19 @@ namespace ts { context += resetEscapeSequence; } - output += host.getNewLine(); - output += `${ relativeFileName }(${ firstLine + 1 },${ firstLineChar + 1 }): `; + output += formatColorAndReset(relativeFileName, foregroundColorEscapeSequences.cyan); + output += "("; + output += formatColorAndReset(`${ firstLine + 1 }`, foregroundColorEscapeSequences.yellow); + output += ","; + output += formatColorAndReset(`${ firstLineChar + 1 }`, foregroundColorEscapeSequences.yellow); + output += "): "; } const categoryColor = getCategoryFormat(diagnostic.category); const category = DiagnosticCategory[diagnostic.category].toLowerCase(); - output += `${ formatAndReset(category, categoryColor) } TS${ diagnostic.code }: ${ flattenDiagnosticMessageText(diagnostic.messageText, host.getNewLine()) }`; + output += formatColorAndReset(category, categoryColor); + output += formatColorAndReset(` TS${ diagnostic.code }: `, foregroundColorEscapeSequences.grey); + output += flattenDiagnosticMessageText(diagnostic.messageText, host.getNewLine()); if (diagnostic.file) { output += host.getNewLine(); @@ -339,7 +350,7 @@ namespace ts { output += host.getNewLine(); } - return output; + return output + host.getNewLine(); } export function flattenDiagnosticMessageText(messageText: string | DiagnosticMessageChain, newLine: string): string { diff --git a/src/compiler/watch.ts b/src/compiler/watch.ts index a9e5fab2026..94cf7d87256 100644 --- a/src/compiler/watch.ts +++ b/src/compiler/watch.ts @@ -48,6 +48,14 @@ namespace ts { }; } + export function createWatchDiagnosticReporterWithColor(system = sys): DiagnosticReporter { + return diagnostic => { + let output = `[${ formatColorAndReset(new Date().toLocaleTimeString(), foregroundColorEscapeSequences.grey) }] `; + output += `${flattenDiagnosticMessageText(diagnostic.messageText, system.newLine)}${system.newLine + system.newLine + system.newLine}`; + system.write(output); + }; + } + export function reportDiagnostics(diagnostics: Diagnostic[], reportDiagnostic: DiagnosticReporter): void { for (const diagnostic of diagnostics) { reportDiagnostic(diagnostic); @@ -131,7 +139,7 @@ namespace ts { reportWatchDiagnostic?: DiagnosticReporter ): WatchingSystemHost { reportDiagnostic = reportDiagnostic || createDiagnosticReporter(system, pretty ? reportDiagnosticWithColorAndContext : reportDiagnosticSimply); - reportWatchDiagnostic = reportWatchDiagnostic || createWatchDiagnosticReporter(system); + reportWatchDiagnostic = reportWatchDiagnostic || pretty ? createWatchDiagnosticReporterWithColor(system) : createWatchDiagnosticReporter(system); parseConfigFile = parseConfigFile || ts.parseConfigFile; return { system,