[gtksourceview/wip/chergert/vim: 58/293] implement f and F




commit ff2a617a113fb43ac2c8ab920ab66ea20e578940
Author: Christian Hergert <chergert redhat com>
Date:   Sat Oct 23 15:09:25 2021 -0700

    implement f and F

 gtksourceview/vim/gtk-source-vim-motion.c | 191 ++++++++++++++++++++----------
 1 file changed, 129 insertions(+), 62 deletions(-)
---
diff --git a/gtksourceview/vim/gtk-source-vim-motion.c b/gtksourceview/vim/gtk-source-vim-motion.c
index b4aa7dcd..abcc6fd7 100644
--- a/gtksourceview/vim/gtk-source-vim-motion.c
+++ b/gtksourceview/vim/gtk-source-vim-motion.c
@@ -25,8 +25,8 @@
 
 #include "gtk-source-vim-motion.h"
 
-typedef gboolean (*Motion) (GtkTextIter   *iter,
-                            GtkSourceView *view);
+typedef gboolean (*Motion) (GtkTextIter        *iter,
+                            GtkSourceVimMotion *state);
 
 struct _GtkSourceVimMotion
 {
@@ -38,6 +38,9 @@ struct _GtkSourceVimMotion
        /* A number for the motion like `3e`. */
        int number;
 
+       /* character for f or F */
+       gunichar f_char;
+
        /* Apply the motion when leaving the state. This is useful
         * so that you can either capture a motion for future use
         * or simply apply it immediately.
@@ -49,6 +52,9 @@ struct _GtkSourceVimMotion
 
        /* If we called gtk_source_vim_motion_bail(). */
        guint failed : 1;
+
+       /* If we just did f/F and need another char */
+       guint waiting_for_f_char : 1;
 };
 
 G_DEFINE_TYPE (GtkSourceVimMotion, gtk_source_vim_motion, GTK_SOURCE_TYPE_VIM_STATE)
@@ -334,8 +340,8 @@ get_iter_at_visual_column (GtkSourceView *view,
 }
 
 static gboolean
-motion_line_start (GtkTextIter   *iter,
-                   GtkSourceView *view)
+motion_line_start (GtkTextIter        *iter,
+                   GtkSourceVimMotion *state)
 {
        if (!gtk_text_iter_starts_line (iter))
        {
@@ -347,8 +353,8 @@ motion_line_start (GtkTextIter   *iter,
 }
 
 static gboolean
-motion_line_first_char (GtkTextIter   *iter,
-                        GtkSourceView *view)
+motion_line_first_char (GtkTextIter        *iter,
+                        GtkSourceVimMotion *state)
 {
        if (!gtk_text_iter_starts_line (iter))
        {
@@ -368,8 +374,8 @@ motion_line_first_char (GtkTextIter   *iter,
 }
 
 static gboolean
-motion_forward_char (GtkTextIter   *iter,
-                     GtkSourceView *view)
+motion_forward_char (GtkTextIter        *iter,
+                     GtkSourceVimMotion *state)
 {
        GtkTextIter begin = *iter;
 
@@ -387,8 +393,8 @@ motion_forward_char (GtkTextIter   *iter,
 }
 
 static gboolean
-motion_forward_char_same_line (GtkTextIter   *iter,
-                               GtkSourceView *view)
+motion_forward_char_same_line (GtkTextIter        *iter,
+                               GtkSourceVimMotion *state)
 {
        GtkTextIter begin = *iter;
 
@@ -403,8 +409,8 @@ motion_forward_char_same_line (GtkTextIter   *iter,
 }
 
 static gboolean
-motion_backward_char (GtkTextIter   *iter,
-                      GtkSourceView *view)
+motion_backward_char (GtkTextIter        *iter,
+                      GtkSourceVimMotion *state)
 {
        GtkTextIter begin = *iter;
 
@@ -420,8 +426,8 @@ motion_backward_char (GtkTextIter   *iter,
 }
 
 static gboolean
-motion_backward_char_same_line (GtkTextIter   *iter,
-                                GtkSourceView *view)
+motion_backward_char_same_line (GtkTextIter        *iter,
+                                GtkSourceVimMotion *state)
 {
        if (!gtk_text_iter_starts_line (iter))
        {
@@ -432,8 +438,8 @@ motion_backward_char_same_line (GtkTextIter   *iter,
 }
 
 static gboolean
-motion_prev_line (GtkTextIter   *iter,
-                  GtkSourceView *view)
+motion_prev_line (GtkTextIter        *iter,
+                  GtkSourceVimMotion *state)
 {
        guint line = gtk_text_iter_get_line (iter);
 
@@ -450,8 +456,8 @@ motion_prev_line (GtkTextIter   *iter,
 }
 
 static gboolean
-motion_next_line (GtkTextIter   *iter,
-                  GtkSourceView *view)
+motion_next_line (GtkTextIter        *iter,
+                  GtkSourceVimMotion *state)
 {
        if (!gtk_text_iter_ends_line (iter))
        {
@@ -462,17 +468,18 @@ motion_next_line (GtkTextIter   *iter,
 }
 
 static gboolean
-motion_next_line_first_char (GtkTextIter   *iter,
-                             GtkSourceView *view)
+motion_next_line_first_char (GtkTextIter        *iter,
+                             GtkSourceVimMotion *state)
 {
-       return motion_next_line (iter, view) &&
-              motion_line_first_char (iter, view);
+       return motion_next_line (iter, state) &&
+              motion_line_first_char (iter, state);
 }
 
 static gboolean
-motion_next_line_visual_column (GtkTextIter   *iter,
-                                GtkSourceView *view)
+motion_next_line_visual_column (GtkTextIter        *iter,
+                                GtkSourceVimMotion *state)
 {
+       GtkSourceView *view = gtk_source_vim_state_get_view (GTK_SOURCE_VIM_STATE (state));
        guint column;
 
        /* TODO: We need a way to persist the visual column across
@@ -481,7 +488,7 @@ motion_next_line_visual_column (GtkTextIter   *iter,
         */
        column = gtk_source_view_get_visual_column (view, iter);
 
-       if (!motion_next_line (iter, view))
+       if (!motion_next_line (iter, state))
                return FALSE;
 
        get_iter_at_visual_column (view, iter, column);
@@ -490,9 +497,10 @@ motion_next_line_visual_column (GtkTextIter   *iter,
 }
 
 static gboolean
-motion_prev_line_visual_column (GtkTextIter   *iter,
-                                GtkSourceView *view)
+motion_prev_line_visual_column (GtkTextIter        *iter,
+                                GtkSourceVimMotion *state)
 {
+       GtkSourceView *view = gtk_source_vim_state_get_view (GTK_SOURCE_VIM_STATE (state));
        guint column;
 
        /* TODO: We need a way to persist the visual column across
@@ -501,7 +509,7 @@ motion_prev_line_visual_column (GtkTextIter   *iter,
         */
        column = gtk_source_view_get_visual_column (view, iter);
 
-       if (!motion_prev_line (iter, view))
+       if (!motion_prev_line (iter, state))
                return FALSE;
 
        get_iter_at_visual_column (view, iter, column);
@@ -510,8 +518,8 @@ motion_prev_line_visual_column (GtkTextIter   *iter,
 }
 
 static gboolean
-motion_line_end (GtkTextIter   *iter,
-                 GtkSourceView *view)
+motion_line_end (GtkTextIter        *iter,
+                 GtkSourceVimMotion *state)
 {
        GtkTextIter begin = *iter;
 
@@ -523,8 +531,8 @@ motion_line_end (GtkTextIter   *iter,
 }
 
 static gboolean
-motion_last_line_first_char (GtkTextIter   *iter,
-                             GtkSourceView *view)
+motion_last_line_first_char (GtkTextIter        *iter,
+                             GtkSourceVimMotion *state)
 {
        gtk_text_buffer_get_end_iter (gtk_text_iter_get_buffer (iter), iter);
        gtk_text_iter_set_line_offset (iter, 0);
@@ -535,9 +543,10 @@ motion_last_line_first_char (GtkTextIter   *iter,
 }
 
 static gboolean
-motion_screen_top (GtkTextIter   *iter,
-                   GtkSourceView *view)
+motion_screen_top (GtkTextIter        *iter,
+                   GtkSourceVimMotion *state)
 {
+       GtkSourceView *view = gtk_source_vim_state_get_view (GTK_SOURCE_VIM_STATE (state));
        GdkRectangle rect;
 
        gtk_text_view_get_visible_rect (GTK_TEXT_VIEW (view), &rect);
@@ -547,9 +556,10 @@ motion_screen_top (GtkTextIter   *iter,
 }
 
 static gboolean
-motion_screen_bottom (GtkTextIter   *iter,
-                      GtkSourceView *view)
+motion_screen_bottom (GtkTextIter        *iter,
+                      GtkSourceVimMotion *state)
 {
+       GtkSourceView *view = gtk_source_vim_state_get_view (GTK_SOURCE_VIM_STATE (state));
        GdkRectangle rect;
 
        gtk_text_view_get_visible_rect (GTK_TEXT_VIEW (view), &rect);
@@ -559,9 +569,10 @@ motion_screen_bottom (GtkTextIter   *iter,
 }
 
 static gboolean
-motion_screen_middle (GtkTextIter   *iter,
-                      GtkSourceView *view)
+motion_screen_middle (GtkTextIter        *iter,
+                      GtkSourceVimMotion *state)
 {
+       GtkSourceView *view = gtk_source_vim_state_get_view (GTK_SOURCE_VIM_STATE (state));
        GdkRectangle rect;
 
        gtk_text_view_get_visible_rect (GTK_TEXT_VIEW (view), &rect);
@@ -571,64 +582,64 @@ motion_screen_middle (GtkTextIter   *iter,
 }
 
 static gboolean
-motion_forward_word_start (GtkTextIter   *iter,
-                           GtkSourceView *view)
+motion_forward_word_start (GtkTextIter        *iter,
+                           GtkSourceVimMotion *state)
 {
        return forward_classified_start (iter, classify_word_newline_stop);
 }
 
 static gboolean
-motion_forward_WORD_start (GtkTextIter   *iter,
-                           GtkSourceView *view)
+motion_forward_WORD_start (GtkTextIter        *iter,
+                           GtkSourceVimMotion *state)
 {
        return forward_classified_start (iter, classify_WORD_newline_stop);
 }
 
 static gboolean
-motion_forward_word_end (GtkTextIter   *iter,
-                         GtkSourceView *view)
+motion_forward_word_end (GtkTextIter        *iter,
+                         GtkSourceVimMotion *state)
 {
        return forward_classified_end (iter, classify_word_newline_stop);
 }
 
 static gboolean
-motion_forward_WORD_end (GtkTextIter   *iter,
-                         GtkSourceView *view)
+motion_forward_WORD_end (GtkTextIter        *iter,
+                         GtkSourceVimMotion *state)
 {
        return forward_classified_end (iter, classify_WORD_newline_stop);
 }
 
 static gboolean
-motion_backward_word_start (GtkTextIter   *iter,
-                            GtkSourceView *view)
+motion_backward_word_start (GtkTextIter        *iter,
+                            GtkSourceVimMotion *state)
 {
        return backward_classified_start (iter, classify_word_newline_stop);
 }
 
 static gboolean
-motion_backward_WORD_start (GtkTextIter   *iter,
-                            GtkSourceView *view)
+motion_backward_WORD_start (GtkTextIter        *iter,
+                            GtkSourceVimMotion *state)
 {
        return backward_classified_start (iter, classify_WORD_newline_stop);
 }
 
 static gboolean
-motion_backward_word_end (GtkTextIter   *iter,
-                          GtkSourceView *view)
+motion_backward_word_end (GtkTextIter        *iter,
+                          GtkSourceVimMotion *state)
 {
        return backward_classified_end (iter, classify_word_newline_stop);
 }
 
 static gboolean
-motion_backward_WORD_end (GtkTextIter   *iter,
-                          GtkSourceView *view)
+motion_backward_WORD_end (GtkTextIter        *iter,
+                          GtkSourceVimMotion *state)
 {
        return backward_classified_end (iter, classify_WORD_newline_stop);
 }
 
 static gboolean
-motion_buffer_start (GtkTextIter   *iter,
-                     GtkSourceView *view)
+motion_buffer_start (GtkTextIter        *iter,
+                     GtkSourceVimMotion *state)
 {
        if (!gtk_text_iter_is_start (iter))
        {
@@ -640,12 +651,12 @@ motion_buffer_start (GtkTextIter   *iter,
 }
 
 static gboolean
-motion_buffer_start_first_char (GtkTextIter   *iter,
-                               GtkSourceView *view)
+motion_buffer_start_first_char (GtkTextIter        *iter,
+                                GtkSourceVimMotion *state)
 {
        GtkTextIter before = *iter;
 
-       motion_buffer_start (iter, view);
+       motion_buffer_start (iter, state);
 
        while (!gtk_text_iter_ends_line (iter) &&
               g_unichar_isspace (gtk_text_iter_get_char (iter)))
@@ -657,6 +668,46 @@ motion_buffer_start_first_char (GtkTextIter   *iter,
        return !gtk_text_iter_equal (&before, iter);
 }
 
+static gboolean
+motion_f_char (GtkTextIter        *iter,
+               GtkSourceVimMotion *state)
+{
+       GtkTextIter before = *iter;
+
+       while (!gtk_text_iter_ends_line (iter))
+       {
+               if (!gtk_text_iter_forward_char (iter))
+                       break;
+
+               if (gtk_text_iter_get_char (iter) == state->f_char)
+                       return TRUE;
+       }
+
+       *iter = before;
+
+       return FALSE;
+}
+
+static gboolean
+motion_F_char (GtkTextIter        *iter,
+               GtkSourceVimMotion *state)
+{
+       GtkTextIter before = *iter;
+
+       while (!gtk_text_iter_starts_line (iter))
+       {
+               if (!gtk_text_iter_backward_char (iter))
+                       break;
+
+               if (gtk_text_iter_get_char (iter) == state->f_char)
+                       return TRUE;
+       }
+
+       *iter = before;
+
+       return FALSE;
+}
+
 GtkSourceVimState *
 gtk_source_vim_motion_new (void)
 {
@@ -696,6 +747,16 @@ gtk_source_vim_motion_handle_keypress (GtkSourceVimState *state,
 
        g_assert (GTK_SOURCE_IS_VIM_MOTION (self));
 
+       if (self->waiting_for_f_char)
+       {
+               if (string == NULL || string[0] == 0)
+                       return gtk_source_vim_motion_bail (self);
+
+               self->f_char = g_utf8_get_char (string);
+               gtk_source_vim_state_pop (state);
+               return TRUE;
+       }
+
        if (self->g_command)
        {
                switch (keyval)
@@ -818,7 +879,15 @@ gtk_source_vim_motion_handle_keypress (GtkSourceVimState *state,
                        return gtk_source_vim_motion_complete (self, motion_forward_WORD_end);
 
                case GDK_KEY_f:
+                       self->waiting_for_f_char = TRUE;
+                       self->motion = motion_f_char;
+                       return TRUE;
+
                case GDK_KEY_F:
+                       self->waiting_for_f_char = TRUE;
+                       self->motion = motion_F_char;
+                       return TRUE;
+
                case GDK_KEY_n:
                case GDK_KEY_N:
                case GDK_KEY_parenleft:
@@ -920,9 +989,7 @@ gtk_source_vim_motion_apply (GtkSourceVimMotion *self,
 
        do
        {
-               GtkSourceView *view = gtk_source_vim_state_get_view (GTK_SOURCE_VIM_STATE (self));
-
-               if (!self->motion (iter, view))
+               if (!self->motion (iter, self))
                {
                        return FALSE;
                }


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