[gtksourceview/wip/chergert/vim] add replace one command



commit ef34e4f2903a2ae5425bb0bda17e52232397244d
Author: Christian Hergert <chergert redhat com>
Date:   Wed Nov 3 15:38:28 2021 -0700

    add replace one command
    
    this is easier than doubling up replace mode

 gtksourceview/vim/gtk-source-vim-command.c | 71 ++++++++++++++++++++++++++++++
 gtksourceview/vim/gtk-source-vim-visual.c  |  9 ++--
 2 files changed, 76 insertions(+), 4 deletions(-)
---
diff --git a/gtksourceview/vim/gtk-source-vim-command.c b/gtksourceview/vim/gtk-source-vim-command.c
index d691c510..5bde1700 100644
--- a/gtksourceview/vim/gtk-source-vim-command.c
+++ b/gtksourceview/vim/gtk-source-vim-command.c
@@ -25,6 +25,7 @@
 
 #include "gtksourcebuffer.h"
 
+#include "gtk-source-vim-char-pending.h"
 #include "gtk-source-vim-command.h"
 #include "gtk-source-vim-registers.h"
 
@@ -37,6 +38,7 @@ struct _GtkSourceVimCommand
        GtkSourceVimMotion *motion;
        GtkSourceVimMotion *selection_motion;
        char               *command;
+       char                char_pending[16];
 
        guint               ignore_mark : 1;
 };
@@ -359,6 +361,58 @@ gtk_source_vim_command_rot13 (GtkSourceVimCommand *self)
        g_free (new_text);
 }
 
+static char *
+replace_chars_with (const char *text,
+                    const char *replacement)
+{
+       GString *str;
+       gsize len;
+
+       g_assert (text != NULL);
+       g_assert (replacement != NULL);
+
+       str = g_string_new (NULL);
+       len = strlen (replacement);
+
+       for (const char *c = text; *c; c = g_utf8_next_char (c))
+       {
+               if (*c == '\n')
+                       g_string_append_c (str, '\n');
+               else
+                       g_string_append_len (str, replacement, len);
+       }
+
+       return g_string_free (str, FALSE);
+}
+
+static void
+gtk_source_vim_command_replace_one (GtkSourceVimCommand *self)
+{
+       GtkTextIter iter, selection;
+       GtkSourceBuffer *buffer;
+       char *text;
+       char *new_text;
+
+       g_assert (GTK_SOURCE_IS_VIM_COMMAND (self));
+
+       if (self->char_pending[0] == 0)
+       {
+               return;
+       }
+
+       buffer = gtk_source_vim_state_get_buffer (GTK_SOURCE_VIM_STATE (self), &iter, &selection);
+       text = gtk_text_iter_get_slice (&iter, &selection);
+       new_text = replace_chars_with (text, self->char_pending);
+
+       gtk_text_buffer_begin_user_action (GTK_TEXT_BUFFER (buffer));
+       gtk_text_buffer_delete (GTK_TEXT_BUFFER (buffer), &iter, &selection);
+       gtk_text_buffer_insert (GTK_TEXT_BUFFER (buffer), &iter, new_text, -1);
+       gtk_text_buffer_end_user_action (GTK_TEXT_BUFFER (buffer));
+
+       g_free (text);
+       g_free (new_text);
+}
+
 static void
 gtk_source_vim_command_undo (GtkSourceVimCommand *self)
 {
@@ -486,6 +540,22 @@ gtk_source_vim_command_resume (GtkSourceVimState *state,
        {
                g_set_object (&self->motion, GTK_SOURCE_VIM_MOTION (from));
                gtk_source_vim_state_pop (state);
+               return;
+       }
+
+       /* If we're waiting for a character, that could complete too */
+       if (GTK_SOURCE_IS_VIM_CHAR_PENDING (from))
+       {
+               gunichar ch = gtk_source_vim_char_pending_get_character (GTK_SOURCE_VIM_CHAR_PENDING (from));
+               const char *string = gtk_source_vim_char_pending_get_string (GTK_SOURCE_VIM_CHAR_PENDING 
(from));
+
+               if (ch && string && string[0])
+               {
+                       g_strlcpy (self->char_pending, string, sizeof self->char_pending);
+               }
+
+               gtk_source_vim_state_pop (state);
+               return;
        }
 }
 
@@ -612,6 +682,7 @@ gtk_source_vim_command_class_init (GtkSourceVimCommandClass *klass)
        ADD_COMMAND ("upcase",         gtk_source_vim_command_upcase);
        ADD_COMMAND ("downcase",       gtk_source_vim_command_downcase);
        ADD_COMMAND ("rot13",          gtk_source_vim_command_rot13);
+       ADD_COMMAND ("replace-one",    gtk_source_vim_command_replace_one);
 #undef ADD_COMMAND
 }
 
diff --git a/gtksourceview/vim/gtk-source-vim-visual.c b/gtksourceview/vim/gtk-source-vim-visual.c
index 5b110f3c..cc89274d 100644
--- a/gtksourceview/vim/gtk-source-vim-visual.c
+++ b/gtksourceview/vim/gtk-source-vim-visual.c
@@ -452,7 +452,7 @@ gtk_source_vim_visual_replace (GtkSourceVimVisual *self)
 {
        g_assert (GTK_SOURCE_IS_VIM_VISUAL (self));
 
-       self->command = gtk_source_vim_replace_new ();
+       self->command = gtk_source_vim_command_new ("replace-one");
 
        gtk_source_vim_state_set_can_repeat (GTK_SOURCE_VIM_STATE (self), TRUE);
        gtk_source_vim_state_push (GTK_SOURCE_VIM_STATE (self),
@@ -644,8 +644,6 @@ gtk_source_vim_visual_resume (GtkSourceVimState *state,
 
        self->handler = key_handler_initial;
 
-       update_cursor_visible (self);
-
        if (GTK_SOURCE_IS_VIM_MOTION (from))
        {
                GtkSourceVimState *chained;
@@ -669,8 +667,11 @@ gtk_source_vim_visual_resume (GtkSourceVimState *state,
                g_object_unref (chained);
        }
 
+       update_cursor_visible (self);
+
        if (GTK_SOURCE_IS_VIM_INSERT (from) ||
-           GTK_SOURCE_IS_VIM_REPLACE (from))
+           GTK_SOURCE_IS_VIM_REPLACE (from) ||
+           GTK_SOURCE_IS_VIM_COMMAND (from))
        {
                gtk_source_vim_state_pop (state);
        }


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