[gnome-builder/wip/vim] vim: try to keep the cursor set on the non-EOL like VIM does.
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-builder/wip/vim] vim: try to keep the cursor set on the non-EOL like VIM does.
- Date: Tue, 30 Sep 2014 04:35:08 +0000 (UTC)
commit e16544f75263bc8a321e955761e70f5fc5ebb2d9
Author: Christian Hergert <christian hergert me>
Date: Mon Sep 29 21:33:51 2014 -0700
vim: try to keep the cursor set on the non-EOL like VIM does.
src/editor/gb-editor-vim.c | 85 ++++++++++++++++++++++++++++++++++++++-----
1 files changed, 75 insertions(+), 10 deletions(-)
---
diff --git a/src/editor/gb-editor-vim.c b/src/editor/gb-editor-vim.c
index 9acb549..0f8bd8e 100644
--- a/src/editor/gb-editor-vim.c
+++ b/src/editor/gb-editor-vim.c
@@ -30,6 +30,7 @@ struct _GbEditorVimPrivate
GtkTextView *text_view;
GbEditorVimMode mode;
guint key_press_event_handler;
+ guint mark_set_handler;
guint target_line_offset;
guint enabled : 1;
guint connected : 1;
@@ -58,14 +59,6 @@ gb_editor_vim_new (GtkTextView *text_view)
NULL);
}
-GbEditorVimMode
-gb_editor_vim_get_mode (GbEditorVim *vim)
-{
- g_return_val_if_fail (GB_IS_EDITOR_VIM (vim), 0);
-
- return vim->priv->mode;
-}
-
static guint
gb_editor_vim_get_line_offset (GbEditorVim *vim)
{
@@ -80,6 +73,14 @@ gb_editor_vim_get_line_offset (GbEditorVim *vim)
return gtk_text_iter_get_line_offset (&iter);
}
+GbEditorVimMode
+gb_editor_vim_get_mode (GbEditorVim *vim)
+{
+ g_return_val_if_fail (GB_IS_EDITOR_VIM (vim), 0);
+
+ return vim->priv->mode;
+}
+
static void
gb_editor_vim_set_mode (GbEditorVim *vim,
GbEditorVimMode mode)
@@ -88,6 +89,10 @@ gb_editor_vim_set_mode (GbEditorVim *vim,
vim->priv->mode = mode;
+ /*
+ * If we are going back to navigation mode, stash our current buffer
+ * position for use in commands like j and k.
+ */
if (mode == GB_EDITOR_VIM_NORMAL)
vim->priv->target_line_offset = gb_editor_vim_get_line_offset (vim);
@@ -98,6 +103,26 @@ gb_editor_vim_set_mode (GbEditorVim *vim,
gtk_text_view_set_overwrite (vim->priv->text_view,
(mode != GB_EDITOR_VIM_INSERT));
+ /*
+ * If we are are going to normal mode and are at the end of the line,
+ * then move back a character so we are on the last character as opposed
+ * to after it. This matches closer to VIM.
+ */
+ if (mode == GB_EDITOR_VIM_NORMAL)
+ {
+ GtkTextBuffer *buffer;
+ GtkTextMark *insert;
+ GtkTextIter iter;
+
+ buffer = gtk_text_view_get_buffer (vim->priv->text_view);
+ insert = gtk_text_buffer_get_insert (buffer);
+ gtk_text_buffer_get_iter_at_mark (buffer, &iter, insert);
+
+ if (gtk_text_iter_ends_line (&iter) && !gtk_text_iter_starts_line (&iter))
+ if (gtk_text_iter_backward_char (&iter))
+ gtk_text_buffer_select_range (buffer, &iter, &iter);
+ }
+
g_object_notify_by_pspec (G_OBJECT (vim), gParamSpecs [PROP_MODE]);
}
@@ -759,16 +784,16 @@ gb_editor_vim_handle_normal (GbEditorVim *vim,
/*
* Start insert mode at the end of the line.
*/
- gb_editor_vim_move_line_end (vim);
gb_editor_vim_set_mode (vim, GB_EDITOR_VIM_INSERT);
+ gb_editor_vim_move_line_end (vim);
return TRUE;
case GDK_KEY_a:
/*
* Start insert mode after the current character.
*/
- gb_editor_vim_move_forward (vim);
gb_editor_vim_set_mode (vim, GB_EDITOR_VIM_INSERT);
+ gb_editor_vim_move_forward (vim);
return TRUE;
case GDK_KEY_D:
@@ -1021,6 +1046,35 @@ gb_editor_vim_key_press_event_cb (GtkTextView *text_view,
}
static void
+gb_editor_vim_mark_set_cb (GtkTextBuffer *buffer,
+ GtkTextIter *iter,
+ GtkTextMark *mark,
+ GbEditorVim *vim)
+{
+ g_return_if_fail (GTK_IS_TEXT_BUFFER (buffer));
+ g_return_if_fail (iter);
+ g_return_if_fail (GTK_IS_TEXT_MARK (mark));
+ g_return_if_fail (GB_IS_EDITOR_VIM (vim));
+
+ if (vim->priv->mode == GB_EDITOR_VIM_INSERT)
+ return;
+
+ if (mark != gtk_text_buffer_get_insert (buffer))
+ return;
+
+ if (gtk_text_iter_ends_line (iter) &&
+ !gtk_text_iter_starts_line (iter) &&
+ !gtk_text_buffer_get_has_selection (buffer))
+ {
+ /*
+ * Probably want to add a canary here for dealing with reentrancy.
+ */
+ if (gtk_text_iter_backward_char (iter))
+ gtk_text_buffer_select_range (buffer, iter, iter);
+ }
+}
+
+static void
gb_editor_vim_connect (GbEditorVim *vim)
{
g_return_if_fail (GB_IS_EDITOR_VIM (vim));
@@ -1032,6 +1086,12 @@ gb_editor_vim_connect (GbEditorVim *vim)
G_CALLBACK (gb_editor_vim_key_press_event_cb),
vim);
+ vim->priv->mark_set_handler =
+ g_signal_connect (gtk_text_view_get_buffer (vim->priv->text_view),
+ "mark-set",
+ G_CALLBACK (gb_editor_vim_mark_set_cb),
+ vim);
+
gb_editor_vim_set_mode (vim, GB_EDITOR_VIM_NORMAL);
vim->priv->connected = TRUE;
@@ -1047,6 +1107,10 @@ gb_editor_vim_disconnect (GbEditorVim *vim)
vim->priv->key_press_event_handler);
vim->priv->key_press_event_handler = 0;
+ g_signal_handler_disconnect (vim->priv->text_view,
+ vim->priv->mark_set_handler);
+ vim->priv->mark_set_handler = 0;
+
vim->priv->connected = FALSE;
}
@@ -1135,6 +1199,7 @@ gb_editor_vim_finalize (GObject *object)
if (priv->text_view)
{
+ gb_editor_vim_disconnect (GB_EDITOR_VIM (object));
g_object_remove_weak_pointer (G_OBJECT (priv->text_view),
(gpointer *)&priv->text_view);
priv->text_view = NULL;
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]