[gtksourceview/wip/chergert/vim: 94/293] start on line changes
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtksourceview/wip/chergert/vim: 94/293] start on line changes
- Date: Fri, 5 Nov 2021 04:22:59 +0000 (UTC)
commit 911d108ad2e0655782c3dc5a15d53ed7b407dcbb
Author: Christian Hergert <chergert redhat com>
Date: Wed Oct 27 12:19:24 2021 -0700
start on line changes
requires doing some inclusive/exclusive work which i dont love. however as
we get to linewise/block stuff, that will likely affect how we implement it
and i dont want to do that prematurely.
gtksourceview/vim/gtk-source-vim-motion.c | 108 +++++++++++++++++++++---------
gtksourceview/vim/gtk-source-vim-motion.h | 3 +-
gtksourceview/vim/gtk-source-vim-normal.c | 60 ++++++++++++++++-
3 files changed, 134 insertions(+), 37 deletions(-)
---
diff --git a/gtksourceview/vim/gtk-source-vim-motion.c b/gtksourceview/vim/gtk-source-vim-motion.c
index 0e201d34..37b73392 100644
--- a/gtksourceview/vim/gtk-source-vim-motion.c
+++ b/gtksourceview/vim/gtk-source-vim-motion.c
@@ -28,6 +28,11 @@
typedef gboolean (*Motion) (GtkTextIter *iter,
GtkSourceVimMotion *state);
+typedef enum {
+ INCLUSIVE = 0,
+ EXCLUSIVE = 1,
+} Inclusivity;
+
struct _GtkSourceVimMotion
{
GtkSourceVimState parent_instance;
@@ -58,6 +63,9 @@ struct _GtkSourceVimMotion
/* If we just did f/F and need another char */
guint waiting_for_f_char : 1;
+
+ /* If the motion is exclusive (does not include char) */
+ guint inclusivity : 1;
};
G_DEFINE_TYPE (GtkSourceVimMotion, gtk_source_vim_motion, GTK_SOURCE_TYPE_VIM_STATE)
@@ -578,7 +586,9 @@ motion_line_end (GtkTextIter *iter,
{
GtkTextIter begin = *iter;
- gtk_text_iter_forward_to_line_end (iter);
+ if (!gtk_text_iter_ends_line (iter))
+ gtk_text_iter_forward_to_line_end (iter);
+
if (!gtk_text_iter_starts_line (iter))
gtk_text_iter_backward_char (iter);
@@ -1023,11 +1033,14 @@ gtk_source_vim_motion_bail (GtkSourceVimMotion *self)
static gboolean
gtk_source_vim_motion_complete (GtkSourceVimMotion *self,
- Motion motion)
+ Motion motion,
+ Inclusivity inclusivity)
{
g_assert (GTK_SOURCE_IS_VIM_MOTION (self));
self->motion = motion;
+ self->inclusivity = inclusivity;
+
g_string_truncate (self->command_text, 0);
gtk_source_vim_state_pop (GTK_SOURCE_VIM_STATE (self));
@@ -1063,13 +1076,13 @@ gtk_source_vim_motion_handle_keypress (GtkSourceVimState *state,
switch (keyval)
{
case GDK_KEY_g:
- return gtk_source_vim_motion_complete (self, motion_buffer_start_first_char);
+ return gtk_source_vim_motion_complete (self, motion_buffer_start_first_char,
INCLUSIVE);
case GDK_KEY_e:
- return gtk_source_vim_motion_complete (self, motion_backward_word_end);
+ return gtk_source_vim_motion_complete (self, motion_backward_word_end,
EXCLUSIVE);
case GDK_KEY_E:
- return gtk_source_vim_motion_complete (self, motion_backward_WORD_end);
+ return gtk_source_vim_motion_complete (self, motion_backward_WORD_end,
EXCLUSIVE);
default:
return gtk_source_vim_motion_bail (self);
@@ -1093,7 +1106,7 @@ gtk_source_vim_motion_handle_keypress (GtkSourceVimState *state,
case GDK_KEY_KP_0:
case GDK_KEY_Home:
case GDK_KEY_bar:
- return gtk_source_vim_motion_complete (self, motion_line_start);
+ return gtk_source_vim_motion_complete (self, motion_line_start, INCLUSIVE);
case GDK_KEY_1: case GDK_KEY_KP_1:
case GDK_KEY_2: case GDK_KEY_KP_2:
@@ -1112,94 +1125,96 @@ gtk_source_vim_motion_handle_keypress (GtkSourceVimState *state,
case GDK_KEY_asciicircum:
case GDK_KEY_underscore:
- return gtk_source_vim_motion_complete (self, motion_line_first_char);
+ return gtk_source_vim_motion_complete (self, motion_line_first_char, INCLUSIVE);
case GDK_KEY_space:
- return gtk_source_vim_motion_complete (self, motion_forward_char);
+ return gtk_source_vim_motion_complete (self, motion_forward_char, EXCLUSIVE);
case GDK_KEY_BackSpace:
- return gtk_source_vim_motion_complete (self, motion_backward_char);
+ return gtk_source_vim_motion_complete (self, motion_backward_char, INCLUSIVE);
case GDK_KEY_Left:
case GDK_KEY_h:
- return gtk_source_vim_motion_complete (self, motion_backward_char_same_line);
+ return gtk_source_vim_motion_complete (self, motion_backward_char_same_line,
INCLUSIVE);
case GDK_KEY_Right:
case GDK_KEY_l:
- return gtk_source_vim_motion_complete (self, motion_forward_char_same_line);
+ return gtk_source_vim_motion_complete (self, motion_forward_char_same_line,
EXCLUSIVE);
case GDK_KEY_ISO_Enter:
case GDK_KEY_KP_Enter:
case GDK_KEY_Return:
- return gtk_source_vim_motion_complete (self, motion_next_line_first_char);
+ return gtk_source_vim_motion_complete (self, motion_next_line_first_char, EXCLUSIVE);
case GDK_KEY_End:
case GDK_KEY_dollar:
- return gtk_source_vim_motion_complete (self, motion_line_end);
+ return gtk_source_vim_motion_complete (self, motion_line_end, EXCLUSIVE);
case GDK_KEY_Down:
case GDK_KEY_j:
- return gtk_source_vim_motion_complete (self, motion_next_line_visual_column);
+ return gtk_source_vim_motion_complete (self, motion_next_line_visual_column,
EXCLUSIVE);
case GDK_KEY_Up:
case GDK_KEY_k:
- return gtk_source_vim_motion_complete (self, motion_prev_line_visual_column);
+ return gtk_source_vim_motion_complete (self, motion_prev_line_visual_column,
INCLUSIVE);
case GDK_KEY_G:
- return gtk_source_vim_motion_complete (self, motion_last_line_first_char);
+ return gtk_source_vim_motion_complete (self, motion_last_line_first_char, EXCLUSIVE);
case GDK_KEY_g:
self->g_command = TRUE;
return TRUE;
case GDK_KEY_H:
- return gtk_source_vim_motion_complete (self, motion_screen_top);
+ return gtk_source_vim_motion_complete (self, motion_screen_top, INCLUSIVE);
case GDK_KEY_M:
- return gtk_source_vim_motion_complete (self, motion_screen_middle);
+ return gtk_source_vim_motion_complete (self, motion_screen_middle, INCLUSIVE);
case GDK_KEY_L:
- return gtk_source_vim_motion_complete (self, motion_screen_bottom);
+ return gtk_source_vim_motion_complete (self, motion_screen_bottom, INCLUSIVE);
case GDK_KEY_w:
- return gtk_source_vim_motion_complete (self, motion_forward_word_start);
+ return gtk_source_vim_motion_complete (self, motion_forward_word_start, EXCLUSIVE);
case GDK_KEY_W:
- return gtk_source_vim_motion_complete (self, motion_forward_WORD_start);
+ return gtk_source_vim_motion_complete (self, motion_forward_WORD_start, EXCLUSIVE);
case GDK_KEY_b:
- return gtk_source_vim_motion_complete (self, motion_backward_word_start);
+ return gtk_source_vim_motion_complete (self, motion_backward_word_start, INCLUSIVE);
case GDK_KEY_B:
- return gtk_source_vim_motion_complete (self, motion_backward_WORD_start);
+ return gtk_source_vim_motion_complete (self, motion_backward_WORD_start, INCLUSIVE);
case GDK_KEY_e:
- return gtk_source_vim_motion_complete (self, motion_forward_word_end);
+ return gtk_source_vim_motion_complete (self, motion_forward_word_end, INCLUSIVE);
case GDK_KEY_E:
- return gtk_source_vim_motion_complete (self, motion_forward_WORD_end);
+ return gtk_source_vim_motion_complete (self, motion_forward_WORD_end, INCLUSIVE);
case GDK_KEY_f:
self->waiting_for_f_char = TRUE;
self->motion = motion_f_char;
+ self->inclusivity = EXCLUSIVE;
return TRUE;
case GDK_KEY_F:
self->waiting_for_f_char = TRUE;
self->motion = motion_F_char;
+ self->inclusivity = INCLUSIVE;
return TRUE;
case GDK_KEY_parenleft:
- return gtk_source_vim_motion_complete (self, motion_backward_sentence_start);
+ return gtk_source_vim_motion_complete (self, motion_backward_sentence_start,
INCLUSIVE);
case GDK_KEY_parenright:
- return gtk_source_vim_motion_complete (self, motion_forward_sentence_start);
+ return gtk_source_vim_motion_complete (self, motion_forward_sentence_start,
EXCLUSIVE);
case GDK_KEY_braceleft:
- return gtk_source_vim_motion_complete (self, motion_backward_paragraph_start);
+ return gtk_source_vim_motion_complete (self, motion_backward_paragraph_start,
INCLUSIVE);
case GDK_KEY_braceright:
- return gtk_source_vim_motion_complete (self, motion_forward_paragraph_end);
+ return gtk_source_vim_motion_complete (self, motion_forward_paragraph_end, EXCLUSIVE);
case GDK_KEY_n:
case GDK_KEY_N:
@@ -1235,7 +1250,7 @@ gtk_source_vim_motion_repeat (GtkSourceVimState *state,
do
{
- if (!gtk_source_vim_motion_apply (self, &insert))
+ if (!gtk_source_vim_motion_apply (self, &insert, FALSE))
{
break;
}
@@ -1313,8 +1328,12 @@ gtk_source_vim_motion_init (GtkSourceVimMotion *self)
gboolean
gtk_source_vim_motion_apply (GtkSourceVimMotion *self,
- GtkTextIter *iter)
+ GtkTextIter *iter,
+ gboolean apply_inclusive)
{
+ gboolean ret = FALSE;
+ guint begin_offset;
+
g_return_val_if_fail (GTK_SOURCE_IS_VIM_MOTION (self), FALSE);
if (self->motion == NULL || self->failed)
@@ -1322,15 +1341,35 @@ gtk_source_vim_motion_apply (GtkSourceVimMotion *self,
return FALSE;
}
+ begin_offset = gtk_text_iter_get_offset (iter);
+
do
{
if (!self->motion (iter, self))
{
- return FALSE;
+ goto do_inclusive;
}
} while (--self->number > 1);
- return TRUE;
+ ret = TRUE;
+
+do_inclusive:
+ if (apply_inclusive)
+ {
+ guint end_offset = gtk_text_iter_get_offset (iter);
+
+ if (FALSE) {}
+ else if (self->inclusivity == INCLUSIVE &&
+ end_offset > begin_offset &&
+ !gtk_text_iter_ends_line (iter))
+ gtk_text_iter_forward_char (iter);
+ else if (self->inclusivity == EXCLUSIVE
+ && end_offset < begin_offset &&
+ !gtk_text_iter_ends_line (iter))
+ gtk_text_iter_forward_char (iter);
+ }
+
+ return ret;
}
void
@@ -1360,6 +1399,7 @@ gtk_source_vim_motion_new_line_end (void)
self = g_object_new (GTK_SOURCE_TYPE_VIM_MOTION, NULL);
self->motion = motion_line_end;
+ self->inclusivity = EXCLUSIVE;
return GTK_SOURCE_VIM_STATE (self);
}
@@ -1371,6 +1411,7 @@ gtk_source_vim_motion_new_line_start (void)
self = g_object_new (GTK_SOURCE_TYPE_VIM_MOTION, NULL);
self->motion = motion_line_start;
+ self->inclusivity = INCLUSIVE;
return GTK_SOURCE_VIM_STATE (self);
}
@@ -1382,6 +1423,7 @@ gtk_source_vim_motion_new_previous_line_end (void)
self = g_object_new (GTK_SOURCE_TYPE_VIM_MOTION, NULL);
self->motion = motion_prev_line_end;
+ self->inclusivity = EXCLUSIVE;
return GTK_SOURCE_VIM_STATE (self);
}
diff --git a/gtksourceview/vim/gtk-source-vim-motion.h b/gtksourceview/vim/gtk-source-vim-motion.h
index 127cad96..2748ae0f 100644
--- a/gtksourceview/vim/gtk-source-vim-motion.h
+++ b/gtksourceview/vim/gtk-source-vim-motion.h
@@ -40,6 +40,7 @@ GtkSourceVimState *gtk_source_vim_motion_new_line_start (void);
void gtk_source_vim_motion_set_apply_on_leave (GtkSourceVimMotion *self,
gboolean apply_on_leave);
gboolean gtk_source_vim_motion_apply (GtkSourceVimMotion *self,
- GtkTextIter *iter);
+ GtkTextIter *iter,
+ gboolean apply_inclusive);
G_END_DECLS
diff --git a/gtksourceview/vim/gtk-source-vim-normal.c b/gtksourceview/vim/gtk-source-vim-normal.c
index bafb4cb7..f5ba5add 100644
--- a/gtksourceview/vim/gtk-source-vim-normal.c
+++ b/gtksourceview/vim/gtk-source-vim-normal.c
@@ -139,10 +139,54 @@ typedef enum
{
INSERT_HERE,
INSERT_AFTER_CHAR,
- INSERT_AFTER_CHAR_UNLESS_SOL,
INSERT_AFTER_CHAR_UNLESS_BOF,
+ INSERT_AFTER_CHAR_UNLESS_SOL,
} InsertAt;
+G_GNUC_NULL_TERMINATED
+static GtkSourceVimState *
+gtk_source_vim_normal_begin_change (GtkSourceVimNormal *self,
+ GtkSourceVimState *motion,
+ ...)
+{
+ GtkSourceVimState *ret;
+ GtkSourceBuffer *buffer;
+ const char *first_property_name;
+ GtkTextIter iter, selection;
+ va_list args;
+
+ 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);
+
+ gtk_text_buffer_begin_user_action (GTK_TEXT_BUFFER (buffer));
+
+ if (motion != NULL)
+ {
+ /* Just to attach it to the state machine */
+ gtk_source_vim_motion_set_apply_on_leave (GTK_SOURCE_VIM_MOTION (motion), FALSE);
+ gtk_source_vim_state_push (GTK_SOURCE_VIM_STATE (self), motion);
+ gtk_source_vim_state_pop (g_object_ref (motion));
+
+ /* Apply it to our selection bound */
+ gtk_source_vim_motion_apply (GTK_SOURCE_VIM_MOTION (motion), &iter, TRUE);
+ gtk_text_buffer_delete (GTK_TEXT_BUFFER (buffer), &iter, &selection);
+ gtk_text_buffer_select_range (GTK_TEXT_BUFFER (buffer), &iter, &iter);
+ }
+
+ va_start (args, motion);
+ first_property_name = va_arg (args, const char *);
+ 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_push (GTK_SOURCE_VIM_STATE (self), ret);
+
+ gtk_text_buffer_end_user_action (GTK_TEXT_BUFFER (buffer));
+
+ return ret;
+}
+
G_GNUC_NULL_TERMINATED
static GtkSourceVimState *
gtk_source_vim_normal_begin_insert (GtkSourceVimNormal *self,
@@ -173,7 +217,8 @@ gtk_source_vim_normal_begin_insert (GtkSourceVimNormal *self,
(at == INSERT_AFTER_CHAR_UNLESS_BOF && !gtk_text_iter_is_start (&iter)) ||
(at == INSERT_AFTER_CHAR_UNLESS_SOL && !gtk_text_iter_starts_line (&iter)))
{
- gtk_text_iter_forward_char (&iter);
+ if (!gtk_text_iter_ends_line (&iter))
+ gtk_text_iter_forward_char (&iter);
}
gtk_source_vim_state_select (GTK_SOURCE_VIM_STATE (self), &iter, &iter);
@@ -253,8 +298,14 @@ key_handler_command (GtkSourceVimNormal *self,
NULL);
return TRUE;
- case GDK_KEY_asciitilde:
case GDK_KEY_C:
+ gtk_source_vim_normal_begin_change (self,
+ gtk_source_vim_motion_new_line_end (),
+ INSERT_HERE,
+ NULL);
+ return TRUE;
+
+ case GDK_KEY_asciitilde:
case GDK_KEY_D:
case GDK_KEY_J:
case GDK_KEY_p:
@@ -265,7 +316,10 @@ key_handler_command (GtkSourceVimNormal *self,
case GDK_KEY_x:
case GDK_KEY_equal:
case GDK_KEY_plus:
+ break;
+
case GDK_KEY_Y:
+ /* synonum for yy */
break;
default:
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]