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
20 * Brosch Florian <flo.brosch@gmail.com>
24 public class Valadoc
.ErrorReporter
: Object
{
25 private int _warnings
= 0;
26 private int _errors
= 0;
29 * SGR (Select Graphic Rendition) end tag
31 private const string ANSI_COLOR_END
= "\x1b[0m";
34 * SGR (Select Graphic Rendition) start tag for source location
36 private string locus_color_start
= "";
39 * SGR (Select Graphic Rendition) end tag for source location
41 private unowned
string locus_color_end
= "";
44 * SGR (Select Graphic Rendition) start tag for warning titles
46 private string warning_color_start
= "";
49 * SGR (Select Graphic Rendition) end tag for warning titles
51 private unowned
string warning_color_end
= "";
54 * SGR (Select Graphic Rendition) start tag for error titles
56 private string error_color_start
= "";
59 * SGR (Select Graphic Rendition) end tag for error titles
61 private unowned
string error_color_end
= "";
64 * SGR (Select Graphic Rendition) start tag for note titles
66 private string note_color_start
= "";
69 * SGR (Select Graphic Rendition) end tag for note titles
71 private unowned
string note_color_end
= "";
74 * SGR (Select Graphic Rendition) start tag for caret line (^^^)
76 private string caret_color_start
= "";
79 * SGR (Select Graphic Rendition) end tag for caret line (^^^)
81 private unowned
string caret_color_end
= "";
84 * SGR (Select Graphic Rendition) start tag for quotes line ('...', `...`, `...')
86 private string quote_color_start
= "";
89 * SGR (Select Graphic Rendition) end tag for quotes line ('...', `...`, `...')
91 private unowned
string quote_color_end
= "";
94 public int warnings_offset
{
99 public int errors_offset
{
104 public unowned GLib
.FileStream stream
{
109 public Settings? settings
{
116 return this
._errors
+ errors_offset
;
120 public int warnings
{
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
136 * "error=01;31:warning=01;35:note=01;36:caret=01;32:locus=01:quote=01"
139 public bool set_colors (string str
) {
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) {
161 if (!val_regex
.match (eq
[1])) {
166 unowned
string checked_value
= eq
[1]._strip ();
167 switch (eq
[0]._strip ()) {
169 error_color
= checked_value
;
173 warning_color
= checked_value
;
177 note_color
= checked_value
;
181 caret_color
= checked_value
;
185 locus_color
= checked_value
;
189 quote_color
= checked_value
;
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
;
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) {
241 module
.symbol ("isatty", out _func
);
246 AttyFunc? func
= (AttyFunc
) _func
;
247 return func (fd
) == 1;
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 ("^");
270 this
.stream
.printf (" ");
273 this
.stream
.puts (caret_color_end
);
274 this
.stream
.printf ("\n");
278 private void print_highlighted_message (string message
) {
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
));
289 while (message
[cur
] != '\0' && end_chars
.index_of_char (message
[cur
]) < 0) {
292 if (message
[cur
] == '\0') {
293 this
.stream
.puts (message
.substring (start
, cur
- start
));
297 this
.stream
.printf ("%s%s%s", quote_color_start
, message
.substring (start
, cur
- start
), quote_color_end
);
305 this
.stream
.puts (message
.offset (start
));
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');
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');
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');
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
);
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
);