vis

a vi-like editor based on Plan 9's structural regular expressions

git clone https://9o.is/git/vis.git

commit 5daceaa9d6f3f54cfdda2e91b4779b5de88db16d
parent 3fae3cbe64a51f3a33ff1627fed4cd34a7f7e665
Author: Marc André Tanner <mat@brain-dump.org>
Date:   Fri,  2 Jan 2015 21:18:05 +0100

Make last insertion/replacement repeatable with '.'

Diffstat:
Mconfig.def.h | 16++++++++++++++++
Meditor.c | 1-
Mvis.c | 31+++++++++++++++++++++++++++++++
3 files changed, 47 insertions(+), 1 deletion(-)

diff --git 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 @@ -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 @@ -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() {