[gnome-latex: 163/205] Compil output: filter the messages



commit 0b2fd2f4343469e319c68d870da71b72e3fa2ca0
Author: Sébastien Wilmet <sebastien wilmet gmail com>
Date:   Tue Jan 5 01:11:28 2010 +0100

    Compil output: filter the messages
    
    For the moment it's only matching if we take a line or not, we don't
    extract informations from it (like the line or the filename).

 TODO                    |  11 ++
 src/CMakeLists.txt      |   3 +-
 src/callbacks.c         |  20 +--
 src/external_commands.c | 347 ++++++++++++++++++++++++++----------------------
 src/external_commands.h |   4 +-
 src/print.c             |  10 +-
 src/print.h             |  10 +-
 src/utils.c             |  31 +++++
 src/utils.h             |  25 ++++
 9 files changed, 283 insertions(+), 178 deletions(-)
---
diff --git a/TODO b/TODO
index bda32f1..0370b29 100644
--- a/TODO
+++ b/TODO
@@ -1,2 +1,13 @@
 TODO LaTeXila
 
+- User-friendly output for the compilation
+       x filter the messages
+       - show the exit code
+       - show statistics: nb of errors, warnings and badboxes
+       - jump to lines: GtkTextBuffer -> GtkListStore
+       - colors
+       - go to the previous/next error/warning/badbox
+
+- Auto-completion of LaTeX commands
+
+- Change the title of the window with the filename of the current document
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index b05a6c2..6904912 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -8,7 +8,8 @@ SET(latexila_src main.c                 main.h
                 ui.c                   ui.h
                 tool_menu_action.c     tool_menu_action.h
                 file_browser.c         file_browser.h
-                templates.c            templates.h)
+                templates.c            templates.h
+                utils.c                utils.h)
 
 ADD_EXECUTABLE(latexila ${latexila_src})
 TARGET_LINK_LIBRARIES(latexila ${GTK2_LIBRARIES})
diff --git a/src/callbacks.c b/src/callbacks.c
index 6684bd6..7027043 100644
--- a/src/callbacks.c
+++ b/src/callbacks.c
@@ -613,16 +613,20 @@ cb_latex (void)
 
        gchar *title = _("Compile (latex)");
        gchar *command[] = {
-        g_strdup (latexila.prefs.command_latex),
+        latexila.prefs.command_latex,
         "-interaction=nonstopmode",
-        g_strdup (latexila.active_doc->path),
+               "-file-line-error",
+               // we take the basename because the command is run inside the directory
+               // of the document, and the output lines which contains the filename
+               // are shorter (the lines too long are splitted, so the user can not
+               // see all the line if there is a filter which operate line per line)
+        g_path_get_basename (latexila.active_doc->path),
         NULL
     };
 
     compile_document (title, command);
 
-    g_free (command[0]);
-    g_free (command[2]);
+       g_free (command[3]);
 }
 
 void
@@ -635,16 +639,16 @@ cb_pdflatex (void)
 
        gchar *title = _("Compile (pdflatex)");
        gchar *command[] = {
-        g_strdup (latexila.prefs.command_pdflatex),
+        latexila.prefs.command_pdflatex,
         "-interaction=nonstopmode",
-        g_strdup (latexila.active_doc->path),
+               "-file-line-error",
+        g_path_get_basename (latexila.active_doc->path),
         NULL
     };
 
     compile_document (title, command);
 
-    g_free (command[0]);
-    g_free (command[2]);
+       g_free (command[3]);
 }
 
 void
diff --git a/src/external_commands.c b/src/external_commands.c
index 81d3b59..da0da78 100644
--- a/src/external_commands.c
+++ b/src/external_commands.c
@@ -1,7 +1,7 @@
 /*
  * This file is part of LaTeXila.
  *
- * Copyright © 2009 Sébastien Wilmet
+ * Copyright © 2009, 2010 Sébastien Wilmet
  *
  * LaTeXila is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -29,115 +29,23 @@
 
 #include "main.h"
 #include "config.h"
-#include "external_commands.h"
 #include "print.h"
+#include "utils.h"
+#include "external_commands.h"
 #include "file_browser.h"
 
+static void add_action (const gchar *title, const gchar *command);
+static void set_action_sensitivity (gboolean sensitive);
 static gchar * get_command_line (gchar **command);
-static void command_running_finished (void);
 static gboolean cb_watch_output_command (GIOChannel *channel,
                GIOCondition condition, gpointer user_data);
-static void add_action (const gchar *title, const gchar *command);
-static void set_action_sensitivity (gboolean sensitive);
+static void output_filter_line (const gchar *line);
+static void command_running_finished (void);
 static void view_document_run (gchar *filename);
 static void run_command_on_other_extension (gchar *title, gchar *message,
                gchar *command, gchar *extension);
 
-static gchar *
-get_command_line (gchar **command)
-{
-       if (command[0] == NULL)
-               return NULL;
-
-       gchar *command_line = g_strdup (command[0]);
-       gchar *tmp;
-       gchar **arg = command;
-       arg++;
-       while (*arg != NULL)
-       {
-               tmp = g_strdup_printf ("%s %s", command_line, *arg);
-               g_free (command_line);
-               command_line = tmp;
-               arg++;
-       }
-
-       return command_line;
-}
-
-static void
-command_running_finished (void)
-{
-       // the magic formula
-       while (gtk_events_pending ())
-               gtk_main_iteration ();
-
-       // unlock the action list and all the build actions
-       set_action_sensitivity (TRUE);
-
-       // pop the message from the statusbar
-       guint context_id = gtk_statusbar_get_context_id (latexila.statusbar,
-                       "running-action");
-       gtk_statusbar_pop (latexila.statusbar, context_id);
-
-       cb_file_browser_refresh (NULL, NULL);
-}
-
-static gboolean
-cb_watch_output_command (GIOChannel *channel, GIOCondition condition,
-               gpointer user_data)
-{
-       static int nb_lines = 0;
-       static int nb_channels_active = 2;
-
-       if (condition == G_IO_HUP)
-       {
-               g_io_channel_unref (channel);
-               nb_channels_active--;
-               
-               if (nb_channels_active == 0)
-               {
-                       command_running_finished ();
-                       nb_lines = 0;
-                       nb_channels_active = 2;
-               }
-
-               return FALSE;
-       }
-
-       GError *error = NULL;
-       gchar *line;
-       g_io_channel_read_line (channel, &line, NULL, NULL, &error);
-
-       if (error != NULL)
-       {
-               print_warning ("read line from output command failed: %s", error->message);
-               g_error_free (error);
-               return FALSE;
-       }
-
-       if (line != NULL)
-       {
-               // print the command output line to the log zone
-               print_log_add (latexila.action_log.text_view, line, FALSE);
-       }
-       
-       /* Apply the magic formula for the 200 first lines and then every 20 lines.
-        * This is for the fluidity of the output, without that the lines do not
-        * appear directly and it's ugly. But it is very slow, for a command that
-        * execute for example in 10 seconds, it could take 250 seconds (!) if we
-        * apply the magic formula for each line... But with commands that take 1
-        * second or so there is not a big difference.
-        */
-       if (nb_lines < 200 || nb_lines % 20 == 0)
-       {
-               while (gtk_events_pending ())
-                       gtk_main_iteration ();
-       }
-
-       nb_lines++;
-
-       return TRUE;
-}
+static gboolean show_all_output = TRUE;
 
 void
 compile_document (gchar *title, gchar **command)
@@ -169,9 +77,7 @@ compile_document (gchar *title, gchar **command)
                        _("Compilation in progress. Please wait..."));
 
        // without that, the message in the statusbar does not appear
-       while (gtk_events_pending ())
-               gtk_main_iteration ();
-
+       flush_queue ();
 
        /* run the command */
        gchar *dir = g_path_get_dirname (latexila.active_doc->path);
@@ -198,6 +104,7 @@ compile_document (gchar *title, gchar **command)
        GIOChannel *out_channel = g_io_channel_unix_new (out);
        GIOChannel *err_channel = g_io_channel_unix_new (err);
 
+#if 0
        // the encoding of the output of the latex and the pdflatex commands is not
        // UTF-8...
        g_io_channel_set_encoding (out_channel, "ISO-8859-1", &error);
@@ -213,10 +120,13 @@ compile_document (gchar *title, gchar **command)
                g_error_free (error);
                return;
        }
+#endif
 
        // lock the action list and all the build actions
        set_action_sensitivity (FALSE);
 
+       show_all_output = FALSE;
+
        // add watches to channels
        g_io_add_watch (out_channel, G_IO_IN | G_IO_HUP,
                        (GIOFunc) cb_watch_output_command, NULL);
@@ -286,38 +196,6 @@ view_document (gchar *title, gchar *filename)
        view_document_run (filename);
 }
 
-static void
-view_document_run (gchar *filename)
-{
-       // we use here g_spawn_async () and not g_spawn_command_line_async ()
-       // because the spaces in doc_path are not escaped, so with the command line
-       // it doesn't work fine...
-       
-       GError *error = NULL;
-       gchar *argv[] = {latexila.prefs.command_view, filename, NULL};
-       g_spawn_async (NULL, argv, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL, NULL, &error);
-
-       gboolean is_error = TRUE;
-       gchar *command_output;
-
-       if (error != NULL)
-       {
-               command_output = g_strdup_printf (_("execution failed: %s"),
-                               error->message);
-               g_error_free (error);
-               error = NULL;
-       }
-       else
-       {
-               command_output = g_strdup (_("Viewing in progress. Please wait..."));
-               is_error = FALSE;
-       }
-
-       print_log_add (latexila.action_log.text_view, command_output, is_error);
-
-       g_free (command_output);
-}
-
 void
 convert_document (gchar *title, gchar *doc_extension, gchar *command)
 {
@@ -328,6 +206,26 @@ convert_document (gchar *title, gchar *doc_extension, gchar *command)
                        doc_extension);
 }
 
+void
+run_bibtex (void)
+{
+       run_command_on_other_extension (
+                       "BibTeX",
+                       _("BibTeX is running. Please wait..."),
+                       latexila.prefs.command_bibtex,
+                       ".aux");
+}
+
+void
+run_makeindex (void)
+{
+       run_command_on_other_extension (
+                       "MakeIndex",
+                       _("MakeIndex is running. Please wait..."),
+                       latexila.prefs.command_makeindex,
+                       ".idx");
+}
+
 void
 view_in_web_browser (gchar *title, gchar *filename)
 {
@@ -361,26 +259,6 @@ view_in_web_browser (gchar *title, gchar *filename)
        g_free (command_output);
 }
 
-void
-run_bibtex (void)
-{
-       run_command_on_other_extension (
-                       "BibTeX",
-                       _("BibTeX is running. Please wait..."),
-                       latexila.prefs.command_bibtex,
-                       ".aux");
-}
-
-void
-run_makeindex (void)
-{
-       run_command_on_other_extension (
-                       "MakeIndex",
-                       _("MakeIndex is running. Please wait..."),
-                       latexila.prefs.command_makeindex,
-                       ".idx");
-}
-
 static void
 add_action (const gchar *title, const gchar *command)
 {
@@ -453,6 +331,162 @@ set_action_sensitivity (gboolean sensitive)
        gtk_action_set_sensitive (latexila.actions.makeindex, sensitive);
 }
 
+static gchar *
+get_command_line (gchar **command)
+{
+       if (command[0] == NULL)
+               return NULL;
+
+       gchar *command_line = g_strdup (command[0]);
+       gchar *tmp;
+       gchar **arg = command;
+       arg++;
+       while (*arg != NULL)
+       {
+               tmp = g_strdup_printf ("%s %s", command_line, *arg);
+               g_free (command_line);
+               command_line = tmp;
+               arg++;
+       }
+
+       return command_line;
+}
+
+static gboolean
+cb_watch_output_command (GIOChannel *channel, GIOCondition condition,
+               gpointer user_data)
+{
+       static int nb_lines = 0;
+       static int nb_channels_active = 2;
+
+       if (condition == G_IO_HUP)
+       {
+               g_io_channel_unref (channel);
+               nb_channels_active--;
+               
+               if (nb_channels_active == 0)
+               {
+                       command_running_finished ();
+                       nb_lines = 0;
+                       nb_channels_active = 2;
+               }
+
+               return FALSE;
+       }
+
+       GError *error = NULL;
+       gchar *line;
+       g_io_channel_read_line (channel, &line, NULL, NULL, &error);
+
+       if (error != NULL)
+       {
+               print_warning ("read line from output command failed: %s", error->message);
+               g_error_free (error);
+               return FALSE;
+       }
+
+       if (line != NULL)
+       {
+               if (show_all_output)
+                       // print the command output line to the log zone
+                       print_log_add (latexila.action_log.text_view, line, FALSE);
+               else
+                       output_filter_line (line);
+       }
+       
+       /* Flush the queue for the 200 first lines and then every 20 lines.
+        * This is for the fluidity of the output, without that the lines do not
+        * appear directly and it's ugly. But it is very slow, for a command that
+        * execute for example in 10 seconds, it could take 250 seconds (!) if we
+        * flush the queue at each line... But with commands that take 1
+        * second or so there is not a big difference.
+        */
+       if (show_all_output && (nb_lines < 200 || nb_lines % 20 == 0))
+               flush_queue ();
+
+       nb_lines++;
+
+       return TRUE;
+}
+
+static void
+output_filter_line (const gchar *line)
+{
+       if (line == NULL || strlen (line) == 0)
+               return;
+
+       printf ("%s", line);
+
+       if (g_regex_match_simple ("[^:]+:[0-9]+:.*", line, 0, 0)
+                       || g_regex_match_simple ("lines? [0-9]+", line, 0, 0)
+                       || strstr (line, "LaTeX Error")
+                       || strstr (line, "Output written on")
+                       || strstr (line, "Warning")
+                       || strstr (line, "Overfull")
+                       || strstr (line, "Underfull"))
+       {
+               print_log_add (latexila.action_log.text_view, line, FALSE);
+               flush_queue ();
+       }
+}
+
+static void
+command_running_finished (void)
+{
+       print_info ("\n\n\n");
+       flush_queue ();
+
+       show_all_output = TRUE;
+
+       // unlock the action list and all the build actions
+       set_action_sensitivity (TRUE);
+
+       // pop the message from the statusbar
+       guint context_id = gtk_statusbar_get_context_id (latexila.statusbar,
+                       "running-action");
+       gtk_statusbar_pop (latexila.statusbar, context_id);
+
+       cb_file_browser_refresh (NULL, NULL);
+}
+
+static void
+view_document_run (gchar *filename)
+{
+       // we use here g_spawn_async () and not g_spawn_command_line_async ()
+       // because the spaces in doc_path are not escaped, so with the command line
+       // it doesn't work fine...
+       
+       GError *error = NULL;
+       gchar *argv[] = {latexila.prefs.command_view, filename, NULL};
+       g_spawn_async (NULL, argv, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL, NULL, &error);
+
+       gboolean is_error = TRUE;
+       gchar *command_output;
+
+       if (error != NULL)
+       {
+               command_output = g_strdup_printf (_("execution failed: %s"),
+                               error->message);
+               g_error_free (error);
+               error = NULL;
+       }
+       else
+       {
+               command_output = g_strdup (_("Viewing in progress. Please wait..."));
+               is_error = FALSE;
+       }
+
+       print_log_add (latexila.action_log.text_view, command_output, is_error);
+
+       g_free (command_output);
+}
+
+/* Run a command on the current document but with an other extension.
+ * For example the current document is doc.tex, and we want to run
+ * "bibtex doc.aux". In this case, command will be "bibtex" and extension
+ * ".aux".
+ * The output of the command is displayed.
+ */
 static void
 run_command_on_other_extension (gchar *title, gchar *message, gchar *command,
                gchar *extension)
@@ -491,8 +525,7 @@ run_command_on_other_extension (gchar *title, gchar *message, gchar *command,
        gtk_statusbar_push (latexila.statusbar, context_id, message);
 
        // without that, the message in the statusbar does not appear
-       while (gtk_events_pending ())
-               gtk_main_iteration ();
+       flush_queue ();
 
        /* run the command */
        gchar *argv[] = {command, doc_path, NULL};
diff --git a/src/external_commands.h b/src/external_commands.h
index d50de1a..97aa3ca 100644
--- a/src/external_commands.h
+++ b/src/external_commands.h
@@ -1,7 +1,7 @@
 /*
  * This file is part of LaTeXila.
  *
- * Copyright © 2009 Sébastien Wilmet
+ * Copyright © 2009, 2010 Sébastien Wilmet
  *
  * LaTeXila is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -24,8 +24,8 @@ void compile_document (gchar *title, gchar **command);
 void view_current_document (gchar *title, gchar *doc_extension);
 void view_document (gchar *title, gchar *filename);
 void convert_document (gchar *title, gchar *doc_extension, gchar *command);
-void view_in_web_browser (gchar *title, gchar *filename);
 void run_bibtex (void);
 void run_makeindex (void);
+void view_in_web_browser (gchar *title, gchar *filename);
 
 #endif /* EXTERNAL_COMMANDS_H */
diff --git a/src/print.c b/src/print.c
index 5e9ef1a..583d949 100644
--- a/src/print.c
+++ b/src/print.c
@@ -1,7 +1,7 @@
 /*
  * This file is part of LaTeXila.
  *
- * Copyright © 2009 Sébastien Wilmet
+ * Copyright © 2009, 2010 Sébastien Wilmet
  *
  * LaTeXila is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -53,7 +53,7 @@ print_log (GtkTextBuffer *log_buffer, gchar *title, gchar *command,
 }
 
 void
-print_log_add (GtkTextView *log, gchar *text, gboolean error)
+print_log_add (GtkTextView *log, const gchar *text, gboolean error)
 {
        GtkTextBuffer *log_buffer = gtk_text_view_get_buffer (log);
        GtkTextIter end;
@@ -72,7 +72,7 @@ print_log_add (GtkTextView *log, gchar *text, gboolean error)
 }
 
 void
-print_info (char *format, ...)
+print_info (const char *format, ...)
 {
        va_list va;
        va_start (va, format);
@@ -81,7 +81,7 @@ print_info (char *format, ...)
 }
 
 void
-print_warning (char *format, ...)
+print_warning (const char *format, ...)
 {
        va_list va;
        va_start (va, format);
@@ -91,7 +91,7 @@ print_warning (char *format, ...)
 }
 
 void
-print_error (char *format, ...)
+print_error (const char *format, ...)
 {
        va_list va;
        va_start (va, format);
diff --git a/src/print.h b/src/print.h
index c73b15e..93c0911 100644
--- a/src/print.h
+++ b/src/print.h
@@ -1,7 +1,7 @@
 /*
  * This file is part of LaTeXila.
  *
- * Copyright © 2009 Sébastien Wilmet
+ * Copyright © 2009, 2010 Sébastien Wilmet
  *
  * LaTeXila is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -22,10 +22,10 @@
 
 void print_log (GtkTextBuffer *log_buffer, gchar *title, gchar *command,
                gchar *command_output, gboolean error);
-void print_log_add (GtkTextView *log, gchar *text, gboolean error);
+void print_log_add (GtkTextView *log, const gchar *text, gboolean error);
 
-void print_info (char *, ...);
-void print_warning (char *, ...);
-void print_error (char *, ...);
+void print_info (const char *, ...);
+void print_warning (const char *, ...);
+void print_error (const char *, ...);
 
 #endif /* PRINT_H */
diff --git a/src/utils.c b/src/utils.c
new file mode 100644
index 0000000..ac29f2f
--- /dev/null
+++ b/src/utils.c
@@ -0,0 +1,31 @@
+/*
+ * This file is part of LaTeXila.
+ *
+ * Copyright © 2010 Sébastien Wilmet
+ *
+ * LaTeXila is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * LaTeXila is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with LaTeXila.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <gtk/gtk.h>
+
+#include "utils.h"
+
+void
+flush_queue (void)
+{
+       while (g_main_context_pending (NULL))
+               g_main_context_iteration (NULL, TRUE);
+}
diff --git a/src/utils.h b/src/utils.h
new file mode 100644
index 0000000..dbab2fd
--- /dev/null
+++ b/src/utils.h
@@ -0,0 +1,25 @@
+/*
+ * This file is part of LaTeXila.
+ *
+ * Copyright © 2010 Sébastien Wilmet
+ *
+ * LaTeXila is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * LaTeXila is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with LaTeXila.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef UTILS_H
+#define UTILS_H
+
+void flush_queue (void);
+
+#endif /* UTILS_H */


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]