[gnome-builder] vim: add support for repeat `.'
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-builder] vim: add support for repeat `.'
- Date: Mon, 22 Dec 2014 17:32:35 +0000 (UTC)
commit 63abd3a543ee2d75f071e33bf5b32a84679c54bb
Author: Christian Hergert <christian hergert me>
Date: Mon Dec 22 09:32:21 2014 -0800
vim: add support for repeat `.'
src/vim/gb-source-vim.c | 159 ++++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 156 insertions(+), 3 deletions(-)
---
diff --git a/src/vim/gb-source-vim.c b/src/vim/gb-source-vim.c
index 67406a3..03423a5 100644
--- a/src/vim/gb-source-vim.c
+++ b/src/vim/gb-source-vim.c
@@ -79,8 +79,10 @@ struct _GbSourceVimPrivate
GtkTextMark *selection_anchor_end;
GtkSourceSearchContext *search_context;
GtkSourceSearchSettings *search_settings;
+ GPtrArray *captured_events;
GbSourceVimMode mode;
gulong key_press_event_handler;
+ gulong key_release_event_handler;
gulong focus_in_event_handler;
gulong mark_set_handler;
gulong delete_range_handler;
@@ -88,8 +90,12 @@ struct _GbSourceVimPrivate
guint stash_line;
guint stash_line_offset;
guint anim_timeout;
+ gchar recording_trigger;
+ gchar recording_modifier;
guint enabled : 1;
guint connected : 1;
+ guint recording : 1;
+ guint in_replay : 1;
};
typedef enum
@@ -214,6 +220,92 @@ gb_source_vim_new (GtkTextView *text_view)
NULL);
}
+/**
+ * gb_source_vim_recording_begin:
+ * @trigger: the character used to trigger recording
+ *
+ * This begins capturing keys so that they may be replayed later using a
+ * command such as ".". @trigger is the key that was used to begin this
+ * recording such as (A, a, i, I, s, etc).
+ *
+ * gb_source_vim_recording_end() must be called to complete the capture.
+ */
+static void
+gb_source_vim_recording_begin (GbSourceVim *vim,
+ gchar trigger,
+ gchar modifier)
+{
+ g_return_if_fail (!vim->priv->recording || vim->priv->in_replay);
+ g_return_if_fail (trigger);
+
+ if (vim->priv->in_replay)
+ return;
+
+ if (vim->priv->captured_events->len)
+ g_ptr_array_remove_range (vim->priv->captured_events, 0,
+ vim->priv->captured_events->len);
+
+ g_assert (vim->priv->captured_events->len == 0);
+
+ vim->priv->recording = TRUE;
+ vim->priv->recording_trigger = trigger;
+ vim->priv->recording_modifier = modifier;
+}
+
+static void
+gb_source_vim_recording_capture (GbSourceVim *vim,
+ GdkEvent *event)
+{
+ GdkEvent *copy;
+
+ g_return_if_fail (GB_IS_SOURCE_VIM (vim));
+ g_return_if_fail (event);
+ g_return_if_fail ((event->type == GDK_KEY_PRESS) ||
+ (event->type == GDK_KEY_RELEASE));
+
+ copy = gdk_event_copy (event);
+ g_ptr_array_add (vim->priv->captured_events, copy);
+}
+
+static void
+gb_source_vim_recording_replay (GbSourceVim *vim)
+{
+ GbSourceVimCommand *cmd;
+ guint i;
+
+ g_return_if_fail (GB_IS_SOURCE_VIM (vim));
+ g_return_if_fail (vim->priv->recording_trigger);
+ g_return_if_fail (!vim->priv->in_replay);
+
+ cmd = g_hash_table_lookup (gCommands,
+ GINT_TO_POINTER (vim->priv->recording_trigger));
+ if (!cmd)
+ return;
+
+ vim->priv->in_replay = TRUE;
+
+ cmd->func (vim, 1, vim->priv->recording_modifier);
+
+ for (i = 0; i < vim->priv->captured_events->len; i++)
+ {
+ GdkEventKey *event;
+
+ event = g_ptr_array_index (vim->priv->captured_events, i);
+ event->time = GDK_CURRENT_TIME;
+ gtk_widget_event (GTK_WIDGET (vim->priv->text_view), (GdkEvent *)event);
+ }
+
+ vim->priv->in_replay = FALSE;
+}
+
+static void
+gb_source_vim_recording_end (GbSourceVim *vim)
+{
+ g_return_if_fail (vim->priv->recording);
+
+ vim->priv->recording = FALSE;
+}
+
static int
gb_source_vim_classify (gunichar ch)
{
@@ -479,6 +571,12 @@ gb_source_vim_set_mode (GbSourceVim *vim,
if (mode == vim->priv->mode)
return;
+ /*
+ * If we are leaving insert mode, stop recording.
+ */
+ if ((vim->priv->mode == GB_SOURCE_VIM_INSERT) && vim->priv->recording)
+ gb_source_vim_recording_end (vim);
+
buffer = gtk_text_view_get_buffer (vim->priv->text_view);
/*
@@ -2943,6 +3041,9 @@ static gboolean
gb_source_vim_handle_insert (GbSourceVim *vim,
GdkEventKey *event)
{
+ if (!vim->priv->in_replay)
+ gb_source_vim_recording_capture (vim, (GdkEvent *)event);
+
switch (event->keyval)
{
case GDK_KEY_bracketleft:
@@ -3047,6 +3148,21 @@ gb_source_vim_key_press_event_cb (GtkTextView *text_view,
}
static gboolean
+gb_source_vim_key_release_event_cb (GtkTextView *text_view,
+ GdkEventKey *event,
+ GbSourceVim *vim)
+{
+ g_return_val_if_fail (GTK_IS_TEXT_VIEW (text_view), FALSE);
+ g_return_val_if_fail (event, FALSE);
+ g_return_val_if_fail (GB_IS_SOURCE_VIM (vim), FALSE);
+
+ if ((vim->priv->mode == GB_SOURCE_VIM_INSERT) && vim->priv->recording)
+ gb_source_vim_recording_capture (vim, (GdkEvent *)event);
+
+ return FALSE;
+}
+
+static gboolean
gb_source_vim_focus_in_event_cb (GtkTextView *text_view,
GdkEvent *event,
GbSourceVim *vim)
@@ -3224,6 +3340,13 @@ gb_source_vim_connect (GbSourceVim *vim)
vim,
0);
+ vim->priv->key_release_event_handler =
+ g_signal_connect_object (vim->priv->text_view,
+ "key-release-event",
+ G_CALLBACK (gb_source_vim_key_release_event_cb),
+ vim,
+ 0);
+
vim->priv->focus_in_event_handler =
g_signal_connect_object (vim->priv->text_view,
"focus-in-event",
@@ -3269,6 +3392,10 @@ gb_source_vim_disconnect (GbSourceVim *vim)
vim->priv->key_press_event_handler = 0;
g_signal_handler_disconnect (vim->priv->text_view,
+ vim->priv->key_release_event_handler);
+ vim->priv->key_release_event_handler = 0;
+
+ g_signal_handler_disconnect (vim->priv->text_view,
vim->priv->focus_in_event_handler);
vim->priv->focus_in_event_handler = 0;
@@ -3650,8 +3777,6 @@ gb_source_vim_op_set_pair (GbSourceVim *vim,
g_return_if_fail (key);
g_return_if_fail (value);
- g_print ("KEY %s VALUE %s\n", key, value);
-
if (!GTK_SOURCE_IS_VIEW (vim->priv->text_view))
return;
@@ -3820,6 +3945,8 @@ gb_source_vim_finalize (GObject *object)
g_string_free (priv->phrase, TRUE);
priv->phrase = NULL;
+ g_clear_pointer (&priv->captured_events, g_ptr_array_unref);
+
G_OBJECT_CLASS (gb_source_vim_parent_class)->finalize (object);
}
@@ -3882,7 +4009,22 @@ gb_source_vim_cmd_repeat (GbSourceVim *vim,
guint count,
gchar modifier)
{
- /* TODO! */
+ GtkSourceCompletion *completion;
+ GtkSourceView *source_view;
+
+ g_return_if_fail (GB_IS_SOURCE_VIM (vim));
+
+ if (!GTK_SOURCE_IS_VIEW (vim->priv->text_view) ||
+ !vim->priv->recording_trigger ||
+ !vim->priv->captured_events->len)
+ return;
+
+ source_view = GTK_SOURCE_VIEW (vim->priv->text_view);
+ completion = gtk_source_view_get_completion (source_view);
+
+ gtk_source_completion_block_interactive (completion);
+ gb_source_vim_recording_replay (vim);
+ gtk_source_completion_unblock_interactive (completion);
}
static void
@@ -4045,6 +4187,7 @@ gb_source_vim_cmd_insert_end (GbSourceVim *vim,
g_assert (GB_IS_SOURCE_VIM (vim));
gb_source_vim_set_mode (vim, GB_SOURCE_VIM_INSERT);
+ gb_source_vim_recording_begin (vim, 'A', modifier);
gb_source_vim_clear_selection (vim);
gb_source_vim_move_line_end (vim);
}
@@ -4057,6 +4200,7 @@ gb_source_vim_cmd_insert_after (GbSourceVim *vim,
g_assert (GB_IS_SOURCE_VIM (vim));
gb_source_vim_set_mode (vim, GB_SOURCE_VIM_INSERT);
+ gb_source_vim_recording_begin (vim, 'a', modifier);
gb_source_vim_clear_selection (vim);
gb_source_vim_move_forward (vim);
}
@@ -4093,6 +4237,7 @@ gb_source_vim_cmd_change (GbSourceVim *vim,
/* cd should do nothing */
gb_source_vim_cmd_delete (vim, count, modifier);
gb_source_vim_set_mode (vim, GB_SOURCE_VIM_INSERT);
+ gb_source_vim_recording_begin (vim, 'c', modifier);
}
}
@@ -4105,6 +4250,7 @@ gb_source_vim_cmd_change_to_end (GbSourceVim *vim,
gb_source_vim_cmd_delete_to_end (vim, count, '\0');
gb_source_vim_set_mode (vim, GB_SOURCE_VIM_INSERT);
+ gb_source_vim_recording_begin (vim, 'C', modifier);
gb_source_vim_move_forward (vim);
}
@@ -4267,6 +4413,7 @@ gb_source_vim_cmd_insert_start (GbSourceVim *vim,
g_assert (GB_IS_SOURCE_VIM (vim));
gb_source_vim_set_mode (vim, GB_SOURCE_VIM_INSERT);
+ gb_source_vim_recording_begin (vim, 'I', modifier);
gb_source_vim_clear_selection (vim);
gb_source_vim_move_line_start (vim, TRUE);
}
@@ -4279,6 +4426,7 @@ gb_source_vim_cmd_insert (GbSourceVim *vim,
g_assert (GB_IS_SOURCE_VIM (vim));
gb_source_vim_set_mode (vim, GB_SOURCE_VIM_INSERT);
+ gb_source_vim_recording_begin (vim, 'i', modifier);
gb_source_vim_clear_selection (vim);
}
@@ -4354,6 +4502,7 @@ gb_source_vim_cmd_insert_before_line (GbSourceVim *vim,
g_assert (GB_IS_SOURCE_VIM (vim));
gb_source_vim_set_mode (vim, GB_SOURCE_VIM_INSERT);
+ gb_source_vim_recording_begin (vim, 'O', modifier);
gb_source_vim_insert_nl_before (vim);
}
@@ -4365,6 +4514,7 @@ gb_source_vim_cmd_insert_after_line (GbSourceVim *vim,
g_assert (GB_IS_SOURCE_VIM (vim));
gb_source_vim_set_mode (vim, GB_SOURCE_VIM_INSERT);
+ gb_source_vim_recording_begin (vim, 'o', modifier);
gb_source_vim_insert_nl_after (vim, TRUE);
}
@@ -4402,6 +4552,7 @@ gb_source_vim_cmd_overwrite (GbSourceVim *vim,
g_assert (GB_IS_SOURCE_VIM (vim));
gb_source_vim_set_mode (vim, GB_SOURCE_VIM_INSERT);
+ gb_source_vim_recording_begin (vim, 'R', modifier);
gtk_text_view_set_overwrite (vim->priv->text_view, TRUE);
}
@@ -5036,6 +5187,8 @@ gb_source_vim_init (GbSourceVim *vim)
vim->priv->mode = 0;
vim->priv->phrase = g_string_new (NULL);
vim->priv->search_settings = gtk_source_search_settings_new ();
+ vim->priv->captured_events =
+ g_ptr_array_new_with_free_func ((GDestroyNotify)gdk_event_free);
}
GType
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]