[latexila] Build Tools: big code clean-up
- From: SÃbastien Wilmet <swilmet src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [latexila] Build Tools: big code clean-up
- Date: Sat, 30 Jul 2011 22:48:55 +0000 (UTC)
commit 0f0a2568d120c065659e0e43ae97c6cd7503ff67
Author: SÃbastien Wilmet <swilmet src gnome org>
Date: Sun Jul 31 00:46:21 2011 +0200
Build Tools: big code clean-up
Rename BuildIssue -> BuildMsg, since the build view contains other types
of messages than issues.
The post processors messages are stored in a GNode. It's more flexible
than previously, and it's cleaner.
src/build_tool_runner.vala | 55 +++-----
src/build_view.vala | 183 ++++++++++++++------------
src/latex_post_processor.vala | 90 ++++++-------
src/post_processors.vala | 292 ++++++++++++++++++++---------------------
4 files changed, 308 insertions(+), 312 deletions(-)
---
diff --git a/src/build_tool_runner.vala b/src/build_tool_runner.vala
index a059bbc..5b20732 100644
--- a/src/build_tool_runner.vala
+++ b/src/build_tool_runner.vala
@@ -51,6 +51,7 @@ public class BuildToolRunner : GLib.Object
public BuildToolRunner (File file, BuildTool? tool, BuildView view,
Gtk.Action action_stop_exec)
{
+ // FIXME really useful?
return_if_fail (tool != null);
this.file = file;
@@ -68,7 +69,7 @@ public class BuildToolRunner : GLib.Object
// verify if file extension is allowed for the build tool
string[] extensions = tool.extensions.split (" ");
- if (tool.extensions.length > 0
+ if (0 < tool.extensions.length
&& ! (Utils.get_extension (filename) in extensions))
{
stderr.printf ("Warning: bad file extension\n");
@@ -252,20 +253,10 @@ public class BuildToolRunner : GLib.Object
break;
}
- post_processor.process (file, output, status);
+ post_processor.set_status (status);
+ post_processor.process (file, output);
- PostProcessorIssues[] all_issues = post_processor.get_issues ();
- foreach (PostProcessorIssues issues in all_issues)
- {
- if (issues.partition_msg != null)
- {
- TreeIter iter = view.add_partition (issues.partition_msg,
- issues.partition_state, job_partitions[job_num]);
- view.append_issues (iter, issues.issues);
- }
- else
- view.append_issues (job_partitions[job_num], issues.issues);
- }
+ view.append_messages (job_partitions[job_num], post_processor.get_messages ());
if (post_processor.successful)
{
@@ -307,15 +298,14 @@ public class BuildToolRunner : GLib.Object
if (current_job.post_processor == PostProcessorType.RUBBER
&& filename.contains (" "))
{
- Gee.ArrayList<BuildIssue?> issues = new Gee.ArrayList<BuildIssue?> ();
- BuildIssue issue = BuildIssue ();
- issue.message =
+ BuildMsg message = BuildMsg ();
+ message.text =
_("Rubber may not support filenames with spaces (even in a directory)");
- issue.message_type = BuildMessageType.WARNING;
- issue.filename = filename;
- issues.add (issue);
+ message.type = BuildMsgType.WARNING;
+ message.filename = filename;
+ message.lines_set = false;
- view.append_issues (job_partitions[job_num], issues);
+ view.append_single_message (job_partitions[job_num], message);
}
try
@@ -329,27 +319,24 @@ public class BuildToolRunner : GLib.Object
{
view.set_partition_state (job_partitions[job_num], PartitionState.FAILED);
- Gee.ArrayList<BuildIssue?> issues = new Gee.ArrayList<BuildIssue?> ();
- BuildIssue error_issue = BuildIssue ();
- error_issue.message = e.message;
- error_issue.message_type = BuildMessageType.ERROR;
- error_issue.start_line = -1;
- issues.add (error_issue);
+ BuildMsg error_msg = BuildMsg ();
+ error_msg.text = e.message;
+ error_msg.type = BuildMsgType.ERROR;
+ error_msg.lines_set = false;
+ view.append_single_message (job_partitions[job_num], error_msg);
// If the command doesn't seem to be installed, display a more understandable
// message.
if (e is SpawnError.NOENT)
{
- BuildIssue info_issue = BuildIssue ();
- info_issue.message =
+ BuildMsg info_msg = BuildMsg ();
+ info_msg.text =
_("%s doesn't seem to be installed.").printf (command[0]);
- info_issue.message_type = BuildMessageType.OTHER;
- info_issue.start_line = -1;
- issues.add (info_issue);
+ info_msg.type = BuildMsgType.OTHER;
+ info_msg.lines_set = false;
+ view.append_single_message (job_partitions[job_num], info_msg);
}
- view.append_issues (job_partitions[job_num], issues);
-
if (current_job.must_succeed)
failed ();
else
diff --git a/src/build_view.vala b/src/build_view.vala
index 1ff2f6b..6d4d981 100644
--- a/src/build_view.vala
+++ b/src/build_view.vala
@@ -27,7 +27,7 @@ public enum PartitionState
ABORTED
}
-public enum BuildMessageType
+public enum BuildMsgType
{
ERROR,
WARNING,
@@ -35,21 +35,22 @@ public enum BuildMessageType
OTHER
}
-public struct BuildIssue
+public struct BuildMsg
{
- public string message;
- public BuildMessageType message_type;
+ public string text;
+ public BuildMsgType type;
public string? filename;
- // no line: -1
- // if end_line is -1, end_line takes the same value as start_line
+ public bool lines_set;
public int start_line;
+
+ // if -1, takes the same value as start_line
public int end_line;
}
public class BuildView : HBox
{
- enum BuildInfo
+ private enum BuildInfo
{
ICON,
MESSAGE,
@@ -68,22 +69,22 @@ public class BuildView : HBox
public bool show_warnings { get; set; }
public bool show_badboxes { get; set; }
- private unowned MainWindow main_window;
- private TreeStore store;
- private TreeModelFilter filtered_model;
- private TreeView view;
- private unowned ToggleAction action_view_bottom_panel;
+ private unowned MainWindow _main_window;
+ private TreeStore _store;
+ private TreeModelFilter _filtered_model;
+ private TreeView _view;
+ private unowned ToggleAction _action_view_bottom_panel;
public BuildView (MainWindow main_window, Toolbar toolbar,
ToggleAction view_bottom_panel)
{
- this.main_window = main_window;
- this.action_view_bottom_panel = view_bottom_panel;
+ _main_window = main_window;
+ _action_view_bottom_panel = view_bottom_panel;
- store = new TreeStore (BuildInfo.N_COLUMNS,
+ _store = new TreeStore (BuildInfo.N_COLUMNS,
typeof (string), // icon (stock-id)
typeof (string), // message
- typeof (BuildMessageType),
+ typeof (BuildMsgType),
typeof (int), // weight (normal or bold)
typeof (string), // basename
typeof (string), // path
@@ -94,31 +95,31 @@ public class BuildView : HBox
);
/* filter errors/warnings/badboxes */
- filtered_model = new TreeModelFilter (store, null);
- filtered_model.set_visible_func ((model, iter) =>
+ _filtered_model = new TreeModelFilter (_store, null);
+ _filtered_model.set_visible_func ((model, iter) =>
{
- BuildMessageType msg_type;
+ BuildMsgType msg_type;
model.get (iter, BuildInfo.MESSAGE_TYPE, out msg_type, -1);
switch (msg_type)
{
- case BuildMessageType.ERROR:
+ case BuildMsgType.ERROR:
return show_errors;
- case BuildMessageType.WARNING:
+ case BuildMsgType.WARNING:
return show_warnings;
- case BuildMessageType.BADBOX:
+ case BuildMsgType.BADBOX:
return show_badboxes;
default:
return true;
}
});
- this.notify["show-errors"].connect (() => filtered_model.refilter ());
- this.notify["show-warnings"].connect (() => filtered_model.refilter ());
- this.notify["show-badboxes"].connect (() => filtered_model.refilter ());
+ this.notify["show-errors"].connect (() => _filtered_model.refilter ());
+ this.notify["show-warnings"].connect (() => _filtered_model.refilter ());
+ this.notify["show-badboxes"].connect (() => _filtered_model.refilter ());
/* create tree view */
- view = new TreeView.with_model (filtered_model);
+ _view = new TreeView.with_model (_filtered_model);
TreeViewColumn column_job = new TreeViewColumn ();
column_job.title = _("Job");
@@ -135,17 +136,17 @@ public class BuildView : HBox
column_job.add_attribute (renderer_text, "text", BuildInfo.MESSAGE);
column_job.add_attribute (renderer_text, "weight", BuildInfo.WEIGHT);
- view.append_column (column_job);
+ _view.append_column (column_job);
- view.insert_column_with_attributes (-1, _("File"), new CellRendererText (),
+ _view.insert_column_with_attributes (-1, _("File"), new CellRendererText (),
"text", BuildInfo.BASENAME);
- view.insert_column_with_attributes (-1, _("Line"), new CellRendererText (),
+ _view.insert_column_with_attributes (-1, _("Line"), new CellRendererText (),
"text", BuildInfo.LINE);
- view.set_tooltip_column (BuildInfo.PATH);
+ _view.set_tooltip_column (BuildInfo.PATH);
// selection
- TreeSelection select = view.get_selection ();
+ TreeSelection select = _view.get_selection ();
select.set_mode (SelectionMode.SINGLE);
select.set_select_function ((select, model, path, path_currently_selected) =>
{
@@ -157,7 +158,7 @@ public class BuildView : HBox
});
// double-click
- view.row_activated.connect ((path) => select_row (filtered_model, path));
+ _view.row_activated.connect ((path) => select_row (_filtered_model, path));
// close button
Button close_button = new Button ();
@@ -168,11 +169,11 @@ public class BuildView : HBox
close_button.clicked.connect (() =>
{
this.hide ();
- action_view_bottom_panel.active = false;
+ _action_view_bottom_panel.active = false;
});
// with a scrollbar
- Widget sw = Utils.add_scrollbar (view);
+ Widget sw = Utils.add_scrollbar (_view);
pack_start (sw);
VBox vbox = new VBox (false, 0);
@@ -188,7 +189,7 @@ public class BuildView : HBox
// the row is not selected
return false;
- BuildMessageType msg_type;
+ BuildMsgType msg_type;
File file;
int start_line, end_line;
@@ -199,7 +200,7 @@ public class BuildView : HBox
BuildInfo.END_LINE, out end_line,
-1);
- if (msg_type != BuildMessageType.OTHER && file != null)
+ if (msg_type != BuildMsgType.OTHER && file != null)
{
jump_to_file (file, start_line, end_line);
@@ -208,14 +209,14 @@ public class BuildView : HBox
}
// maybe it's a parent, so we can show or hide its children
- else if (msg_type == BuildMessageType.OTHER)
+ else if (msg_type == BuildMsgType.OTHER)
{
if (model.iter_has_child (iter))
{
- if (view.is_row_expanded (path))
- view.collapse_row (path);
+ if (_view.is_row_expanded (path))
+ _view.collapse_row (path);
else
- view.expand_to_path (path);
+ _view.expand_to_path (path);
// the row is not selected
return false;
@@ -228,7 +229,7 @@ public class BuildView : HBox
private void jump_to_file (File file, int start_line, int end_line)
{
- DocumentTab tab = main_window.open_document (file);
+ DocumentTab tab = _main_window.open_document (file);
// If the file was not yet opened, it takes some time. If we try to select the
// lines when the file is not fully charged, the lines are simply not selected.
@@ -244,67 +245,85 @@ public class BuildView : HBox
public void clear ()
{
- store.clear ();
- view.columns_autosize ();
+ _store.clear ();
+ _view.columns_autosize ();
}
public TreeIter add_partition (string msg, PartitionState state, TreeIter? parent,
bool bold = false)
{
TreeIter iter;
- store.append (out iter, parent);
- store.set (iter,
+ _store.append (out iter, parent);
+ _store.set (iter,
BuildInfo.ICON, get_icon_from_state (state),
BuildInfo.MESSAGE, msg,
- BuildInfo.MESSAGE_TYPE, BuildMessageType.OTHER,
+ BuildInfo.MESSAGE_TYPE, BuildMsgType.OTHER,
BuildInfo.WEIGHT, bold ? 800 : 400,
-1);
- view.expand_all ();
+ _view.expand_all ();
return iter;
}
public void set_partition_state (TreeIter partition_id, PartitionState state)
{
- store.set (partition_id, BuildInfo.ICON, get_icon_from_state (state), -1);
+ _store.set (partition_id, BuildInfo.ICON, get_icon_from_state (state), -1);
}
- public void append_issues (TreeIter partition_id, Gee.ArrayList<BuildIssue?> issues)
+ public void append_messages (TreeIter partition_id, Node<BuildMsg?> messages)
{
- foreach (BuildIssue issue in issues)
+ unowned Node<BuildMsg?> cur_node = messages.first_child ();
+ while (cur_node != null)
{
- File file = null;
- string path = null;
+ TreeIter iter = append_single_message (partition_id, cur_node.data);
+ append_messages (iter, cur_node);
+ cur_node = cur_node.next_sibling ();
+ }
- if (issue.filename != null)
- {
- file = File.new_for_path (issue.filename);
- path = Utils.replace_home_dir_with_tilde (issue.filename);
+ _view.expand_all ();
+ }
- // the path is displayed in a tooltip
- path = Markup.escape_text (path);
- }
+ public TreeIter append_single_message (TreeIter partition_id, BuildMsg message)
+ {
+ File file = null;
+ string path = null;
+
+ if (message.filename != null)
+ {
+ file = File.new_for_path (message.filename);
+ path = Utils.replace_home_dir_with_tilde (message.filename);
- TreeIter iter;
- store.append (out iter, partition_id);
- store.set (iter,
- BuildInfo.ICON, get_icon_from_msg_type (issue.message_type),
- BuildInfo.MESSAGE, issue.message,
- BuildInfo.MESSAGE_TYPE, issue.message_type,
- BuildInfo.WEIGHT, 400,
- BuildInfo.BASENAME, issue.filename != null ?
- Path.get_basename (issue.filename) : null,
- BuildInfo.FILE, file,
- BuildInfo.PATH, path,
- BuildInfo.START_LINE, issue.start_line,
- BuildInfo.END_LINE, issue.end_line,
- BuildInfo.LINE, issue.start_line != -1 ?
- issue.start_line.to_string () : null,
- -1);
+ // the path is displayed in a tooltip
+ path = Markup.escape_text (path);
}
- view.expand_all ();
+ int start_line = -1;
+ int end_line = -1;
+ string line_str = null;
+ if (message.lines_set)
+ {
+ start_line = message.start_line;
+ end_line = message.end_line;
+ line_str = start_line.to_string ();
+ }
+
+ TreeIter iter;
+ _store.append (out iter, partition_id);
+ _store.set (iter,
+ BuildInfo.ICON, get_icon_from_msg_type (message.type),
+ BuildInfo.MESSAGE, message.text,
+ BuildInfo.MESSAGE_TYPE, message.type,
+ BuildInfo.WEIGHT, 400,
+ BuildInfo.BASENAME, file != null ? file.get_basename () : null,
+ BuildInfo.FILE, file,
+ BuildInfo.PATH, path,
+ BuildInfo.START_LINE, start_line,
+ BuildInfo.END_LINE, end_line,
+ BuildInfo.LINE, line_str,
+ -1);
+
+ return iter;
}
private string? get_icon_from_state (PartitionState state)
@@ -324,17 +343,17 @@ public class BuildView : HBox
}
}
- private string? get_icon_from_msg_type (BuildMessageType type)
+ private string? get_icon_from_msg_type (BuildMsgType type)
{
switch (type)
{
- case BuildMessageType.ERROR:
+ case BuildMsgType.ERROR:
return Stock.DIALOG_ERROR;
- case BuildMessageType.WARNING:
+ case BuildMsgType.WARNING:
return Stock.DIALOG_WARNING;
- case BuildMessageType.BADBOX:
+ case BuildMsgType.BADBOX:
return "badbox";
- case BuildMessageType.OTHER:
+ case BuildMsgType.OTHER:
return null;
default:
return_val_if_reached (null);
@@ -344,6 +363,6 @@ public class BuildView : HBox
public new void show ()
{
base.show ();
- action_view_bottom_panel.active = true;
+ _action_view_bottom_panel.active = true;
}
}
diff --git a/src/latex_post_processor.vala b/src/latex_post_processor.vala
index 210f0d8..6814e4d 100644
--- a/src/latex_post_processor.vala
+++ b/src/latex_post_processor.vala
@@ -17,11 +17,8 @@
* along with LaTeXila. If not, see <http://www.gnu.org/licenses/>.
*/
-private class LatexPostProcessor : GLib.Object, PostProcessor
+private class LatexPostProcessor : PostProcessor
{
- public bool successful { get; protected set; }
- private Gee.ArrayList<BuildIssue?> issues = new Gee.ArrayList<BuildIssue?> ();
-
private enum FilterStatus
{
START,
@@ -47,7 +44,7 @@ private class LatexPostProcessor : GLib.Object, PostProcessor
private const int NO_LINE = -1;
// the current message
- private BuildIssue msg;
+ private BuildMsg msg;
// if a message is splitted, we enter in a different status, so we fetch the end
// of the message
@@ -132,9 +129,8 @@ private class LatexPostProcessor : GLib.Object, PostProcessor
}
}
- public void process (File file, string output, int status)
+ public override void process (File file, string output)
{
- successful = status == 0;
directory_path = file.get_parent ().get_parse_name ();
string[] lines = output.split ("\n");
@@ -145,22 +141,14 @@ private class LatexPostProcessor : GLib.Object, PostProcessor
// Stats.
// Since all the messages printed by the 'latex' or 'pdflatex' command are in
// English, it would be strange to have only this one translated.
- msg.message = "%d %s, %d %s, %d %s".printf (
+ msg.text = "%d %s, %d %s, %d %s".printf (
nb_errors, nb_errors == 1 ? "error" : "errors",
nb_warnings, nb_warnings == 1 ? "warning" : "warnings",
nb_badboxes, nb_badboxes == 1 ? "badbox" : "badboxes");
- msg.message_type = BuildMessageType.OTHER;
+ msg.type = BuildMsgType.OTHER;
add_msg (false);
}
- public PostProcessorIssues[] get_issues ()
- {
- PostProcessorIssues[] pp_issues = new PostProcessorIssues[1];
- pp_issues[0].partition_msg = null;
- pp_issues[0].issues = issues;
- return pp_issues;
- }
-
private void latex_output_filter (string line)
{
switch (status)
@@ -210,7 +198,7 @@ private class LatexPostProcessor : GLib.Object, PostProcessor
if (! reg_badbox.match (line))
return false;
- msg.message_type = BuildMessageType.BADBOX;
+ msg.type = BuildMsgType.BADBOX;
if (detect_badbox_line (line, false))
add_msg ();
@@ -245,7 +233,7 @@ private class LatexPostProcessor : GLib.Object, PostProcessor
{
status = FilterStatus.START;
string[] strings = reg_badbox_lines.split (badbox);
- msg.message = strings[1];
+ msg.text = strings[1];
int n1 = int.parse (strings[2]);
int n2 = int.parse (strings[3]);
@@ -267,7 +255,7 @@ private class LatexPostProcessor : GLib.Object, PostProcessor
{
status = FilterStatus.START;
string[] strings = reg_badbox_line.split (badbox);
- msg.message = strings[1];
+ msg.text = strings[1];
msg.start_line = int.parse (strings[2]);
return true;
}
@@ -276,7 +264,7 @@ private class LatexPostProcessor : GLib.Object, PostProcessor
{
status = FilterStatus.START;
string[] strings = reg_badbox_output.split (badbox);
- msg.message = strings[1];
+ msg.text = strings[1];
msg.start_line = NO_LINE;
return true;
}
@@ -284,7 +272,7 @@ private class LatexPostProcessor : GLib.Object, PostProcessor
else if (nb_lines > 4 || current_line_is_empty)
{
status = FilterStatus.START;
- msg.message = badbox;
+ msg.text = badbox;
msg.start_line = NO_LINE;
return true;
}
@@ -301,7 +289,7 @@ private class LatexPostProcessor : GLib.Object, PostProcessor
MatchInfo match_info;
if (reg_warning.match (line, 0, out match_info))
{
- msg.message_type = BuildMessageType.WARNING;
+ msg.type = BuildMsgType.WARNING;
string contents = match_info.fetch_named ("contents");
@@ -322,9 +310,9 @@ private class LatexPostProcessor : GLib.Object, PostProcessor
else if (reg_warning_no_file.match (line))
{
- msg.message_type = BuildMessageType.WARNING;
+ msg.type = BuildMsgType.WARNING;
string[] strings = reg_warning_no_file.split (line);
- msg.message = strings[1];
+ msg.text = strings[1];
msg.start_line = NO_LINE;
add_msg ();
return true;
@@ -355,7 +343,7 @@ private class LatexPostProcessor : GLib.Object, PostProcessor
{
status = FilterStatus.START;
string[] strings = reg_warning_line.split (warning);
- msg.message = strings[1];
+ msg.text = strings[1];
msg.start_line = int.parse (strings[2]);
return true;
}
@@ -364,7 +352,7 @@ private class LatexPostProcessor : GLib.Object, PostProcessor
{
status = FilterStatus.START;
string[] strings = reg_warning_international_line.split (warning);
- msg.message = strings[1];
+ msg.text = strings[1];
msg.start_line = int.parse (strings[2]);
return true;
}
@@ -372,7 +360,7 @@ private class LatexPostProcessor : GLib.Object, PostProcessor
else if (warning[warning.length - 1] == '.')
{
status = FilterStatus.START;
- msg.message = warning;
+ msg.text = warning;
msg.start_line = NO_LINE;
return true;
}
@@ -380,7 +368,7 @@ private class LatexPostProcessor : GLib.Object, PostProcessor
else if (nb_lines > 5 || current_line_is_empty)
{
status = FilterStatus.START;
- msg.message = warning;
+ msg.text = warning;
msg.start_line = NO_LINE;
return true;
}
@@ -420,12 +408,12 @@ private class LatexPostProcessor : GLib.Object, PostProcessor
if (found)
{
nb_lines++;
- msg.message_type = BuildMessageType.ERROR;
+ msg.type = BuildMsgType.ERROR;
// the message is complete
if (line[line.length - 1] == '.')
{
- msg.message = tmp;
+ msg.text = tmp;
status = FilterStatus.ERROR_SEARCH_LINE;
}
// the message is splitted
@@ -445,12 +433,12 @@ private class LatexPostProcessor : GLib.Object, PostProcessor
if (line[line.length - 1] == '.')
{
- msg.message = line_buf;
+ msg.text = line_buf;
status = FilterStatus.ERROR_SEARCH_LINE;
}
else if (nb_lines > 4)
{
- msg.message = line_buf;
+ msg.text = line_buf;
msg.start_line = NO_LINE;
add_msg ();
nb_lines = 0;
@@ -494,11 +482,11 @@ private class LatexPostProcessor : GLib.Object, PostProcessor
return false;
msg.start_line = NO_LINE;
- msg.message_type = BuildMessageType.OTHER;
+ msg.type = BuildMsgType.OTHER;
if (! reg_other_bytes.match (line))
{
- msg.message = line;
+ msg.text = line;
add_msg (false);
return true;
}
@@ -512,7 +500,7 @@ private class LatexPostProcessor : GLib.Object, PostProcessor
// do nothing
if (nb_bytes < 1024)
- msg.message = line;
+ msg.text = line;
// size in KB (less than 1 MB)
else if (nb_bytes < 1024 * 1024)
@@ -536,13 +524,13 @@ private class LatexPostProcessor : GLib.Object, PostProcessor
{
string new_line =
reg_other_bytes.replace_literal (line, -1, 0, human_size);
- msg.message = new_line;
+ msg.text = new_line;
}
// nice try!
catch (RegexError e)
{
- msg.message = line;
+ msg.text = line;
}
}
@@ -822,8 +810,8 @@ private class LatexPostProcessor : GLib.Object, PostProcessor
private void add_msg (bool set_filename = true)
{
// exclude some useless messages here
- if (msg.message_type == BuildMessageType.WARNING
- && msg.message == "There were undefined references.")
+ if (msg.type == BuildMsgType.WARNING
+ && msg.text == "There were undefined references.")
{
reset_msg ();
return;
@@ -836,39 +824,43 @@ private class LatexPostProcessor : GLib.Object, PostProcessor
{
// A message on several lines are sometimes indented, so when the lines are
// catenated there are a lot of spaces. We replace these spaces by one space.
- msg.message = reg_spaces.replace (msg.message, -1, 0, " ");
+ msg.text = reg_spaces.replace (msg.text, -1, 0, " ");
}
catch (RegexError e)
{
stderr.printf ("Latex post processor warning: %s\n", e.message);
}
- switch (msg.message_type)
+ switch (msg.type)
{
- case BuildMessageType.BADBOX:
+ case BuildMsgType.BADBOX:
nb_badboxes++;
break;
- case BuildMessageType.WARNING:
+ case BuildMsgType.WARNING:
nb_warnings++;
break;
- case BuildMessageType.ERROR:
+ case BuildMsgType.ERROR:
nb_errors++;
break;
}
- issues.add (msg);
+ if (msg.start_line != NO_LINE)
+ msg.lines_set = true;
+
+ append_message (msg);
reset_msg ();
}
private void reset_msg ()
{
- msg = BuildIssue ();
- msg.message = null;
- msg.message_type = BuildMessageType.OTHER;
+ msg = BuildMsg ();
+ msg.text = null;
+ msg.type = BuildMsgType.OTHER;
msg.filename = null;
msg.start_line = NO_LINE;
msg.end_line = NO_LINE;
+ msg.lines_set = false;
}
}
diff --git a/src/post_processors.vala b/src/post_processors.vala
index 7ee6701..4fc487b 100644
--- a/src/post_processors.vala
+++ b/src/post_processors.vala
@@ -17,94 +17,96 @@
* along with LaTeXila. If not, see <http://www.gnu.org/licenses/>.
*/
-public struct PostProcessorIssues
+private abstract class PostProcessor : GLib.Object
{
- public string? partition_msg;
- public PartitionState partition_state;
- public Gee.ArrayList<BuildIssue?> issues;
-}
-
-private interface PostProcessor : GLib.Object
-{
- public abstract bool successful { get; protected set; }
- public abstract void process (File file, string output, int status);
- public abstract PostProcessorIssues[] get_issues ();
-}
+ protected Node<BuildMsg?> _all_messages = new Node<BuildMsg?> (BuildMsg ());
+ private unowned Node<BuildMsg?> _prev_message = null;
-private class NoOutputPostProcessor : GLib.Object, PostProcessor
-{
public bool successful { get; protected set; }
- public void process (File file, string output, int status)
+ public Node<BuildMsg?> get_messages ()
{
- successful = status == 0;
+ return (owned) _all_messages;
+ }
+
+ protected unowned Node<BuildMsg?> append_message (BuildMsg message)
+ {
+ unowned Node<BuildMsg?> new_message;
+
+ bool prev_msg_is_invalid = _prev_message != null && _prev_message.next != null;
+
+ // If _prev_message is not the last node, do a normal 'append'.
+ if (_prev_message == null || prev_msg_is_invalid)
+ new_message = _all_messages.append_data (message);
+
+ else
+ {
+ // 'insert_after' is O(1), whereas 'append' is O(N).
+ // That's why we keep the previous node.
+ new_message = _all_messages.insert_after (_prev_message,
+ new Node<BuildMsg?> (message));
+ }
+
+ _prev_message = new_message;
+ return new_message;
}
- public PostProcessorIssues[] get_issues ()
+ public void set_status (int status)
{
- // empty
- PostProcessorIssues[] issues = {};
- return issues;
+ successful = status == 0;
}
+
+ public abstract void process (File file, string output);
}
-private class AllOutputPostProcessor : GLib.Object, PostProcessor
+private class NoOutputPostProcessor : PostProcessor
{
- public bool successful { get; protected set; }
- private Gee.ArrayList<BuildIssue?> issues = new Gee.ArrayList<BuildIssue?> ();
-
- public void process (File file, string output, int status)
+ public override void process (File file, string output)
{
- successful = status == 0;
+ }
+}
+private class AllOutputPostProcessor : PostProcessor
+{
+ public override void process (File file, string output)
+ {
if (output.length == 0)
return;
string[] lines = output.split ("\n");
- int l = lines.length;
- return_if_fail (l > 0);
+ int nb_lines = lines.length;
+ return_if_fail (nb_lines > 0);
// Generally there is a \n at the end of the output so an empty line is added,
// but we don't want to display it.
- if (lines[l-1].length == 0)
- l--;
+ if (lines[nb_lines - 1].length == 0)
+ nb_lines--;
- BuildIssue issue = BuildIssue ();
- issue.message_type = BuildMessageType.OTHER;
- issue.filename = null;
- issue.start_line = -1;
- issue.end_line = -1;
+ BuildMsg message = BuildMsg ();
+ message.type = BuildMsgType.OTHER;
+ message.filename = null;
+ message.lines_set = false;
- for (int i = 0 ; i < l ; i++)
+ for (int line_num = 0 ; line_num < nb_lines ; line_num++)
{
- issue.message = lines[i];
- issues.add (issue);
+ message.text = lines[line_num];
+ append_message (message);
}
}
-
- public PostProcessorIssues[] get_issues ()
- {
- PostProcessorIssues[] pp_issues = new PostProcessorIssues[1];
- pp_issues[0].partition_msg = null;
- pp_issues[0].issues = issues;
- return pp_issues;
- }
}
-private class RubberPostProcessor : GLib.Object, PostProcessor
+private class RubberPostProcessor : PostProcessor
{
- public bool successful { get; protected set; }
- private static Regex? pattern = null;
- private Gee.ArrayList<BuildIssue?> issues = new Gee.ArrayList<BuildIssue?> ();
+ private static Regex? _pattern = null;
public RubberPostProcessor ()
{
- if (pattern != null)
+ if (_pattern != null)
return;
try
{
- pattern = new Regex (
+ _pattern = new Regex (
"(?P<file>[^:\n]+)(:(?P<line>[\\d\\-]+))?:(?P<text>.+)$",
RegexCompileFlags.MULTILINE | RegexCompileFlags.OPTIMIZE);
}
@@ -114,43 +116,44 @@ private class RubberPostProcessor : GLib.Object, PostProcessor
}
}
- public void process (File file, string output, int status)
+ public override void process (File file, string output)
{
- successful = status == 0;
- if (pattern == null)
- return;
+ return_if_fail (_pattern != null);
string parent_path = file.get_parent ().get_parse_name ();
MatchInfo match_info;
- pattern.match (output, 0, out match_info);
+ _pattern.match (output, 0, out match_info);
while (match_info.matches ())
{
- BuildIssue issue = BuildIssue ();
- string text = issue.message = match_info.fetch_named ("text");
+ BuildMsg message = BuildMsg ();
+ message.text = match_info.fetch_named ("text");
// message type
- issue.message_type = BuildMessageType.ERROR;
- if (text.contains ("Underfull") || text.contains ("Overfull"))
- issue.message_type = BuildMessageType.BADBOX;
+ message.type = BuildMsgType.ERROR;
+ if (message.text.contains ("Underfull") || message.text.contains ("Overfull"))
+ message.type = BuildMsgType.BADBOX;
// line
- issue.start_line = issue.end_line = -1;
- string line = match_info.fetch_named ("line");
- if (line != null && line.length > 0)
+ message.lines_set = false;
+ string? line = match_info.fetch_named ("line");
+ if (line != null && 0 < line.length)
{
+ message.lines_set = true;
string[] parts = line.split ("-");
- issue.start_line = int.parse (parts[0]);
- if (parts.length > 1 && parts[1] != null && parts[1].length > 0)
- issue.end_line = int.parse (parts[1]);
+ message.start_line = int.parse (parts[0]);
+ if (1 < parts.length && parts[1] != null && 0 < parts[1].length)
+ message.end_line = int.parse (parts[1]);
+ else
+ message.end_line = -1;
}
// filename
- issue.filename = match_info.fetch_named ("file");
- if (issue.filename[0] != '/')
- issue.filename = "%s/%s".printf (parent_path, issue.filename);
+ message.filename = match_info.fetch_named ("file");
+ if (message.filename[0] != '/')
+ message.filename = "%s/%s".printf (parent_path, message.filename);
- issues.add (issue);
+ append_message (message);
try
{
@@ -163,30 +166,19 @@ private class RubberPostProcessor : GLib.Object, PostProcessor
}
}
}
-
- public PostProcessorIssues[] get_issues ()
- {
- PostProcessorIssues[] pp_issues = new PostProcessorIssues[1];
- pp_issues[0].partition_msg = null;
- pp_issues[0].issues = issues;
- return pp_issues;
- }
}
-private class LatexmkPostProcessor : GLib.Object, PostProcessor
+private class LatexmkPostProcessor : PostProcessor
{
- public bool successful { get; protected set; }
- private PostProcessorIssues[] all_issues = {};
+ private static Regex? _reg_rule = null;
+ private static Regex? _reg_no_rule = null;
+ private bool _force_show_all;
- private static Regex? reg_rule = null;
- private static Regex? reg_no_rule = null;
- private bool show_all;
-
- public LatexmkPostProcessor (bool show_all = false)
+ public LatexmkPostProcessor (bool force_show_all)
{
- this.show_all = show_all;
+ _force_show_all = force_show_all;
- if (reg_rule != null)
+ if (_reg_rule != null)
return;
try
@@ -194,7 +186,7 @@ private class LatexmkPostProcessor : GLib.Object, PostProcessor
string ungreedy_lines = "((?U)(.*\\R)*)";
string reg_rule_str = "-{12}\\R";
- reg_rule_str += "(?P<line>Run number \\d+ of rule '(?P<rule>.*)')\\R";
+ reg_rule_str += "(?P<title>Run number \\d+ of rule '(?P<rule>.*)')\\R";
reg_rule_str += "(-{12}\\R){2}";
reg_rule_str += "Running '(?P<cmd>.*)'\\R";
reg_rule_str += "-{12}\\R";
@@ -204,13 +196,13 @@ private class LatexmkPostProcessor : GLib.Object, PostProcessor
reg_rule_str += "(?P<output>" + ungreedy_lines + ")";
reg_rule_str += "(Latexmk:|Rule '.*':)";
- reg_rule = new Regex (reg_rule_str, RegexCompileFlags.OPTIMIZE);
+ _reg_rule = new Regex (reg_rule_str, RegexCompileFlags.OPTIMIZE);
string reg_no_rule_str = "(Latexmk: This is Latexmk.*\\R)?";
reg_no_rule_str += "(\\*{4} Report bugs.*\\R)?";
reg_no_rule_str += "(?P<output>(.*\\R)*)";
- reg_no_rule = new Regex (reg_no_rule_str);
+ _reg_no_rule = new Regex (reg_no_rule_str);
}
catch (RegexError e)
{
@@ -218,40 +210,28 @@ private class LatexmkPostProcessor : GLib.Object, PostProcessor
}
}
- public void process (File file, string output, int status)
+ public override void process (File file, string output)
{
- successful = status == 0;
+ return_if_fail (_reg_rule != null && _reg_no_rule != null);
- return_if_fail (reg_rule != null && reg_no_rule != null);
-
- string latex_output = null;
- int last_latex_cmd_index = 0;
+ string last_latex_output = null;
+ unowned Node<BuildMsg?> last_latex_node = null;
MatchInfo match_info;
- reg_rule.match (output, 0, out match_info);
-
- int i;
- for (i = 0 ; match_info.matches () ; i++)
+ _reg_rule.match (output, 0, out match_info);
+ while (match_info.matches ())
{
- PostProcessorIssues pp_issues = PostProcessorIssues ();
- pp_issues.partition_msg = match_info.fetch_named ("line");
- pp_issues.partition_state = PartitionState.SUCCEEDED;
-
- Gee.ArrayList<BuildIssue?> issues = new Gee.ArrayList<BuildIssue?> ();
-
- BuildIssue issue = BuildIssue ();
- issue.message_type = BuildMessageType.OTHER;
- issue.start_line = -1;
- issue.message = "$ " + match_info.fetch_named ("cmd");
- issues.add (issue);
+ Node<BuildMsg?> cmd_messages = null;
+ /* command output */
string rule = match_info.fetch_named ("rule");
// if the rule is latex or pdflatex, we store the output
- if (rule.has_suffix ("latex"))
+ bool is_latex_cmd = rule == "latex" || rule == "pdflatex";
+ if (is_latex_cmd)
{
- latex_output = match_info.fetch_named ("output");
- last_latex_cmd_index = i;
+ last_latex_output = match_info.fetch_named ("output");
+ cmd_messages = new Node<BuildMsg?> (BuildMsg ());
}
// if it's another rule (bibtex, makeindex, etc), we show all output
@@ -259,18 +239,30 @@ private class LatexmkPostProcessor : GLib.Object, PostProcessor
{
string cmd_output = match_info.fetch_named ("output");
PostProcessor all_output_pp = new AllOutputPostProcessor ();
- all_output_pp.process (file, cmd_output, 0);
- PostProcessorIssues[] all_output_issues = all_output_pp.get_issues ();
+ all_output_pp.process (file, cmd_output);
+ cmd_messages = all_output_pp.get_messages ();
+ }
- // normally there is no partition in the output
- return_if_fail (all_output_issues.length == 1
- && all_output_issues[0].partition_msg == null);
+ /* title */
+ BuildMsg title_msg = BuildMsg ();
+ title_msg.type = BuildMsgType.OTHER;
+ title_msg.lines_set = false;
+ title_msg.text = match_info.fetch_named ("title");
- issues.add_all (all_output_issues[0].issues);
- }
+ cmd_messages.data = title_msg;
- pp_issues.issues = issues;
- all_issues += pp_issues;
+ /* command line */
+ BuildMsg cmd_line_msg = BuildMsg ();
+ cmd_line_msg.type = BuildMsgType.OTHER;
+ cmd_line_msg.lines_set = false;
+ cmd_line_msg.text = "$ " + match_info.fetch_named ("cmd");
+
+ cmd_messages.insert_data (0, cmd_line_msg);
+
+ if (is_latex_cmd)
+ last_latex_node = _all_messages.append ((owned) cmd_messages);
+ else
+ _all_messages.append ((owned) cmd_messages);
try
{
@@ -283,47 +275,53 @@ private class LatexmkPostProcessor : GLib.Object, PostProcessor
}
}
- // Run latex post processor on the last latex or pdflatex output
- if (latex_output != null)
+ /* Run the latex post processor on the last latex or pdflatex output */
+ if (last_latex_output != null)
{
PostProcessor latex_pp = new LatexPostProcessor ();
- latex_pp.process (file, latex_output, 0);
- PostProcessorIssues[] latex_issues = latex_pp.get_issues ();
+ latex_pp.process (file, last_latex_output);
+ Node<BuildMsg?> latex_messages = latex_pp.get_messages ();
- // normally there is no partition in the latex output
- return_if_fail (latex_issues.length == 1
- && latex_issues[0].partition_msg == null);
+ bool last_cmd_is_latex_cmd = _all_messages.last_child () == last_latex_node;
// 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.
- if (! show_all && (successful || last_latex_cmd_index == i - 1))
- all_issues = latex_issues;
+ if (! _force_show_all && (successful || last_cmd_is_latex_cmd))
+ _all_messages = (owned) latex_messages;
+
+ // Replace 'last_latex_node' by 'latex_messages'
else
- all_issues[last_latex_cmd_index].issues.add_all (latex_issues[0].issues);
+ {
+ // take the title
+ latex_messages.data = last_latex_node.data;
+
+ // take the command line
+ latex_messages.insert (0, last_latex_node.first_child ().unlink ());
+
+ // replace
+ int pos = _all_messages.child_position (last_latex_node);
+ last_latex_node.unlink ();
+ _all_messages.insert (pos, (owned) latex_messages);
+ }
}
- if (i > 0)
+ if (_all_messages.children != null)
return;
- // show all output since there were no rule executed
+ /* show all output since there were no rule executed */
PostProcessor all_output_pp = new AllOutputPostProcessor ();
- if (reg_no_rule.match (output, 0, out match_info))
+ if (_reg_no_rule.match (output, 0, out match_info))
{
// almost all output
string all_output = match_info.fetch_named ("output");
- all_output_pp.process (file, all_output, 0);
+ all_output_pp.process (file, all_output);
}
else
- all_output_pp.process (file, output, 0);
+ all_output_pp.process (file, output);
- all_issues = all_output_pp.get_issues ();
- }
-
- public PostProcessorIssues[] get_issues ()
- {
- return all_issues;
+ _all_messages = all_output_pp.get_messages ();
}
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]