[gtksourceview/wip/chergert/vim] improve yank/paste



commit 882296207062b2a12921fdf0c1e09216e6e08380
Author: Christian Hergert <chergert redhat com>
Date:   Fri Oct 29 15:50:12 2021 -0700

    improve yank/paste
    
    use internal command name for paste

 gtksourceview/vim/gtk-source-vim-command.c | 124 ++++++++++++++++++++++++-----
 gtksourceview/vim/gtk-source-vim-normal.c  |   5 +-
 2 files changed, 110 insertions(+), 19 deletions(-)
---
diff --git a/gtksourceview/vim/gtk-source-vim-command.c b/gtksourceview/vim/gtk-source-vim-command.c
index 134b9f1e..bf7c9f75 100644
--- a/gtksourceview/vim/gtk-source-vim-command.c
+++ b/gtksourceview/vim/gtk-source-vim-command.c
@@ -21,18 +21,24 @@
 
 #include "config.h"
 
+#include <string.h>
+
 #include "gtksourcebuffer.h"
 
 #include "gtk-source-vim-command.h"
+#include "gtk-source-vim-registers.h"
 
 typedef void (*Command) (GtkSourceVimCommand *self);
 
 struct _GtkSourceVimCommand
 {
        GtkSourceVimState   parent_instance;
+
        GtkSourceVimMotion *motion;
        GtkSourceVimMotion *selection_motion;
        char               *command;
+
+       guint               ignore_mark : 1;
 };
 
 G_DEFINE_TYPE (GtkSourceVimCommand, gtk_source_vim_command, GTK_SOURCE_TYPE_VIM_STATE)
@@ -76,20 +82,90 @@ gtk_source_vim_command_join (GtkSourceVimCommand *self)
        gtk_text_buffer_end_user_action (GTK_TEXT_BUFFER (buffer));
 
        gtk_source_vim_state_set_can_repeat (GTK_SOURCE_VIM_STATE (self), TRUE);
+
+       self->ignore_mark = TRUE;
 }
 
 static void
 gtk_source_vim_command_yank (GtkSourceVimCommand *self)
 {
+       GtkSourceVimState *registers;
+       GtkTextIter iter;
+       GtkTextIter selection;
+       gboolean needs_newline = FALSE;
+       char *text;
+
+       gtk_source_vim_state_get_buffer (GTK_SOURCE_VIM_STATE (self), &iter, &selection);
+
+       /* Swallow the \n too if we can for line-wise copy */
+       gtk_text_iter_order (&selection, &iter);
+
+       if (gtk_text_iter_ends_line (&iter))
+               gtk_text_iter_forward_char (&iter);
+
+       if (gtk_text_iter_is_end (&iter))
+               needs_newline = TRUE;
+
+       text = gtk_text_iter_get_slice (&iter, &selection);
+       registers = gtk_source_vim_state_get_registers (GTK_SOURCE_VIM_STATE (self));
+
+       if (needs_newline)
+               gtk_source_vim_registers_take (GTK_SOURCE_VIM_REGISTERS (registers),
+                                              NULL,
+                                              g_strdup_printf ("%s\n", text));
+       else
+               gtk_source_vim_registers_take (GTK_SOURCE_VIM_REGISTERS (registers),
+                                              NULL,
+                                              g_steal_pointer (&text));
+
+       g_free (text);
+}
+
+static void
+gtk_source_vim_command_paste_after (GtkSourceVimCommand *self)
+{
+       GtkSourceVimState *registers;
        GtkSourceBuffer *buffer;
-       GtkSourceView *view;
-       GdkClipboard *clipboard;
+       GtkTextIter iter;
+       GtkTextIter selection;
+       const char *text;
+       int count;
 
-       buffer = gtk_source_vim_state_get_buffer (GTK_SOURCE_VIM_STATE (self), NULL, NULL);
-       view = gtk_source_vim_state_get_view (GTK_SOURCE_VIM_STATE (self));
-       clipboard = gtk_widget_get_primary_clipboard (GTK_WIDGET (view));
+       buffer = gtk_source_vim_state_get_buffer (GTK_SOURCE_VIM_STATE (self), &iter, &selection);
+       registers = gtk_source_vim_state_get_registers (GTK_SOURCE_VIM_STATE (self));
+       text = gtk_source_vim_registers_get (GTK_SOURCE_VIM_REGISTERS (registers), NULL);
+       count = gtk_source_vim_state_get_count (GTK_SOURCE_VIM_STATE (self));
 
-       gtk_text_buffer_copy_clipboard (GTK_TEXT_BUFFER (buffer), clipboard);
+       if (text == NULL)
+       {
+               return;
+       }
+
+       gtk_text_iter_order (&selection, &iter);
+
+       gtk_source_vim_state_begin_user_action (GTK_SOURCE_VIM_STATE (self));
+
+       /* If there is a \n, this is a linewise paste */
+       if (g_str_has_suffix (text, "\n"))
+       {
+               do
+               {
+                       if (!gtk_text_iter_ends_line (&iter))
+                               gtk_text_iter_forward_to_line_end (&iter);
+
+                       gtk_text_buffer_insert (GTK_TEXT_BUFFER (buffer), &iter, "\n", -1);
+                       gtk_text_buffer_insert (GTK_TEXT_BUFFER (buffer), &iter, text, strlen (text) - 1);
+               } while (--count > 0);
+       }
+       else
+       {
+               do
+               {
+                       gtk_text_buffer_insert (GTK_TEXT_BUFFER (buffer), &iter, text, -1);
+               } while (--count > 0);
+       }
+
+       gtk_source_vim_state_end_user_action (GTK_SOURCE_VIM_STATE (self));
 }
 
 static void
@@ -140,19 +216,22 @@ static void
 gtk_source_vim_command_repeat (GtkSourceVimState *state)
 {
        GtkSourceVimCommand *self = (GtkSourceVimCommand *)state;
+       GtkSourceBuffer *buffer;
        Command command;
        GtkTextIter iter;
        GtkTextIter selection;
+       GtkTextMark *mark;
 
        g_assert (GTK_SOURCE_IS_VIM_COMMAND (self));
 
-       if (self->command == NULL)
-               return;
-
-       if (!(command = g_hash_table_lookup (commands, self->command)))
+       if (self->command == NULL ||
+           !(command = g_hash_table_lookup (commands, self->command)))
+       {
                return;
+       }
 
-       gtk_source_vim_state_get_buffer (state, &iter, &selection);
+       buffer = gtk_source_vim_state_get_buffer (state, &iter, &selection);
+       mark = gtk_text_buffer_create_mark (GTK_TEXT_BUFFER (buffer), NULL, &iter, TRUE);
 
        if (self->motion)
        {
@@ -167,6 +246,14 @@ gtk_source_vim_command_repeat (GtkSourceVimState *state)
        gtk_source_vim_state_select (state, &iter, &selection);
 
        command (self);
+
+       if (!self->ignore_mark)
+       {
+               gtk_text_buffer_get_iter_at_mark (GTK_TEXT_BUFFER (buffer), &iter, mark);
+               gtk_text_buffer_select_range (GTK_TEXT_BUFFER (buffer), &iter, &iter);
+       }
+
+       gtk_text_buffer_delete_mark (GTK_TEXT_BUFFER (buffer), mark);
 }
 
 static void
@@ -292,13 +379,14 @@ gtk_source_vim_command_class_init (GtkSourceVimCommandClass *klass)
 
 #define ADD_COMMAND(name, func) \
        g_hash_table_insert(commands, (char*)name, (gpointer)func)
-       ADD_COMMAND (":join", gtk_source_vim_command_join);
-       ADD_COMMAND (":j",    gtk_source_vim_command_join);
-       ADD_COMMAND (":undo", gtk_source_vim_command_undo);
-       ADD_COMMAND (":u",    gtk_source_vim_command_undo);
-       ADD_COMMAND (":redo", gtk_source_vim_command_redo);
-       ADD_COMMAND (":yank", gtk_source_vim_command_yank);
-       ADD_COMMAND (":y",    gtk_source_vim_command_yank);
+       ADD_COMMAND (":join",         gtk_source_vim_command_join);
+       ADD_COMMAND (":j",            gtk_source_vim_command_join);
+       ADD_COMMAND (":undo",         gtk_source_vim_command_undo);
+       ADD_COMMAND (":u",            gtk_source_vim_command_undo);
+       ADD_COMMAND (":redo",         gtk_source_vim_command_redo);
+       ADD_COMMAND (":yank",         gtk_source_vim_command_yank);
+       ADD_COMMAND (":y",            gtk_source_vim_command_yank);
+       ADD_COMMAND (":_paste_after", gtk_source_vim_command_paste_after);
 #undef ADD_COMMAND
 }
 
diff --git a/gtksourceview/vim/gtk-source-vim-normal.c b/gtksourceview/vim/gtk-source-vim-normal.c
index 3547aad3..18133c34 100644
--- a/gtksourceview/vim/gtk-source-vim-normal.c
+++ b/gtksourceview/vim/gtk-source-vim-normal.c
@@ -416,8 +416,11 @@ key_handler_command (GtkSourceVimNormal *self,
                                                             ":yank");
                        return TRUE;
 
-               case GDK_KEY_asciitilde:
                case GDK_KEY_p:
+                       gtk_source_vim_normal_begin_command (self, NULL, NULL, ":_paste_after");
+                       return TRUE;
+
+               case GDK_KEY_asciitilde:
                case GDK_KEY_P:
                case GDK_KEY_equal:
                case GDK_KEY_plus:


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