From d76bdd4e7d3ff83da5f2c4943da96df7dc98d8fd Mon Sep 17 00:00:00 2001 From: ankit Date: Sun, 11 Oct 2009 01:15:17 +0000 Subject: [PATCH] Add color support for errors/warnings etc. In class/Microsoft.Build.Engine/Microsoft.Build.BuildEngine: * ConsoleLogger.cs: Use ColorSetter and ColorResetter . Support 'XBUILD_COLORS' to set colors for errors, warnings, events and messages. In tools/xbuild: * Main.cs: Add support for emitting messages in color. Taking relevant code from mcs/report.cs . Using ANSI color codes here instead of Console.ForegroundColor because of a bug in Console. git-svn-id: svn+ssh://mono-cvs.ximian.com/source/trunk/mcs@143902 e3ebcda4-bce8-0310-ba0a-eca2169e7518 --- .../Microsoft.Build.BuildEngine/ChangeLog | 6 + .../Microsoft.Build.BuildEngine/ConsoleLogger.cs | 160 ++++++++++++++++++-- tools/xbuild/ChangeLog | 7 + tools/xbuild/Main.cs | 166 ++++++++++++++++++++- 4 files changed, 328 insertions(+), 11 deletions(-) diff --git a/class/Microsoft.Build.Engine/Microsoft.Build.BuildEngine/ChangeLog b/class/Microsoft.Build.Engine/Microsoft.Build.BuildEngine/ChangeLog index 4f5a1b29ef..515ef2e844 100644 --- a/class/Microsoft.Build.Engine/Microsoft.Build.BuildEngine/ChangeLog +++ b/class/Microsoft.Build.Engine/Microsoft.Build.BuildEngine/ChangeLog @@ -1,3 +1,9 @@ +2009-10-11 Ankit Jain + + * ConsoleLogger.cs: Use ColorSetter and ColorResetter . + Support 'XBUILD_COLORS' to set colors for errors, warnings, + events and messages. + 2009-10-10 Ankit Jain * ConsoleLogger.cs (ProjectFinishedHandler): Once projectFailed diff --git a/class/Microsoft.Build.Engine/Microsoft.Build.BuildEngine/ConsoleLogger.cs b/class/Microsoft.Build.Engine/Microsoft.Build.BuildEngine/ConsoleLogger.cs index 8156cc598b..b2bdfe7aba 100644 --- a/class/Microsoft.Build.Engine/Microsoft.Build.BuildEngine/ConsoleLogger.cs +++ b/class/Microsoft.Build.Engine/Microsoft.Build.BuildEngine/ConsoleLogger.cs @@ -32,6 +32,7 @@ using System.Runtime.InteropServices; using System.Collections.Generic; using System.IO; using System.Security; +using System.Text; using Microsoft.Build.Framework; namespace Microsoft.Build.BuildEngine { @@ -49,6 +50,10 @@ namespace Microsoft.Build.BuildEngine { bool skipProjectStartedText; List errors, warnings; bool projectFailed; + ConsoleColor errorColor, warningColor, eventColor, messageColor, highMessageColor; + ColorSetter colorSet; + ColorResetter colorReset; + bool no_message_color, no_colors; public ConsoleLogger () : this (LoggerVerbosity.Normal, null, null, null) @@ -60,7 +65,6 @@ namespace Microsoft.Build.BuildEngine { { } - // FIXME: what about colorSet and colorReset? public ConsoleLogger (LoggerVerbosity verbosity, WriteHandler write, ColorSetter colorSet, @@ -79,6 +83,93 @@ namespace Microsoft.Build.BuildEngine { this.skipProjectStartedText = false; errors = new List (); warnings = new List (); + this.colorSet = colorSet; + this.colorReset = colorReset; + + //defaults + errorColor = ConsoleColor.DarkRed; + warningColor = ConsoleColor.DarkYellow; + eventColor = ConsoleColor.DarkCyan; + messageColor = ConsoleColor.DarkGray; + highMessageColor = ConsoleColor.White; + + // if message color is not set via the env var, + // then don't use any color for it. + no_message_color = true; + + no_colors = true; + if (colorSet == null || colorReset == null) + return; + + // color support + string config = Environment.GetEnvironmentVariable ("XBUILD_COLORS"); + if (config != null && config != "disable") { + no_colors = false; + string [] pairs = config.Split (new char[] {','}, StringSplitOptions.RemoveEmptyEntries); + foreach (string pair in pairs) { + string [] parts = pair.Split (new char[] {'='}, StringSplitOptions.RemoveEmptyEntries); + if (parts.Length != 2) + continue; + + if (parts [0] == "errors") + TryParseConsoleColor (parts [1], ref errorColor); + else if (parts [0] == "warnings") + TryParseConsoleColor (parts [1], ref warningColor); + else if (parts [0] == "events") + TryParseConsoleColor (parts [1], ref eventColor); + else if (parts [0] == "messages") { + if (TryParseConsoleColor (parts [1], ref messageColor)) { + highMessageColor = GetBrightColorFor (messageColor); + no_message_color = false; + } + } + } + } + } + + bool TryParseConsoleColor (string color_str, ref ConsoleColor color) + { + switch (color_str.ToLower ()) { + case "black": color = ConsoleColor.Black; break; + + case "blue": color = ConsoleColor.DarkBlue; break; + case "green": color = ConsoleColor.DarkGreen; break; + case "cyan": color = ConsoleColor.DarkCyan; break; + case "red": color = ConsoleColor.DarkRed; break; + case "magenta": color = ConsoleColor.DarkMagenta; break; + case "yellow": color = ConsoleColor.DarkYellow; break; + case "grey": color = ConsoleColor.DarkGray; break; + + case "brightgrey": color = ConsoleColor.Gray; break; + case "brightblue": color = ConsoleColor.Blue; break; + case "brightgreen": color = ConsoleColor.Green; break; + case "brightcyan": color = ConsoleColor.Cyan; break; + case "brightred": color = ConsoleColor.Red; break; + case "brightmagenta": color = ConsoleColor.Magenta; break; + case "brightyellow": color = ConsoleColor.Yellow; break; + + case "white": + case "brightwhite": color = ConsoleColor.White; break; + default: return false; + } + + return true; + } + + ConsoleColor GetBrightColorFor (ConsoleColor color) + { + switch (color) { + case ConsoleColor.DarkBlue: return ConsoleColor.Blue; + case ConsoleColor.DarkGreen: return ConsoleColor.Green; + case ConsoleColor.DarkCyan: return ConsoleColor.Cyan; + case ConsoleColor.DarkRed: return ConsoleColor.Red; + case ConsoleColor.DarkMagenta: return ConsoleColor.Magenta; + case ConsoleColor.DarkYellow: return ConsoleColor.Yellow; + case ConsoleColor.DarkGray: return ConsoleColor.Gray; + case ConsoleColor.Gray: return ConsoleColor.White; + + default: return color; + } } public void ApplyParameter (string parameterName, @@ -123,15 +214,19 @@ namespace Microsoft.Build.BuildEngine { if (warnings.Count > 0) { WriteLine (Environment.NewLine + "Warnings:"); + SetColor (warningColor); foreach (string warning in warnings) WriteLine (warning); + ResetColor (); WriteLine (""); } if (errors.Count > 0) { WriteLine ("Errors:"); + SetColor (errorColor); foreach (string error in errors) WriteLine (error); + ResetColor (); } if (showSummary == true){ @@ -145,7 +240,9 @@ namespace Microsoft.Build.BuildEngine { public void ProjectStartedHandler (object sender, ProjectStartedEventArgs args) { + SetColor (eventColor); WriteLine (String.Format ("Project \"{0}\" ({1} target(s)):", args.ProjectFile, args.TargetNames)); + ResetColor (); WriteLine (String.Empty); } @@ -154,8 +251,10 @@ namespace Microsoft.Build.BuildEngine { if (IsVerbosityGreaterOrEqual (LoggerVerbosity.Normal)) { if (indent == 1) indent --; + SetColor (eventColor); WriteLine (String.Format ("Done building project \"{0}\".{1}", args.ProjectFile, args.Succeeded ? String.Empty : "-- FAILED")); + ResetColor (); WriteLine (String.Empty); } if (!projectFailed) @@ -166,24 +265,32 @@ namespace Microsoft.Build.BuildEngine { public void TargetStartedHandler (object sender, TargetStartedEventArgs args) { indent++; + SetColor (eventColor); WriteLine (String.Format ("Target {0}:",args.TargetName)); + ResetColor (); } public void TargetFinishedHandler (object sender, TargetFinishedEventArgs args) { - indent--; - if (IsVerbosityGreaterOrEqual (LoggerVerbosity.Detailed) || !args.Succeeded) + if (IsVerbosityGreaterOrEqual (LoggerVerbosity.Detailed) || !args.Succeeded) { + SetColor (eventColor); WriteLine (String.Format ("Done building target \"{0}\" in project \"{1}\".{2}", args.TargetName, args.ProjectFile, args.Succeeded ? String.Empty : "-- FAILED")); + ResetColor (); + } + indent--; WriteLine (String.Empty); } public void TaskStartedHandler (object sender, TaskStartedEventArgs args) { - if (this.verbosity == LoggerVerbosity.Detailed) + if (this.verbosity == LoggerVerbosity.Detailed) { + SetColor (eventColor); WriteLine (String.Format ("Task \"{0}\"",args.TaskName)); + ResetColor (); + } indent++; } @@ -191,25 +298,36 @@ namespace Microsoft.Build.BuildEngine { { indent--; if (this.verbosity == LoggerVerbosity.Detailed || !args.Succeeded) { + SetColor (eventColor); if (args.Succeeded) WriteLine (String.Format ("Done executing task \"{0}\"", args.TaskName)); else WriteLine (String.Format ("Task \"{0}\" execution -- FAILED", args.TaskName)); + ResetColor (); } } public void MessageHandler (object sender, BuildMessageEventArgs args) { if (IsMessageOk (args)) { - WriteLine (args.Message); + if (no_message_color) { + WriteLine (args.Message); + } else { + SetColor (args.Importance == MessageImportance.High ? highMessageColor : messageColor); + WriteLine (args.Message); + ResetColor (); + } } } public void WarningHandler (object sender, BuildWarningEventArgs args) { string msg = FormatWarningEvent (args); - if (IsVerbosityGreaterOrEqual (LoggerVerbosity.Normal)) + if (IsVerbosityGreaterOrEqual (LoggerVerbosity.Normal)) { + SetColor (warningColor); WriteLineWithoutIndent (msg); + ResetColor (); + } warnings.Add (msg); warningCount++; } @@ -217,8 +335,11 @@ namespace Microsoft.Build.BuildEngine { public void ErrorHandler (object sender, BuildErrorEventArgs args) { string msg = FormatErrorEvent (args); - if (IsVerbosityGreaterOrEqual (LoggerVerbosity.Minimal)) + if (IsVerbosityGreaterOrEqual (LoggerVerbosity.Minimal)) { + SetColor (errorColor); WriteLineWithoutIndent (msg); + ResetColor (); + } errors.Add (msg); errorCount++; } @@ -230,9 +351,16 @@ namespace Microsoft.Build.BuildEngine { private void WriteLine (string message) { - for (int i = 0; i < indent; i++) - Console.Write ('\t'); - writeHandler (message); + if (indent > 0) { + StringBuilder sb = new StringBuilder (); + for (int i = 0; i < indent; i++) + sb.Append ('\t'); + sb.Append (message); + + writeHandler (sb.ToString ()); + } else { + writeHandler (message); + } } private void WriteLineWithoutIndent (string message) @@ -244,6 +372,18 @@ namespace Microsoft.Build.BuildEngine { { Console.WriteLine (message); } + + void SetColor (ConsoleColor color) + { + if (!no_colors) + colorSet (color); + } + + void ResetColor () + { + if (!no_colors) + colorReset (); + } private void ParseParameters () { diff --git a/tools/xbuild/ChangeLog b/tools/xbuild/ChangeLog index 903ab24e0d..28ad2145cb 100644 --- a/tools/xbuild/ChangeLog +++ b/tools/xbuild/ChangeLog @@ -1,3 +1,10 @@ +2009-10-11 Ankit Jain + + * Main.cs: Add support for emitting messages in color. + Taking relevant code from mcs/report.cs . Using ANSI + color codes here instead of Console.ForegroundColor + because of a bug in Console. + 2009-10-08 Ankit Jain * xbuild/Microsoft.Common.targets: Don't get list of files diff --git a/tools/xbuild/Main.cs b/tools/xbuild/Main.cs index 8dc189e703..346e9a210b 100644 --- a/tools/xbuild/Main.cs +++ b/tools/xbuild/Main.cs @@ -3,8 +3,11 @@ // // Author: // Marek Sieradzki (marek.sieradzki@gmail.com) +// Miguel de Icaza (miguel@ximian.com) +// Marek Safar (marek.safar@seznam.cz) // // (C) 2005 Marek Sieradzki +// Copyright 2009 Novell, Inc (http://www.novell.com) // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the @@ -46,6 +49,8 @@ namespace Mono.XBuild.CommandLine { Engine engine; Project project; + ConsoleReportPrinter printer; + public static void Main (string[] args) { @@ -79,7 +84,10 @@ namespace Mono.XBuild.CommandLine { engine.GlobalProperties = this.parameters.Properties; if (!parameters.NoConsoleLogger) { - ConsoleLogger cl = new ConsoleLogger (); + printer = new ConsoleReportPrinter (); + ConsoleLogger cl = new ConsoleLogger (parameters.LoggerVerbosity, + printer.Print, printer.SetForeground, printer.ResetColor); + cl.Parameters = parameters.ConsoleLoggerParameters; cl.Verbosity = parameters.LoggerVerbosity; engine.RegisterLogger (cl); @@ -141,7 +149,163 @@ namespace Mono.XBuild.CommandLine { } } + + } + + // code from mcs/report.cs + class ConsoleReportPrinter + { + string prefix, postfix; + bool color_supported; + TextWriter writer; + string [] colorPrefixes; + + public ConsoleReportPrinter () + : this (Console.Out) + { + } + + public ConsoleReportPrinter (TextWriter writer) + { + this.writer = writer; + + string term = Environment.GetEnvironmentVariable ("TERM"); + bool xterm_colors = false; + + color_supported = false; + switch (term){ + case "xterm": + case "rxvt": + case "rxvt-unicode": + if (Environment.GetEnvironmentVariable ("COLORTERM") != null){ + xterm_colors = true; + } + break; + + case "xterm-color": + xterm_colors = true; + break; + } + if (!xterm_colors) + return; + + if (!(UnixUtils.isatty (1) && UnixUtils.isatty (2))) + return; + + color_supported = true; + PopulateColorPrefixes (); + postfix = "\x001b[0m"; + } + + void PopulateColorPrefixes () + { + colorPrefixes = new string [16]; + + colorPrefixes [(int)ConsoleColor.Black] = GetForeground ("black"); + colorPrefixes [(int)ConsoleColor.DarkBlue] = GetForeground ("blue"); + colorPrefixes [(int)ConsoleColor.DarkGreen] = GetForeground ("green"); + colorPrefixes [(int)ConsoleColor.DarkCyan] = GetForeground ("cyan"); + colorPrefixes [(int)ConsoleColor.DarkRed] = GetForeground ("red"); + colorPrefixes [(int)ConsoleColor.DarkMagenta] = GetForeground ("magenta"); + colorPrefixes [(int)ConsoleColor.DarkYellow] = GetForeground ("yellow"); + colorPrefixes [(int)ConsoleColor.DarkGray] = GetForeground ("grey"); + + colorPrefixes [(int)ConsoleColor.Gray] = GetForeground ("brightgrey"); + colorPrefixes [(int)ConsoleColor.Blue] = GetForeground ("brightblue"); + colorPrefixes [(int)ConsoleColor.Green] = GetForeground ("brightgreen"); + colorPrefixes [(int)ConsoleColor.Cyan] = GetForeground ("brightcyan"); + colorPrefixes [(int)ConsoleColor.Red] = GetForeground ("brightred"); + colorPrefixes [(int)ConsoleColor.Magenta] = GetForeground ("brightmagenta"); + colorPrefixes [(int)ConsoleColor.Yellow] = GetForeground ("brightyellow"); + + colorPrefixes [(int)ConsoleColor.White] = GetForeground ("brightwhite"); + } + + public void SetForeground (ConsoleColor color) + { + if (color_supported) + prefix = colorPrefixes [(int)color]; + } + + public void ResetColor () + { + prefix = "\x001b[0m"; + } + + static int NameToCode (string s) + { + switch (s) { + case "black": + return 0; + case "red": + return 1; + case "green": + return 2; + case "yellow": + return 3; + case "blue": + return 4; + case "magenta": + return 5; + case "cyan": + return 6; + case "grey": + case "white": + return 7; + } + return 7; + } + + // + // maps a color name to its xterm color code + // + static string GetForeground (string s) + { + string highcode; + + if (s.StartsWith ("bright")) { + highcode = "1;"; + s = s.Substring (6); + } else + highcode = ""; + + return "\x001b[" + highcode + (30 + NameToCode (s)).ToString () + "m"; + } + + static string GetBackground (string s) + { + return "\x001b[" + (40 + NameToCode (s)).ToString () + "m"; + } + + string FormatText (string txt) + { + if (prefix != null && color_supported) + return prefix + txt + postfix; + + return txt; + } + + public void Print (string message) + { + writer.WriteLine (FormatText (message)); + } + + } + + class UnixUtils { + [System.Runtime.InteropServices.DllImport ("libc", EntryPoint="isatty")] + extern static int _isatty (int fd); + + public static bool isatty (int fd) + { + try { + return _isatty (fd) == 1; + } catch { + return false; + } + } } + } #endif -- 2.11.4.GIT