[gtksourceview/wip/chergert/vim: 188/363] implement history without commands
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtksourceview/wip/chergert/vim: 188/363] implement history without commands
- Date: Mon, 8 Nov 2021 19:53:50 +0000 (UTC)
commit 7113baf4998a333dc30c24d7c292575cc836d9f7
Author: Christian Hergert <chergert redhat com>
Date: Mon Nov 1 17:06:18 2021 -0700
implement history without commands
we actually want truncatd history as if you move around while in insert
mode we should be truncating what gets replayed.
gtksourceview/vim/gtk-source-vim-insert.c | 46 ++----
gtksourceview/vim/gtk-source-vim-text-history.c | 205 +++++++++++++++++++++---
gtksourceview/vim/gtk-source-vim-text-history.h | 4 +-
3 files changed, 197 insertions(+), 58 deletions(-)
---
diff --git a/gtksourceview/vim/gtk-source-vim-insert.c b/gtksourceview/vim/gtk-source-vim-insert.c
index 38506a64..1a52dc6a 100644
--- a/gtksourceview/vim/gtk-source-vim-insert.c
+++ b/gtksourceview/vim/gtk-source-vim-insert.c
@@ -95,33 +95,9 @@ static gboolean
gtk_source_vim_insert_capture (GtkSourceVimState *state,
GdkEvent *event)
{
- GtkSourceVimInsert *self = (GtkSourceVimInsert *)state;
- GtkSourceVimState *child;
- GdkModifierType mods;
- guint keyval;
-
- g_assert (GTK_SOURCE_IS_VIM_INSERT (self));
+ g_assert (GTK_SOURCE_IS_VIM_INSERT (state));
g_assert (event != NULL);
- if (self->finished)
- {
- return FALSE;
- }
-
- child = gtk_source_vim_state_get_child (state);
- keyval = gdk_key_event_get_keyval (event);
- mods = gdk_event_get_modifier_state (event)
- & gtk_accelerator_get_default_mod_mask ();
-
- if (child != NULL)
- {
- gtk_source_vim_text_history_record (self->history, event);
- }
- else if (!gtk_source_vim_state_is_escape (keyval, mods))
- {
- gtk_source_vim_text_history_record (self->history, event);
- }
-
return FALSE;
}
@@ -315,32 +291,34 @@ gtk_source_vim_insert_enter (GtkSourceVimState *state)
gtk_source_vim_state_set_overwrite (state, FALSE);
g_clear_object (&self->history);
- self->history = g_object_new (GTK_SOURCE_TYPE_VIM_TEXT_HISTORY, NULL);
+ self->history = g_object_new (GTK_SOURCE_TYPE_VIM_TEXT_HISTORY,
+ "parent", self,
+ NULL);
gtk_source_vim_insert_prepare (self);
+
+ gtk_source_vim_text_history_begin (self->history);
}
static void
gtk_source_vim_insert_leave (GtkSourceVimState *state)
{
GtkSourceVimInsert *self = (GtkSourceVimInsert *)state;
- GtkSourceVimState *history;
int count;
g_assert (GTK_SOURCE_IS_VIM_INSERT (self));
self->finished = TRUE;
+ gtk_source_vim_text_history_end (self->history);
+
count = gtk_source_vim_state_get_count (state);
- history = GTK_SOURCE_VIM_STATE (self->history);
- gtk_source_vim_state_push (state, g_object_ref (history));
while (--count > 0)
{
gtk_source_vim_insert_prepare (self);
gtk_source_vim_text_history_replay (self->history);
}
- gtk_source_vim_state_pop (history);
gtk_source_vim_state_end_user_action (state);
}
@@ -349,21 +327,21 @@ static void
gtk_source_vim_insert_repeat (GtkSourceVimState *state)
{
GtkSourceVimInsert *self = (GtkSourceVimInsert *)state;
- GtkSourceVimState *history;
int count;
g_assert (GTK_SOURCE_IS_VIM_INSERT (self));
count = gtk_source_vim_state_get_count (state);
- history = GTK_SOURCE_VIM_STATE (self->history);
- gtk_source_vim_state_push (state, g_object_ref (history));
+ gtk_source_vim_state_begin_user_action (state);
+
for (int i = 0; i < count; i++)
{
gtk_source_vim_insert_prepare (self);
gtk_source_vim_text_history_replay (self->history);
}
- gtk_source_vim_state_pop (history);
+
+ gtk_source_vim_state_end_user_action (state);
}
static void
diff --git a/gtksourceview/vim/gtk-source-vim-text-history.c b/gtksourceview/vim/gtk-source-vim-text-history.c
index fa0f1738..ece86630 100644
--- a/gtksourceview/vim/gtk-source-vim-text-history.c
+++ b/gtksourceview/vim/gtk-source-vim-text-history.c
@@ -21,12 +21,30 @@
#include "config.h"
+#include "gtksourcebuffer.h"
+
#include "gtk-source-vim-text-history.h"
+typedef enum
+{
+ OP_INSERT,
+ OP_DELETE,
+ OP_BACKSPACE,
+} OpKind;
+
+typedef struct
+{
+ OpKind kind : 2;
+ guint length : 30;
+ guint offset;
+} Op;
+
struct _GtkSourceVimTextHistory
{
GObject parent_instance;
- GPtrArray *events;
+ GArray *ops;
+ GString *bytes;
+ int cursor_position;
};
G_DEFINE_TYPE (GtkSourceVimTextHistory, gtk_source_vim_text_history, GTK_SOURCE_TYPE_VIM_STATE)
@@ -37,12 +55,110 @@ gtk_source_vim_text_history_new (void)
return g_object_new (GTK_SOURCE_TYPE_VIM_TEXT_HISTORY, NULL);
}
+static void
+gtk_source_vim_text_history_truncate (GtkSourceVimTextHistory *self)
+{
+ g_assert (GTK_SOURCE_IS_VIM_TEXT_HISTORY (self));
+
+ g_string_truncate (self->bytes, 0);
+
+ if (self->ops->len > 0)
+ {
+ g_array_remove_range (self->ops, 0, self->ops->len);
+ }
+}
+
+static void
+gtk_source_vim_text_history_insert_text_cb (GtkSourceVimTextHistory *self,
+ const GtkTextIter *iter,
+ const char *text,
+ int len,
+ GtkSourceBuffer *buffer)
+{
+ guint position;
+ Op op;
+
+ g_assert (GTK_SOURCE_IS_VIM_TEXT_HISTORY (self));
+ g_assert (GTK_SOURCE_IS_BUFFER (buffer));
+ g_assert (iter != NULL);
+ g_assert (gtk_text_iter_get_buffer (iter) == GTK_TEXT_BUFFER (buffer));
+ g_assert (text != NULL);
+
+ if (len == 0)
+ return;
+
+ position = gtk_text_iter_get_offset (iter);
+
+ if ((int)position != self->cursor_position)
+ {
+ gtk_source_vim_text_history_truncate (self);
+ }
+
+ op.kind = OP_INSERT;
+ op.length = g_utf8_strlen (text, len);
+ op.offset = self->bytes->len;
+
+ g_string_append_len (self->bytes, text, len);
+ g_array_append_val (self->ops, op);
+
+ self->cursor_position = position + op.length;
+}
+
+static void
+gtk_source_vim_text_history_delete_range_cb (GtkSourceVimTextHistory *self,
+ const GtkTextIter *begin,
+ const GtkTextIter *end,
+ GtkSourceBuffer *buffer)
+{
+ GtkTextIter a, b;
+ Op op;
+
+ g_assert (GTK_SOURCE_IS_VIM_TEXT_HISTORY (self));
+ g_assert (GTK_SOURCE_IS_BUFFER (buffer));
+ g_assert (begin != NULL);
+ g_assert (end != NULL);
+ g_assert (gtk_text_iter_get_buffer (begin) == gtk_text_iter_get_buffer (end));
+
+ if (gtk_text_iter_get_offset (begin) == gtk_text_iter_get_offset (end))
+ return;
+
+ a = *begin;
+ b = *end;
+ gtk_text_iter_order (&a, &b);
+
+ op.length = (int)gtk_text_iter_get_offset (&b) - (int)gtk_text_iter_get_offset (&a);
+ op.offset = 0;
+
+ if (gtk_text_iter_get_offset (&a) == self->cursor_position)
+ {
+ op.kind = OP_DELETE;
+ }
+ else if (gtk_text_iter_get_offset (&b) == self->cursor_position)
+ {
+ op.kind = OP_BACKSPACE;
+ }
+ else
+ {
+ gtk_source_vim_text_history_truncate (self);
+ }
+
+ self->cursor_position = gtk_text_iter_get_offset (&a);
+
+ g_array_append_val (self->ops, op);
+}
+
static void
gtk_source_vim_text_history_dispose (GObject *object)
{
GtkSourceVimTextHistory *self = (GtkSourceVimTextHistory *)object;
- g_clear_pointer (&self->events, g_ptr_array_unref);
+ g_clear_pointer (&self->ops, g_array_unref);
+
+ if (self->bytes)
+ {
+ g_string_free (self->bytes, TRUE);
+ self->bytes = NULL;
+ }
G_OBJECT_CLASS (gtk_source_vim_text_history_parent_class)->dispose (object);
}
@@ -58,43 +174,88 @@ gtk_source_vim_text_history_class_init (GtkSourceVimTextHistoryClass *klass)
static void
gtk_source_vim_text_history_init (GtkSourceVimTextHistory *self)
{
- self->events = g_ptr_array_new_with_free_func ((GDestroyNotify)gdk_event_unref);
+ self->bytes = g_string_new (NULL);
+ self->ops = g_array_new (FALSE, FALSE, sizeof (Op));
}
void
-gtk_source_vim_text_history_record (GtkSourceVimTextHistory *self,
- GdkEvent *event)
+gtk_source_vim_text_history_begin (GtkSourceVimTextHistory *self)
{
+ GtkSourceBuffer *buffer;
+
g_return_if_fail (GTK_SOURCE_IS_VIM_TEXT_HISTORY (self));
- g_return_if_fail (event != NULL);
- g_ptr_array_add (self->events, gdk_event_ref (event));
+ buffer = gtk_source_vim_state_get_buffer (GTK_SOURCE_VIM_STATE (self), NULL, NULL);
+
+ g_signal_connect_object (buffer,
+ "insert-text",
+ G_CALLBACK (gtk_source_vim_text_history_insert_text_cb),
+ self,
+ G_CONNECT_SWAPPED);
+
+ g_signal_connect_object (buffer,
+ "delete-range",
+ G_CALLBACK (gtk_source_vim_text_history_delete_range_cb),
+ self,
+ G_CONNECT_SWAPPED);
+}
+
+void
+gtk_source_vim_text_history_end (GtkSourceVimTextHistory *self)
+{
+ GtkSourceBuffer *buffer;
+
+ g_return_if_fail (GTK_SOURCE_IS_VIM_TEXT_HISTORY (self));
+
+ buffer = gtk_source_vim_state_get_buffer (GTK_SOURCE_VIM_STATE (self), NULL, NULL);
+
+ g_signal_handlers_disconnect_by_func (buffer,
+ G_CALLBACK (gtk_source_vim_text_history_insert_text_cb),
+ self);
+ g_signal_handlers_disconnect_by_func (buffer,
+ G_CALLBACK (gtk_source_vim_text_history_delete_range_cb),
+ self);
}
void
gtk_source_vim_text_history_replay (GtkSourceVimTextHistory *self)
{
- static guint signal_id;
- GtkSourceView *view;
- GdkSurface *surface;
- GtkNative *native;
+ GtkSourceBuffer *buffer;
+ GtkTextIter iter;
+ GtkTextIter end;
+ const char *str;
+ int len;
g_return_if_fail (GTK_SOURCE_IS_VIM_TEXT_HISTORY (self));
- if (signal_id == 0)
+ buffer = gtk_source_vim_state_get_buffer (GTK_SOURCE_VIM_STATE (self), &iter, NULL);
+
+ for (guint i = 0; i < self->ops->len; i++)
{
- signal_id = g_signal_lookup ("event", GDK_TYPE_SURFACE);
- }
+ const Op *op = &g_array_index (self->ops, Op, i);
- view = gtk_source_vim_state_get_view (GTK_SOURCE_VIM_STATE (self));
- native = gtk_widget_get_native (GTK_WIDGET (view));
- surface = gtk_native_get_surface (native);
+ switch (op->kind)
+ {
+ case OP_INSERT:
+ str = self->bytes->str + op->offset;
+ len = g_utf8_offset_to_pointer (str, op->length) - str;
+ gtk_text_buffer_insert (GTK_TEXT_BUFFER (buffer), &iter, str, len);
+ break;
- for (guint i = 0; i < self->events->len; i++)
- {
- GdkEvent *event = g_ptr_array_index (self->events, i);
- gboolean ret;
+ case OP_DELETE:
+ end = iter;
+ gtk_text_iter_forward_chars (&end, op->length);
+ gtk_text_buffer_delete (GTK_TEXT_BUFFER (buffer), &iter, &end);
+ break;
+
+ case OP_BACKSPACE:
+ end = iter;
+ gtk_text_iter_backward_chars (&end, op->length);
+ gtk_text_buffer_delete (GTK_TEXT_BUFFER (buffer), &iter, &end);
+ break;
- g_signal_emit (surface, signal_id, 0, event, &ret);
+ default:
+ g_assert_not_reached ();
+ }
}
}
diff --git a/gtksourceview/vim/gtk-source-vim-text-history.h b/gtksourceview/vim/gtk-source-vim-text-history.h
index de56daec..e64db007 100644
--- a/gtksourceview/vim/gtk-source-vim-text-history.h
+++ b/gtksourceview/vim/gtk-source-vim-text-history.h
@@ -31,7 +31,7 @@ G_DECLARE_FINAL_TYPE (GtkSourceVimTextHistory, gtk_source_vim_text_history, GTK_
GtkSourceVimState *gtk_source_vim_text_history_new (void);
void gtk_source_vim_text_history_replay (GtkSourceVimTextHistory *self);
-void gtk_source_vim_text_history_record (GtkSourceVimTextHistory *self,
- GdkEvent *event);
+void gtk_source_vim_text_history_begin (GtkSourceVimTextHistory *self);
+void gtk_source_vim_text_history_end (GtkSourceVimTextHistory *self);
G_END_DECLS
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]