[gtksourceview/wip/chergert/vim: 336/363] start adding search movements




commit bea68bba943d0a7a3c64e0b7085c0b48ef96802a
Author: Christian Hergert <chergert redhat com>
Date:   Sat Nov 6 15:20:25 2021 -0700

    start adding search movements

 gtksourceview/vim/gtk-source-vim-motion.c | 148 +++++++++++++++++++++++++++++-
 gtksourceview/vim/gtk-source-vim-normal.c |  19 +---
 gtksourceview/vim/gtk-source-vim-state.c  |  49 ++++++++++
 gtksourceview/vim/gtk-source-vim-state.h  | 137 +++++++++++++--------------
 4 files changed, 268 insertions(+), 85 deletions(-)
---
diff --git a/gtksourceview/vim/gtk-source-vim-motion.c b/gtksourceview/vim/gtk-source-vim-motion.c
index 578000f8..c278b613 100644
--- a/gtksourceview/vim/gtk-source-vim-motion.c
+++ b/gtksourceview/vim/gtk-source-vim-motion.c
@@ -21,7 +21,9 @@
 
 #include "config.h"
 
-#include "gtksourceview.h"
+#include <gtksourceview/gtksourceview.h>
+#include <gtksourceview/gtksourcesearchcontext.h>
+#include <gtksourceview/gtksourcesearchsettings.h>
 
 #include "gtk-source-vim-char-pending.h"
 #include "gtk-source-vim-motion.h"
@@ -105,6 +107,9 @@ struct _GtkSourceVimMotion
         * as paragraph or sentence movements.
         */
        MotionWise wise : 1;
+
+       /* If search is reversed (flips n vs N) */
+       guint reverse_search : 1;
 };
 
 G_DEFINE_TYPE (GtkSourceVimMotion, gtk_source_vim_motion, GTK_SOURCE_TYPE_VIM_STATE)
@@ -1243,6 +1248,141 @@ motion_line_number (GtkTextIter        *iter,
        return TRUE;
 }
 
+static char *
+word_under_cursor (const GtkTextIter *iter)
+{
+       GtkTextIter begin, end;
+
+       end = *iter;
+       if (!gtk_source_vim_iter_ends_word (&end))
+       {
+               if (!gtk_source_vim_iter_forward_word_end (&end))
+                       return FALSE;
+       }
+
+       begin = end;
+       if (!gtk_source_vim_iter_starts_word (&begin))
+       {
+               gtk_source_vim_iter_backward_word_start (&begin);
+       }
+
+       gtk_text_iter_forward_char (&end);
+
+       return gtk_text_iter_get_slice (&begin, &end);
+}
+
+static char *
+WORD_under_cursor (const GtkTextIter *iter)
+{
+       GtkTextIter begin, end;
+
+       end = *iter;
+       if (!gtk_source_vim_iter_ends_WORD (&end))
+       {
+               if (!gtk_source_vim_iter_forward_WORD_end (&end))
+                       return FALSE;
+       }
+
+       begin = end;
+       if (!gtk_source_vim_iter_starts_WORD (&begin))
+       {
+               gtk_source_vim_iter_backward_WORD_start (&begin);
+       }
+
+       gtk_text_iter_forward_char (&end);
+
+       return gtk_text_iter_get_slice (&begin, &end);
+}
+
+static gboolean
+motion_forward_search (GtkTextIter        *iter,
+                       GtkSourceVimMotion *self,
+                       gboolean            WORD,
+                       gboolean            reverse)
+{
+       GtkSourceSearchContext *context;
+       GtkSourceSearchSettings *settings;
+       const char *search_text;
+       char *word;
+       gboolean has_wrapped_around;
+       gboolean ret = FALSE;
+       int count;
+
+       g_assert (iter != NULL);
+       g_assert (GTK_SOURCE_IS_VIM_MOTION (self));
+
+       if (self->apply_count != 1)
+       {
+               return FALSE;
+       }
+
+       self->reverse_search = !!reverse;
+
+       gtk_source_vim_state_get_search (GTK_SOURCE_VIM_STATE (self), &settings, &context);
+
+       if (!gtk_source_search_settings_get_at_word_boundaries (settings))
+       {
+               gtk_source_search_settings_set_at_word_boundaries (settings, TRUE);
+       }
+
+       word = WORD ? WORD_under_cursor (iter) : word_under_cursor (iter);
+       search_text = gtk_source_search_settings_get_search_text (settings);
+
+       if (g_strcmp0 (word, search_text) != 0)
+       {
+               gtk_source_search_settings_set_search_text (settings, word);
+       }
+
+       if (!reverse)
+       {
+               gtk_text_iter_forward_char (iter);
+       }
+
+       g_free (word);
+
+       count = gtk_source_vim_state_get_count (GTK_SOURCE_VIM_STATE (self));
+
+       for (guint i = 0; i < count; i++)
+       {
+               gboolean matched;
+
+               if (reverse)
+                        matched = gtk_source_search_context_backward (context, iter, iter, NULL, 
&has_wrapped_around);
+               else
+                        matched = gtk_source_search_context_forward (context, iter, iter, NULL, 
&has_wrapped_around);
+
+               if (!matched)
+                       break;
+
+               ret = TRUE;
+       }
+
+       return ret;
+}
+
+static gboolean
+motion_forward_search_word (GtkTextIter        *iter,
+                            GtkSourceVimMotion *self)
+{
+       return motion_forward_search (iter, self, FALSE, FALSE);
+}
+
+static gboolean
+motion_backward_search_word (GtkTextIter        *iter,
+                             GtkSourceVimMotion *self)
+{
+       return motion_forward_search (iter, self, FALSE, TRUE);
+}
+
+#if 0
+static gboolean
+motion_forward_search_WORD (GtkTextIter        *iter,
+                            GtkSourceVimMotion *self)
+{
+       return motion_forward_search (iter, self, TRUE, FALSE);
+}
+#endif
+
 GtkSourceVimState *
 gtk_source_vim_motion_new (void)
 {
@@ -1514,6 +1654,12 @@ gtk_source_vim_motion_handle_keypress (GtkSourceVimState *state,
                case GDK_KEY_braceright:
                        return gtk_source_vim_motion_complete (self, motion_forward_paragraph_end, EXCLUSIVE, 
CHARWISE);
 
+               case GDK_KEY_asterisk:
+                       return gtk_source_vim_motion_complete (self, motion_forward_search_word, EXCLUSIVE, 
CHARWISE);
+
+               case GDK_KEY_numbersign:
+                       return gtk_source_vim_motion_complete (self, motion_backward_search_word, INCLUSIVE, 
CHARWISE);
+
                case GDK_KEY_n:
                case GDK_KEY_N:
                case GDK_KEY_percent:
diff --git a/gtksourceview/vim/gtk-source-vim-normal.c b/gtksourceview/vim/gtk-source-vim-normal.c
index 7a70dddb..33c380a0 100644
--- a/gtksourceview/vim/gtk-source-vim-normal.c
+++ b/gtksourceview/vim/gtk-source-vim-normal.c
@@ -901,18 +901,6 @@ key_handler_shift (GtkSourceVimNormal *self,
        }
 }
 
-static gboolean
-key_handler_search_word (GtkSourceVimNormal *self,
-                         guint               keyval,
-                         guint               keycode,
-                         GdkModifierType     mods,
-                         const char         *string)
-{
-       g_assert (GTK_SOURCE_IS_VIM_NORMAL (self));
-
-       return TRUE;
-}
-
 static gboolean
 key_handler_search (GtkSourceVimNormal *self,
                     guint               keyval,
@@ -1085,6 +1073,7 @@ key_handler_initial (GtkSourceVimNormal *self,
                        case GDK_KEY_0:
                        case GDK_KEY_KP_0:
                        case GDK_KEY_asciicircum:
+                       case GDK_KEY_asterisk:
                        case GDK_KEY_b:
                        case GDK_KEY_bar:
                        case GDK_KEY_B:
@@ -1110,6 +1099,7 @@ key_handler_initial (GtkSourceVimNormal *self,
                        case GDK_KEY_Left:
                        case GDK_KEY_M:
                        case GDK_KEY_n:
+                       case GDK_KEY_numbersign:
                        case GDK_KEY_N:
                        case GDK_KEY_parenleft:
                        case GDK_KEY_parenright:
@@ -1196,11 +1186,6 @@ key_handler_initial (GtkSourceVimNormal *self,
                        case GDK_KEY_r:
                                return gtk_source_vim_normal_replace_one (self);
 
-                       case GDK_KEY_asterisk:
-                       case GDK_KEY_numbersign:
-                               self->handler = key_handler_search_word;
-                               break;
-
                        case GDK_KEY_slash:
                        case GDK_KEY_question:
                                self->handler = key_handler_search;
diff --git a/gtksourceview/vim/gtk-source-vim-state.c b/gtksourceview/vim/gtk-source-vim-state.c
index a32cc173..58bfbbaf 100644
--- a/gtksourceview/vim/gtk-source-vim-state.c
+++ b/gtksourceview/vim/gtk-source-vim-state.c
@@ -24,6 +24,8 @@
 #include <string.h>
 
 #include "gtksourcebuffer.h"
+#include "gtksourcesearchcontext.h"
+#include "gtksourcesearchsettings.h"
 #include "gtksourceutils-private.h"
 #include "gtksourceview.h"
 
@@ -51,6 +53,10 @@ typedef struct
         */
        GtkSourceVimState *child;
 
+       /* We have a custom search context/settings just for our VIM */
+       GtkSourceSearchContext *search_context;
+       GtkSourceSearchSettings *search_settings;
+
        /* A queue of all our children, using @link of the children nodes
         * to insert into the queue without extra allocations.
         */
@@ -274,6 +280,9 @@ gtk_source_vim_state_dispose (GObject *object)
 
        priv->current_register = NULL;
 
+       g_clear_object (&priv->search_context);
+       g_clear_object (&priv->search_settings);
+
        g_clear_weak_pointer (&priv->view);
        gtk_source_vim_state_release (&priv->registers);
 
@@ -1240,3 +1249,43 @@ gtk_source_vim_state_get_editable (GtkSourceVimState *self)
 
        return gtk_text_view_get_editable (GTK_TEXT_VIEW (view));
 }
+
+void
+gtk_source_vim_state_get_search (GtkSourceVimState        *self,
+                                 GtkSourceSearchSettings **settings,
+                                 GtkSourceSearchContext  **context)
+{
+       GtkSourceVimStatePrivate *priv;
+       GtkSourceVimState *root;
+       GtkSourceBuffer *buffer;
+
+       g_return_if_fail (GTK_SOURCE_IS_VIM_STATE (self));
+
+       root = gtk_source_vim_state_get_root (self);
+       priv = gtk_source_vim_state_get_instance_private (root);
+       buffer = gtk_source_vim_state_get_buffer (self, NULL, NULL);
+
+       if (priv->search_settings == NULL)
+       {
+               priv->search_settings = gtk_source_search_settings_new ();
+               gtk_source_search_settings_set_wrap_around (priv->search_settings, TRUE);
+               gtk_source_search_settings_set_regex_enabled (priv->search_settings, TRUE);
+               gtk_source_search_settings_set_case_sensitive (priv->search_settings, TRUE);
+       }
+
+       if (priv->search_context == NULL)
+       {
+               priv->search_context = gtk_source_search_context_new (buffer, priv->search_settings);
+               gtk_source_search_context_set_highlight (priv->search_context, TRUE);
+       }
+
+       if (settings != NULL)
+       {
+               *settings = priv->search_settings;
+       }
+
+       if (context != NULL)
+       {
+               *context = priv->search_context;
+       }
+}
diff --git a/gtksourceview/vim/gtk-source-vim-state.h b/gtksourceview/vim/gtk-source-vim-state.h
index f980b697..1ff0b065 100644
--- a/gtksourceview/vim/gtk-source-vim-state.h
+++ b/gtksourceview/vim/gtk-source-vim-state.h
@@ -57,73 +57,76 @@ struct _GtkSourceVimStateClass
                                             GString           *string);
 };
 
-gboolean           gtk_source_vim_state_get_editable               (GtkSourceVimState *self);
-void               gtk_source_vim_state_set_parent                 (GtkSourceVimState *self,
-                                                                    GtkSourceVimState *parent);
-void               gtk_source_vim_state_unparent                   (GtkSourceVimState *self);
-void               gtk_source_vim_state_push                       (GtkSourceVimState *self,
-                                                                    GtkSourceVimState *new_state);
-void               gtk_source_vim_state_pop                        (GtkSourceVimState *self);
-void               gtk_source_vim_state_append_command             (GtkSourceVimState *self,
-                                                                    GString           *string);
-void               gtk_source_vim_state_beep                       (GtkSourceVimState *self);
-GtkSourceVimState *gtk_source_vim_state_get_child                  (GtkSourceVimState *self);
-GtkSourceVimState *gtk_source_vim_state_get_current                (GtkSourceVimState *self);
-GtkSourceView     *gtk_source_vim_state_get_view                   (GtkSourceVimState *self);
-GtkSourceBuffer   *gtk_source_vim_state_get_buffer                 (GtkSourceVimState *self,
-                                                                    GtkTextIter       *insert,
-                                                                    GtkTextIter       *selection_bound);
-GtkSourceVimState *gtk_source_vim_state_get_root                   (GtkSourceVimState *self);
-GtkSourceVimState *gtk_source_vim_state_get_parent                 (GtkSourceVimState *self);
-GtkSourceVimState *gtk_source_vim_state_get_registers              (GtkSourceVimState *self);
-int                gtk_source_vim_state_get_count                  (GtkSourceVimState *self);
-gboolean           gtk_source_vim_state_get_count_set              (GtkSourceVimState *self);
-void               gtk_source_vim_state_set_count                  (GtkSourceVimState *self,
-                                                                    int                count);
-gboolean           gtk_source_vim_state_get_can_repeat             (GtkSourceVimState *self);
-void               gtk_source_vim_state_set_can_repeat             (GtkSourceVimState *self,
-                                                                    gboolean           can_repeat);
-void               gtk_source_vim_state_begin_user_action          (GtkSourceVimState *self);
-void               gtk_source_vim_state_end_user_action            (GtkSourceVimState *self);
-gboolean           gtk_source_vim_state_handle_event               (GtkSourceVimState *self,
-                                                                    GdkEvent          *event);
-void               gtk_source_vim_state_set_overwrite              (GtkSourceVimState *self,
-                                                                    gboolean           overwrite);
-gboolean           gtk_source_vim_state_synthesize                 (GtkSourceVimState *self,
-                                                                    guint              keyval,
-                                                                    GdkModifierType    mods);
-void               gtk_source_vim_state_repeat                     (GtkSourceVimState *self);
-int                gtk_source_vim_state_get_visible_lines          (GtkSourceVimState *self);
-void               gtk_source_vim_state_scroll_page                (GtkSourceVimState *self,
-                                                                    int                count);
-void               gtk_source_vim_state_scroll_half_page           (GtkSourceVimState *self,
-                                                                    int                count);
-void               gtk_source_vim_state_scroll_line                (GtkSourceVimState *self,
-                                                                    int                count);
-void               gtk_source_vim_state_z_scroll                   (GtkSourceVimState *self,
-                                                                    double             yalign);
-void               gtk_source_vim_state_select                     (GtkSourceVimState *self,
-                                                                    const GtkTextIter *insert,
-                                                                    const GtkTextIter *selection);
-const char        *gtk_source_vim_state_get_current_register       (GtkSourceVimState *self);
-void               gtk_source_vim_state_set_current_register       (GtkSourceVimState *self,
-                                                                    const char        *current_register);
-const char        *gtk_source_vim_state_get_current_register_value (GtkSourceVimState *self);
-void               gtk_source_vim_state_set_current_register_value (GtkSourceVimState *self,
-                                                                    const char        *value);
-void               gtk_source_vim_state_place_cursor_onscreen      (GtkSourceVimState *self);
-void               gtk_source_vim_state_keyval_to_string           (guint              keyval,
-                                                                    GdkModifierType    mods,
-                                                                    char               str[16]);
-void               gtk_source_vim_state_keyval_unescaped           (guint              keyval,
-                                                                    GdkModifierType    mods,
-                                                                    char               str[16]);
-guint              gtk_source_vim_state_get_visual_column          (GtkSourceVimState *self);
-void               gtk_source_vim_state_set_visual_column          (GtkSourceVimState *self,
-                                                                    int                visual_column);
-void               gtk_source_vim_state_select_linewise            (GtkSourceVimState *self,
-                                                                    GtkTextIter       *insert,
-                                                                    GtkTextIter       *selection);
+gboolean           gtk_source_vim_state_get_editable               (GtkSourceVimState        *self);
+void               gtk_source_vim_state_set_parent                 (GtkSourceVimState        *self,
+                                                                    GtkSourceVimState        *parent);
+void               gtk_source_vim_state_unparent                   (GtkSourceVimState        *self);
+void               gtk_source_vim_state_push                       (GtkSourceVimState        *self,
+                                                                    GtkSourceVimState        *new_state);
+void               gtk_source_vim_state_pop                        (GtkSourceVimState        *self);
+void               gtk_source_vim_state_append_command             (GtkSourceVimState        *self,
+                                                                    GString                  *string);
+void               gtk_source_vim_state_beep                       (GtkSourceVimState        *self);
+GtkSourceVimState *gtk_source_vim_state_get_child                  (GtkSourceVimState        *self);
+GtkSourceVimState *gtk_source_vim_state_get_current                (GtkSourceVimState        *self);
+GtkSourceView     *gtk_source_vim_state_get_view                   (GtkSourceVimState        *self);
+GtkSourceBuffer   *gtk_source_vim_state_get_buffer                 (GtkSourceVimState        *self,
+                                                                    GtkTextIter              *insert,
+                                                                    GtkTextIter              
*selection_bound);
+GtkSourceVimState *gtk_source_vim_state_get_root                   (GtkSourceVimState        *self);
+GtkSourceVimState *gtk_source_vim_state_get_parent                 (GtkSourceVimState        *self);
+GtkSourceVimState *gtk_source_vim_state_get_registers              (GtkSourceVimState        *self);
+int                gtk_source_vim_state_get_count                  (GtkSourceVimState        *self);
+gboolean           gtk_source_vim_state_get_count_set              (GtkSourceVimState        *self);
+void               gtk_source_vim_state_set_count                  (GtkSourceVimState        *self,
+                                                                    int                       count);
+gboolean           gtk_source_vim_state_get_can_repeat             (GtkSourceVimState        *self);
+void               gtk_source_vim_state_set_can_repeat             (GtkSourceVimState        *self,
+                                                                    gboolean                  can_repeat);
+void               gtk_source_vim_state_begin_user_action          (GtkSourceVimState        *self);
+void               gtk_source_vim_state_end_user_action            (GtkSourceVimState        *self);
+gboolean           gtk_source_vim_state_handle_event               (GtkSourceVimState        *self,
+                                                                    GdkEvent                 *event);
+void               gtk_source_vim_state_set_overwrite              (GtkSourceVimState        *self,
+                                                                    gboolean                  overwrite);
+gboolean           gtk_source_vim_state_synthesize                 (GtkSourceVimState        *self,
+                                                                    guint                     keyval,
+                                                                    GdkModifierType           mods);
+void               gtk_source_vim_state_repeat                     (GtkSourceVimState        *self);
+int                gtk_source_vim_state_get_visible_lines          (GtkSourceVimState        *self);
+void               gtk_source_vim_state_scroll_page                (GtkSourceVimState        *self,
+                                                                    int                       count);
+void               gtk_source_vim_state_scroll_half_page           (GtkSourceVimState        *self,
+                                                                    int                       count);
+void               gtk_source_vim_state_scroll_line                (GtkSourceVimState        *self,
+                                                                    int                       count);
+void               gtk_source_vim_state_z_scroll                   (GtkSourceVimState        *self,
+                                                                    double                    yalign);
+void               gtk_source_vim_state_select                     (GtkSourceVimState        *self,
+                                                                    const GtkTextIter        *insert,
+                                                                    const GtkTextIter        *selection);
+const char        *gtk_source_vim_state_get_current_register       (GtkSourceVimState        *self);
+void               gtk_source_vim_state_set_current_register       (GtkSourceVimState        *self,
+                                                                    const char               
*current_register);
+const char        *gtk_source_vim_state_get_current_register_value (GtkSourceVimState        *self);
+void               gtk_source_vim_state_set_current_register_value (GtkSourceVimState        *self,
+                                                                    const char               *value);
+void               gtk_source_vim_state_place_cursor_onscreen      (GtkSourceVimState        *self);
+guint              gtk_source_vim_state_get_visual_column          (GtkSourceVimState        *self);
+void               gtk_source_vim_state_set_visual_column          (GtkSourceVimState        *self,
+                                                                    int                       visual_column);
+void               gtk_source_vim_state_select_linewise            (GtkSourceVimState        *self,
+                                                                    GtkTextIter              *insert,
+                                                                    GtkTextIter              *selection);
+void               gtk_source_vim_state_get_search                 (GtkSourceVimState        *self,
+                                                                    GtkSourceSearchSettings **settings,
+                                                                    GtkSourceSearchContext  **context);
+void               gtk_source_vim_state_keyval_to_string           (guint                     keyval,
+                                                                    GdkModifierType           mods,
+                                                                    char                      string[16]);
+void               gtk_source_vim_state_keyval_unescaped           (guint                     keyval,
+                                                                    GdkModifierType           mods,
+                                                                    char                      string[16]);
 
 static inline void
 gtk_source_vim_state_release (GtkSourceVimState **dest)


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