[latexila/wip/latexila-next: 1/2] PostProcessorLatexmk: start the implementation



commit 0d86cd35f8d82ba83bb11d90c04d39e7c2b0dc96
Author: Sébastien Wilmet <swilmet gnome org>
Date:   Wed Sep 17 22:15:11 2014 +0200

    PostProcessorLatexmk: start the implementation

 docs/reference/latexila-docs.xml                  |    1 +
 docs/reference/latexila-sections.txt              |   17 +
 src/liblatexila/Makefile.am                       |    2 +
 src/liblatexila/latexila-build-job.c              |    4 +-
 src/liblatexila/latexila-post-processor-latexmk.c |  674 +++++++++++++++++++++
 src/liblatexila/latexila-post-processor-latexmk.h |   57 ++
 src/liblatexila/latexila-types.h                  |    1 +
 7 files changed, 754 insertions(+), 2 deletions(-)
---
diff --git a/docs/reference/latexila-docs.xml b/docs/reference/latexila-docs.xml
index 0a693c3..f8e08c3 100644
--- a/docs/reference/latexila-docs.xml
+++ b/docs/reference/latexila-docs.xml
@@ -20,6 +20,7 @@
     <xi:include href="xml/post-processor.xml"/>
     <xi:include href="xml/post-processor-all-output.xml"/>
     <xi:include href="xml/post-processor-latex.xml"/>
+    <xi:include href="xml/post-processor-latexmk.xml"/>
     <xi:include href="xml/synctex.xml"/>
     <xi:include href="xml/utils.xml"/>
   </chapter>
diff --git a/docs/reference/latexila-sections.txt b/docs/reference/latexila-sections.txt
index 8abaf5d..c76bee2 100644
--- a/docs/reference/latexila-sections.txt
+++ b/docs/reference/latexila-sections.txt
@@ -195,6 +195,23 @@ latexila_post_processor_latex_get_type
 </SECTION>
 
 <SECTION>
+<FILE>post-processor-latexmk</FILE>
+<TITLE>LatexilaPostProcessorLatexmk</TITLE>
+LatexilaPostProcessorLatexmk
+latexila_post_processor_latexmk_new
+<SUBSECTION Standard>
+LATEXILA_IS_POST_PROCESSOR_LATEXMK
+LATEXILA_IS_POST_PROCESSOR_LATEXMK_CLASS
+LATEXILA_POST_PROCESSOR_LATEXMK
+LATEXILA_POST_PROCESSOR_LATEXMK_CLASS
+LATEXILA_POST_PROCESSOR_LATEXMK_GET_CLASS
+LATEXILA_TYPE_POST_PROCESSOR_LATEXMK
+LatexilaPostProcessorLatexmkClass
+LatexilaPostProcessorLatexmkPrivate
+latexila_post_processor_latexmk_get_type
+</SECTION>
+
+<SECTION>
 <FILE>synctex</FILE>
 <TITLE>LatexilaSynctex</TITLE>
 LatexilaSynctex
diff --git a/src/liblatexila/Makefile.am b/src/liblatexila/Makefile.am
index e2e33fa..c0998e1 100644
--- a/src/liblatexila/Makefile.am
+++ b/src/liblatexila/Makefile.am
@@ -21,6 +21,7 @@ liblatexila_headers =                         \
        latexila-post-processor.h               \
        latexila-post-processor-all-output.h    \
        latexila-post-processor-latex.h         \
+       latexila-post-processor-latexmk.h       \
        latexila-synctex.h                      \
        latexila-types.h                        \
        latexila-utils.h
@@ -35,6 +36,7 @@ liblatexila_sources =                         \
        latexila-post-processor.c               \
        latexila-post-processor-all-output.c    \
        latexila-post-processor-latex.c         \
+       latexila-post-processor-latexmk.c       \
        latexila-synctex.c                      \
        latexila-utils.c
 
diff --git a/src/liblatexila/latexila-build-job.c b/src/liblatexila/latexila-build-job.c
index 96668bb..78f3664 100644
--- a/src/liblatexila/latexila-build-job.c
+++ b/src/liblatexila/latexila-build-job.c
@@ -31,6 +31,7 @@
 #include "latexila-build-view.h"
 #include "latexila-post-processor-all-output.h"
 #include "latexila-post-processor-latex.h"
+#include "latexila-post-processor-latexmk.h"
 #include "latexila-utils.h"
 #include "latexila-enum-types.h"
 
@@ -492,8 +493,7 @@ launch_subprocess (LatexilaBuildJob *build_job)
       break;
 
     case LATEXILA_POST_PROCESSOR_TYPE_LATEXMK:
-      /* TODO implement the latexmk post-processor. */
-      build_job->priv->post_processor = latexila_post_processor_all_output_new ();
+      build_job->priv->post_processor = latexila_post_processor_latexmk_new ();
       break;
 
     default:
diff --git a/src/liblatexila/latexila-post-processor-latexmk.c 
b/src/liblatexila/latexila-post-processor-latexmk.c
new file mode 100644
index 0000000..806117d
--- /dev/null
+++ b/src/liblatexila/latexila-post-processor-latexmk.c
@@ -0,0 +1,674 @@
+/*
+ * This file is part of LaTeXila.
+ *
+ * Copyright (C) 2014 - Sébastien Wilmet <swilmet gnome org>
+ *
+ * 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/>.
+ */
+
+/**
+ * SECTION:post-processor-latexmk
+ * @title: LatexilaPostProcessorLatexmk
+ * @short_description: latexmk post-processor
+ *
+ * A post-processor used for the latexmk command. Internally, this
+ * post-processor uses #LatexilaPostProcessorLatex.
+ */
+
+#include "latexila-post-processor-latexmk.h"
+#include "latexila-post-processor-latex.h"
+#include "latexila-build-view.h"
+
+typedef enum
+{
+  /* Try to find something like:
+   * ------------
+   * Run number 1 of rule 'pdflatex'
+   * ------------
+   */
+  STATE_SUB_TITLE_START,
+  STATE_SUB_TITLE_END,
+
+  /* Try to find something like:
+   * ------------
+   * Running 'pdflatex  -synctex=1 -recorder  "test.tex"'
+   * ------------
+   */
+  STATE_SUB_COMMAND_START,
+  STATE_SUB_COMMAND_END,
+
+  /* Fetch the sub-command output. */
+  STATE_SUB_COMMAND_OUTPUT_START,
+  STATE_SUB_COMMAND_OUTPUT_IN,
+
+  /* Fetch the Latexmk messages after a command output. */
+  STATE_LATEXMK_MESSAGES,
+
+  /* If no sub-titles have been found, display almost all output. */
+  STATE_FALLBACK_START,
+  STATE_FALLBACK_IN
+} State;
+
+struct _LatexilaPostProcessorLatexmkPrivate
+{
+  /* The tree of all messages. */
+  GQueue *messages;
+
+  State state;
+
+  /* Number of separators encountered for the current state. */
+  gint separator_count;
+
+  LatexilaBuildMsg *last_latex_sub_command;
+  GQueue *last_latex_lines;
+
+  GFile *file;
+
+  GQueue *all_lines;
+
+  guint last_rule_is_latex_rule : 1;
+  guint store_all_lines : 1;
+};
+
+G_DEFINE_TYPE_WITH_PRIVATE (LatexilaPostProcessorLatexmk,
+                            latexila_post_processor_latexmk,
+                            LATEXILA_TYPE_POST_PROCESSOR)
+
+static void
+latexila_post_processor_latexmk_start (LatexilaPostProcessor *post_processor,
+                                       GFile                 *file)
+{
+  LatexilaPostProcessorLatexmk *pp = LATEXILA_POST_PROCESSOR_LATEXMK (post_processor);
+
+  g_clear_object (&pp->priv->file);
+  pp->priv->file = g_object_ref (file);
+}
+
+static void
+add_top_level_message (LatexilaPostProcessorLatexmk *pp,
+                       LatexilaBuildMsg             *msg)
+{
+  g_assert (msg != NULL);
+
+  msg->type = LATEXILA_BUILD_MSG_TYPE_JOB_SUB_COMMAND;
+
+  /* Do not expand the row, so the user has first a global view of what have
+   * been executed.
+   */
+  msg->expand = FALSE;
+
+  g_queue_push_tail (pp->priv->messages, msg);
+
+  pp->priv->store_all_lines = FALSE;
+}
+
+static void
+add_sub_message (LatexilaPostProcessorLatexmk *pp,
+                 LatexilaBuildMsg             *sub_msg)
+{
+  LatexilaBuildMsg *last_toplevel_msg;
+
+  g_assert (sub_msg != NULL);
+
+  last_toplevel_msg = g_queue_peek_tail (pp->priv->messages);
+
+  if (last_toplevel_msg == NULL)
+    {
+      g_warning ("PostProcessorLatexmk: try to add a sub-message without a top-level message.");
+      latexila_build_msg_free (sub_msg);
+      return;
+    }
+
+  sub_msg->type = LATEXILA_BUILD_MSG_TYPE_INFO;
+
+  if (last_toplevel_msg->children == NULL)
+    last_toplevel_msg->children = g_queue_new ();
+
+  g_queue_push_tail (last_toplevel_msg->children, sub_msg);
+}
+
+static void
+set_last_latex_sub_command (LatexilaPostProcessorLatexmk *pp,
+                            LatexilaBuildMsg             *msg)
+{
+  if (pp->priv->last_latex_lines != NULL)
+    g_queue_free_full (pp->priv->last_latex_lines, g_free);
+
+  pp->priv->last_latex_lines = g_queue_new ();
+  pp->priv->last_latex_sub_command = msg;
+}
+
+static gboolean
+is_separator (const gchar *line)
+{
+  return g_str_has_prefix (line, "------------");
+}
+
+static void
+fetch_sub_title (LatexilaPostProcessorLatexmk *pp,
+                 gchar                        *line)
+{
+  static GRegex *regex_sub_title = NULL;
+  GMatchInfo *match_info;
+
+  g_assert (pp->priv->state == STATE_SUB_TITLE_START ||
+            pp->priv->state == STATE_SUB_TITLE_END);
+
+  if (G_UNLIKELY (regex_sub_title == NULL))
+    {
+      GError *error = NULL;
+
+      regex_sub_title = g_regex_new ("Run number \\d+ of rule '(?P<rule>.*)'",
+                                     G_REGEX_OPTIMIZE,
+                                     0,
+                                     &error);
+
+      if (error != NULL)
+        {
+          g_warning ("PostProcessorLatexmk: %s", error->message);
+          g_error_free (error);
+          return;
+        }
+    }
+
+  if (pp->priv->state == STATE_SUB_TITLE_END)
+    {
+      g_assert (pp->priv->separator_count == 1);
+
+      if (is_separator (line))
+        {
+          pp->priv->separator_count = 0;
+          pp->priv->state = STATE_SUB_COMMAND_START;
+        }
+
+      goto end;
+    }
+
+  if (is_separator (line))
+    {
+      pp->priv->separator_count++;
+
+      if (pp->priv->separator_count == 2)
+        {
+          pp->priv->separator_count = 0;
+          g_warning ("PostProcessorLatexmk: fetch sub-title failed, try again.");
+        }
+
+      goto end;
+    }
+
+  if (pp->priv->separator_count != 1)
+    goto end;
+
+  g_regex_match (regex_sub_title, line, 0, &match_info);
+
+  if (g_match_info_matches (match_info))
+    {
+      LatexilaBuildMsg *msg;
+      gchar *rule;
+
+      msg = latexila_build_msg_new ();
+      msg->text = line;
+      line = NULL;
+
+      add_top_level_message (pp, msg);
+      pp->priv->state = STATE_SUB_TITLE_END;
+
+      rule = g_match_info_fetch_named (match_info, "rule");
+
+      pp->priv->last_rule_is_latex_rule = (g_strcmp0 (rule, "latex") == 0 ||
+                                           g_strcmp0 (rule, "pdflatex") == 0);
+
+      if (pp->priv->last_rule_is_latex_rule)
+        set_last_latex_sub_command (pp, msg);
+
+      g_free (rule);
+    }
+
+  g_match_info_free (match_info);
+
+end:
+
+  if (pp->priv->store_all_lines)
+    {
+      if (pp->priv->all_lines == NULL)
+        pp->priv->all_lines = g_queue_new ();
+
+      g_queue_push_tail (pp->priv->all_lines, line);
+    }
+  else
+    {
+      g_free (line);
+    }
+}
+
+static void
+fetch_sub_command (LatexilaPostProcessorLatexmk *pp,
+                   gchar                        *line)
+{
+  static GRegex *regex_sub_command = NULL;
+  GMatchInfo *match_info;
+
+  g_assert (pp->priv->state == STATE_SUB_COMMAND_START ||
+            pp->priv->state == STATE_SUB_COMMAND_END);
+
+  if (G_UNLIKELY (regex_sub_command == NULL))
+    {
+      GError *error = NULL;
+
+      regex_sub_command = g_regex_new ("Running '(?P<command>.*)'",
+                                       G_REGEX_OPTIMIZE,
+                                       0,
+                                       &error);
+
+      if (error != NULL)
+        {
+          g_warning ("PostProcessorLatexmk: %s", error->message);
+          g_error_free (error);
+          return;
+        }
+    }
+
+  if (pp->priv->state == STATE_SUB_COMMAND_END)
+    {
+      g_assert (pp->priv->separator_count == 1);
+
+      if (is_separator (line))
+        {
+          pp->priv->separator_count = 0;
+          pp->priv->state = STATE_SUB_COMMAND_OUTPUT_START;
+        }
+
+      goto end;
+    }
+
+  if (is_separator (line))
+    {
+      pp->priv->separator_count++;
+
+      if (pp->priv->separator_count == 2)
+        {
+          pp->priv->separator_count = 0;
+          g_warning ("PostProcessorLatexmk: fetch sub-command failed, try again.");
+        }
+
+      goto end;
+    }
+
+  if (pp->priv->separator_count != 1)
+    goto end;
+
+  g_regex_match (regex_sub_command, line, 0, &match_info);
+
+  if (g_match_info_matches (match_info))
+    {
+      LatexilaBuildMsg *msg;
+      gchar *command;
+
+      msg = latexila_build_msg_new ();
+
+      command = g_match_info_fetch_named (match_info, "command");
+      msg->text = g_strdup_printf ("$ %s", command);
+      g_free (command);
+
+      add_sub_message (pp, msg);
+      pp->priv->state = STATE_SUB_COMMAND_END;
+    }
+
+  g_match_info_free (match_info);
+
+end:
+  g_free (line);
+}
+
+static void
+fetch_latexmk_messages (LatexilaPostProcessorLatexmk *pp,
+                        gchar                        *line)
+{
+  LatexilaBuildMsg *msg;
+
+  g_assert (pp->priv->state == STATE_LATEXMK_MESSAGES);
+
+  if (is_separator (line))
+    {
+      pp->priv->state = STATE_SUB_TITLE_START;
+      fetch_sub_title (pp, line);
+      return;
+    }
+
+  msg = latexila_build_msg_new ();
+  msg->text = line;
+  add_sub_message (pp, msg);
+}
+
+static void
+fetch_sub_command_output (LatexilaPostProcessorLatexmk *pp,
+                          gchar                        *line)
+{
+  static GRegex *regex_for_rule = NULL;
+  static GRegex *regex_rule = NULL;
+  GError *error = NULL;
+
+  g_assert (pp->priv->state == STATE_SUB_COMMAND_OUTPUT_START ||
+            pp->priv->state == STATE_SUB_COMMAND_OUTPUT_IN);
+
+  if (G_UNLIKELY (regex_for_rule == NULL))
+    {
+      regex_for_rule = g_regex_new ("^For rule '.*', running",
+                                    G_REGEX_OPTIMIZE,
+                                    0,
+                                    &error);
+
+      if (error != NULL)
+        {
+          g_warning ("PostProcessorLatexmk: %s", error->message);
+          g_error_free (error);
+          return;
+        }
+    }
+
+  if (G_UNLIKELY (regex_rule == NULL))
+    {
+      regex_rule = g_regex_new ("^Rule '.*':",
+                                G_REGEX_OPTIMIZE,
+                                0,
+                                &error);
+
+      if (error != NULL)
+        {
+          g_warning ("PostProcessorLatexmk: %s", error->message);
+          g_error_free (error);
+          return;
+        }
+    }
+
+  if (pp->priv->state == STATE_SUB_COMMAND_OUTPUT_START)
+    {
+      if (g_str_has_prefix (line, "Latexmk: applying rule") ||
+          g_regex_match (regex_for_rule, line, 0, NULL))
+        goto end;
+
+      pp->priv->state = STATE_SUB_COMMAND_OUTPUT_IN;
+    }
+
+  if (g_str_has_prefix (line, "Latexmk:") ||
+      g_regex_match (regex_rule, line, 0, NULL))
+    {
+      LatexilaBuildMsg *msg;
+
+      pp->priv->state = STATE_LATEXMK_MESSAGES;
+
+      msg = latexila_build_msg_new ();
+      /* The latex command output is in English, so for consistency no need to
+       * translate this.
+       */
+      msg->text = g_strdup ("Latexmk messages");
+      add_top_level_message (pp, msg);
+
+      fetch_latexmk_messages (pp, line);
+      return;
+    }
+
+  /* If the rule is latex or pdflatex, we store the output. */
+  if (pp->priv->last_rule_is_latex_rule)
+    {
+      g_queue_push_tail (pp->priv->last_latex_lines, line);
+      line = NULL;
+    }
+
+  /* If it's another rule (bibtex, makeindex, etc), we show all output. */
+  else
+    {
+      LatexilaBuildMsg *msg;
+
+      msg = latexila_build_msg_new ();
+      msg->text = line;
+      line = NULL;
+
+      add_sub_message (pp, msg);
+    }
+
+end:
+  g_free (line);
+}
+
+static void
+process_line_fallback (LatexilaPostProcessorLatexmk *pp,
+                       gchar                        *line)
+{
+  g_assert (pp->priv->state == STATE_FALLBACK_START ||
+            pp->priv->state == STATE_FALLBACK_IN);
+
+  if (pp->priv->state == STATE_FALLBACK_START &&
+      !g_str_has_prefix (line, "Latexmk: This is Latexmk") &&
+      !g_str_has_prefix (line, "**** Report bugs"))
+    pp->priv->state = STATE_FALLBACK_IN;
+
+  if (pp->priv->state == STATE_FALLBACK_IN)
+    {
+      LatexilaBuildMsg *msg;
+
+      msg = latexila_build_msg_new ();
+      msg->type = LATEXILA_BUILD_MSG_TYPE_INFO;
+      msg->text = line;
+      line = NULL;
+
+      g_queue_push_tail (pp->priv->messages, msg);
+    }
+
+  g_free (line);
+}
+
+static void
+latexila_post_processor_latexmk_process_line (LatexilaPostProcessor *post_processor,
+                                              gchar                 *line)
+{
+  LatexilaPostProcessorLatexmk *pp = LATEXILA_POST_PROCESSOR_LATEXMK (post_processor);
+
+  switch (pp->priv->state)
+    {
+    case STATE_SUB_TITLE_START:
+    case STATE_SUB_TITLE_END:
+      fetch_sub_title (pp, line);
+      break;
+
+    case STATE_SUB_COMMAND_START:
+    case STATE_SUB_COMMAND_END:
+      fetch_sub_command (pp, line);
+      break;
+
+    case STATE_SUB_COMMAND_OUTPUT_START:
+    case STATE_SUB_COMMAND_OUTPUT_IN:
+      fetch_sub_command_output (pp, line);
+      break;
+
+    case STATE_LATEXMK_MESSAGES:
+      fetch_latexmk_messages (pp, line);
+      break;
+
+    case STATE_FALLBACK_START:
+    case STATE_FALLBACK_IN:
+      process_line_fallback (pp, line);
+      break;
+
+    default:
+      g_return_if_reached ();
+    }
+}
+
+static void
+run_latex_post_processor (LatexilaPostProcessorLatexmk *pp)
+{
+  LatexilaPostProcessor *pp_latex;
+  LatexilaBuildMsg *msg;
+  GQueue *initial_children;
+  GList *l;
+
+  g_assert (pp->priv->last_latex_sub_command != NULL);
+  g_assert (pp->priv->last_latex_lines != NULL);
+
+  pp_latex = latexila_post_processor_latex_new ();
+
+  latexila_post_processor_start (pp_latex, pp->priv->file);
+
+  for (l = pp->priv->last_latex_lines->head; l != NULL; l = l->next)
+    latexila_post_processor_process_line (pp_latex, l->data);
+
+  g_queue_free (pp->priv->last_latex_lines);
+  pp->priv->last_latex_lines = NULL;
+
+  latexila_post_processor_end (pp_latex);
+
+  msg = pp->priv->last_latex_sub_command;
+  initial_children = msg->children;
+  msg->children = latexila_post_processor_take_messages (pp_latex);
+  g_object_unref (pp_latex);
+
+  if (initial_children != NULL)
+    {
+      for (l = initial_children->tail; l != NULL; l = l->prev)
+        g_queue_push_head (msg->children, l->data);
+
+      g_queue_free (initial_children);
+    }
+
+  /* Expand only the last latex command. */
+  msg->expand = TRUE;
+
+  /* Almost all the time, the user wants to see only the latex output.
+   * If an error has occured, we verify if the last command was a latex command.
+   * If it is the case, there is no need to show all output.
+   */
+  /* TODO check the subprocess exit code */
+  if (pp->priv->last_rule_is_latex_rule)
+    g_object_set (pp, "has-details", TRUE, NULL);
+}
+
+static void
+process_all_output (LatexilaPostProcessorLatexmk *pp)
+{
+  LatexilaPostProcessor *post_processor = LATEXILA_POST_PROCESSOR (pp);
+  GList *l;
+
+  g_assert (pp->priv->messages->length == 0);
+  g_assert (pp->priv->store_all_lines);
+
+  if (pp->priv->all_lines == NULL)
+    return;
+
+  pp->priv->state = STATE_FALLBACK_START;
+  pp->priv->store_all_lines = FALSE;
+
+  for (l = pp->priv->all_lines->head; l != NULL; l = l->next)
+    latexila_post_processor_latexmk_process_line (post_processor, l->data);
+
+  g_queue_free (pp->priv->all_lines);
+  pp->priv->all_lines = NULL;
+}
+
+static void
+latexila_post_processor_latexmk_end (LatexilaPostProcessor *post_processor)
+{
+  LatexilaPostProcessorLatexmk *pp = LATEXILA_POST_PROCESSOR_LATEXMK (post_processor);
+
+  if (pp->priv->last_latex_sub_command != NULL)
+    run_latex_post_processor (pp);
+
+  if (pp->priv->messages->length == 0)
+    process_all_output (pp);
+}
+
+static const GQueue *
+latexila_post_processor_latexmk_get_messages (LatexilaPostProcessor *post_processor)
+{
+  LatexilaPostProcessorLatexmk *pp = LATEXILA_POST_PROCESSOR_LATEXMK (post_processor);
+
+  return pp->priv->messages;
+}
+
+static GQueue *
+latexila_post_processor_latexmk_take_messages (LatexilaPostProcessor *post_processor)
+{
+  LatexilaPostProcessorLatexmk *pp = LATEXILA_POST_PROCESSOR_LATEXMK (post_processor);
+  GQueue *ret;
+
+  ret = pp->priv->messages;
+  pp->priv->messages = NULL;
+
+  return ret;
+}
+
+static void
+latexila_post_processor_latexmk_dispose (GObject *object)
+{
+  LatexilaPostProcessorLatexmk *pp = LATEXILA_POST_PROCESSOR_LATEXMK (object);
+
+  g_clear_object (&pp->priv->file);
+
+  G_OBJECT_CLASS (latexila_post_processor_latexmk_parent_class)->dispose (object);
+}
+
+static void
+latexila_post_processor_latexmk_finalize (GObject *object)
+{
+  LatexilaPostProcessorLatexmk *pp = LATEXILA_POST_PROCESSOR_LATEXMK (object);
+
+  if (pp->priv->messages != NULL)
+    g_queue_free_full (pp->priv->messages, (GDestroyNotify) latexila_build_msg_free);
+
+  if (pp->priv->last_latex_lines != NULL)
+    g_queue_free_full (pp->priv->last_latex_lines, g_free);
+
+  if (pp->priv->all_lines != NULL)
+    g_queue_free_full (pp->priv->all_lines, g_free);
+
+  G_OBJECT_CLASS (latexila_post_processor_latexmk_parent_class)->finalize (object);
+}
+
+static void
+latexila_post_processor_latexmk_class_init (LatexilaPostProcessorLatexmkClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  LatexilaPostProcessorClass *pp_class = LATEXILA_POST_PROCESSOR_CLASS (klass);
+
+  object_class->dispose = latexila_post_processor_latexmk_dispose;
+  object_class->finalize = latexila_post_processor_latexmk_finalize;
+
+  pp_class->start = latexila_post_processor_latexmk_start;
+  pp_class->process_line = latexila_post_processor_latexmk_process_line;
+  pp_class->end = latexila_post_processor_latexmk_end;
+  pp_class->get_messages = latexila_post_processor_latexmk_get_messages;
+  pp_class->take_messages = latexila_post_processor_latexmk_take_messages;
+}
+
+static void
+latexila_post_processor_latexmk_init (LatexilaPostProcessorLatexmk *pp)
+{
+  pp->priv = latexila_post_processor_latexmk_get_instance_private (pp);
+
+  pp->priv->messages = g_queue_new ();
+  pp->priv->state = STATE_SUB_TITLE_START;
+  pp->priv->store_all_lines = TRUE;
+}
+
+/**
+ * latexila_post_processor_latexmk_new:
+ *
+ * Returns: a new #LatexilaPostProcessorLatexmk object.
+ */
+LatexilaPostProcessor *
+latexila_post_processor_latexmk_new (void)
+{
+  return g_object_new (LATEXILA_TYPE_POST_PROCESSOR_LATEXMK, NULL);
+}
diff --git a/src/liblatexila/latexila-post-processor-latexmk.h 
b/src/liblatexila/latexila-post-processor-latexmk.h
new file mode 100644
index 0000000..f30382f
--- /dev/null
+++ b/src/liblatexila/latexila-post-processor-latexmk.h
@@ -0,0 +1,57 @@
+/*
+ * This file is part of LaTeXila.
+ *
+ * Copyright (C) 2014 - Sébastien Wilmet <swilmet gnome org>
+ *
+ * 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 __LATEXILA_POST_PROCESSOR_LATEXMK_H__
+#define __LATEXILA_POST_PROCESSOR_LATEXMK_H__
+
+#include <glib-object.h>
+#include "latexila-post-processor.h"
+#include "latexila-types.h"
+
+G_BEGIN_DECLS
+
+#define LATEXILA_TYPE_POST_PROCESSOR_LATEXMK             (latexila_post_processor_latexmk_get_type ())
+#define LATEXILA_POST_PROCESSOR_LATEXMK(obj)             (G_TYPE_CHECK_INSTANCE_CAST ((obj), 
LATEXILA_TYPE_POST_PROCESSOR_LATEXMK, LatexilaPostProcessorLatexmk))
+#define LATEXILA_POST_PROCESSOR_LATEXMK_CLASS(klass)     (G_TYPE_CHECK_CLASS_CAST ((klass), 
LATEXILA_TYPE_POST_PROCESSOR_LATEXMK, LatexilaPostProcessorLatexmkClass))
+#define LATEXILA_IS_POST_PROCESSOR_LATEXMK(obj)          (G_TYPE_CHECK_INSTANCE_TYPE ((obj), 
LATEXILA_TYPE_POST_PROCESSOR_LATEXMK))
+#define LATEXILA_IS_POST_PROCESSOR_LATEXMK_CLASS(klass)  (G_TYPE_CHECK_CLASS_TYPE ((klass), 
LATEXILA_TYPE_POST_PROCESSOR_LATEXMK))
+#define LATEXILA_POST_PROCESSOR_LATEXMK_GET_CLASS(obj)   (G_TYPE_INSTANCE_GET_CLASS ((obj), 
LATEXILA_TYPE_POST_PROCESSOR_LATEXMK, LatexilaPostProcessorLatexmkClass))
+
+typedef struct _LatexilaPostProcessorLatexmkClass   LatexilaPostProcessorLatexmkClass;
+typedef struct _LatexilaPostProcessorLatexmkPrivate LatexilaPostProcessorLatexmkPrivate;
+
+struct _LatexilaPostProcessorLatexmk
+{
+  LatexilaPostProcessor parent;
+
+  LatexilaPostProcessorLatexmkPrivate *priv;
+};
+
+struct _LatexilaPostProcessorLatexmkClass
+{
+  LatexilaPostProcessorClass parent_class;
+};
+
+GType                   latexila_post_processor_latexmk_get_type  (void) G_GNUC_CONST;
+
+LatexilaPostProcessor * latexila_post_processor_latexmk_new       (void);
+
+G_END_DECLS
+
+#endif /* __LATEXILA_POST_PROCESSOR_LATEXMK_H__ */
diff --git a/src/liblatexila/latexila-types.h b/src/liblatexila/latexila-types.h
index 997aa99..6c01249 100644
--- a/src/liblatexila/latexila-types.h
+++ b/src/liblatexila/latexila-types.h
@@ -33,6 +33,7 @@ typedef struct _LatexilaBuildView               LatexilaBuildView;
 typedef struct _LatexilaPostProcessor           LatexilaPostProcessor;
 typedef struct _LatexilaPostProcessorAllOutput  LatexilaPostProcessorAllOutput;
 typedef struct _LatexilaPostProcessorLatex      LatexilaPostProcessorLatex;
+typedef struct _LatexilaPostProcessorLatexmk    LatexilaPostProcessorLatexmk;
 typedef struct _LatexilaSynctex                 LatexilaSynctex;
 
 G_END_DECLS


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