[gnome-builder] movements: short circuit line movements with large repeat



commit 003b7d695ad2e70456f0eea46527f154a4cd5b5d
Author: Christian Hergert <chergert redhat com>
Date:   Sat Feb 27 13:27:11 2016 -0800

    movements: short circuit line movements with large repeat
    
    This could still be better, but we need to break out a bunch of the weird
    logic going on in here to make that possible. Most of the complexity is
    due to an impedance mismatch between GtkTextBuffer and vim.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=762776

 libide/ide-source-view-movements.c |   43 ++++++++++++++++++++++++++++++------
 1 files changed, 36 insertions(+), 7 deletions(-)
---
diff --git a/libide/ide-source-view-movements.c b/libide/ide-source-view-movements.c
index a4de6fb..5e1f82c 100644
--- a/libide/ide-source-view-movements.c
+++ b/libide/ide-source-view-movements.c
@@ -491,9 +491,11 @@ ide_source_view_movements_last_line (Movement *mv)
     }
 }
 
-static void
+static gboolean
 ide_source_view_movements_next_line (Movement *mv)
 {
+  GtkTextIter prev_insert = mv->insert;
+  GtkTextIter prev_selection = mv->selection;
   GtkTextBuffer *buffer;
   gboolean has_selection;
   guint line;
@@ -533,7 +535,7 @@ ide_source_view_movements_next_line (Movement *mv)
 
       select_range (mv, &mv->insert, &mv->selection);
       ensure_anchor_selected (mv);
-      return;
+      return TRUE;
     }
 
   if (is_single_char_selection (&mv->insert, &mv->selection))
@@ -557,11 +559,16 @@ select_to_end:
   /* make sure selection/insert are up to date */
   if (!gtk_text_buffer_get_has_selection (buffer))
     mv->selection = mv->insert;
+
+  return (!gtk_text_iter_equal (&prev_selection, &mv->selection) ||
+          !gtk_text_iter_equal (&prev_insert, &mv->insert));
 }
 
-static void
+static gboolean
 ide_source_view_movements_previous_line (Movement *mv)
 {
+  GtkTextIter prev_insert = mv->insert;
+  GtkTextIter prev_selection = mv->selection;
   GtkTextBuffer *buffer;
   gboolean has_selection;
   guint line;
@@ -578,7 +585,7 @@ ide_source_view_movements_previous_line (Movement *mv)
     offset = *mv->target_offset;
 
   if (line == 0)
-    return;
+    return FALSE;
 
   /*
    * If we have a whole line selected (from say `V`), then we need to swap the cursor and
@@ -592,7 +599,7 @@ ide_source_view_movements_previous_line (Movement *mv)
       gtk_text_iter_set_line (&mv->insert, gtk_text_iter_get_line (&mv->insert) - 1);
       select_range (mv, &mv->insert, &mv->selection);
       ensure_anchor_selected (mv);
-      return;
+      return TRUE;
     }
 
   if (is_single_char_selection (&mv->insert, &mv->selection))
@@ -624,6 +631,9 @@ ide_source_view_movements_previous_line (Movement *mv)
   /* make sure selection/insert are up to date */
   if (!gtk_text_buffer_get_has_selection (buffer))
     mv->selection = mv->insert;
+
+  return (!gtk_text_iter_equal (&prev_selection, &mv->selection) ||
+          !gtk_text_iter_equal (&prev_insert, &mv->insert));
 }
 
 static void
@@ -1890,7 +1900,9 @@ _ide_source_view_apply_movement (IdeSourceView         *self,
   Movement mv = { 0 };
   GtkTextBuffer *buffer;
   GtkTextMark *insert;
+  GtkTextIter end_iter;
   gint min_count = 1;
+  gint end_line;
   gsize i;
 
   g_return_if_fail (IDE_IS_SOURCE_VIEW (self));
@@ -1924,6 +1936,9 @@ _ide_source_view_apply_movement (IdeSourceView         *self,
         count = 0;
     }
 
+  gtk_text_buffer_get_end_iter (buffer, &end_iter);
+  end_line = gtk_text_iter_get_line (&end_iter);
+
   mv.self = self;
   mv.target_offset = target_offset;
   mv.type = movement;
@@ -2061,15 +2076,29 @@ _ide_source_view_apply_movement (IdeSourceView         *self,
     case IDE_SOURCE_VIEW_MOVEMENT_PREVIOUS_LINE:
       mv.ignore_target_offset = TRUE;
       mv.ignore_select = TRUE;
+      mv.count = MIN (mv.count, end_line);
+      /*
+       * It would be nice to do this as one large movement, but
+       * ide_source_view_movements_previous_line() needs to be
+       * split up into movements for different line-wise options.
+       */
       for (i = MAX (1, mv.count); i > 0; i--)
-        ide_source_view_movements_previous_line (&mv);
+        if (!ide_source_view_movements_previous_line (&mv))
+          break;
       break;
 
     case IDE_SOURCE_VIEW_MOVEMENT_NEXT_LINE:
       mv.ignore_target_offset = TRUE;
       mv.ignore_select = TRUE;
+      mv.count = MIN (mv.count, end_line);
+      /*
+       * It would be nice to do this as one large movement, but
+       * ide_source_view_movements_next_line() needs to be
+       * split up into movements for different line-wise options.
+       */
       for (i = MAX (min_count, mv.count); i > 0; i--)
-        ide_source_view_movements_next_line (&mv);
+        if (!ide_source_view_movements_next_line (&mv))
+          break;
       break;
 
     case IDE_SOURCE_VIEW_MOVEMENT_FIRST_LINE:


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