linux: Add constants from program_invocation_name(3)
[vala-gnome.git] / libvaladoc / errorreporter.vala
blobec189528cf0ded5182d862f2ca54c8ed7a7f6a5c
1 /* errorreporter.vala
3 * Copyright (C) 2008-2011 Florian Brosch
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 * Author:
20 * Brosch Florian <flo.brosch@gmail.com>
24 public class Valadoc.ErrorReporter : Object {
25 private int _warnings = 0;
26 private int _errors = 0;
28 /**
29 * SGR (Select Graphic Rendition) end tag
31 private const string ANSI_COLOR_END = "\x1b[0m";
33 /**
34 * SGR (Select Graphic Rendition) start tag for source location
36 private string locus_color_start = "";
38 /**
39 * SGR (Select Graphic Rendition) end tag for source location
41 private unowned string locus_color_end = "";
43 /**
44 * SGR (Select Graphic Rendition) start tag for warning titles
46 private string warning_color_start = "";
48 /**
49 * SGR (Select Graphic Rendition) end tag for warning titles
51 private unowned string warning_color_end = "";
53 /**
54 * SGR (Select Graphic Rendition) start tag for error titles
56 private string error_color_start = "";
58 /**
59 * SGR (Select Graphic Rendition) end tag for error titles
61 private unowned string error_color_end = "";
63 /**
64 * SGR (Select Graphic Rendition) start tag for note titles
66 private string note_color_start = "";
68 /**
69 * SGR (Select Graphic Rendition) end tag for note titles
71 private unowned string note_color_end = "";
73 /**
74 * SGR (Select Graphic Rendition) start tag for caret line (^^^)
76 private string caret_color_start = "";
78 /**
79 * SGR (Select Graphic Rendition) end tag for caret line (^^^)
81 private unowned string caret_color_end = "";
83 /**
84 * SGR (Select Graphic Rendition) start tag for quotes line ('...', `...`, `...')
86 private string quote_color_start = "";
88 /**
89 * SGR (Select Graphic Rendition) end tag for quotes line ('...', `...`, `...')
91 private unowned string quote_color_end = "";
94 public int warnings_offset {
95 get;
96 set;
99 public int errors_offset {
100 get;
101 set;
104 public unowned GLib.FileStream stream {
105 get;
106 set;
109 public Settings? settings {
110 get;
111 set;
114 public int errors {
115 get {
116 return this._errors + errors_offset;
120 public int warnings {
121 get {
122 return this._warnings + warnings_offset;
127 public ErrorReporter (Settings? settings = null) {
128 this.stream = GLib.stderr;
129 this.settings = settings;
133 * Set all colors by string
135 * {{{
136 * "error=01;31:warning=01;35:note=01;36:caret=01;32:locus=01:quote=01"
137 * }}}
139 public bool set_colors (string str) {
140 Regex val_regex;
141 try {
142 val_regex = new Regex ("^\\s*[0-9]+(;[0-9]*)*\\s*$");
143 } catch (RegexError e) {
144 assert_not_reached ();
147 string error_color = null;
148 string warning_color = null;
149 string note_color = null;
150 string caret_color = null;
151 string locus_color = null;
152 string quote_color = null;
154 string[] fragments = str.split (":");
155 foreach (unowned string fragment in fragments) {
156 string[] eq = fragment.split ("=", 2);
157 if (eq.length != 2) {
158 return false;
161 if (!val_regex.match (eq[1])) {
162 return false;
166 unowned string checked_value = eq[1]._strip ();
167 switch (eq[0]._strip ()) {
168 case "error":
169 error_color = checked_value;
170 break;
172 case "warning":
173 warning_color = checked_value;
174 break;
176 case "note":
177 note_color = checked_value;
178 break;
180 case "caret":
181 caret_color = checked_value;
182 break;
184 case "locus":
185 locus_color = checked_value;
186 break;
188 case "quote":
189 quote_color = checked_value;
190 break;
192 default:
193 return false;
197 if (is_atty (this.stream.fileno ())) {
198 if (error_color != null) {
199 this.error_color_start = "\x1b[0" + error_color + "m";
200 this.error_color_end = ANSI_COLOR_END;
203 if (warning_color != null) {
204 this.warning_color_start = "\x1b[0" + warning_color + "m";
205 this.warning_color_end = ANSI_COLOR_END;
208 if (note_color != null) {
209 this.note_color_start = "\x1b[0" + note_color + "m";
210 this.note_color_end = ANSI_COLOR_END;
213 if (caret_color != null) {
214 this.caret_color_start = "\x1b[0" + caret_color + "m";
215 this.caret_color_end = ANSI_COLOR_END;
218 if (locus_color != null) {
219 this.locus_color_start = "\x1b[0" + locus_color + "m";
220 this.locus_color_end = ANSI_COLOR_END;
223 if (quote_color != null) {
224 this.quote_color_start = "\x1b[0" + quote_color + "m";
225 this.quote_color_end = ANSI_COLOR_END;
228 return true;
231 [CCode (has_target = false)]
232 private delegate int AttyFunc (int fd);
234 private bool is_atty (int fd) {
235 Module module = Module.open (null, ModuleFlags.BIND_LAZY);
236 if (module == null) {
237 return false;
240 void* _func;
241 module.symbol ("isatty", out _func);
242 if (_func == null) {
243 return false;
246 AttyFunc? func = (AttyFunc) _func;
247 return func (fd) == 1;
250 [PrintfFormat]
251 private inline void msg (string type, string type_color_start, string type_color_end, string file, long line, long startpos, long endpos,
252 string errline, string msg_format, va_list args)
254 this.stream.printf ("%s%s:%lu.%lu-%lu.%lu:%s %s%s:%s ",
255 locus_color_start, file, line, startpos, line, endpos, locus_color_end,
256 type_color_start, type, type_color_end);
257 print_highlighted_message (msg_format.vprintf (args));
258 this.stream.putc ('\n');
260 if (startpos <= endpos) {
261 this.stream.printf ("%s\n", errline);
263 this.stream.puts (caret_color_start);
264 for (int i = 0; i < errline.char_count ()+1; i++) {
265 if (errline[i] == '\t') {
266 this.stream.printf ("\t");
267 } else if (i >= startpos - 1 && i < endpos - 1) {
268 this.stream.printf ("^");
269 } else {
270 this.stream.printf (" ");
273 this.stream.puts (caret_color_end);
274 this.stream.printf ("\n");
278 private void print_highlighted_message (string message) {
279 int start = 0;
280 int cur = 0;
282 while (message[cur] != '\0') {
283 if (message[cur] == '\'' || message[cur] == '`') {
284 unowned string end_chars = (message[cur] == '`')? "`'" : "'";
285 this.stream.puts (message.substring (start, cur - start));
286 start = cur;
287 cur++;
289 while (message[cur] != '\0' && end_chars.index_of_char (message[cur]) < 0) {
290 cur++;
292 if (message[cur] == '\0') {
293 this.stream.puts (message.substring (start, cur - start));
294 start = cur;
295 } else {
296 cur++;
297 this.stream.printf ("%s%s%s", quote_color_start, message.substring (start, cur - start), quote_color_end);
298 start = cur;
300 } else {
301 cur++;
305 this.stream.puts (message.offset (start));
308 [PrintfFormat]
309 public void simple_warning (string? location, string msg_format, ...) {
310 var args = va_list();
312 if (location != null) {
313 this.stream.puts (locus_color_start);
314 this.stream.puts (location);
315 this.stream.puts (": ");
316 this.stream.puts (locus_color_end);
319 this.stream.puts (warning_color_start);
320 this.stream.puts ("warning: ");
321 this.stream.puts (warning_color_end);
323 print_highlighted_message (msg_format.vprintf (args));
324 this.stream.putc ('\n');
325 this._warnings++;
328 [PrintfFormat]
329 public void simple_error (string? location, string msg_format, ...) {
330 var args = va_list();
332 if (location != null) {
333 this.stream.puts (locus_color_start);
334 this.stream.puts (location);
335 this.stream.puts (": ");
336 this.stream.puts (locus_color_end);
337 this.stream.putc (' ');
340 this.stream.puts (error_color_start);
341 this.stream.puts ("error: ");
342 this.stream.puts (error_color_end);
344 print_highlighted_message (msg_format.vprintf (args));
345 this.stream.putc ('\n');
346 this._errors++;
349 [PrintfFormat]
350 public void simple_note (string? location, string msg_format, ...) {
351 if (_settings == null || _settings.verbose) {
352 var args = va_list();
354 if (location != null) {
355 this.stream.puts (locus_color_start);
356 this.stream.puts (location);
357 this.stream.puts (": ");
358 this.stream.puts (locus_color_end);
359 this.stream.putc (' ');
362 this.stream.puts (note_color_start);
363 this.stream.puts ("note: ");
364 this.stream.puts (note_color_end);
366 print_highlighted_message (msg_format.vprintf (args));
367 this.stream.putc ('\n');
368 this._warnings++;
372 [PrintfFormat]
373 public void error (string file, long line, long startpos, long endpos, string errline,
374 string msg_format, ...)
376 var args = va_list();
377 this.msg ("error", error_color_start, error_color_end, file, line, startpos, endpos, errline, msg_format, args);
378 this._errors++;
381 [PrintfFormat]
382 public void warning (string file, long line, long startpos, long endpos, string errline,
383 string msg_format, ...)
385 var args = va_list();
386 this.msg ("warning", warning_color_start, warning_color_end, file, line, startpos, endpos, errline, msg_format, args);
387 this._warnings++;