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"/>
-
+
-
+