[gtksourceview/wip/chergert/vim] some slight work on transitions



commit a26a5d3c7743aa9fba23d83b1a54c452af89ff20
Author: Christian Hergert <chergert redhat com>
Date:   Tue Oct 19 12:28:32 2021 -0700

    some slight work on transitions
    
    I think we'll want a way to enter/exit a state so that we can more easily
    handle transitions.

 gtksourceview/gtksourcevim-private.h  |  15 +++--
 gtksourceview/gtksourcevim.c          | 114 +++++++++++++++++++++++++++++++---
 gtksourceview/gtksourcevimimcontext.c |   5 +-
 3 files changed, 119 insertions(+), 15 deletions(-)
---
diff --git a/gtksourceview/gtksourcevim-private.h b/gtksourceview/gtksourcevim-private.h
index 8c0d186c..28964cb1 100644
--- a/gtksourceview/gtksourcevim-private.h
+++ b/gtksourceview/gtksourcevim-private.h
@@ -23,6 +23,7 @@
 
 #include <gdk/gdk.h>
 
+#include "gtksourcetypes.h"
 #include "gtksourcetypes-private.h"
 
 G_BEGIN_DECLS
@@ -58,11 +59,13 @@ struct _GtkSourceVimCallbacks
                                     gpointer           user_data);
 };
 
-GtkSourceVim *gtk_source_vim_new     (const GtkSourceVimCallbacks *callbacks,
-                                      gpointer                     user_data);
-gboolean      gtk_source_vim_deliver (GtkSourceVim                *self,
-                                     GdkEvent                    *event);
-void          gtk_source_vim_reset   (GtkSourceVim                *self);
-void          gtk_source_vim_free    (GtkSourceVim                *self);
+GtkSourceVim *gtk_source_vim_new      (const GtkSourceVimCallbacks *callbacks,
+                                       gpointer                     user_data);
+void          gtk_source_vim_set_view (GtkSourceVim                *self,
+                                       GtkSourceView               *view);
+gboolean      gtk_source_vim_deliver  (GtkSourceVim                *self,
+                                       GdkEvent                    *event);
+void          gtk_source_vim_reset    (GtkSourceVim                *self);
+void          gtk_source_vim_free     (GtkSourceVim                *self);
 
 G_END_DECLS
diff --git a/gtksourceview/gtksourcevim.c b/gtksourceview/gtksourcevim.c
index ce52b06b..1f470cbc 100644
--- a/gtksourceview/gtksourcevim.c
+++ b/gtksourceview/gtksourcevim.c
@@ -21,6 +21,9 @@
 
 #include "config.h"
 
+#include <gtk/gtk.h>
+
+#include "gtksourceview.h"
 #include "gtksourcevim-private.h"
 
 typedef struct
@@ -30,13 +33,20 @@ typedef struct
        GString          *command_label;
        GString          *command_bar_label;
        int               count;
+
+       union {
+               struct {
+                       char begin;
+               } insert;
+       };
 } GtkSourceVimState;
 
 struct _GtkSourceVim
 {
-       GtkSourceVimCallbacks callbacks;
-       gpointer              callback_data;
-       GQueue                state;
+       GtkSourceView         *view;
+       GtkSourceVimCallbacks  callbacks;
+       gpointer               callback_data;
+       GQueue                 state;
 };
 
 static inline gboolean
@@ -48,6 +58,33 @@ key_is_escape (guint           keyval,
                (keyval == GDK_KEY_bracketleft && (state & GDK_CONTROL_MASK) != 0);
 }
 
+static gboolean
+get_iter_at_insert (GtkSourceVim *self,
+                    GtkTextIter  *iter)
+{
+       GtkTextBuffer *buffer;
+
+       g_assert (self != NULL);
+
+       if (self->view == NULL ||
+           !(buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (self->view))))
+               return FALSE;
+
+       gtk_text_buffer_get_iter_at_mark (buffer, iter, gtk_text_buffer_get_insert (buffer));
+
+       return TRUE;
+}
+
+static void
+move_insert (GtkSourceVim *self,
+             GtkTextIter  *iter)
+{
+       g_assert (self != NULL);
+       g_assert (iter != NULL);
+
+       gtk_text_buffer_select_range (gtk_text_iter_get_buffer (iter), iter, iter);
+}
+
 static inline gboolean
 gtk_source_vim_filter_keypress (GtkSourceVim *self,
                                 GdkEvent     *event)
@@ -172,6 +209,21 @@ gtk_source_vim_pop (GtkSourceVim *self)
                }
 
                gtk_source_vim_notify_labels (self);
+
+               if (state->mode == GTK_SOURCE_VIM_NORMAL &&
+                   (popped->mode == GTK_SOURCE_VIM_INSERT ||
+                    popped->mode == GTK_SOURCE_VIM_REPLACE))
+               {
+                       GtkTextIter iter;
+
+                       if (get_iter_at_insert (self, &iter) &&
+                           gtk_text_iter_ends_line (&iter) &&
+                           gtk_text_iter_backward_char (&iter))
+                       {
+                               move_insert (self, &iter);
+                       }
+               }
+
        }
 
        gtk_source_vim_state_free (popped);
@@ -204,6 +256,7 @@ gtk_source_vim_free (GtkSourceVim *self)
                        gtk_source_vim_pop (self);
                }
 
+               g_clear_weak_pointer (&self->view);
                g_free (self);
        }
 }
@@ -229,6 +282,8 @@ gtk_source_vim_handle_normal (GtkSourceVim      *self,
                              guint              keyval,
                              GdkModifierType    mods)
 {
+       GtkSourceVimState *new_state;
+
        g_assert (self != NULL);
        g_assert (state != NULL);
        g_assert (state->mode == GTK_SOURCE_VIM_NORMAL);
@@ -249,7 +304,39 @@ gtk_source_vim_handle_normal (GtkSourceVim      *self,
                return TRUE;
 
        case GDK_KEY_i:
-               gtk_source_vim_push (self, GTK_SOURCE_VIM_INSERT);
+               new_state = gtk_source_vim_push (self, GTK_SOURCE_VIM_INSERT);
+               new_state->insert.begin = 'i';
+               return TRUE;
+       case GDK_KEY_I:
+               new_state = gtk_source_vim_push (self, GTK_SOURCE_VIM_INSERT);
+               new_state->insert.begin = 'I';
+               return TRUE;
+
+       case GDK_KEY_a:
+               new_state = gtk_source_vim_push (self, GTK_SOURCE_VIM_INSERT);
+               new_state->insert.begin = 'a';
+               return TRUE;
+       case GDK_KEY_A:
+               new_state = gtk_source_vim_push (self, GTK_SOURCE_VIM_INSERT);
+               new_state->insert.begin = 'A';
+               return TRUE;
+
+       case GDK_KEY_o:
+               new_state = gtk_source_vim_push (self, GTK_SOURCE_VIM_INSERT);
+               new_state->insert.begin = 'o';
+               return TRUE;
+       case GDK_KEY_O:
+               new_state = gtk_source_vim_push (self, GTK_SOURCE_VIM_INSERT);
+               new_state->insert.begin = 'O';
+               return TRUE;
+
+       case GDK_KEY_s:
+               new_state = gtk_source_vim_push (self, GTK_SOURCE_VIM_INSERT);
+               new_state->insert.begin = 's';
+               return TRUE;
+       case GDK_KEY_S: /* synonym cc */
+               new_state = gtk_source_vim_push (self, GTK_SOURCE_VIM_INSERT);
+               new_state->insert.begin = 'S';
                return TRUE;
 
        default:
@@ -259,8 +346,8 @@ gtk_source_vim_handle_normal (GtkSourceVim      *self,
 }
 
 gboolean
-gtk_source_vim_deliver (GtkSourceVim *self,
-                        GdkEvent     *event)
+gtk_source_vim_deliver (GtkSourceVim  *self,
+                        GdkEvent      *event)
 {
        GtkSourceVimState *state;
        GdkEventType event_type;
@@ -269,6 +356,8 @@ gtk_source_vim_deliver (GtkSourceVim *self,
 
        g_return_val_if_fail (self != NULL, FALSE);
        g_return_val_if_fail (self->state.length > 0, FALSE);
+       g_return_val_if_fail (GTK_SOURCE_IS_VIEW (self->view), FALSE);
+       g_return_val_if_fail (event != NULL, FALSE);
 
        state = g_queue_peek_tail (&self->state);
 
@@ -294,8 +383,7 @@ gtk_source_vim_deliver (GtkSourceVim *self,
                return FALSE;
        }
 
-       switch (state->mode)
-       {
+       switch (state->mode) {
        case GTK_SOURCE_VIM_INSERT:
 
                if (key_is_escape (keyval, keycode, mods))
@@ -335,3 +423,13 @@ gtk_source_vim_deliver (GtkSourceVim *self,
 
        return FALSE;
 }
+
+void
+gtk_source_vim_set_view (GtkSourceVim  *self,
+                         GtkSourceView *view)
+{
+       g_return_if_fail (self != NULL);
+       g_return_if_fail (!view || GTK_SOURCE_IS_VIEW (view));
+
+       g_set_weak_pointer (&self->view, view);
+}
diff --git a/gtksourceview/gtksourcevimimcontext.c b/gtksourceview/gtksourcevimimcontext.c
index 1bbbff5b..0e7a6c6a 100644
--- a/gtksourceview/gtksourcevimimcontext.c
+++ b/gtksourceview/gtksourcevimimcontext.c
@@ -64,7 +64,10 @@ gtk_source_vim_im_context_set_client_widget (GtkIMContext *context,
 
        g_return_if_fail (GTK_SOURCE_IS_VIM_IM_CONTEXT (self));
 
-       g_set_weak_pointer (&self->view, GTK_SOURCE_VIEW (widget));
+       if (g_set_weak_pointer (&self->view, GTK_SOURCE_VIEW (widget)))
+       {
+               gtk_source_vim_set_view (self->vim, self->view);
+       }
 }
 
 static void


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