aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarc André Tanner <mat@brain-dump.org>2015-01-02 21:18:05 +0100
committerMarc André Tanner <mat@brain-dump.org>2015-01-02 21:32:13 +0100
commitb55fd4416267295bba5f09762a94b93e37640525 (patch)
treedfd7dcf9d471709fe402a16e82cc33361dabb3a6
parentc44f18b0c4fff5122c683c108cd831ece1c46049 (diff)
downloadvis-b55fd4416267295bba5f09762a94b93e37640525.tar.gz
vis-b55fd4416267295bba5f09762a94b93e37640525.tar.xz
Make last insertion/replacement repeatable with '.'
-rw-r--r--config.def.h16
-rw-r--r--editor.c1
-rw-r--r--vis.c31
3 files changed, 47 insertions, 1 deletions
diff --git a/config.def.h b/config.def.h
index 58af491..05bfabd 100644
--- a/config.def.h
+++ b/config.def.h
@@ -567,6 +567,14 @@ static void vis_mode_insert_idle(void) {
}
static void vis_mode_insert_input(const char *str, size_t len) {
+ static size_t oldpos = EPOS;
+ size_t pos = window_cursor_get(vis->win->win);
+ if (pos != oldpos)
+ buffer_truncate(&buffer_repeat);
+ buffer_append(&buffer_repeat, str, len);
+ oldpos = pos + len;
+ action_reset(&action_prev);
+ action_prev.op = &ops[OP_REPEAT_INSERT];
editor_insert_key(vis, str, len);
}
@@ -581,6 +589,14 @@ static void vis_mode_replace_leave(Mode *old) {
}
static void vis_mode_replace_input(const char *str, size_t len) {
+ static size_t oldpos = EPOS;
+ size_t pos = window_cursor_get(vis->win->win);
+ if (pos != oldpos)
+ buffer_truncate(&buffer_repeat);
+ buffer_append(&buffer_repeat, str, len);
+ oldpos = pos + len;
+ action_reset(&action_prev);
+ action_prev.op = &ops[OP_REPEAT_REPLACE];
editor_replace_key(vis, str, len);
}
diff --git a/editor.c b/editor.c
index a8c7c18..ef59242 100644
--- a/editor.c
+++ b/editor.c
@@ -499,7 +499,6 @@ void editor_delete(Editor *ed, size_t pos, size_t len) {
editor_windows_invalidate(ed, pos, pos + len);
}
-
static void editor_prompt_free(Prompt *prompt) {
if (!prompt)
return;
diff --git a/vis.c b/vis.c
index 8542f63..aa3360e 100644
--- a/vis.c
+++ b/vis.c
@@ -155,6 +155,7 @@ static Mode *mode_prev; /* previsouly active user mode */
static Mode *mode_before_prompt; /* user mode which was active before entering prompt */
static Action action; /* current action which is in progress */
static Action action_prev; /* last operator action used by the repeat '.' key */
+static Buffer buffer_repeat;/* repeat last modification i.e. insertion/replacement */
/** operators */
static void op_change(OperatorContext *c);
@@ -165,6 +166,8 @@ static void op_shift_right(OperatorContext *c);
static void op_shift_left(OperatorContext *c);
static void op_case_change(OperatorContext *c);
static void op_join(OperatorContext *c);
+static void op_repeat_insert(OperatorContext *c);
+static void op_repeat_replace(OperatorContext *c);
/* these can be passed as int argument to operator(&(const Arg){ .i = OP_*}) */
enum {
@@ -176,6 +179,8 @@ enum {
OP_SHIFT_LEFT,
OP_CASE_CHANGE,
OP_JOIN,
+ OP_REPEAT_INSERT,
+ OP_REPEAT_REPLACE,
};
static Operator ops[] = {
@@ -187,6 +192,8 @@ static Operator ops[] = {
[OP_SHIFT_LEFT] = { op_shift_left },
[OP_CASE_CHANGE] = { op_case_change },
[OP_JOIN] = { op_join },
+ [OP_REPEAT_INSERT] = { op_repeat_insert },
+ [OP_REPEAT_REPLACE] = { op_repeat_replace },
};
#define PAGE INT_MAX
@@ -666,6 +673,30 @@ static void op_join(OperatorContext *c) {
editor_draw(vis);
}
+static void op_repeat_insert(OperatorContext *c) {
+ if (!buffer_repeat.len)
+ return;
+ editor_insert(vis, c->pos, buffer_repeat.data, buffer_repeat.len);
+ window_cursor_to(vis->win->win, c->pos + buffer_repeat.len);
+}
+
+static void op_repeat_replace(OperatorContext *c) {
+ if (!buffer_repeat.len)
+ return;
+
+ size_t chars = 0;
+ for (size_t i = 0; i < buffer_repeat.len; i++) {
+ if (ISUTF8(buffer_repeat.data[i]))
+ chars++;
+ }
+
+ Iterator it = text_iterator_get(vis->win->text, c->pos);
+ while (chars-- > 0)
+ text_iterator_char_next(&it, NULL);
+ editor_delete(vis, c->pos, it.pos - c->pos);
+ op_repeat_insert(c);
+}
+
/** movement implementations of type: size_t (*move)(const Arg*) */
static char *get_word_under_cursor() {