SF.net SVN: geany:[2988] trunk

ntrel at users.sourceforge.net ntrel at xxxxx
Tue Sep 23 16:12:41 UTC 2008


Revision: 2988
          http://geany.svn.sourceforge.net/geany/?rev=2988&view=rev
Author:   ntrel
Date:     2008-09-23 16:12:40 +0000 (Tue, 23 Sep 2008)

Log Message:
-----------
Add filetypes.* [build_settings] key 'error_regex' to support custom
error message parsing using an extended regular expression.

Modified Paths:
--------------
    trunk/ChangeLog
    trunk/HACKING
    trunk/TODO
    trunk/doc/geany.html
    trunk/doc/geany.txt
    trunk/src/filetypes.c
    trunk/src/filetypes.h
    trunk/src/msgwindow.c

Modified: trunk/ChangeLog
===================================================================
--- trunk/ChangeLog	2008-09-23 15:19:46 UTC (rev 2987)
+++ trunk/ChangeLog	2008-09-23 16:12:40 UTC (rev 2988)
@@ -8,6 +8,10 @@
    Remove ParseData::dir argument as it's not necessary for parsing;
    instead, use function make_absolute().
    Refactor msgwin_parse_compiler_error_line().
+ * src/msgwindow.c, src/filetypes.c, src/filetypes.h, doc/geany.txt,
+   doc/geany.html, HACKING, TODO:
+   Add filetypes.* [build_settings] key 'error_regex' to support custom
+   error message parsing using an extended regular expression.
 
 
 2008-09-22  Nick Treleaven  <nick(dot)treleaven(at)btinternet(dot)com>

Modified: trunk/HACKING
===================================================================
--- trunk/HACKING	2008-09-23 15:19:46 UTC (rev 2987)
+++ trunk/HACKING	2008-09-23 16:12:40 UTC (rev 2988)
@@ -217,12 +217,18 @@
 4. Add this in highlighting_set_styles():
 styleset_case(GEANY_FILETYPES_FOO, foo);
 
+Error message parsing
+^^^^^^^^^^^^^^^^^^^^^
+New-style error message parsing is done with an extended GNU-style regex
+stored in the filetypes.foo file - see the [build_settings] information
+in the manual for details.
+
+Old-style error message parsing is done in
+msgwin_parse_compiler_error_line() of msgwindow.c - see the ParseData
+typedef for more information.
+
 Other features
 ^^^^^^^^^^^^^^
-Error message parsing is done in msgwin_parse_compiler_error_line() of
-msgwindow.c. See the ParseData typedef for more information. (In future
-this may be done with a regex).
-
 For brace indentation, update lexer_has_braces() in editor.c;
 indentation after ':' is done from on_new_line_added().
 
@@ -250,7 +256,7 @@
 In foo.c:
 Edit FooKinds 3rd column to match a s_tag_type_names string in tm_tag.c.
 
-In filetypes.c, filetypes_init_types():
+In filetypes.c, init_builtin_filetypes():
 Set filetypes[GEANY_FILETYPES_FOO].lang = foo's parser number.
 
 In symbols.c:

Modified: trunk/TODO
===================================================================
--- trunk/TODO	2008-09-23 15:19:46 UTC (rev 2987)
+++ trunk/TODO	2008-09-23 16:12:40 UTC (rev 2988)
@@ -14,7 +14,6 @@
 	o basic support for adding custom filetypes?
 	o configurable filetype and project make commands (e.g. using
 	  bud for D)
-	o configurable filetype regex for build errors
 	o recent projects menu
 	o project indentation settings support
 	o improve Compile toolbar button for Make (drop down radio list?)

Modified: trunk/doc/geany.html
===================================================================
--- trunk/doc/geany.html	2008-09-23 15:19:46 UTC (rev 2987)
+++ trunk/doc/geany.html	2008-09-23 16:12:40 UTC (rev 2988)
@@ -6,7 +6,7 @@
 <meta name="generator" content="Docutils 0.4: http://docutils.sourceforge.net/" />
 <title>Geany</title>
 <meta name="authors" content="Enrico Tröger  Nick Treleaven  Frank Lanitz" />
-<meta name="date" content="2008-09-17" />
+<meta name="date" content="2008-09-18" />
 <style type="text/css">
 
 /*
@@ -139,7 +139,7 @@
 <br />Nick Treleaven
 <br />Frank Lanitz</td></tr>
 <tr><th class="docinfo-name">Date:</th>
-<td>2008-09-17</td></tr>
+<td>2008-09-18</td></tr>
 <tr><th class="docinfo-name">Version:</th>
 <td>0.15</td></tr>
 </tbody>
@@ -3042,6 +3042,21 @@
 <div class="section">
 <h4><a class="toc-backref" href="#id136" id="build-settings-section" name="build-settings-section">[build_settings] Section</a></h4>
 <dl class="docutils">
+<dt>error_regex</dt>
+<dd><p class="first">This is a GNU-style extended regular expression to parse a filename
+and line number from build output. If undefined, Geany will fall
+back to its default error message parsing.</p>
+<p><em>Example:</em> <tt class="docutils literal"><span class="pre">error_regex=^(.+?):([0-9]+)</span></tt></p>
+<p class="last">This will parse a message of the form <tt class="docutils literal"><span class="pre">filename.c:123</span></tt>. (It uses
+non-greedy matching for the filename using the string <tt class="docutils literal"><span class="pre">+?</span></tt>).</p>
+</dd>
+</dl>
+<div class="note">
+<p class="first admonition-title">Note</p>
+<p class="last">The build commands are all configurable using <em>Build->Set Includes
+and Arguments</em>.</p>
+</div>
+<dl class="docutils">
 <dt>compiler</dt>
 <dd><p class="first">This item specifies the command to compile source code files. But
 it is also possible to use it with interpreted languages like Perl
@@ -4247,7 +4262,7 @@
 <div class="footer">
 <hr class="footer" />
 <a class="reference" href="geany.txt">View document source</a>.
-Generated on: 2008-09-18 12:00 UTC.
+Generated on: 2008-09-23 15:55 UTC.
 Generated by <a class="reference" href="http://docutils.sourceforge.net/">Docutils</a> from <a class="reference" href="http://docutils.sourceforge.net/rst.html">reStructuredText</a> source.
 
 </div>

Modified: trunk/doc/geany.txt
===================================================================
--- trunk/doc/geany.txt	2008-09-23 15:19:46 UTC (rev 2987)
+++ trunk/doc/geany.txt	2008-09-23 16:12:40 UTC (rev 2988)
@@ -2693,7 +2693,20 @@
 
 [build_settings] Section
 ````````````````````````
+error_regex
+    This is a GNU-style extended regular expression to parse a filename
+    and line number from build output. If undefined, Geany will fall
+    back to its default error message parsing.
 
+    *Example:* ``error_regex=^(.+?):([0-9]+)``
+
+    This will parse a message of the form ``filename.c:123``. (It uses
+    non-greedy matching for the filename using the string ``+?``).
+
+.. note::
+    The build commands are all configurable using *Build->Set Includes
+    and Arguments*.
+
 compiler
     This item specifies the command to compile source code files. But
     it is also possible to use it with interpreted languages like Perl

Modified: trunk/src/filetypes.c
===================================================================
--- trunk/src/filetypes.c	2008-09-23 15:19:46 UTC (rev 2987)
+++ trunk/src/filetypes.c	2008-09-23 16:12:40 UTC (rev 2988)
@@ -41,12 +41,22 @@
 #include "sciwrappers.h"
 #include "ui_utils.h"
 
+#ifdef HAVE_REGCOMP
+# ifdef HAVE_REGEX_H
+#  include <regex.h>
+# else
+#  include "gnuregex.h"
+# endif
+#endif
 
+
 /* Private GeanyFiletype fields */
 typedef struct GeanyFiletypePrivate
 {
-	GtkWidget		*menu_item;			/* holds a pointer to the menu item for this filetype */
-	gboolean		keyfile_loaded;
+	GtkWidget	*menu_item;			/* holds a pointer to the menu item for this filetype */
+	gboolean	keyfile_loaded;
+	regex_t		error_regex;
+	gboolean	error_regex_compiled;
 }
 GeanyFiletypePrivate;
 
@@ -59,6 +69,7 @@
 static void create_radio_menu_item(GtkWidget *menu, const gchar *label, GeanyFiletype *ftype);
 
 
+/* Note: remember to update HACKING if this function is renamed. */
 static void init_builtin_filetypes(void)
 {
 	GeanyFiletype *ft;
@@ -837,6 +848,18 @@
 #endif
 
 
+static void set_error_regex(GeanyFiletype *ft, gchar *string)
+{
+	setptr(ft->error_regex_string, string);
+
+	if (ft->priv->error_regex_compiled)
+		regfree(&ft->priv->error_regex);
+
+	ft->priv->error_regex_compiled = FALSE;
+	/* regex will be compiled when needed */
+}
+
+
 static void filetype_free(gpointer data, G_GNUC_UNUSED gpointer user_data)
 {
 	GeanyFiletype *ft = data;
@@ -855,6 +878,7 @@
 	g_free(ft->programs->run_cmd2);
 	g_free(ft->programs);
 	g_free(ft->actions);
+	set_error_regex(ft, NULL);
 
 	g_strfreev(ft->pattern);
 	g_free(ft);
@@ -875,6 +899,7 @@
 
 static void load_settings(gint ft_id, GKeyFile *config, GKeyFile *configh)
 {
+	GeanyFiletype *ft = filetypes[ft_id];
 	gchar *result;
 	GError *error = NULL;
 	gboolean tmp;
@@ -955,6 +980,13 @@
 		filetypes[ft_id]->programs->run_cmd2 = result;
 		filetypes[ft_id]->actions->can_exec = TRUE;
 	}
+
+	result = g_key_file_get_string(configh, "build_settings", "error_regex", NULL);
+	if (result == NULL) result = g_key_file_get_string(config, "build_settings", "error_regex", NULL);
+	if (result != NULL)
+	{
+		set_error_regex(ft, result);
+	}
 }
 
 
@@ -1146,3 +1178,68 @@
 }
 
 
+#ifdef HAVE_REGCOMP
+static gchar *get_regex_match_string(const gchar *message, regmatch_t *pmatch, gint match_idx)
+{
+	return g_strndup(&message[pmatch[match_idx].rm_so],
+		pmatch[match_idx].rm_eo - pmatch[match_idx].rm_so);
+}
+
+
+static void compile_regex(GeanyFiletype *ft, regex_t *regex)
+{
+	gint retval = regcomp(regex, ft->error_regex_string, REG_EXTENDED);
+
+	ft->priv->error_regex_compiled = (retval == 0);	/* prevent recompilation */
+
+	if (retval != 0)
+	{
+		gchar buf[256];
+		regerror(retval, regex, buf, sizeof buf);
+		ui_set_statusbar(TRUE, _("Bad regex for filetype %s: %s"),
+			ft->name, buf);
+	}
+	/* regex will be freed in set_error_regex(). */
+}
+#endif
+
+
+gboolean filetypes_parse_error_message(GeanyFiletype *ft, const gchar *message,
+		gchar **filename, gint *line)
+{
+#ifndef HAVE_REGCOMP
+	return FALSE;
+#else
+	regex_t *regex = &ft->priv->error_regex;
+	regmatch_t pmatch[3];
+
+	*filename = NULL;
+	*line = -1;
+
+	if (!NZV(ft->error_regex_string))
+		return FALSE;
+
+	if (!ft->priv->error_regex_compiled)
+		compile_regex(ft, regex);
+	if (!ft->priv->error_regex_compiled)	/* regex error */
+		return FALSE;
+
+	if (regexec(regex, message, G_N_ELEMENTS(pmatch), pmatch, 0) != 0)
+		return FALSE;
+
+	if (pmatch[0].rm_so != -1 && pmatch[1].rm_so != -1 && pmatch[2].rm_so != -1)
+	{
+		gchar *line_str;
+		glong l;
+
+		*filename = get_regex_match_string(message, pmatch, 1);
+		line_str = get_regex_match_string(message, pmatch, 2);
+		l = g_ascii_strtod(line_str, NULL);
+		g_free(line_str);
+		*line = l;
+		/* TODO: detect swapped line, file match order */
+	}
+	return *filename != NULL;
+#endif
+}
+

Modified: trunk/src/filetypes.h
===================================================================
--- trunk/src/filetypes.h	2008-09-23 15:19:46 UTC (rev 2987)
+++ trunk/src/filetypes.h	2008-09-23 16:12:40 UTC (rev 2988)
@@ -130,8 +130,9 @@
 	gchar	 		 *comment_close;
 	gboolean  		  comment_use_indent;
 	struct build_programs	*programs;
-	struct build_actions	*actions;
+	struct build_actions	*actions;	/* TODO: make private */
 	GeanyFiletypeGroupID	group;
+	gchar			 *error_regex_string;
 
 	struct GeanyFiletypePrivate	*priv;	/* must be last, append fields before this item */
 };
@@ -172,4 +173,7 @@
 
 gboolean filetype_has_tags(GeanyFiletype *ft);
 
+gboolean filetypes_parse_error_message(GeanyFiletype *ft, const gchar *message,
+		gchar **filename, gint *line);
+
 #endif

Modified: trunk/src/msgwindow.c
===================================================================
--- trunk/src/msgwindow.c	2008-09-23 15:19:46 UTC (rev 2987)
+++ trunk/src/msgwindow.c	2008-09-23 16:12:40 UTC (rev 2988)
@@ -854,6 +854,8 @@
 void msgwin_parse_compiler_error_line(const gchar *string, const gchar *dir,
 		gchar **filename, gint *line)
 {
+	GeanyFiletype *ft;
+
 	*filename = NULL;
 	*line = -1;
 
@@ -864,7 +866,14 @@
 		dir = build_info.dir;
 	g_return_if_fail(dir != NULL);
 
-	parse_compiler_error_line(string, filename, line);
+	ft = filetypes[build_info.file_type_id];
+
+	/* try parsing with a custom regex */
+	if (!filetypes_parse_error_message(ft, string, filename, line))
+	{
+		/* fallback to default old-style parsing */
+		parse_compiler_error_line(string, filename, line);
+	}
 	make_absolute(filename, dir);
 }
 


This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.



More information about the Commits mailing list