[gnome-latex: 164/205] Clean the code of external_commands.c
- From: Sébastien Wilmet <swilmet src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-latex: 164/205] Clean the code of external_commands.c
- Date: Fri, 14 Dec 2018 11:00:40 +0000 (UTC)
commit 8ad1d766a81239fce32ba6ad059ecd612fbe493b
Author: Sébastien Wilmet <sebastien wilmet gmail com>
Date: Wed Jan 6 18:31:34 2010 +0100
Clean the code of external_commands.c
Now there are two functions for starting a command:
- start_command_with_output()
- start_command_without_output()
The variable "show_all_output" must be set before calling
start_command_with_output(), so the output lines can go into the filter
only when needed.
dup2() is used to include stderr into the output, so we have only one IO
channel.
CMakeLists.txt | 2 +-
TODO | 5 +
src/callbacks.c | 18 ++-
src/external_commands.c | 333 ++++++++++++++++++++++--------------------------
4 files changed, 164 insertions(+), 194 deletions(-)
---
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 1a6b28c..369f0fe 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -5,7 +5,7 @@ PROJECT(latexila)
# version
SET(latexila_MAJOR 0)
SET(latexila_MINOR 1)
-SET(latexila_PATCH 0)
+SET(latexila_PATCH 99)
SET(latexila_VERSION ${latexila_MAJOR}.${latexila_MINOR}.${latexila_PATCH})
MESSAGE(STATUS "*** Building LaTeXila ${latexila_VERSION} ***")
diff --git a/TODO b/TODO
index 0370b29..1f8b343 100644
--- a/TODO
+++ b/TODO
@@ -4,10 +4,15 @@ TODO LaTeXila
x filter the messages
- show the exit code
- show statistics: nb of errors, warnings and badboxes
+ - extract informations: file, line, message
- jump to lines: GtkTextBuffer -> GtkListStore
- colors
- go to the previous/next error/warning/badbox
+ - button to stop the execution
- Auto-completion of LaTeX commands
- Change the title of the window with the filename of the current document
+
+- New action: clean-up auxiliaries file
+ (for the moment it is possible when we close the document)
diff --git a/src/callbacks.c b/src/callbacks.c
index 7027043..f839082 100644
--- a/src/callbacks.c
+++ b/src/callbacks.c
@@ -613,20 +613,19 @@ cb_latex (void)
gchar *title = _("Compile (latex)");
gchar *command[] = {
- latexila.prefs.command_latex,
- "-interaction=nonstopmode",
+ latexila.prefs.command_latex,
"-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
+ g_path_get_basename (latexila.active_doc->path),
+ NULL
};
compile_document (title, command);
- g_free (command[3]);
+ g_free (command[2]);
}
void
@@ -639,16 +638,15 @@ cb_pdflatex (void)
gchar *title = _("Compile (pdflatex)");
gchar *command[] = {
- latexila.prefs.command_pdflatex,
- "-interaction=nonstopmode",
+ latexila.prefs.command_pdflatex,
"-file-line-error",
- g_path_get_basename (latexila.active_doc->path),
- NULL
+ g_path_get_basename (latexila.active_doc->path),
+ NULL
};
compile_document (title, command);
- g_free (command[3]);
+ g_free (command[2]);
}
void
diff --git a/src/external_commands.c b/src/external_commands.c
index da0da78..89423df 100644
--- a/src/external_commands.c
+++ b/src/external_commands.c
@@ -20,6 +20,8 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
+#include <sys/wait.h>
+#include <unistd.h> // for dup2
#include <locale.h>
#include <libintl.h>
#include <gtk/gtk.h>
@@ -37,15 +39,20 @@
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 start_command_without_output (gchar **command, gchar *message);
+static void start_command_with_output (gchar **command);
+static void cb_spawn_setup (gpointer data);
static gboolean cb_watch_output_command (GIOChannel *channel,
GIOCondition condition, gpointer user_data);
static void output_filter_line (const gchar *line);
+static void cb_child_watch (GPid pid, gint status, gpointer user_data);
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 gboolean is_current_doc_tex_file (void);
static gboolean show_all_output = TRUE;
+static gint child_pid_exit_code = 0;
void
compile_document (gchar *title, gchar **command)
@@ -53,22 +60,12 @@ compile_document (gchar *title, gchar **command)
if (latexila.active_doc == NULL)
return;
- gchar *command_output;
-
gchar *command_line = get_command_line (command);
add_action (title, command_line);
g_free (command_line);
- /* the current document is a *.tex file? */
- gboolean tex_file = g_str_has_suffix (latexila.active_doc->path, ".tex");
- if (! tex_file)
- {
- command_output = g_strdup_printf (_("compilation failed: %s is not a *.tex file"),
- g_path_get_basename (latexila.active_doc->path));
- print_log_add (latexila.action_log.text_view, command_output, TRUE);
- g_free (command_output);
+ if (! is_current_doc_tex_file ())
return;
- }
/* print a message in the statusbar */
guint context_id = gtk_statusbar_get_context_id (latexila.statusbar,
@@ -79,59 +76,8 @@ compile_document (gchar *title, gchar **command)
// without that, the message in the statusbar does not appear
flush_queue ();
- /* run the command */
- gchar *dir = g_path_get_dirname (latexila.active_doc->path);
- GError *error = NULL;
- GPid pid;
- gint out, err;
- g_spawn_async_with_pipes (dir, command, NULL, G_SPAWN_SEARCH_PATH, NULL,
- NULL, &pid, NULL, &out, &err, &error);
- g_free (dir);
-
- // an error occured
- if (error != NULL)
- {
- command_output = g_strdup_printf (_("execution failed: %s"),
- error->message);
- print_log_add (latexila.action_log.text_view, command_output, TRUE);
-
- g_free (command_output);
- g_error_free (error);
- return;
- }
-
- // create the channels
- 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);
- g_io_channel_set_encoding (err_channel, "ISO-8859-1", &error);
-
- if (error != NULL)
- {
- command_output = g_strdup_printf (
- "conversion of the command output failed: %s", error->message);
- print_log_add (latexila.action_log.text_view, command_output, TRUE);
-
- g_free (command_output);
- 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);
- g_io_add_watch (err_channel, G_IO_IN | G_IO_HUP,
- (GIOFunc) cb_watch_output_command, NULL);
+ start_command_with_output (command);
}
void
@@ -140,30 +86,19 @@ view_current_document (gchar *title, gchar *doc_extension)
if (latexila.active_doc == NULL)
return;
- gchar *command_output;
-
- GRegex *regex = g_regex_new ("\\.tex$", 0, 0, NULL);
-
/* replace .tex by doc_extension (.pdf, .dvi, ...) */
+ GRegex *regex = g_regex_new ("\\.tex$", 0, 0, NULL);
gchar *doc_path = g_regex_replace_literal (regex, latexila.active_doc->path,
-1, 0, doc_extension, 0, NULL);
+ g_regex_unref (regex);
gchar *command_line = g_strdup_printf ("%s %s", latexila.prefs.command_view,
doc_path);
add_action (title, command_line);
g_free (command_line);
- /* the current document is a *.tex file? */
- gboolean tex_file = g_regex_match (regex, latexila.active_doc->path, 0, NULL);
- g_regex_unref (regex);
-
- if (! tex_file)
+ if (! is_current_doc_tex_file ())
{
- command_output = g_strdup_printf (_("failed: %s is not a *.tex file"),
- g_path_get_basename (latexila.active_doc->path));
- print_log_add (latexila.action_log.text_view, command_output, TRUE);
-
- g_free (command_output);
g_free (doc_path);
return;
}
@@ -171,17 +106,17 @@ view_current_document (gchar *title, gchar *doc_extension)
/* the document (PDF, DVI, ...) file exist? */
if (! g_file_test (doc_path, G_FILE_TEST_IS_REGULAR))
{
- command_output = g_strdup_printf (
+ gchar *command_output = g_strdup_printf (
_("%s does not exist. If this is not already made, compile the document with
the right command."),
g_path_get_basename (doc_path));
print_log_add (latexila.action_log.text_view, command_output, TRUE);
-
g_free (command_output);
g_free (doc_path);
return;
}
- view_document_run (doc_path);
+ gchar *command[] = {latexila.prefs.command_view, doc_path, NULL};
+ start_command_without_output (command, NULL);
g_free (doc_path);
}
@@ -193,7 +128,8 @@ view_document (gchar *title, gchar *filename)
add_action (title, command_line);
g_free (command_line);
- view_document_run (filename);
+ gchar *command[] = {latexila.prefs.command_view, filename, NULL};
+ start_command_without_output (command, NULL);
}
void
@@ -234,29 +170,8 @@ view_in_web_browser (gchar *title, gchar *filename)
add_action (title, command_line);
g_free (command_line);
- GError *error = NULL;
- gchar *argv[] = {latexila.prefs.command_web_browser, 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);
+ gchar *command[] = {latexila.prefs.command_web_browser, filename, NULL};
+ start_command_without_output (command, NULL);
}
static void
@@ -352,25 +267,99 @@ get_command_line (gchar **command)
return command_line;
}
+static void
+start_command_without_output (gchar **command, gchar *message)
+{
+ GError *error = NULL;
+ g_spawn_async (NULL, command, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL, NULL, &error);
+
+ if (error != NULL)
+ {
+ gchar *command_output = g_strdup_printf (_("execution failed: %s"),
+ error->message);
+ print_log_add (latexila.action_log.text_view, command_output, TRUE);
+ g_free (command_output);
+ g_error_free (error);
+ }
+ else if (message == NULL)
+ print_log_add (latexila.action_log.text_view,
+ _("Viewing in progress. Please wait..."), FALSE);
+ else
+ print_log_add (latexila.action_log.text_view, message, FALSE);
+}
+
+// Attention, before calling this function, set the variable "show_all_output"
+// to TRUE or FALSE. If it is FALSE, the output will be filtered by the function
+// output_filter_line().
+static void
+start_command_with_output (gchar **command)
+{
+ gchar *dir = g_path_get_dirname (latexila.active_doc->path);
+ GError *error = NULL;
+ GPid pid;
+ gint out;
+ g_spawn_async_with_pipes (dir, command, NULL,
+ G_SPAWN_DO_NOT_REAP_CHILD | G_SPAWN_SEARCH_PATH,
+ (GSpawnChildSetupFunc) cb_spawn_setup, NULL,
+ &pid, NULL, &out, NULL, &error);
+ g_free (dir);
+
+ // an error occured
+ if (error != NULL)
+ {
+ gchar *command_output = g_strdup_printf (_("execution failed: %s"),
+ error->message);
+ print_log_add (latexila.action_log.text_view, command_output, TRUE);
+ g_free (command_output);
+ g_error_free (error);
+ return;
+ }
+
+ // we want to know the exit code
+ g_child_watch_add (pid, (GChildWatchFunc) cb_child_watch, NULL);
+
+ // create the channel
+ GIOChannel *out_channel = g_io_channel_unix_new (out);
+
+#if 0
+ g_io_channel_set_encoding (out_channel, "ISO-8859-1", &error);
+ if (error != NULL)
+ {
+ command_output = g_strdup_printf (
+ "conversion of the command output failed: %s", error->message);
+ print_log_add (latexila.action_log.text_view, command_output, TRUE);
+ g_free (command_output);
+ g_error_free (error);
+ return;
+ }
+#endif
+
+ // lock the action list and all the build actions
+ set_action_sensitivity (FALSE);
+
+ // add watches to channels
+ g_io_add_watch (out_channel, G_IO_IN | G_IO_HUP,
+ (GIOFunc) cb_watch_output_command, NULL);
+}
+
+static void
+cb_spawn_setup (gpointer data)
+{
+ // include stderr in the output
+ dup2 (STDOUT_FILENO, STDERR_FILENO);
+}
+
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;
- }
-
+ command_running_finished ();
+ nb_lines = 0;
return FALSE;
}
@@ -388,7 +377,6 @@ cb_watch_output_command (GIOChannel *channel, GIOCondition condition,
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);
@@ -415,8 +403,6 @@ 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")
@@ -431,54 +417,52 @@ output_filter_line (const gchar *line)
}
static void
-command_running_finished (void)
+cb_child_watch (GPid pid, gint status, gpointer user_data)
{
- print_info ("\n\n\n");
- flush_queue ();
+ print_info ("cb_child_watch ()");
- show_all_output = TRUE;
-
- // unlock the action list and all the build actions
- set_action_sensitivity (TRUE);
+ g_spawn_close_pid (pid);
- // 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);
+ if (WIFEXITED (status))
+ child_pid_exit_code = WEXITSTATUS (status);
+ else
+ child_pid_exit_code = -1;
}
static void
-view_document_run (gchar *filename)
+command_running_finished (void)
{
- // 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;
+ print_info ("command_running_finished ()");
- if (error != NULL)
+ /*
+ if (child_pid_exit_code > -1)
{
- command_output = g_strdup_printf (_("execution failed: %s"),
- error->message);
- g_error_free (error);
- error = NULL;
+ gchar *exit_code = g_strdup_printf ("exit code: %d\n",
+ child_pid_exit_code);
+
+ if (child_pid_exit_code == 0)
+ print_log_add (latexila.action_log.text_view, exit_code, FALSE);
+ else
+ print_log_add (latexila.action_log.text_view, exit_code, TRUE);
+
+ g_free (exit_code);
}
else
- {
- command_output = g_strdup (_("Viewing in progress. Please wait..."));
- is_error = FALSE;
- }
+ print_log_add (latexila.action_log.text_view,
+ _("the child process exited abnormally"), TRUE);
+ */
+
+ flush_queue ();
- print_log_add (latexila.action_log.text_view, command_output, is_error);
+ // 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);
- g_free (command_output);
+ cb_file_browser_refresh (NULL, NULL);
}
/* Run a command on the current document but with an other extension.
@@ -506,14 +490,13 @@ run_command_on_other_extension (gchar *title, gchar *message, gchar *command,
add_action (title, full_command);
g_free (full_command);
- /* the document to convert exist? */
+ /* the document with the other extension exist? */
if (! g_file_test (doc_path, G_FILE_TEST_IS_REGULAR))
{
command_output = g_strdup_printf (
_("%s does not exist. If this is not already made, compile the document with
the right command."),
g_path_get_basename (doc_path));
print_log_add (latexila.action_log.text_view, command_output, TRUE);
-
g_free (command_output);
g_free (doc_path);
return;
@@ -529,39 +512,23 @@ run_command_on_other_extension (gchar *title, gchar *message, gchar *command,
/* run the command */
gchar *argv[] = {command, doc_path, NULL};
-
- GError *error = NULL;
- gchar *dir = g_path_get_dirname (latexila.active_doc->path);
- GPid pid;
- gint out, err;
- g_spawn_async_with_pipes (dir, argv, NULL, G_SPAWN_SEARCH_PATH, NULL,
- NULL, &pid, NULL, &out, &err, &error);
-
- g_free (dir);
+ show_all_output = TRUE;
+ start_command_with_output (argv);
g_free (doc_path);
+}
- // an error occured
- if (error != NULL)
+static gboolean
+is_current_doc_tex_file (void)
+{
+ /* the current document is a *.tex file? */
+ if (! g_str_has_suffix (latexila.active_doc->path, ".tex"))
{
- command_output = g_strdup_printf (_("execution failed: %s"),
- error->message);
+ gchar *command_output = g_strdup_printf (_("failed: %s is not a *.tex file"),
+ g_path_get_basename (latexila.active_doc->path));
print_log_add (latexila.action_log.text_view, command_output, TRUE);
-
g_free (command_output);
- g_error_free (error);
- return;
+ return FALSE;
}
- // create the channels
- GIOChannel *out_channel = g_io_channel_unix_new (out);
- GIOChannel *err_channel = g_io_channel_unix_new (err);
-
- // lock the action list and all the build actions
- set_action_sensitivity (FALSE);
-
- // add watches to channels
- g_io_add_watch (out_channel, G_IO_IN | G_IO_HUP,
- (GIOFunc) cb_watch_output_command, NULL);
- g_io_add_watch (err_channel, G_IO_IN | G_IO_HUP,
- (GIOFunc) cb_watch_output_command, NULL);
+ return TRUE;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]