[gnome-builder/gnome-builder-3-18] vim-mode: add , and ; for fFtT command



commit 1f667120f2fe09856c82e191e97c61a59e33c7fa
Author: Sebastien Lafargue <slafargue gnome org>
Date:   Tue Oct 13 23:16:05 2015 +0200

    vim-mode: add , and ; for fFtT command
    
    - We can now use , and ; after f F t T commands like in Vim.
    
      To do so we add a new 'save-search-char' action signal,
      usuable from css binding too and two new movements:
      previous-search-char and next-search-char
    
    - some fixes about FfTt selections

 data/keybindings/vim.css           |  102 ++++++++++++++++++++++++++++++-----
 libide/ide-source-view-movements.c |   96 +++++++++++++++++++++++++++++++++
 libide/ide-source-view-movements.h |    1 +
 libide/ide-source-view.c           |   33 +++++++++++-
 libide/ide-source-view.h           |    6 ++
 5 files changed, 221 insertions(+), 17 deletions(-)
---
diff --git a/data/keybindings/vim.css b/data/keybindings/vim.css
index 361d472..7ba5745 100644
--- a/data/keybindings/vim.css
+++ b/data/keybindings/vim.css
@@ -279,19 +279,31 @@
                     "clear-count" () };
 
   /* find matching char */
-  bind "f" { "capture-modifier" ()
+  bind "f" { "save-command" ()
+             "capture-modifier" ()
+             "save-search-char" ()
              "movement" (next-match-modifier, 0, 1, 1)
              "clear-modifier" () };
-  bind "t" { "capture-modifier" ()
+  bind "t" { "save-command" ()
+             "capture-modifier" ()
+             "save-search-char" ()
              "movement" (next-match-modifier, 0, 1, 1)
              "movement" (previous-char, 0, 1, 0)
              "clear-modifier" () };
-  bind "<shift>f" { "capture-modifier" ()
+  bind "<shift>f" { "save-command" ()
+                    "capture-modifier" ()
+                    "save-search-char" ()
                     "movement" (previous-match-modifier, 0, 1, 1)
                     "clear-modifier" () };
-  bind "<shift>t" { "capture-modifier" ()
-                    "movement" (previous-match-modifier, 0, 0, 1)
+  bind "<shift>t" { "save-command" ()
+                    "capture-modifier" ()
+                    "save-search-char" ()
+                    "movement" (previous-match-modifier, 0, 1, 1)
                     "clear-modifier" () };
+  bind "comma" { "movement" (previous-match-search-char, 0, 0, 1)
+                 "clear-count" () };
+  bind "semicolon" { "movement" (next-match-search-char, 0, 0, 1)
+                     "clear-count" () };
 
   bind "n" { "move-search" (tab-forward, 0, 0, 1, 1, 0) };
   bind "<shift>n" { "move-search" (tab-backward, 0, 0, 0, 1, 0) };
@@ -549,7 +561,9 @@
              "delete-selection" () };
 
   bind "f" { "begin-macro" ()
+             "save-command" ()
              "capture-modifier" ()
+             "save-search-char" ()
              "set-mode" ("vim-insert", permanent)
              "movement" (next-match-modifier, 1, 0, 1)
              "copy-clipboard" ()
@@ -558,7 +572,9 @@
              "clear-modifier" () };
 
   bind "t" { "begin-macro" ()
+             "save-command" ()
              "capture-modifier" ()
+             "save-search-char" ()
              "set-mode" ("vim-insert", permanent)
              "movement" (next-match-modifier, 1, 1, 1)
              "copy-clipboard" ()
@@ -575,22 +591,42 @@
              "set-mode" ("vim-insert", permanent) };
 
   bind "<shift>f" { "begin-macro" ()
+                    "save-command" ()
                     "capture-modifier" ()
+                    "save-search-char" ()
                     "set-mode" ("vim-insert", permanent)
-                    "movement" (previous-match-modifier, 1, 1, 1)
+                    "movement" (previous-match-modifier, 1, 0, 1)
                     "copy-clipboard" ()
                     "selection-theatric" (shrink)
                     "delete-selection" ()
                     "clear-modifier" () };
 
   bind "<shift>t" { "begin-macro" ()
+                    "save-command" ()
                     "capture-modifier" ()
+                    "save-search-char" ()
                     "set-mode" ("vim-insert", permanent)
-                    "movement" (previous-match-modifier, 1, 0, 1)
+                    "movement" (previous-match-modifier, 1, 1, 1)
                     "copy-clipboard" ()
                     "selection-theatric" (shrink)
                     "delete-selection" ()
                     "clear-modifier" () };
+
+  bind "comma" { "begin-macro" ()
+                 "movement" (previous-match-search-char, 1, 0, 1)
+                 "set-mode" ("vim-insert", permanent)
+                 "copy-clipboard" ()
+                 "selection-theatric" (shrink)
+                 "delete-selection" ()
+                 "clear-count" () };
+
+  bind "semicolon" { "begin-macro" ()
+                     "movement" (next-match-search-char, 1, 0, 1)
+                     "set-mode" ("vim-insert", permanent)
+                     "copy-clipboard" ()
+                     "selection-theatric" (shrink)
+                     "delete-selection" ()
+                     "clear-count" () };
 }
 
 @binding-set builder-vim-source-view-normal-c-i
@@ -698,7 +734,9 @@
   bind "g" { "set-mode" ("vim-normal-d-g", transient) };
 
   bind "f" { "begin-macro" ()
+             "save-command" ()
              "capture-modifier" ()
+             "save-search-char" ()
              "movement" (next-match-modifier, 1, 0, 1)
              "copy-clipboard" ()
              "selection-theatric" (shrink)
@@ -706,7 +744,9 @@
              "clear-modifier" ()
              "end-macro" () };
   bind "t" { "begin-macro" ()
+             "save-command" ()
              "capture-modifier" ()
+             "save-search-char" ()
              "movement" (next-match-modifier, 1, 1, 1)
              "copy-clipboard" ()
              "selection-theatric" (shrink)
@@ -715,21 +755,41 @@
              "end-macro" () };
 
   bind "<shift>f" { "begin-macro" ()
+                    "save-command" ()
                     "capture-modifier" ()
-                    "movement" (previous-match-modifier, 1, 1, 1)
+                    "save-search-char" ()
+                    "movement" (previous-match-modifier, 1, 0, 1)
                     "copy-clipboard" ()
                     "selection-theatric" (shrink)
                     "delete-selection" ()
                     "clear-modifier" ()
                     "end-macro" () };
   bind "<shift>t" { "begin-macro" ()
+                    "save-command" ()
                     "capture-modifier" ()
-                    "movement" (previous-match-modifier, 1, 0, 1)
+                    "save-search-char" ()
+                    "movement" (previous-match-modifier, 1, 1, 1)
                     "copy-clipboard" ()
                     "selection-theatric" (shrink)
                     "delete-selection" ()
                     "clear-modifier" ()
                     "end-macro" () };
+  bind "comma" { "begin-macro" ()
+                 "movement" (previous-match-search-char, 1, 1, 1)
+                 "copy-clipboard" ()
+                 "selection-theatric" (shrink)
+                 "delete-selection" ()
+                 "clear-count" ()
+                 "end-macro" () };
+
+  bind "semicolon" { "begin-macro" ()
+                     "movement" (next-match-search-char, 1, 0, 1)
+                     "copy-clipboard" ()
+                     "selection-theatric" (shrink)
+                     "delete-selection" ()
+                     "clear-count" ()
+                     "end-macro" () };
+
 
   bind "d" { "begin-macro" ()
              "save-insert-mark" ()
@@ -1247,19 +1307,31 @@
   bind "g" { "set-mode" ("vim-visual-g", transient) };
   bind "z" { "set-mode" ("vim-visual-z", transient) };
 
-  bind "f" { "capture-modifier" ()
+  bind "f" { "save-command" ()
+             "capture-modifier" ()
+             "save-search-char" ()
              "movement" (next-match-modifier, 1, 0, 1)
              "clear-modifier" () };
-  bind "t" { "capture-modifier" ()
+  bind "t" { "save-command" ()
+             "capture-modifier" ()
+             "save-search-char" ()
              "movement" (next-match-modifier, 1, 1, 1)
              "clear-modifier" () };
 
-  bind "<shift>f" { "capture-modifier" ()
-                    "movement" (previous-match-modifier, 1, 1, 1)
-                    "clear-modifier" () };
-  bind "<shift>t" { "capture-modifier" ()
+  bind "<shift>f" { "save-command" ()
+                    "capture-modifier" ()
+                    "save-search-char" ()
                     "movement" (previous-match-modifier, 1, 0, 1)
                     "clear-modifier" () };
+  bind "<shift>t" { "save-command" ()
+                    "capture-modifier" ()
+                    "save-search-char" ()
+                    "movement" (previous-match-modifier, 1, 1, 1)
+                    "clear-modifier" () };
+  bind "comma" { "movement" (previous-match-search-char, 1, 0, 1)
+                 "clear-count" () };
+  bind "semicolon" { "movement" (next-match-search-char, 1, 0, 1)
+                     "clear-count" () };
 
   bind "asciitilde" { "selection-theatric" (expand)
                       "change-case" (toggle)
diff --git a/libide/ide-source-view-movements.c b/libide/ide-source-view-movements.c
index ebcffa3..f0e60ca 100644
--- a/libide/ide-source-view-movements.c
+++ b/libide/ide-source-view-movements.c
@@ -47,6 +47,7 @@ typedef struct
   gint                   count;                       /* Repeat count for movement */
   gunichar               command;                     /* Command that trigger some movements type. See , and 
; in vim */
   gunichar               modifier;                    /* For forward/backward char search */
+  gunichar               search_char;                 /* For forward/backward char search according to fFtT 
vim modifier */
   guint                  extend_selection : 1;        /* If selection should be extended */
   guint                  exclusive : 1;               /* See ":help exclusive" in vim */
   guint                  ignore_select : 1;           /* Don't update selection after movement */
@@ -1241,6 +1242,88 @@ ide_source_view_movements_previous_match_modifier (Movement *mv)
     }
 }
 
+static gboolean
+find_char (gunichar ch,
+           gpointer data)
+{
+  gunichar ch_searched = GPOINTER_TO_UINT (data);
+
+  return (ch == ch_searched);
+}
+
+static void
+ide_source_view_movement_match_search_char (Movement *mv, gboolean is_next_direction)
+{
+  GtkTextIter insert;
+  GtkTextIter limit;
+  gboolean is_forward;
+  gboolean is_till;
+  gboolean is_inclusive_mode;
+  gboolean is_selection_positive;
+  const gchar *mode_name;
+
+  limit = insert = mv->insert;
+  is_forward = (mv->command == 'f' || mv->command == 't');
+  is_till = (mv->command == 't' || mv->command == 'T');
+
+  mode_name = _ide_source_view_get_mode_name (mv->self);
+  is_inclusive_mode = (g_str_has_prefix (mode_name, "vim-visual") ||
+                       g_str_has_prefix (mode_name, "vim-normal-c") ||
+                       g_str_has_prefix (mode_name, "vim-normal-d"));
+
+  is_selection_positive = (gtk_text_iter_compare (&insert, &mv->selection) >= 0);
+
+  if (mv->modifier == 0)
+    return;
+
+  if ((is_forward && is_next_direction) || (!is_forward && !is_next_direction))
+    {
+      /* We search to the right */
+      gtk_text_iter_forward_to_line_end (&limit);
+
+      if (is_till)
+        gtk_text_iter_forward_char (&insert);
+
+      if (is_inclusive_mode && is_selection_positive)
+        gtk_text_iter_backward_char (&insert);
+
+      if (gtk_text_iter_forward_find_char (&insert, find_char, GUINT_TO_POINTER (mv->modifier), &limit))
+        {
+          if (is_till)
+            gtk_text_iter_backward_char (&insert);
+
+          is_selection_positive = (gtk_text_iter_compare (&insert, &mv->selection) >= 0);
+          if (is_inclusive_mode && is_selection_positive)
+            gtk_text_iter_forward_char (&insert);
+
+          mv->insert = insert;
+        }
+    }
+  else
+    {
+      /* We search to the left */
+      gtk_text_iter_set_line_offset (&limit, 0);
+
+      if (is_till)
+        gtk_text_iter_backward_char (&insert);
+
+      if (is_inclusive_mode && is_selection_positive)
+        gtk_text_iter_backward_char (&insert);
+
+      if (gtk_text_iter_backward_find_char (&insert, find_char, GUINT_TO_POINTER (mv->modifier), &limit))
+        {
+          if (is_till)
+            gtk_text_iter_forward_char (&insert);
+
+          is_selection_positive = (gtk_text_iter_compare (&insert, &mv->selection) >= 0);
+          if (is_inclusive_mode && is_selection_positive)
+            gtk_text_iter_forward_char (&insert);
+
+          mv->insert = insert;
+        }
+    }
+}
+
 void
 _ide_source_view_apply_movement (IdeSourceView         *self,
                                  IdeSourceViewMovement  movement,
@@ -1249,6 +1332,7 @@ _ide_source_view_apply_movement (IdeSourceView         *self,
                                  guint                  count,
                                  gunichar               command,
                                  gunichar               modifier,
+                                 gunichar               search_char,
                                  gint                  *target_offset)
 {
   Movement mv = { 0 };
@@ -1507,6 +1591,18 @@ _ide_source_view_apply_movement (IdeSourceView         *self,
         ide_source_view_movements_previous_match_modifier (&mv);
       break;
 
+    case IDE_SOURCE_VIEW_MOVEMENT_PREVIOUS_MATCH_SEARCH_CHAR:
+      mv.modifier = search_char;
+      for (i = MAX (1, mv.count); i > 0; i--)
+        ide_source_view_movement_match_search_char (&mv, FALSE);
+      break;
+
+    case IDE_SOURCE_VIEW_MOVEMENT_NEXT_MATCH_SEARCH_CHAR:
+      mv.modifier = search_char;
+      for (i = MAX (1, mv.count); i > 0; i--)
+        ide_source_view_movement_match_search_char (&mv, TRUE);
+      break;
+
     default:
       g_return_if_reached ();
     }
diff --git a/libide/ide-source-view-movements.h b/libide/ide-source-view-movements.h
index cb1106d..c80235e 100644
--- a/libide/ide-source-view-movements.h
+++ b/libide/ide-source-view-movements.h
@@ -30,6 +30,7 @@ void _ide_source_view_apply_movement (IdeSourceView         *source_view,
                                       guint                  count,
                                       gunichar               command,
                                       gunichar               modifier,
+                                      gunichar               search_char,
                                       gint                  *target_offset);
 
 G_END_DECLS
diff --git a/libide/ide-source-view.c b/libide/ide-source-view.c
index f0673c4..ede08fc 100644
--- a/libide/ide-source-view.c
+++ b/libide/ide-source-view.c
@@ -118,6 +118,7 @@ typedef struct
   gint                         target_line_offset;
   gunichar                     command;
   gunichar                     modifier;
+  gunichar                     search_char;
   guint                        count;
 
   guint                        delayed_scroll_replay;
@@ -245,6 +246,7 @@ enum {
   RESTORE_INSERT_MARK,
   SAVE_COMMAND,
   SAVE_INSERT_MARK,
+  SAVE_SEARCH_CHAR,
   SELECTION_THEATRIC,
   SET_MODE,
   SET_OVERWRITE,
@@ -3158,8 +3160,13 @@ ide_source_view_real_movement (IdeSourceView         *self,
     priv->scrolling_to_scroll_mark = FALSE;
 
   _ide_source_view_apply_movement (self,
-                                   movement, extend_selection, exclusive,
-                                   count, priv->command, priv->modifier,
+                                   movement,
+                                   extend_selection,
+                                   exclusive,
+                                   count,
+                                   priv->command,
+                                   priv->modifier,
+                                   priv->search_char,
                                    &priv->target_line_offset);
 }
 
@@ -3574,6 +3581,17 @@ ide_source_view_real_save_command (IdeSourceView *self)
 }
 
 static void
+ide_source_view_real_save_search_char (IdeSourceView *self)
+{
+  IdeSourceViewPrivate *priv = ide_source_view_get_instance_private (self);
+
+  g_assert (IDE_IS_SOURCE_VIEW (self));
+
+  if (priv->modifier)
+    priv->search_char = priv->modifier;
+}
+
+static void
 ide_source_view__completion_hide_cb (IdeSourceView       *self,
                                      GtkSourceCompletion *completion)
 {
@@ -5490,6 +5508,7 @@ ide_source_view_class_init (IdeSourceViewClass *klass)
   klass->restore_insert_mark = ide_source_view_real_restore_insert_mark;
   klass->save_command = ide_source_view_real_save_command;
   klass->save_insert_mark = ide_source_view_real_save_insert_mark;
+  klass->save_search_char = ide_source_view_real_save_search_char;
   klass->selection_theatric = ide_source_view_real_selection_theatric;
   klass->set_mode = ide_source_view_real_set_mode;
   klass->set_overwrite = ide_source_view_real_set_overwrite;
@@ -5745,6 +5764,16 @@ ide_source_view_class_init (IdeSourceViewClass *klass)
                   G_TYPE_NONE,
                   0);
 
+  gSignals [SAVE_SEARCH_CHAR] =
+    g_signal_new ("save-search-char",
+                  G_TYPE_FROM_CLASS (klass),
+                  G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
+                  G_STRUCT_OFFSET (IdeSourceViewClass, save_search_char),
+                  NULL, NULL,
+                  g_cclosure_marshal_VOID__VOID,
+                  G_TYPE_NONE,
+                  0);
+
   /**
    * IdeSourceView::capture-modifier:
    *
diff --git a/libide/ide-source-view.h b/libide/ide-source-view.h
index 265e163..84d30e6 100644
--- a/libide/ide-source-view.h
+++ b/libide/ide-source-view.h
@@ -116,6 +116,8 @@ typedef enum
  * @IDE_SOURCE_VIEW_MOVEMENT_SCROLL_SCREEN_TOP: scroll until insert cursor is at screen top.
  * @IDE_SOURCE_VIEW_MOVEMENT_SCROLL_SCREEN_CENTER: scroll until insert cursor is at screen center.
  * @IDE_SOURCE_VIEW_MOVEMENT_SCROLL_SCREEN_BOTTOM: scroll until insert cursor is at screen bottom.
+ * @IDE_SOURCE_VIEW_MOVEMENT_NEXT_MATCH_SEARCH_CHAR: move to the next matching char according to f and t in 
vim.
+ * @IDE_SOURCE_VIEW_MOVEMENT_PREVIOUS_MATCH_SEARCH_CHAR: move to the previous matching char according to F 
and T in vim.
  *
  * The type of movement.
  *
@@ -190,6 +192,9 @@ typedef enum
 
   IDE_SOURCE_VIEW_MOVEMENT_NEXT_MATCH_MODIFIER,
   IDE_SOURCE_VIEW_MOVEMENT_PREVIOUS_MATCH_MODIFIER,
+
+  IDE_SOURCE_VIEW_MOVEMENT_NEXT_MATCH_SEARCH_CHAR,
+  IDE_SOURCE_VIEW_MOVEMENT_PREVIOUS_MATCH_SEARCH_CHAR,
 } IdeSourceViewMovement;
 
 struct _IdeSourceViewClass
@@ -252,6 +257,7 @@ struct _IdeSourceViewClass
   void (*request_documentation)       (IdeSourceView           *self);
   void (*restore_insert_mark)         (IdeSourceView           *self);
   void (*save_command)                (IdeSourceView           *self);
+  void (*save_search_char)            (IdeSourceView           *self);
   void (*save_insert_mark)            (IdeSourceView           *self);
   void (*selection_theatric)          (IdeSourceView           *self,
                                        IdeSourceViewTheatric    theatric);


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