[latexila] Structure action: select



commit d9a98db1a09e0a0056df013747047f6a7c85e8fb
Author: SÃbastien Wilmet <swilmet src gnome org>
Date:   Thu Jun 30 01:49:10 2011 +0200

    Structure action: select

 TODO                        |   16 +++-
 src/document_structure.vala |  216 ++++++++++++++++++++++++++++++++++++++++---
 src/structure.vala          |    1 +
 3 files changed, 218 insertions(+), 15 deletions(-)
---
diff --git a/TODO b/TODO
index 5d82ad1..c9fcfd1 100644
--- a/TODO
+++ b/TODO
@@ -8,16 +8,28 @@ LaTeXila 2.2
 
 - Structure (list of chapters, sections, etc. to easily navigate in a document):
 	- Right click:
-		- cut, copy, delete, select
-		- comment
+		- cut, copy, delete
+		- comment: remove the item(s) from the model when the item is commented
 		- shift left
 		- shift right:
 			- display a warning if a subparagraph already exists
+		- display a warning if the action fails (most probably when the structure data
+		  is not up-to-date)
 
 	  Shift left/right is new comparated to Kile. For example we have a big section (with
 	  subsections, etc.) and we want to shift it to the left so it becomes a chapter (the
 	  subsections becomes sections, etc.).
 
+	- When setting a model, expand all only if the tree is not too big
+
+	- Insert in middle is very slow comparated to insert at the end
+	  => Insert environments as soon as we find the \begin, and then update the item (or delete it)
+
+	- Create the TextMarks at the right places with get_iter_at_line_index(),
+	  and simplify the code for actions
+
+	- Take into account \end{document}
+
 - Write some documentation:
 	- explain the build tools, how to create a new one, etc.
 	- the difference between Latexmk and Rubber
diff --git a/src/document_structure.vala b/src/document_structure.vala
index 89a17f1..12a3e0b 100644
--- a/src/document_structure.vala
+++ b/src/document_structure.vala
@@ -159,13 +159,7 @@ public class DocumentStructure : GLib.Object
             }
 
             // get the text of the current line
-            TextIter next_line_iter;
-            if (cur_line == nb_lines - 1)
-                _doc.get_end_iter (out next_line_iter);
-            else
-                _doc.get_iter_at_line (out next_line_iter, cur_line + 1);
-
-            string line = _doc.get_text (cur_line_iter, next_line_iter, false);
+            string line = get_document_line_contents (cur_line);
 
             // in one line there could be several items
 
@@ -188,7 +182,7 @@ public class DocumentStructure : GLib.Object
                 start_index = end_match_index;
             }
 
-            cur_line_iter = next_line_iter;
+            cur_line_iter.forward_line ();
             cur_line++;
         }
 
@@ -558,12 +552,20 @@ public class DocumentStructure : GLib.Object
     {
         if (action_type == StructAction.COMMENT)
         {
-            do_comment (tree_iter);
+            comment_item (tree_iter);
             return;
         }
+
+        if (action_type != StructAction.SELECT)
+            return;
+
+        TextIter? start_iter;
+        TextIter? end_iter;
+        if (get_exact_item_bounds (tree_iter, out start_iter, out end_iter))
+            _doc.select_range (start_iter, end_iter);
     }
 
-    private void do_comment (TreeIter tree_iter)
+    private void comment_item (TreeIter tree_iter)
     {
         StructType type;
         TextMark start_mark = null;
@@ -586,7 +588,7 @@ public class DocumentStructure : GLib.Object
         /* comment a simple item */
         if (! Structure.is_section (type))
         {
-            comment (start_iter, end_iter);
+            comment_between (start_iter, end_iter);
             return;
         }
 
@@ -620,11 +622,11 @@ public class DocumentStructure : GLib.Object
                 end_iter = null;
         }
 
-        comment (start_iter, end_iter);
+        comment_between (start_iter, end_iter);
     }
 
     // comment the lines between start_iter and end_iter included
-    private void comment (TextIter start_iter, TextIter? end_iter)
+    private void comment_between (TextIter start_iter, TextIter? end_iter)
     {
         int start_line = start_iter.get_line ();
         int end_line = start_line;
@@ -641,4 +643,192 @@ public class DocumentStructure : GLib.Object
         }
         _doc.end_user_action ();
     }
+
+    // Returns true only if the bounds are correctly set.
+    private bool get_exact_item_bounds (TreeIter tree_iter, out TextIter? start_iter,
+        out TextIter? end_iter)
+    {
+        /* get item data */
+        StructType item_type;
+        TextMark start_mark = null;
+        TextMark end_mark = null;
+        string item_contents = null;
+
+        _model.get (tree_iter,
+            StructColumn.TYPE, out item_type,
+            StructColumn.START_MARK, out start_mark,
+            StructColumn.END_MARK, out end_mark,
+            StructColumn.TEXT, out item_contents,
+            -1);
+
+        /* search 'start_iter' */
+        TextIter line_iter;
+        _doc.get_iter_at_mark (out line_iter, start_mark);
+        int line_num = line_iter.get_line ();
+
+        int? start_match_index;
+        int? end_match_index;
+
+        bool found = get_low_level_item_bounds (item_type, item_contents, line_num, true,
+            out start_match_index, out end_match_index);
+
+        if (! found)
+            return false;
+
+        // set 'start_iter'
+        _doc.get_iter_at_line_index (out start_iter, line_num, start_match_index);
+
+        /* search 'end_iter' */
+
+        // a section
+        if (Structure.is_section (item_type))
+        {
+            TreeIter? next_section_iter = null;
+            try
+            {
+                next_section_iter = _model.get_next_sibling_or_parent (tree_iter);
+            }
+            catch (StructError e)
+            {
+                stderr.printf ("Structure: get next sibling or parent: %s\n", e.message);
+                return false;
+            }
+
+            // the end of the section is the end of the document
+            if (next_section_iter == null)
+            {
+                _doc.get_end_iter (out end_iter);
+                return true;
+            }
+
+            _model.get (next_section_iter,
+                StructColumn.TYPE, out item_type,
+                StructColumn.START_MARK, out start_mark,
+                StructColumn.TEXT, out item_contents,
+                -1);
+
+            _doc.get_iter_at_mark (out line_iter, start_mark);
+            line_num = line_iter.get_line ();
+
+            found = get_low_level_item_bounds (item_type, item_contents, line_num, true,
+                out start_match_index, null);
+
+            if (! found)
+                return false;
+
+            _doc.get_iter_at_line_index (out end_iter, line_num, start_match_index);
+            return true;
+        }
+
+        // an other common type
+        else if (item_type < StructType.NB_COMMON_TYPES)
+        {
+            _doc.get_iter_at_line_index (out end_iter, line_num, end_match_index);
+            return true;
+        }
+
+        // an environment
+        if (end_mark == null)
+            return false;
+
+        _doc.get_iter_at_mark (out line_iter, end_mark);
+        line_num = line_iter.get_line ();
+
+        found = get_low_level_item_bounds (item_type, item_contents, line_num, false,
+            null, out end_match_index);
+
+        if (! found)
+            return false;
+
+        _doc.get_iter_at_line_index (out end_iter, line_num, end_match_index);
+
+        return true;
+    }
+
+    private bool get_low_level_item_bounds (StructType item_type, string item_contents,
+        int line_num, bool is_start, out int? start_match_index, out int? end_match_index)
+    {
+        string line = get_document_line_contents (line_num);
+
+        /* parse the line */
+        int start_index = 0;
+        int line_length = line.length;
+
+        while (true)
+        {
+            if (line_length <= start_index)
+                break;
+
+            LowLevelType? low_level_type;
+            string? contents;
+
+            bool found = search_low_level_item (line, start_index, out low_level_type,
+                out contents, out start_match_index, out end_match_index);
+
+            if (! found)
+                break;
+
+            if (contents == null)
+                contents = "";
+
+            // compare the item found with the structure item
+            if (same_items (item_type, item_contents, low_level_type, contents, is_start))
+                return true;
+
+            start_index = end_match_index;
+        }
+
+        return false;
+    }
+
+    // Compare a structure item with another low-level item
+    // If 'start' is true, and if the structure item is an environment, a \begin{} is
+    // expected. Otherwise, a \end{} is expected.
+    private bool same_items (StructType item_type, string item_contents,
+        LowLevelType item_found_type, string item_found_contents, bool start)
+    {
+        if (item_found_type < LowLevelType.NB_COMMON_TYPES)
+        {
+            bool same_type = item_type == (StructType) item_found_type;
+            bool same_contents = item_contents == item_found_contents;
+            return same_type && same_contents;
+        }
+
+        if (item_type == StructType.FIGURE)
+        {
+            if (start)
+                return item_found_type == LowLevelType.BEGIN_FIGURE;
+            else
+                return item_found_type == LowLevelType.END_FIGURE;
+        }
+
+        if (item_type == StructType.TABLE)
+        {
+            if (start)
+                return item_found_type == LowLevelType.BEGIN_TABLE;
+            else
+                return item_found_type == LowLevelType.END_TABLE;
+        }
+
+        return false;
+    }
+
+    private string? get_document_line_contents (int line_num)
+    {
+        int nb_lines = _doc.get_line_count ();
+        return_val_if_fail (0 <= line_num && line_num < nb_lines, null);
+
+        TextIter begin;
+        _doc.get_iter_at_line (out begin, line_num);
+
+        // If the line is empty, and if we do a forward_to_line_end(), we go to the end of
+        // the _next_ line, so we must handle this special case.
+        if (begin.ends_line ())
+            return "";
+
+        TextIter end = begin;
+        end.forward_to_line_end ();
+
+        return _doc.get_text (begin, end, false);
+    }
 }
diff --git a/src/structure.vala b/src/structure.vala
index ead6d42..968aebc 100644
--- a/src/structure.vala
+++ b/src/structure.vala
@@ -35,6 +35,7 @@ public enum StructType
     IMAGE,
     TODO,
     FIXME,
+    NB_COMMON_TYPES,
 
     // Second part: "high-level" only
     TABLE,



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