I've written up patches to make it so that I, a, A, s, ce, etc can be repeated properly with . -- not sure if I'm doing this the Right Way, but it seems to work in my tests. Feedback appreciated. Patches attached.

--
Stephen Paul Weber, @singpolyma
See <http://singpolyma.net> for how I prefer to be contacted
edition right joseph
From 06e04fa98dda188c440604d457c6497e78873d00 Mon Sep 17 00:00:00 2001
From: Stephen Paul Weber <singpol...@singpolyma.net>
Date: Tue, 18 Nov 2014 17:56:19 -0500
Subject: [PATCH 1/2] Allow repeatable insert-after-move

Previously we forgot what move was made when repeating an insert.
No more!
---
 config.def.h |  5 +----
 vis.c        | 20 +++++++++++++++++---
 2 files changed, 18 insertions(+), 7 deletions(-)

diff --git a/config.def.h b/config.def.h
index f41dd81..160edfc 100644
--- a/config.def.h
+++ b/config.def.h
@@ -390,7 +390,7 @@ static KeyBinding vis_mode_normal[] = {
 	{ { NONE('J')               }, join,           { .i = MOVE_SCREEN_LINE_DOWN} },
 	{ { NONE('x')               }, delete,         { .i = MOVE_CHAR_NEXT       } },
 	{ { NONE('r')               }, replace,        { NULL                      } },
-	{ { NONE('i')               }, switchmode,     { .i = VIS_MODE_INSERT      } },
+	{ { NONE('i')               }, insertmode,     { .i = MOVE_NO_MOVE         } },
 	{ { NONE('v')               }, switchmode,     { .i = VIS_MODE_VISUAL      } },
 	{ { NONE('V')               }, switchmode,     { .i = VIS_MODE_VISUAL_LINE } },
 	{ { NONE('R')               }, switchmode,     { .i = VIS_MODE_REPLACE     } },
@@ -561,9 +561,6 @@ static void vis_mode_insert_idle(void) {
 
 static void vis_mode_insert_input(const char *str, size_t len) {
 	editor_insert_key(vis, str, len);
-	/* make sure we can repeat the last insert */
-	action_reset(&action_prev);
-	action_prev.op = &ops[OP_REPEAT_INSERT];
 }
 
 static KeyBinding vis_mode_replace[] = {
diff --git a/vis.c b/vis.c
index 696d0f2..66d4b5a 100644
--- a/vis.c
+++ b/vis.c
@@ -193,6 +193,7 @@ static Operator ops[] = {
 
 /* these can be passed as int argument to movement(&(const Arg){ .i = MOVE_* }) */
 enum {
+	MOVE_NO_MOVE,
 	MOVE_SCREEN_LINE_UP,
 	MOVE_SCREEN_LINE_DOWN,
 	MOVE_SCREEN_LINE_BEGIN,
@@ -272,6 +273,7 @@ static size_t window_lines_middle(const Arg *arg);
 static size_t window_lines_bottom(const Arg *arg);
 
 static Movement moves[] = {
+	[MOVE_NO_MOVE]             = {                                                             },
 	[MOVE_SCREEN_LINE_UP]      = { .win = window_line_up                                       },
 	[MOVE_SCREEN_LINE_DOWN]    = { .win = window_line_down                                     },
 	[MOVE_SCREEN_LINE_BEGIN]   = { .win = window_line_begin,        .type = CHARWISE           },
@@ -635,8 +637,10 @@ static void op_case_change(OperatorContext *c) {
 static void op_repeat_insert(OperatorContext *c) {
 	const char *content;
 	size_t len = text_last_insertion(vis->win->text, &content);
-	editor_insert(vis, c->pos, content, len);
-	window_cursor_to(vis->win->win, c->pos + len);
+	size_t pos = c->pos == c->range.start ? c->range.end : c->range.start;
+
+	editor_insert(vis, pos, content, len);
+	window_cursor_to(vis->win->win, pos + len);
 }
 
 static void op_join(OperatorContext *c) {
@@ -909,8 +913,18 @@ static void zero(const Arg *arg) {
 }
 
 static void insertmode(const Arg *arg) {
+	bool old_linewise = action.linewise;
+
 	movement(arg);
 	switchmode(&(const Arg){ .i = VIS_MODE_INSERT });
+
+	/* So we can repeat the insert with movement */
+	action_reset(&action_prev);
+	action_prev.op = &ops[OP_REPEAT_INSERT];
+	if (old_linewise && arg->i < LENGTH(moves_linewise))
+		action_prev.textobj = moves_linewise[arg->i];
+	else
+		action_prev.movement = &moves[arg->i];
 }
 
 static void change(const Arg *arg) {
@@ -1090,7 +1104,7 @@ static void action_do(Action *a) {
 				pos = a->movement->txt(txt, pos);
 			else if (a->movement->win)
 				pos = a->movement->win(win);
-			else
+			else if (a->movement->cmd)
 				pos = a->movement->cmd(&a->arg);
 			if (pos == EPOS || a->movement->type & IDEMPOTENT)
 				break;
-- 
1.9.1

From 1e5c8f49d3eafcb3a31e68ad83310546141bd697 Mon Sep 17 00:00:00 2001
From: Stephen Paul Weber <singpol...@singpolyma.net>
Date: Tue, 18 Nov 2014 17:57:02 -0500
Subject: [PATCH 2/2] Allow repeatable change operations

Previously we only repeated the insert.  Then we only repeated the
delete.
This change repeats both the delete and the insert.
---
 vis.c | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/vis.c b/vis.c
index 66d4b5a..0282678 100644
--- a/vis.c
+++ b/vis.c
@@ -161,6 +161,7 @@ static void op_shift_right(OperatorContext *c);
 static void op_shift_left(OperatorContext *c);
 static void op_case_change(OperatorContext *c);
 static void op_repeat_insert(OperatorContext *c);
+static void op_repeat_change(OperatorContext *c);
 static void op_join(OperatorContext *c);
 
 /* these can be passed as int argument to operator(&(const Arg){ .i = OP_*}) */
@@ -173,6 +174,7 @@ enum {
 	OP_SHIFT_LEFT,
 	OP_CASE_CHANGE,
 	OP_REPEAT_INSERT,
+	OP_REPEAT_CHANGE,
 	OP_JOIN,
 };
 
@@ -185,6 +187,7 @@ static Operator ops[] = {
 	[OP_SHIFT_LEFT]  = { op_shift_left  },
 	[OP_CASE_CHANGE] = { op_case_change },
 	[OP_REPEAT_INSERT] = { op_repeat_insert },
+	[OP_REPEAT_CHANGE] = { op_repeat_change },
 	[OP_JOIN]          = { op_join          },
 };
 
@@ -524,6 +527,10 @@ static void op_delete(OperatorContext *c) {
 }
 
 static void op_change(OperatorContext *c) {
+	if(action.op == &ops[OP_CHANGE]) {
+		/* We came in from an action. Change it so repeat works. */
+		action.op = &ops[OP_REPEAT_CHANGE];
+	}
 	op_delete(c);
 	switchmode(&(const Arg){ .i = VIS_MODE_INSERT });
 }
@@ -643,6 +650,12 @@ static void op_repeat_insert(OperatorContext *c) {
 	window_cursor_to(vis->win->win, pos + len);
 }
 
+static void op_repeat_change(OperatorContext *c) {
+	op_delete(c);
+	c->range.end = c->range.start;
+	op_repeat_insert(c);
+}
+
 static void op_join(OperatorContext *c) {
 	Text *txt = vis->win->text;
 	size_t pos = text_line_begin(txt, c->range.end), prev_pos;
-- 
1.9.1

Attachment: signature.asc
Description: Digital signature

Reply via email to