[vala] Add colored output
- From: Luca Bruno <lucabru src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [vala] Add colored output
- Date: Tue, 23 Sep 2014 09:42:25 +0000 (UTC)
commit 4fb521efd3ea9b38aba5ae599d55083d1c2f9a93
Author: Florian Brosch <flo brosch gmail com>
Date: Tue Sep 2 21:17:46 2014 +0200
Add colored output
Use --no-color to disable colors
Use VALA_COLORS to change colors
E.g. VALA_COLORS = "error=01;31:warning=01;35:note=01;36:caret=01;32:locus=01:quote=01"
Fixes bug 734627.
compiler/valacompiler.vala | 21 +++-
vala/Makefile.am | 4 +-
vala/valareport.vala | 281 ++++++++++++++++++++++++++++++++++++++------
3 files changed, 268 insertions(+), 38 deletions(-)
---
diff --git a/compiler/valacompiler.vala b/compiler/valacompiler.vala
index cbb661c..3f88124 100644
--- a/compiler/valacompiler.vala
+++ b/compiler/valacompiler.vala
@@ -24,6 +24,8 @@
using GLib;
class Vala.Compiler {
+ private const string DEFAULT_COLORS =
"error=01;31:warning=01;35:note=01;36:caret=01;32:locus=01:quote=01";
+
static string basedir;
static string directory;
static bool version;
@@ -84,6 +86,7 @@ class Vala.Compiler {
static bool enable_version_header;
static bool disable_version_header;
static bool fatal_warnings;
+ static bool disable_diagnostic_colors;
static string dependencies;
static string entry_point;
@@ -140,6 +143,7 @@ class Vala.Compiler {
{ "profile", 0, 0, OptionArg.STRING, ref profile, "Use the given profile instead of the
default", "PROFILE" },
{ "quiet", 'q', 0, OptionArg.NONE, ref quiet_mode, "Do not print messages to the console",
null },
{ "verbose", 'v', 0, OptionArg.NONE, ref verbose_mode, "Print additional messages to the
console", null },
+ { "no-color", 0, 0, OptionArg.NONE, ref disable_diagnostic_colors, "Disable colored output",
null },
{ "target-glib", 0, 0, OptionArg.STRING, ref target_glib, "Target version of glib for code
generation", "MAJOR.MINOR" },
{ "gresources", 0, 0, OptionArg.STRING_ARRAY, ref gresources, "XML of gresources", "FILE..."
},
{ "enable-version-header", 0, 0, OptionArg.NONE, ref enable_version_header, "Write vala build
version in generated files", null },
@@ -147,7 +151,7 @@ class Vala.Compiler {
{ "", 0, 0, OptionArg.FILENAME_ARRAY, ref sources, null, "FILE..." },
{ null }
};
-
+
private int quit () {
if (context.report.get_errors () == 0 && context.report.get_warnings () == 0) {
return 0;
@@ -169,6 +173,17 @@ class Vala.Compiler {
context = new CodeContext ();
CodeContext.push (context);
+ if (disable_diagnostic_colors == false) {
+ string[] env_args = Environ.get ();
+ unowned string env_colors = Environ.get_variable (env_args, "VALA_COLORS");
+ if (env_colors != null) {
+ context.report.set_colors (env_colors);
+ } else {
+ context.report.set_colors (DEFAULT_COLORS);
+ }
+ }
+
+
// default to build executable
if (!ccode_only && !compile_only && output == null) {
// strip extension if there is one
@@ -292,7 +307,7 @@ class Vala.Compiler {
}
context.gresources = gresources;
-
+
if (context.report.get_errors () > 0 || (fatal_warnings && context.report.get_warnings () >
0)) {
return quit ();
}
@@ -319,7 +334,7 @@ class Vala.Compiler {
if (context.report.get_errors () > 0 || (fatal_warnings && context.report.get_warnings () >
0)) {
return quit ();
}
-
+
var parser = new Parser ();
parser.parse (context);
diff --git a/vala/Makefile.am b/vala/Makefile.am
index 54d01bd..c7fbc0e 100644
--- a/vala/Makefile.am
+++ b/vala/Makefile.am
@@ -6,6 +6,7 @@ AM_CPPFLAGS = \
$(COVERAGE_CFLAGS) \
-I$(top_srcdir)/gee \
$(GLIB_CFLAGS) \
+ $(GMODULE_CFLAGS) \
-DPACKAGE_DATADIR=\"$(pkgdatadir)\" \
$(NULL)
@@ -179,7 +180,7 @@ vala.vapi vala.vala.stamp: $(libvalacore_la_VALASOURCES)
$(COVERAGE_VALAFLAGS) \
$(VALAFLAGS) \
-C \
- --vapidir $(top_srcdir)/vapi --pkg gobject-2.0 \
+ --vapidir $(top_srcdir)/vapi --pkg gmodule-2.0 --pkg gobject-2.0 \
--vapidir $(top_srcdir)/gee --pkg gee \
--pkg config \
-H vala.h \
@@ -190,6 +191,7 @@ vala.vapi vala.vala.stamp: $(libvalacore_la_VALASOURCES)
libvalacore_la_LIBADD = \
$(COVERAGE_LIBS) \
$(GLIB_LIBS) \
+ $(GMODULE_LIBS) \
$(top_builddir)/gee/libgee.la \
$(NULL)
diff --git a/vala/valareport.vala b/vala/valareport.vala
index 18169c5..67b3a80 100644
--- a/vala/valareport.vala
+++ b/vala/valareport.vala
@@ -22,17 +22,184 @@
using GLib;
+
/**
* Namespace to centralize reporting warnings and errors.
*/
public class Vala.Report : Object {
+ /**
+ * SGR end tag
+ */
+ private const string ANSI_COLOR_END = "\x1b[0m";
+
+ /**
+ * SGR start tag for source location
+ */
+ private string locus_color_start = "";
+
+ /**
+ * SGR end tag for source location
+ */
+ private unowned string locus_color_end = "";
+
+ /**
+ * SGR start tag for warning titles
+ */
+ private string warning_color_start = "";
+
+ /**
+ * SGR end tag for warning titles
+ */
+ private unowned string warning_color_end = "";
+
+ /**
+ * SGR start tag for error titles
+ */
+ private string error_color_start = "";
+
+ /**
+ * SGR end tag for error titles
+ */
+ private unowned string error_color_end = "";
+
+ /**
+ * SGR start tag for note titles
+ */
+ private string note_color_start = "";
+
+ /**
+ * SGR end tag for note titles
+ */
+ private unowned string note_color_end = "";
+
+ /**
+ * SGR start tag for caret line (^^^)
+ */
+ private string caret_color_start = "";
+
+ /**
+ * SGR end tag for caret line (^^^)
+ */
+ private unowned string caret_color_end = "";
+
+ /**
+ * SGR start tag for quotes line ('', ``, `')
+ */
+ private string quote_color_start = "";
+
+ /**
+ * SGR end tag for quotes line ('', ``, `')
+ */
+ private unowned string quote_color_end = "";
+
+
protected int warnings;
protected int errors;
- bool verbose_errors;
+ private bool verbose_errors;
public bool enable_warnings { get; set; default = true; }
+
+ /**
+ * Set all colors by string
+ *
+ * {{{
+ * "error=01;31:warning=01;35:note=01;36:caret=01;32:locus=01:quote=01"
+ * }}}
+ */
+ public bool set_colors (string str) {
+ Regex val_regex;
+ try {
+ val_regex = new Regex ("^\\s*[0-9]+(;[0-9]*)*\\s*$");
+ } catch (RegexError e) {
+ assert_not_reached ();
+ }
+
+ string error_color = null;
+ string warning_color = null;
+ string note_color = null;
+ string caret_color = null;
+ string locus_color = null;
+ string quote_color = null;
+
+ string[] fragments = str.split (":");
+ foreach (unowned string fragment in fragments) {
+ string[] eq = fragment.split ("=", 2);
+ if (eq.length != 2) {
+ return false;
+ }
+
+ if (!val_regex.match (eq[1])) {
+ return false;
+ }
+
+
+ unowned string checked_value = eq[1]._strip ();
+ switch (eq[0]._strip ()) {
+ case "error":
+ error_color = checked_value;
+ break;
+
+ case "warning":
+ warning_color = checked_value;
+ break;
+
+ case "note":
+ note_color = checked_value;
+ break;
+
+ case "caret":
+ caret_color = checked_value;
+ break;
+
+ case "locus":
+ locus_color = checked_value;
+ break;
+
+ case "quote":
+ quote_color = checked_value;
+ break;
+
+ default:
+ return false;
+ }
+ }
+
+ if (is_atty (stderr.fileno ())) {
+ if (error_color != null) {
+ this.error_color_start = "\x1b[0" + error_color + "m";
+ this.error_color_end = ANSI_COLOR_END;
+ }
+
+ if (warning_color != null) {
+ this.warning_color_start = "\x1b[0" + warning_color + "m";
+ this.warning_color_end = ANSI_COLOR_END;
+ }
+
+ if (note_color != null) {
+ this.note_color_start = "\x1b[0" + note_color + "m";
+ this.note_color_end = ANSI_COLOR_END;
+ }
+
+ if (caret_color != null) {
+ this.caret_color_start = "\x1b[0" + caret_color + "m";
+ this.caret_color_end = ANSI_COLOR_END;
+ }
+
+ if (locus_color != null) {
+ this.locus_color_start = "\x1b[0" + locus_color + "m";
+ this.locus_color_end = ANSI_COLOR_END;
+ }
+
+ if (quote_color != null) {
+ this.quote_color_start = "\x1b[0" + quote_color + "m";
+ this.quote_color_end = ANSI_COLOR_END;
+ }
+ }
+ return true;
+ }
+
/**
* Set the error verbosity.
*/
@@ -46,7 +213,7 @@ public class Vala.Report : Object {
public int get_warnings () {
return warnings;
}
-
+
/**
* Returns the total number of errors reported.
*/
@@ -57,7 +224,7 @@ public class Vala.Report : Object {
/**
* Pretty-print the actual line of offending code if possible.
*/
- static void report_source (SourceReference source) {
+ private void report_source (SourceReference source) {
if (source.begin.line != source.end.line) {
// FIXME Cannot report multi-line issues currently
return;
@@ -68,7 +235,7 @@ public class Vala.Report : Object {
if (offending_line != null) {
stderr.printf ("%s\n", offending_line);
int idx;
-
+
/* We loop in this manner so that we don't fall over on differing
* tab widths. This means we get the ^s in the right places.
*/
@@ -80,6 +247,7 @@ public class Vala.Report : Object {
}
}
+ stderr.puts (caret_color_start);
for (idx = source.begin.column; idx <= source.end.column; ++idx) {
if (offending_line[idx - 1] == '\t') {
stderr.printf ("\t");
@@ -87,11 +255,58 @@ public class Vala.Report : Object {
stderr.printf ("^");
}
}
+ stderr.puts (caret_color_end);
stderr.printf ("\n");
}
}
+ private void print_highlighted_message (string message) {
+ int start = 0;
+ int cur = 0;
+
+ while (message[cur] != '\0') {
+ if (message[cur] == '\'' || message[cur] == '`') {
+ unowned string end_chars = (message[cur] == '`')? "`'" : "'";
+ stderr.puts (message.substring (start, cur - start));
+ start = cur;
+ cur++;
+
+ while (message[cur] != '\0' && end_chars.index_of_char (message[cur]) < 0) {
+ cur++;
+ }
+ if (message[cur] == '\0') {
+ stderr.puts (message.substring (start, cur - start));
+ start = cur;
+ } else {
+ cur++;
+ stderr.printf ("%s%s%s", quote_color_start, message.substring (start,
cur - start), quote_color_end);
+ start = cur;
+ }
+ } else {
+ cur++;
+ }
+ }
+
+ stderr.puts (message.offset (start));
+ }
+
+ private void print_message (SourceReference? source, string type, string type_color_start, string
type_color_end, string message, bool do_report_source) {
+ if (source != null) {
+ stderr.printf ("%s%s:%s ", locus_color_start, source.to_string (), locus_color_end);
+ }
+
+ stderr.printf ("%s%s:%s ", type_color_start, type, type_color_end);
+
+ // highlight '', `', ``
+ print_highlighted_message (message);
+ stderr.putc ('\n');
+
+ if (do_report_source && source != null) {
+ report_source (source);
+ }
+ }
+
/**
* Reports the specified message as note.
*
@@ -103,14 +318,7 @@ public class Vala.Report : Object {
return;
}
- if (source == null) {
- stderr.printf ("note: %s\n", message);
- } else {
- stderr.printf ("%s: note: %s\n", source.to_string (), message);
- if (verbose_errors) {
- report_source (source);
- }
- }
+ print_message (source, "note", note_color_start, note_color_end, message, verbose_errors);
}
/**
@@ -125,11 +333,8 @@ public class Vala.Report : Object {
}
warnings++;
- if (source == null) {
- stderr.printf ("warning: %s\n", message);
- } else {
- stderr.printf ("%s: warning: %s\n", source.to_string (), message);
- }
+
+ print_message (source, "warning", warning_color_start, warning_color_end, message, false);
}
/**
@@ -144,16 +349,10 @@ public class Vala.Report : Object {
}
warnings++;
- if (source == null) {
- stderr.printf ("warning: %s\n", message);
- } else {
- stderr.printf ("%s: warning: %s\n", source.to_string (), message);
- if (verbose_errors) {
- report_source (source);
- }
- }
+
+ print_message (source, "warning", warning_color_start, warning_color_end, message,
verbose_errors);
}
-
+
/**
* Reports the specified message as error.
*
@@ -162,14 +361,8 @@ public class Vala.Report : Object {
*/
public virtual void err (SourceReference? source, string message) {
errors++;
- if (source == null) {
- stderr.printf ("error: %s\n", message);
- } else {
- stderr.printf ("%s: error: %s\n", source.to_string (), message);
- if (verbose_errors) {
- report_source (source);
- }
- }
+
+ print_message (source, "error", error_color_start, error_color_end, message, verbose_errors);
}
/* Convenience methods calling warn and err on correct instance */
@@ -188,4 +381,24 @@ public class Vala.Report : Object {
public static void error (SourceReference? source, string message) {
CodeContext.get ().report.err (source, message);
}
+
+
+ [CCode (has_target = false)]
+ private delegate int AttyFunc (int fd);
+
+ private bool is_atty (int fd) {
+ Module module = Module.open (null, ModuleFlags.BIND_LAZY);
+ if (module == null) {
+ return false;
+ }
+
+ void* _func;
+ module.symbol ("isatty", out _func);
+ if (_func == null) {
+ return false;
+ }
+
+ AttyFunc? func = (AttyFunc) _func;
+ return func (fd) == 1;
+ }
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]