[gtksourceview/wip/chergert/vim] allow applying motion when leaving state



commit 0f0d354889261909141c3f3b0fcf8cb040f8e8cc
Author: Christian Hergert <chergert redhat com>
Date:   Sat Oct 23 10:24:20 2021 -0700

    allow applying motion when leaving state
    
    that way we can use this to both capture a motion and apply it normally.
    also setup basic repeat for motion.

 gtksourceview/vim/gtk-source-vim-motion.c | 54 +++++++++++++++++++++++++++++++
 gtksourceview/vim/gtk-source-vim-motion.h |  8 +++--
 gtksourceview/vim/gtk-source-vim-normal.c | 28 ++++++----------
 3 files changed, 68 insertions(+), 22 deletions(-)
---
diff --git a/gtksourceview/vim/gtk-source-vim-motion.c b/gtksourceview/vim/gtk-source-vim-motion.c
index e5f033c7..4c321458 100644
--- a/gtksourceview/vim/gtk-source-vim-motion.c
+++ b/gtksourceview/vim/gtk-source-vim-motion.c
@@ -33,6 +33,7 @@ struct _GtkSourceVimMotion
        GtkSourceVimState parent_instance;
        Motion            motion;
        int               number;
+       guint             apply_on_leave : 1;
        guint             failed : 1;
 };
 
@@ -418,6 +419,47 @@ gtk_source_vim_motion_handle_keypress (GtkSourceVimState *state,
        return FALSE;
 }
 
+static void
+gtk_source_vim_motion_repeat (GtkSourceVimState *state,
+                             int                repeat)
+{
+       GtkSourceVimMotion *self = (GtkSourceVimMotion *)state;
+       GtkSourceBuffer *buffer;
+       GtkTextIter insert, selection;
+       gboolean has_selection;
+
+       g_assert (GTK_SOURCE_IS_VIM_MOTION (self));
+
+       buffer = gtk_source_vim_state_get_buffer (state, &insert, &selection);
+       has_selection = !gtk_text_iter_equal (&insert, &selection);
+
+       do
+       {
+               if (!gtk_source_vim_motion_apply (self, &insert))
+               {
+                       break;
+               }
+       } while (--repeat > 0);
+
+       if (has_selection)
+               gtk_text_buffer_move_mark (GTK_TEXT_BUFFER (buffer),
+                                          gtk_text_buffer_get_insert (GTK_TEXT_BUFFER (buffer)),
+                                          &insert);
+       else
+               gtk_text_buffer_select_range (GTK_TEXT_BUFFER (buffer), &insert, &insert);
+}
+
+static void
+gtk_source_vim_motion_leave (GtkSourceVimState *state)
+{
+       GtkSourceVimMotion *self = (GtkSourceVimMotion *)state;
+
+       g_assert (GTK_SOURCE_IS_VIM_MOTION (self));
+
+       if (self->apply_on_leave)
+               gtk_source_vim_motion_repeat (state, 1);
+}
+
 static void
 gtk_source_vim_motion_finalize (GObject *object)
 {
@@ -433,11 +475,14 @@ gtk_source_vim_motion_class_init (GtkSourceVimMotionClass *klass)
        object_class->finalize = gtk_source_vim_motion_finalize;
 
        state_class->handle_keypress = gtk_source_vim_motion_handle_keypress;
+       state_class->leave = gtk_source_vim_motion_leave;
+       state_class->repeat = gtk_source_vim_motion_repeat;
 }
 
 static void
 gtk_source_vim_motion_init (GtkSourceVimMotion *self)
 {
+       self->apply_on_leave = TRUE;
 }
 
 gboolean
@@ -463,3 +508,12 @@ gtk_source_vim_motion_apply (GtkSourceVimMotion *self,
 
        return TRUE;
 }
+
+void
+gtk_source_vim_motion_set_apply_on_leave (GtkSourceVimMotion *self,
+                                          gboolean            apply_on_leave)
+{
+       g_return_if_fail (GTK_SOURCE_IS_VIM_MOTION (self));
+
+       self->apply_on_leave = !!apply_on_leave;
+}
diff --git a/gtksourceview/vim/gtk-source-vim-motion.h b/gtksourceview/vim/gtk-source-vim-motion.h
index 8dc5baa5..8961fa41 100644
--- a/gtksourceview/vim/gtk-source-vim-motion.h
+++ b/gtksourceview/vim/gtk-source-vim-motion.h
@@ -31,8 +31,10 @@ G_BEGIN_DECLS
 
 G_DECLARE_FINAL_TYPE (GtkSourceVimMotion, gtk_source_vim_motion, GTK_SOURCE, VIM_MOTION, GtkSourceVimState)
 
-GtkSourceVimState *gtk_source_vim_motion_new   (void);
-gboolean           gtk_source_vim_motion_apply (GtkSourceVimMotion *self,
-                                                GtkTextIter        *iter);
+GtkSourceVimState *gtk_source_vim_motion_new                (void);
+void               gtk_source_vim_motion_set_apply_on_leave (GtkSourceVimMotion *self,
+                                                             gboolean            apply_on_leave);
+gboolean           gtk_source_vim_motion_apply              (GtkSourceVimMotion *self,
+                                                             GtkTextIter        *iter);
 
 G_END_DECLS
diff --git a/gtksourceview/vim/gtk-source-vim-normal.c b/gtksourceview/vim/gtk-source-vim-normal.c
index d8c3b79f..97bb0740 100644
--- a/gtksourceview/vim/gtk-source-vim-normal.c
+++ b/gtksourceview/vim/gtk-source-vim-normal.c
@@ -306,6 +306,7 @@ key_handler_motion (GtkSourceVimNormal *self,
        g_assert (GTK_SOURCE_IS_VIM_NORMAL (self));
 
        new_state = gtk_source_vim_motion_new ();
+       gtk_source_vim_motion_set_apply_on_leave (GTK_SOURCE_VIM_MOTION (new_state), TRUE);
        gtk_source_vim_state_push (GTK_SOURCE_VIM_STATE (self), new_state);
        GTK_SOURCE_VIM_STATE_GET_CLASS (new_state)->handle_keypress (new_state, keyval, keycode, mods, 
string);
 
@@ -540,10 +541,15 @@ static void
 gtk_source_vim_normal_restore (GtkSourceVimState *state,
                                GtkSourceVimState *from)
 {
-       g_assert (GTK_SOURCE_IS_VIM_STATE (state));
+       GtkSourceVimNormal *self = (GtkSourceVimNormal *)state;
+
+       g_assert (GTK_SOURCE_IS_VIM_NORMAL (self));
        g_assert (GTK_SOURCE_IS_VIM_STATE (from));
 
-       gtk_source_vim_normal_clear (GTK_SOURCE_VIM_NORMAL (state));
+       if (self->repeat > 1)
+       {
+               gtk_source_vim_state_repeat (from, self->repeat - 1);
+       }
 
        /* Go back one character if we exited replace/insert state */
        if (GTK_SOURCE_IS_VIM_INSERT (from) ||
@@ -561,24 +567,8 @@ gtk_source_vim_normal_restore (GtkSourceVimState *state,
                                                      &insert, &insert);
                }
        }
-       else if (GTK_SOURCE_IS_VIM_MOTION (from))
-       {
-               GtkSourceBuffer *buffer;
-               GtkTextIter insert;
-
-               buffer = gtk_source_vim_state_get_buffer (state, &insert, NULL);
-
-               if (gtk_source_vim_motion_apply (GTK_SOURCE_VIM_MOTION (from), &insert))
-               {
-                       gtk_text_buffer_select_range (GTK_TEXT_BUFFER (buffer), &insert, &insert);
-               }
-
-               /* TODO: - keep cursor at end of line.
-                *       - possibly use with command.
-                *  etc..
-                */
-       }
 
+       gtk_source_vim_normal_clear (GTK_SOURCE_VIM_NORMAL (state));
        gtk_source_vim_state_set_overwrite (state, TRUE);
 }
 


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