[gtksourceview/wip/chergert/vim] start on some basic history recording.
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtksourceview/wip/chergert/vim] start on some basic history recording.
- Date: Thu, 28 Oct 2021 04:14:11 +0000 (UTC)
commit 02e4f3816dc41d1193d985e9bf9ebbb5667c7ef2
Author: Christian Hergert <chergert redhat com>
Date: Wed Oct 27 21:14:05 2021 -0700
start on some basic history recording.
gtksourceview/vim/gtk-source-vim-insert.c | 91 +++++++++++++++++----
gtksourceview/vim/gtk-source-vim-normal.c | 22 ++++--
gtksourceview/vim/gtk-source-vim-state.c | 10 +--
gtksourceview/vim/gtk-source-vim-text-history.c | 100 ++++++++++++++++++++++++
gtksourceview/vim/gtk-source-vim-text-history.h | 37 +++++++++
gtksourceview/vim/meson.build | 1 +
6 files changed, 236 insertions(+), 25 deletions(-)
---
diff --git a/gtksourceview/vim/gtk-source-vim-insert.c b/gtksourceview/vim/gtk-source-vim-insert.c
index 52e2b4b7..7df69a71 100644
--- a/gtksourceview/vim/gtk-source-vim-insert.c
+++ b/gtksourceview/vim/gtk-source-vim-insert.c
@@ -29,13 +29,16 @@
#include "gtk-source-vim-insert.h"
#include "gtk-source-vim-insert-literal.h"
#include "gtk-source-vim-replace.h"
+#include "gtk-source-vim-text-history.h"
struct _GtkSourceVimInsert
{
- GtkSourceVimState parent_instance;
- char *prefix;
- char *suffix;
- guint indent : 1;
+ GtkSourceVimState parent_instance;
+ GtkSourceVimTextHistory *history;
+ char *prefix;
+ char *suffix;
+ guint indent : 1;
+ guint finished : 1;
};
G_DEFINE_TYPE (GtkSourceVimInsert, gtk_source_vim_insert, GTK_SOURCE_TYPE_VIM_STATE)
@@ -97,8 +100,6 @@ gtk_source_vim_insert_handle_event (GtkSourceVimState *state,
g_assert (GTK_SOURCE_IS_VIM_INSERT (self));
g_assert (event != NULL);
- /* TODO: Eventually we'll need to stash these events for replay */
-
if (!(view = gtk_source_vim_state_get_view (state)))
return FALSE;
@@ -106,6 +107,11 @@ gtk_source_vim_insert_handle_event (GtkSourceVimState *state,
mods = gdk_event_get_modifier_state (event)
& gtk_accelerator_get_default_mod_mask ();
+ if (!gtk_source_vim_state_is_escape (keyval, mods))
+ {
+ gtk_source_vim_text_history_record (self->history, event);
+ }
+
/* Allow input methods to complete */
if (gtk_text_view_im_context_filter_keypress (GTK_TEXT_VIEW (view), event))
return TRUE;
@@ -177,19 +183,16 @@ gtk_source_vim_insert_resume (GtkSourceVimState *state,
}
static void
-gtk_source_vim_insert_enter (GtkSourceVimState *state)
+gtk_source_vim_insert_prepare (GtkSourceVimInsert *self)
{
- GtkSourceVimInsert *self = (GtkSourceVimInsert *)state;
GtkSourceBuffer *buffer;
GtkSourceView *view;
GtkTextIter iter;
g_assert (GTK_SOURCE_IS_VIM_INSERT (self));
- gtk_source_vim_state_set_overwrite (state, FALSE);
-
- view = gtk_source_vim_state_get_view (state);
- buffer = gtk_source_vim_state_get_buffer (state, &iter, NULL);
+ view = gtk_source_vim_state_get_view (GTK_SOURCE_VIM_STATE (self));
+ buffer = gtk_source_vim_state_get_buffer (GTK_SOURCE_VIM_STATE (self), &iter, NULL);
if (self->suffix)
{
@@ -199,14 +202,14 @@ gtk_source_vim_insert_enter (GtkSourceVimState *state)
{
gtk_text_buffer_insert (GTK_TEXT_BUFFER (buffer), &iter, self->suffix, -1);
gtk_text_iter_backward_chars (&iter, len);
- gtk_source_vim_state_select (state, &iter, &iter);
+ gtk_source_vim_state_select (GTK_SOURCE_VIM_STATE (self), &iter, &iter);
}
}
if (self->prefix)
{
gtk_text_buffer_insert (GTK_TEXT_BUFFER (buffer), &iter, self->prefix, -1);
- gtk_source_vim_state_select (state, &iter, &iter);
+ gtk_source_vim_state_select (GTK_SOURCE_VIM_STATE (self), &iter, &iter);
}
if (self->indent)
@@ -220,6 +223,63 @@ gtk_source_vim_insert_enter (GtkSourceVimState *state)
}
}
+static void
+gtk_source_vim_insert_enter (GtkSourceVimState *state)
+{
+ GtkSourceVimInsert *self = (GtkSourceVimInsert *)state;
+
+ g_assert (GTK_SOURCE_IS_VIM_INSERT (self));
+
+ 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);
+
+ gtk_source_vim_insert_prepare (self);
+}
+
+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));
+
+ 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);
+}
+
+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));
+ 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);
+}
+
static void
gtk_source_vim_insert_append_command (GtkSourceVimState *state,
GString *string)
@@ -288,6 +348,7 @@ gtk_source_vim_insert_dispose (GObject *object)
GtkSourceVimInsert *self = (GtkSourceVimInsert *)object;
g_clear_pointer (&self->prefix, g_free);
+ g_clear_object (&self->history);
G_OBJECT_CLASS (gtk_source_vim_insert_parent_class)->dispose (object);
}
@@ -307,6 +368,8 @@ gtk_source_vim_insert_class_init (GtkSourceVimInsertClass *klass)
state_class->handle_event = gtk_source_vim_insert_handle_event;
state_class->resume = gtk_source_vim_insert_resume;
state_class->enter = gtk_source_vim_insert_enter;
+ state_class->leave = gtk_source_vim_insert_leave;
+ state_class->repeat = gtk_source_vim_insert_repeat;
properties [PROP_INDENT] =
g_param_spec_boolean ("indent",
diff --git a/gtksourceview/vim/gtk-source-vim-normal.c b/gtksourceview/vim/gtk-source-vim-normal.c
index d8b4ad36..c3227167 100644
--- a/gtksourceview/vim/gtk-source-vim-normal.c
+++ b/gtksourceview/vim/gtk-source-vim-normal.c
@@ -183,7 +183,9 @@ gtk_source_vim_normal_begin_delete (GtkSourceVimNormal *self,
del = gtk_source_vim_delete_new (GTK_SOURCE_VIM_MOTION (motion));
+ gtk_source_vim_state_set_count (del, self->count);
gtk_source_vim_state_push (GTK_SOURCE_VIM_STATE (self), del);
+
if (motion != NULL)
gtk_source_vim_state_pop (del);
}
@@ -199,11 +201,13 @@ gtk_source_vim_normal_begin_change (GtkSourceVimNormal *self,
const char *first_property_name;
GtkTextIter iter, selection;
va_list args;
+ int count;
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);
+ count = self->count;
gtk_text_buffer_begin_user_action (GTK_TEXT_BUFFER (buffer));
@@ -225,6 +229,7 @@ gtk_source_vim_normal_begin_change (GtkSourceVimNormal *self,
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_set_count (ret, count);
gtk_source_vim_state_push (GTK_SOURCE_VIM_STATE (self), ret);
gtk_text_buffer_end_user_action (GTK_TEXT_BUFFER (buffer));
@@ -250,10 +255,13 @@ gtk_source_vim_normal_begin_insert (GtkSourceVimNormal *self,
GtkSourceVimState *ret;
const char *first_property_name;
va_list args;
+ int count;
g_assert (GTK_SOURCE_IS_VIM_NORMAL (self));
g_assert (!motion || GTK_SOURCE_IS_VIM_MOTION (motion));
+ count = self->count;
+
if (motion != NULL)
{
gtk_source_vim_state_push (GTK_SOURCE_VIM_STATE (self), motion);
@@ -282,6 +290,7 @@ gtk_source_vim_normal_begin_insert (GtkSourceVimNormal *self,
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_set_count (ret, count);
gtk_source_vim_state_push (GTK_SOURCE_VIM_STATE (self), ret);
return ret;
@@ -294,12 +303,16 @@ key_handler_command (GtkSourceVimNormal *self,
GdkModifierType mods,
const char *string)
{
+ GtkSourceVimState *new_state;
+
g_assert (GTK_SOURCE_IS_VIM_NORMAL (self));
switch (keyval)
{
case GDK_KEY_R:
- gtk_source_vim_state_push (GTK_SOURCE_VIM_STATE (self), gtk_source_vim_replace_new
());
+ new_state = gtk_source_vim_replace_new ();
+ gtk_source_vim_state_set_count (new_state, self->count);
+ gtk_source_vim_state_push (GTK_SOURCE_VIM_STATE (self), new_state);
return TRUE;
case GDK_KEY_i:
@@ -617,6 +630,7 @@ key_handler_g (GtkSourceVimNormal *self,
case GDK_KEY_e:
case GDK_KEY_E:
new_state = gtk_source_vim_motion_new ();
+ gtk_source_vim_state_set_count (new_state, self->count);
gtk_source_vim_state_push (GTK_SOURCE_VIM_STATE (self), new_state);
gtk_source_vim_state_synthesize (new_state, GDK_KEY_g, 0);
gtk_source_vim_state_synthesize (new_state, keyval, mods);
@@ -639,6 +653,7 @@ key_handler_motion (GtkSourceVimNormal *self,
g_assert (GTK_SOURCE_IS_VIM_NORMAL (self));
new_state = gtk_source_vim_motion_new ();
+ gtk_source_vim_state_set_count (new_state, self->count);
gtk_source_vim_state_push (GTK_SOURCE_VIM_STATE (self), new_state);
gtk_source_vim_state_synthesize (new_state, keyval, mods);
@@ -899,11 +914,6 @@ gtk_source_vim_normal_suspend (GtkSourceVimState *state,
g_assert (GTK_SOURCE_IS_VIM_NORMAL (self));
g_assert (GTK_SOURCE_IS_VIM_STATE (to));
- if (self->count)
- {
- gtk_source_vim_state_set_count (to, self->count);
- }
-
buffer = gtk_source_vim_state_get_buffer (state, NULL, NULL);
gtk_text_buffer_begin_user_action (GTK_TEXT_BUFFER (buffer));
}
diff --git a/gtksourceview/vim/gtk-source-vim-state.c b/gtksourceview/vim/gtk-source-vim-state.c
index ba03fd96..9228d698 100644
--- a/gtksourceview/vim/gtk-source-vim-state.c
+++ b/gtksourceview/vim/gtk-source-vim-state.c
@@ -444,11 +444,6 @@ gtk_source_vim_state_pop (GtkSourceVimState *self)
GTK_SOURCE_VIM_STATE_GET_CLASS (self)->leave (self);
}
- if (GTK_SOURCE_VIM_STATE_GET_CLASS (parent)->resume)
- {
- GTK_SOURCE_VIM_STATE_GET_CLASS (parent)->resume (parent, self);
- }
-
/* Clear the parent's child pointer, since we are no longer the
* active event delivery child. However, the parent can still keep
* a reference around elsewhere if they like for replaying things.
@@ -458,6 +453,11 @@ gtk_source_vim_state_pop (GtkSourceVimState *self)
parent_priv->child = NULL;
}
+ if (GTK_SOURCE_VIM_STATE_GET_CLASS (parent)->resume)
+ {
+ GTK_SOURCE_VIM_STATE_GET_CLASS (parent)->resume (parent, self);
+ }
+
g_clear_object (&parent);
g_object_unref (self);
}
diff --git a/gtksourceview/vim/gtk-source-vim-text-history.c b/gtksourceview/vim/gtk-source-vim-text-history.c
new file mode 100644
index 00000000..fa0f1738
--- /dev/null
+++ b/gtksourceview/vim/gtk-source-vim-text-history.c
@@ -0,0 +1,100 @@
+/*
+ * This file is part of GtkSourceView
+ *
+ * Copyright 2021 Christian Hergert <chergert redhat com>
+ *
+ * GtkSourceView is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * GtkSourceView is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#include "config.h"
+
+#include "gtk-source-vim-text-history.h"
+
+struct _GtkSourceVimTextHistory
+{
+ GObject parent_instance;
+ GPtrArray *events;
+};
+
+G_DEFINE_TYPE (GtkSourceVimTextHistory, gtk_source_vim_text_history, GTK_SOURCE_TYPE_VIM_STATE)
+
+GtkSourceVimState *
+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_dispose (GObject *object)
+{
+ GtkSourceVimTextHistory *self = (GtkSourceVimTextHistory *)object;
+
+ g_clear_pointer (&self->events, g_ptr_array_unref);
+
+ G_OBJECT_CLASS (gtk_source_vim_text_history_parent_class)->dispose (object);
+}
+
+static void
+gtk_source_vim_text_history_class_init (GtkSourceVimTextHistoryClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->dispose = gtk_source_vim_text_history_dispose;
+}
+
+static void
+gtk_source_vim_text_history_init (GtkSourceVimTextHistory *self)
+{
+ self->events = g_ptr_array_new_with_free_func ((GDestroyNotify)gdk_event_unref);
+}
+
+void
+gtk_source_vim_text_history_record (GtkSourceVimTextHistory *self,
+ GdkEvent *event)
+{
+ 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));
+}
+
+void
+gtk_source_vim_text_history_replay (GtkSourceVimTextHistory *self)
+{
+ static guint signal_id;
+ GtkSourceView *view;
+ GdkSurface *surface;
+ GtkNative *native;
+
+ g_return_if_fail (GTK_SOURCE_IS_VIM_TEXT_HISTORY (self));
+
+ if (signal_id == 0)
+ {
+ signal_id = g_signal_lookup ("event", GDK_TYPE_SURFACE);
+ }
+
+ 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);
+
+ for (guint i = 0; i < self->events->len; i++)
+ {
+ GdkEvent *event = g_ptr_array_index (self->events, i);
+ gboolean ret;
+
+ g_signal_emit (surface, signal_id, 0, event, &ret);
+ }
+}
diff --git a/gtksourceview/vim/gtk-source-vim-text-history.h b/gtksourceview/vim/gtk-source-vim-text-history.h
new file mode 100644
index 00000000..de56daec
--- /dev/null
+++ b/gtksourceview/vim/gtk-source-vim-text-history.h
@@ -0,0 +1,37 @@
+/*
+ * This file is part of GtkSourceView
+ *
+ * Copyright 2021 Christian Hergert <chergert redhat com>
+ *
+ * GtkSourceView is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * GtkSourceView is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#pragma once
+
+#include "gtk-source-vim-state.h"
+
+G_BEGIN_DECLS
+
+#define GTK_SOURCE_TYPE_VIM_TEXT_HISTORY (gtk_source_vim_text_history_get_type())
+
+G_DECLARE_FINAL_TYPE (GtkSourceVimTextHistory, gtk_source_vim_text_history, GTK_SOURCE, VIM_TEXT_HISTORY,
GtkSourceVimState)
+
+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);
+
+G_END_DECLS
diff --git a/gtksourceview/vim/meson.build b/gtksourceview/vim/meson.build
index a9985840..b164ce2a 100644
--- a/gtksourceview/vim/meson.build
+++ b/gtksourceview/vim/meson.build
@@ -8,4 +8,5 @@ vim_sources = files([
'gtk-source-vim-insert-literal.c',
'gtk-source-vim-replace.c',
'gtk-source-vim-state.c',
+ 'gtk-source-vim-text-history.c',
])
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]