From 5ec45768448ee5f4f58a37669a7f0b07a504b6e4 Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Sat, 13 Jun 2015 14:56:05 +0300 Subject: [PATCH] CLI: add color to compiler output via jansi Disabled on Windows temporarily, because for some reason colors there work only in REPL --- .idea/libraries/jansi.xml | 11 ++++ build.xml | 2 +- compiler/cli/cli.iml | 1 + .../kotlin/cli/common/CLICompiler.java | 6 +- .../cli/common/messages/MessageRenderer.java | 55 ++++++++++++++++++- update_dependencies.xml | 6 +- 6 files changed, 71 insertions(+), 10 deletions(-) create mode 100644 .idea/libraries/jansi.xml diff --git a/.idea/libraries/jansi.xml b/.idea/libraries/jansi.xml new file mode 100644 index 00000000000..fd2f900387f --- /dev/null +++ b/.idea/libraries/jansi.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/build.xml b/build.xml index 34f4458f4a7..0ba0202ddeb 100644 --- a/build.xml +++ b/build.xml @@ -61,8 +61,8 @@ - + diff --git a/compiler/cli/cli.iml b/compiler/cli/cli.iml index f52d3e1cf9a..f1f8ee6d816 100644 --- a/compiler/cli/cli.iml +++ b/compiler/cli/cli.iml @@ -13,6 +13,7 @@ + diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/common/CLICompiler.java b/compiler/cli/src/org/jetbrains/kotlin/cli/common/CLICompiler.java index 197f1321b19..488d099be7a 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/common/CLICompiler.java +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/common/CLICompiler.java @@ -21,6 +21,7 @@ import com.google.common.collect.Lists; import com.intellij.openapi.Disposable; import com.intellij.openapi.util.Disposer; import com.sampullara.cli.Args; +import org.fusesource.jansi.AnsiConsole; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments; @@ -120,15 +121,16 @@ public abstract class CLICompiler { return OK; } - errStream.print(messageRenderer.renderPreamble()); - MessageCollector collector = new PrintingMessageCollector(errStream, messageRenderer, arguments.verbose); try { + AnsiConsole.systemInstall(); + errStream.print(messageRenderer.renderPreamble()); return exec(collector, services, arguments); } finally { errStream.print(messageRenderer.renderConclusion()); + AnsiConsole.systemUninstall(); } } diff --git a/compiler/cli/src/org/jetbrains/kotlin/cli/common/messages/MessageRenderer.java b/compiler/cli/src/org/jetbrains/kotlin/cli/common/messages/MessageRenderer.java index 8c95a54d6d0..3ed4e90614f 100644 --- a/compiler/cli/src/org/jetbrains/kotlin/cli/common/messages/MessageRenderer.java +++ b/compiler/cli/src/org/jetbrains/kotlin/cli/common/messages/MessageRenderer.java @@ -16,10 +16,13 @@ package org.jetbrains.kotlin.cli.common.messages; +import com.intellij.openapi.util.SystemInfo; import com.intellij.openapi.util.text.StringUtil; import com.intellij.util.LineSeparator; import kotlin.KotlinPackage; import kotlin.io.IoPackage; +import org.fusesource.jansi.Ansi; +import org.fusesource.jansi.internal.CLibrary; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -80,6 +83,12 @@ public interface MessageRenderer { }; abstract class PlainText implements MessageRenderer { + // AnsiConsole doesn't check isatty() for stderr (see https://github.com/fusesource/jansi/pull/35). + // TODO: investigate why ANSI escape codes on Windows only work in REPL for some reason + private static final boolean COLOR_ENABLED = + !SystemInfo.isWindows && + CLibrary.isatty(CLibrary.STDERR_FILENO) != 0; + private static final String LINE_SEPARATOR = LineSeparator.getSystemLineSeparator().getSeparatorString(); @Override @@ -110,10 +119,30 @@ public interface MessageRenderer { result.append(" "); } - result.append(severity.name().toLowerCase()); - result.append(": "); + if (COLOR_ENABLED) { + Ansi ansi = Ansi.ansi() + .bold() + .fg(severityColor(severity)) + .a(severity.name().toLowerCase()) + .a(": ") + .reset() + .bold(); - result.append(decapitalizeIfNeeded(message)); + // Only make the first line of the message bold. Otherwise long overload ambiguity errors or exceptions are hard to read + String decapitalized = decapitalizeIfNeeded(message); + int firstNewline = decapitalized.indexOf(LINE_SEPARATOR); + if (firstNewline < 0) { + result.append(ansi.a(decapitalized).reset()); + } + else { + result.append(ansi.a(decapitalized.substring(0, firstNewline)).reset().a(decapitalized.substring(firstNewline))); + } + } + else { + result.append(severity.name().toLowerCase()); + result.append(": "); + result.append(decapitalizeIfNeeded(message)); + } if (lineContent != null && 1 <= column && column <= lineContent.length() + 1) { result.append(LINE_SEPARATOR); @@ -142,6 +171,26 @@ public interface MessageRenderer { return KotlinPackage.decapitalize(message); } + @NotNull + private static Ansi.Color severityColor(@NotNull CompilerMessageSeverity severity) { + switch (severity) { + case EXCEPTION: + return Ansi.Color.RED; + case ERROR: + return Ansi.Color.RED; + case WARNING: + return Ansi.Color.YELLOW; + case INFO: + return Ansi.Color.BLUE; + case LOGGING: + return Ansi.Color.BLUE; + case OUTPUT: + return Ansi.Color.BLUE; + default: + throw new UnsupportedOperationException("Unknown severity: " + severity); + } + } + @Nullable protected abstract String getPath(@NotNull CompilerMessageLocation location); diff --git a/update_dependencies.xml b/update_dependencies.xml index 0025eb8e114..ad7b38a707a 100644 --- a/update_dependencies.xml +++ b/update_dependencies.xml @@ -173,12 +173,10 @@ dest="dependencies/jflex/idea-flex.skeleton" usetimestamp="true"/> - + - +