[gtksourceview/wip/chergert/vim: 94/293] start on line changes




commit 911d108ad2e0655782c3dc5a15d53ed7b407dcbb
Author: Christian Hergert <chergert redhat com>
Date:   Wed Oct 27 12:19:24 2021 -0700

    start on line changes
    
    requires doing some inclusive/exclusive work which i dont love. however as
    we get to linewise/block stuff, that will likely affect how we implement it
    and i dont want to do that prematurely.

 gtksourceview/vim/gtk-source-vim-motion.c | 108 +++++++++++++++++++++---------
 gtksourceview/vim/gtk-source-vim-motion.h |   3 +-
 gtksourceview/vim/gtk-source-vim-normal.c |  60 ++++++++++++++++-
 3 files changed, 134 insertions(+), 37 deletions(-)
---
diff --git a/gtksourceview/vim/gtk-source-vim-motion.c b/gtksourceview/vim/gtk-source-vim-motion.c
index 0e201d34..37b73392 100644
--- a/gtksourceview/vim/gtk-source-vim-motion.c
+++ b/gtksourceview/vim/gtk-source-vim-motion.c
@@ -28,6 +28,11 @@
 typedef gboolean (*Motion) (GtkTextIter        *iter,
                             GtkSourceVimMotion *state);
 
+typedef enum {
+       INCLUSIVE = 0,
+       EXCLUSIVE = 1,
+} Inclusivity;
+
 struct _GtkSourceVimMotion
 {
        GtkSourceVimState parent_instance;
@@ -58,6 +63,9 @@ struct _GtkSourceVimMotion
 
        /* If we just did f/F and need another char */
        guint waiting_for_f_char : 1;
+
+       /* If the motion is exclusive (does not include char) */
+       guint inclusivity : 1;
 };
 
 G_DEFINE_TYPE (GtkSourceVimMotion, gtk_source_vim_motion, GTK_SOURCE_TYPE_VIM_STATE)
@@ -578,7 +586,9 @@ motion_line_end (GtkTextIter        *iter,
 {
        GtkTextIter begin = *iter;
 
-       gtk_text_iter_forward_to_line_end (iter);
+       if (!gtk_text_iter_ends_line (iter))
+               gtk_text_iter_forward_to_line_end (iter);
+
        if (!gtk_text_iter_starts_line (iter))
                gtk_text_iter_backward_char (iter);
 
@@ -1023,11 +1033,14 @@ gtk_source_vim_motion_bail (GtkSourceVimMotion *self)
 
 static gboolean
 gtk_source_vim_motion_complete (GtkSourceVimMotion *self,
-                                Motion              motion)
+                                Motion              motion,
+                                Inclusivity         inclusivity)
 {
        g_assert (GTK_SOURCE_IS_VIM_MOTION (self));
 
        self->motion = motion;
+       self->inclusivity = inclusivity;
+
        g_string_truncate (self->command_text, 0);
 
        gtk_source_vim_state_pop (GTK_SOURCE_VIM_STATE (self));
@@ -1063,13 +1076,13 @@ gtk_source_vim_motion_handle_keypress (GtkSourceVimState *state,
                switch (keyval)
                {
                        case GDK_KEY_g:
-                               return gtk_source_vim_motion_complete (self, motion_buffer_start_first_char);
+                               return gtk_source_vim_motion_complete (self, motion_buffer_start_first_char, 
INCLUSIVE);
 
                        case GDK_KEY_e:
-                               return gtk_source_vim_motion_complete (self, motion_backward_word_end);
+                               return gtk_source_vim_motion_complete (self, motion_backward_word_end, 
EXCLUSIVE);
 
                        case GDK_KEY_E:
-                               return gtk_source_vim_motion_complete (self, motion_backward_WORD_end);
+                               return gtk_source_vim_motion_complete (self, motion_backward_WORD_end, 
EXCLUSIVE);
 
                        default:
                                return gtk_source_vim_motion_bail (self);
@@ -1093,7 +1106,7 @@ gtk_source_vim_motion_handle_keypress (GtkSourceVimState *state,
                case GDK_KEY_KP_0:
                case GDK_KEY_Home:
                case GDK_KEY_bar:
-                       return gtk_source_vim_motion_complete (self, motion_line_start);
+                       return gtk_source_vim_motion_complete (self, motion_line_start, INCLUSIVE);
 
                case GDK_KEY_1: case GDK_KEY_KP_1:
                case GDK_KEY_2: case GDK_KEY_KP_2:
@@ -1112,94 +1125,96 @@ gtk_source_vim_motion_handle_keypress (GtkSourceVimState *state,
 
                case GDK_KEY_asciicircum:
                case GDK_KEY_underscore:
-                       return gtk_source_vim_motion_complete (self, motion_line_first_char);
+                       return gtk_source_vim_motion_complete (self, motion_line_first_char, INCLUSIVE);
 
                case GDK_KEY_space:
-                       return gtk_source_vim_motion_complete (self, motion_forward_char);
+                       return gtk_source_vim_motion_complete (self, motion_forward_char, EXCLUSIVE);
 
                case GDK_KEY_BackSpace:
-                       return gtk_source_vim_motion_complete (self, motion_backward_char);
+                       return gtk_source_vim_motion_complete (self, motion_backward_char, INCLUSIVE);
 
                case GDK_KEY_Left:
                case GDK_KEY_h:
-                       return gtk_source_vim_motion_complete (self, motion_backward_char_same_line);
+                       return gtk_source_vim_motion_complete (self, motion_backward_char_same_line, 
INCLUSIVE);
 
                case GDK_KEY_Right:
                case GDK_KEY_l:
-                       return gtk_source_vim_motion_complete (self, motion_forward_char_same_line);
+                       return gtk_source_vim_motion_complete (self, motion_forward_char_same_line, 
EXCLUSIVE);
 
                case GDK_KEY_ISO_Enter:
                case GDK_KEY_KP_Enter:
                case GDK_KEY_Return:
-                       return gtk_source_vim_motion_complete (self, motion_next_line_first_char);
+                       return gtk_source_vim_motion_complete (self, motion_next_line_first_char, EXCLUSIVE);
 
                case GDK_KEY_End:
                case GDK_KEY_dollar:
-                       return gtk_source_vim_motion_complete (self, motion_line_end);
+                       return gtk_source_vim_motion_complete (self, motion_line_end, EXCLUSIVE);
 
                case GDK_KEY_Down:
                case GDK_KEY_j:
-                       return gtk_source_vim_motion_complete (self, motion_next_line_visual_column);
+                       return gtk_source_vim_motion_complete (self, motion_next_line_visual_column, 
EXCLUSIVE);
 
                case GDK_KEY_Up:
                case GDK_KEY_k:
-                       return gtk_source_vim_motion_complete (self, motion_prev_line_visual_column);
+                       return gtk_source_vim_motion_complete (self, motion_prev_line_visual_column, 
INCLUSIVE);
 
                case GDK_KEY_G:
-                       return gtk_source_vim_motion_complete (self, motion_last_line_first_char);
+                       return gtk_source_vim_motion_complete (self, motion_last_line_first_char, EXCLUSIVE);
 
                case GDK_KEY_g:
                        self->g_command = TRUE;
                        return TRUE;
 
                case GDK_KEY_H:
-                       return gtk_source_vim_motion_complete (self, motion_screen_top);
+                       return gtk_source_vim_motion_complete (self, motion_screen_top, INCLUSIVE);
 
                case GDK_KEY_M:
-                       return gtk_source_vim_motion_complete (self, motion_screen_middle);
+                       return gtk_source_vim_motion_complete (self, motion_screen_middle, INCLUSIVE);
 
                case GDK_KEY_L:
-                       return gtk_source_vim_motion_complete (self, motion_screen_bottom);
+                       return gtk_source_vim_motion_complete (self, motion_screen_bottom, INCLUSIVE);
 
                case GDK_KEY_w:
-                       return gtk_source_vim_motion_complete (self, motion_forward_word_start);
+                       return gtk_source_vim_motion_complete (self, motion_forward_word_start, EXCLUSIVE);
 
                case GDK_KEY_W:
-                       return gtk_source_vim_motion_complete (self, motion_forward_WORD_start);
+                       return gtk_source_vim_motion_complete (self, motion_forward_WORD_start, EXCLUSIVE);
 
                case GDK_KEY_b:
-                       return gtk_source_vim_motion_complete (self, motion_backward_word_start);
+                       return gtk_source_vim_motion_complete (self, motion_backward_word_start, INCLUSIVE);
 
                case GDK_KEY_B:
-                       return gtk_source_vim_motion_complete (self, motion_backward_WORD_start);
+                       return gtk_source_vim_motion_complete (self, motion_backward_WORD_start, INCLUSIVE);
 
                case GDK_KEY_e:
-                       return gtk_source_vim_motion_complete (self, motion_forward_word_end);
+                       return gtk_source_vim_motion_complete (self, motion_forward_word_end, INCLUSIVE);
 
                case GDK_KEY_E:
-                       return gtk_source_vim_motion_complete (self, motion_forward_WORD_end);
+                       return gtk_source_vim_motion_complete (self, motion_forward_WORD_end, INCLUSIVE);
 
                case GDK_KEY_f:
                        self->waiting_for_f_char = TRUE;
                        self->motion = motion_f_char;
+                       self->inclusivity = EXCLUSIVE;
                        return TRUE;
 
                case GDK_KEY_F:
                        self->waiting_for_f_char = TRUE;
                        self->motion = motion_F_char;
+                       self->inclusivity = INCLUSIVE;
                        return TRUE;
 
                case GDK_KEY_parenleft:
-                       return gtk_source_vim_motion_complete (self, motion_backward_sentence_start);
+                       return gtk_source_vim_motion_complete (self, motion_backward_sentence_start, 
INCLUSIVE);
 
                case GDK_KEY_parenright:
-                       return gtk_source_vim_motion_complete (self, motion_forward_sentence_start);
+                       return gtk_source_vim_motion_complete (self, motion_forward_sentence_start, 
EXCLUSIVE);
 
                case GDK_KEY_braceleft:
-                       return gtk_source_vim_motion_complete (self, motion_backward_paragraph_start);
+                       return gtk_source_vim_motion_complete (self, motion_backward_paragraph_start, 
INCLUSIVE);
 
                case GDK_KEY_braceright:
-                       return gtk_source_vim_motion_complete (self, motion_forward_paragraph_end);
+                       return gtk_source_vim_motion_complete (self, motion_forward_paragraph_end, EXCLUSIVE);
 
                case GDK_KEY_n:
                case GDK_KEY_N:
@@ -1235,7 +1250,7 @@ gtk_source_vim_motion_repeat (GtkSourceVimState *state,
 
        do
        {
-               if (!gtk_source_vim_motion_apply (self, &insert))
+               if (!gtk_source_vim_motion_apply (self, &insert, FALSE))
                {
                        break;
                }
@@ -1313,8 +1328,12 @@ gtk_source_vim_motion_init (GtkSourceVimMotion *self)
 
 gboolean
 gtk_source_vim_motion_apply (GtkSourceVimMotion *self,
-                             GtkTextIter        *iter)
+                             GtkTextIter        *iter,
+                             gboolean            apply_inclusive)
 {
+       gboolean ret = FALSE;
+       guint begin_offset;
+
        g_return_val_if_fail (GTK_SOURCE_IS_VIM_MOTION (self), FALSE);
 
        if (self->motion == NULL || self->failed)
@@ -1322,15 +1341,35 @@ gtk_source_vim_motion_apply (GtkSourceVimMotion *self,
                return FALSE;
        }
 
+       begin_offset = gtk_text_iter_get_offset (iter);
+
        do
        {
                if (!self->motion (iter, self))
                {
-                       return FALSE;
+                       goto do_inclusive;
                }
        } while (--self->number > 1);
 
-       return TRUE;
+       ret = TRUE;
+
+do_inclusive:
+       if (apply_inclusive)
+       {
+               guint end_offset = gtk_text_iter_get_offset (iter);
+
+               if (FALSE) {}
+               else if (self->inclusivity == INCLUSIVE &&
+                        end_offset > begin_offset &&
+                        !gtk_text_iter_ends_line (iter))
+                       gtk_text_iter_forward_char (iter);
+               else if (self->inclusivity == EXCLUSIVE
+                        && end_offset < begin_offset &&
+                        !gtk_text_iter_ends_line (iter))
+                       gtk_text_iter_forward_char (iter);
+       }
+
+       return ret;
 }
 
 void
@@ -1360,6 +1399,7 @@ gtk_source_vim_motion_new_line_end (void)
 
        self = g_object_new (GTK_SOURCE_TYPE_VIM_MOTION, NULL);
        self->motion = motion_line_end;
+       self->inclusivity = EXCLUSIVE;
 
        return GTK_SOURCE_VIM_STATE (self);
 }
@@ -1371,6 +1411,7 @@ gtk_source_vim_motion_new_line_start (void)
 
        self = g_object_new (GTK_SOURCE_TYPE_VIM_MOTION, NULL);
        self->motion = motion_line_start;
+       self->inclusivity = INCLUSIVE;
 
        return GTK_SOURCE_VIM_STATE (self);
 }
@@ -1382,6 +1423,7 @@ gtk_source_vim_motion_new_previous_line_end (void)
 
        self = g_object_new (GTK_SOURCE_TYPE_VIM_MOTION, NULL);
        self->motion = motion_prev_line_end;
+       self->inclusivity = EXCLUSIVE;
 
        return GTK_SOURCE_VIM_STATE (self);
 }
diff --git a/gtksourceview/vim/gtk-source-vim-motion.h b/gtksourceview/vim/gtk-source-vim-motion.h
index 127cad96..2748ae0f 100644
--- a/gtksourceview/vim/gtk-source-vim-motion.h
+++ b/gtksourceview/vim/gtk-source-vim-motion.h
@@ -40,6 +40,7 @@ GtkSourceVimState *gtk_source_vim_motion_new_line_start        (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);
+                                                                GtkTextIter        *iter,
+                                                                gboolean            apply_inclusive);
 
 G_END_DECLS
diff --git a/gtksourceview/vim/gtk-source-vim-normal.c b/gtksourceview/vim/gtk-source-vim-normal.c
index bafb4cb7..f5ba5add 100644
--- a/gtksourceview/vim/gtk-source-vim-normal.c
+++ b/gtksourceview/vim/gtk-source-vim-normal.c
@@ -139,10 +139,54 @@ typedef enum
 {
        INSERT_HERE,
        INSERT_AFTER_CHAR,
-       INSERT_AFTER_CHAR_UNLESS_SOL,
        INSERT_AFTER_CHAR_UNLESS_BOF,
+       INSERT_AFTER_CHAR_UNLESS_SOL,
 } InsertAt;
 
+G_GNUC_NULL_TERMINATED
+static GtkSourceVimState *
+gtk_source_vim_normal_begin_change (GtkSourceVimNormal *self,
+                                    GtkSourceVimState  *motion,
+                                    ...)
+{
+       GtkSourceVimState *ret;
+       GtkSourceBuffer *buffer;
+       const char *first_property_name;
+       GtkTextIter iter, selection;
+       va_list args;
+
+       g_assert (GTK_SOURCE_IS_VIM_NORMAL (self));
+       g_assert (!motion || GTK_SOURCE_IS_VIM_MOTION (motion));
+
+       buffer = gtk_source_vim_state_get_buffer (GTK_SOURCE_VIM_STATE (self), &iter, &selection);
+
+       gtk_text_buffer_begin_user_action (GTK_TEXT_BUFFER (buffer));
+
+       if (motion != NULL)
+       {
+               /* Just to attach it to the state machine */
+               gtk_source_vim_motion_set_apply_on_leave (GTK_SOURCE_VIM_MOTION (motion), FALSE);
+               gtk_source_vim_state_push (GTK_SOURCE_VIM_STATE (self), motion);
+               gtk_source_vim_state_pop (g_object_ref (motion));
+
+               /* Apply it to our selection bound */
+               gtk_source_vim_motion_apply (GTK_SOURCE_VIM_MOTION (motion), &iter, TRUE);
+               gtk_text_buffer_delete (GTK_TEXT_BUFFER (buffer), &iter, &selection);
+               gtk_text_buffer_select_range (GTK_TEXT_BUFFER (buffer), &iter, &iter);
+       }
+
+       va_start (args, motion);
+       first_property_name = va_arg (args, const char *);
+       ret = GTK_SOURCE_VIM_STATE (g_object_new_valist (GTK_SOURCE_TYPE_VIM_INSERT, first_property_name, 
args));
+       va_end (args);
+
+       gtk_source_vim_state_push (GTK_SOURCE_VIM_STATE (self), ret);
+
+       gtk_text_buffer_end_user_action (GTK_TEXT_BUFFER (buffer));
+
+       return ret;
+}
+
 G_GNUC_NULL_TERMINATED
 static GtkSourceVimState *
 gtk_source_vim_normal_begin_insert (GtkSourceVimNormal *self,
@@ -173,7 +217,8 @@ gtk_source_vim_normal_begin_insert (GtkSourceVimNormal *self,
                    (at == INSERT_AFTER_CHAR_UNLESS_BOF && !gtk_text_iter_is_start (&iter)) ||
                    (at == INSERT_AFTER_CHAR_UNLESS_SOL && !gtk_text_iter_starts_line (&iter)))
                {
-                       gtk_text_iter_forward_char (&iter);
+                       if (!gtk_text_iter_ends_line (&iter))
+                               gtk_text_iter_forward_char (&iter);
                }
 
                gtk_source_vim_state_select (GTK_SOURCE_VIM_STATE (self), &iter, &iter);
@@ -253,8 +298,14 @@ key_handler_command (GtkSourceVimNormal *self,
                                                            NULL);
                        return TRUE;
 
-               case GDK_KEY_asciitilde:
                case GDK_KEY_C:
+                       gtk_source_vim_normal_begin_change (self,
+                                                           gtk_source_vim_motion_new_line_end (),
+                                                           INSERT_HERE,
+                                                           NULL);
+                       return TRUE;
+
+               case GDK_KEY_asciitilde:
                case GDK_KEY_D:
                case GDK_KEY_J:
                case GDK_KEY_p:
@@ -265,7 +316,10 @@ key_handler_command (GtkSourceVimNormal *self,
                case GDK_KEY_x:
                case GDK_KEY_equal:
                case GDK_KEY_plus:
+                       break;
+
                case GDK_KEY_Y:
+                       /* synonum for yy */
                        break;
 
                default:


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