aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarc André Tanner <mat@brain-dump.org>2016-11-09 14:50:43 +0100
committerMarc André Tanner <mat@brain-dump.org>2016-11-09 14:58:31 +0100
commitef268e029d75ee58fb5a78c203278dfb98d212c5 (patch)
tree59297514906fdbdc9af25fd7f56a43a55d82d3c6
parentff45c36bab3952bb633dd0b8e6c4c90dab9f7e2a (diff)
downloadvis-ef268e029d75ee58fb5a78c203278dfb98d212c5.tar.gz
vis-ef268e029d75ee58fb5a78c203278dfb98d212c5.tar.xz
vis: improve `r` in normal and replace mode
In normal mode `r<key>` was previously implemented as `R<key><Escape>`. However this does not work when the replacement key is `<Enter>` to insert a new line, because in replace mode new lines are not overwritten. The count is now also respected. Also properly support `r` in visual mode where before it was aliased to `c`. Fix #190
-rw-r--r--config.def.h2
-rw-r--r--main.c23
2 files changed, 21 insertions, 4 deletions
diff --git a/config.def.h b/config.def.h
index 150551b..1ae941f 100644
--- a/config.def.h
+++ b/config.def.h
@@ -288,7 +288,7 @@ static const KeyBinding bindings_visual[] = {
{ "J", ACTION(JOIN_LINES) },
{ "gJ", ACTION(JOIN_LINES_TRIM) },
{ "o", ACTION(SELECTION_FLIP) },
- { "r", ALIAS("c") },
+ { "r", ACTION(REPLACE_CHAR) },
{ "s", ALIAS("c") },
{ "<S-Tab>", ACTION(CURSORS_ALIGN_INDENT_RIGHT) },
{ "<Tab>", ACTION(CURSORS_ALIGN_INDENT_LEFT) },
diff --git a/main.c b/main.c
index fa4308d..e439b30 100644
--- a/main.c
+++ b/main.c
@@ -1634,12 +1634,29 @@ static const char *replace(Vis *vis, const char *keys, const Arg *arg) {
vis_keymap_disable(vis);
return NULL;
}
+
const char *next = vis_keys_next(vis, keys);
if (!next)
return NULL;
- vis_operator(vis, VIS_OP_MODESWITCH, VIS_MODE_REPLACE);
- vis_motion(vis, VIS_MOVE_NOP);
- vis_keys_feed(vis, keys);
+
+ char replacement[64];
+ size_t len = next - keys;
+ if (len >= sizeof(replacement))
+ return next;
+
+ memcpy(replacement, keys, len);
+ replacement[len] = '\0';
+
+ if (vis_mode_get(vis) == VIS_MODE_NORMAL) {
+ int count = vis_count_get_default(vis, 1);
+ vis_operator(vis, VIS_OP_CHANGE);
+ vis_motion(vis, VIS_MOVE_CHAR_NEXT);
+ for (; count > 0; count--)
+ vis_keys_feed(vis, replacement);
+ } else {
+ vis_operator(vis, VIS_OP_REPLACE, replacement);
+ }
+
vis_keys_feed(vis, "<Escape>");
return next;
}