vis
a vi-like editor based on Plan 9's structural regular expressions
git clone https://9o.is/git/vis.git
commit 03b2bbc1124b888c7ae3348b326c839d90a27408 parent 92fff3ae9f8e207cbf2b8f4bbeb4ea4f0b681bb6 Author: Marc André Tanner <mat@brain-dump.org> Date: Thu, 10 Mar 2016 20:56:24 +0100 vis: let <C-u> and <C-d> in visual mode move to prev/next cursor We do currently not enforce a strict ordering among cursors. Hence these key bindings can move you to an arbitray position. In practice it somewhat works because most of the time cursors are created in "top-down" i.e from the start of the file towards the end. Diffstat:
| M | config.def.h | | | 8 | ++++---- |
| M | main.c | | | 36 | ++++++++++++++++++++++++++++++++++++ |
2 files changed, 40 insertions(+), 4 deletions(-)
diff --git a/config.def.h b/config.def.h @@ -198,8 +198,8 @@ static const KeyBinding bindings_normal[] = { { "<C-w><Backspace>", ALIAS("<C-w>k") }, { "<C-b>", ALIAS("<PageUp>") }, { "<C-f>", ALIAS("<PageDown>") }, - { "<C-u>", ALIAS("<S-PageUp>") }, - { "<C-d>", ALIAS("<S-PageDown>") }, + { "<C-u>", ACTION(CURSORS_PREV) }, + { "<C-d>", ACTION(CURSORS_NEXT) }, { "<C-e>", ACTION(WINDOW_SLIDE_UP) }, { "<C-y>", ACTION(WINDOW_SLIDE_DOWN) }, { "<C-o>", ACTION(JUMPLIST_PREV) }, @@ -269,8 +269,8 @@ static const KeyBinding bindings_visual[] = { { ":", ACTION(PROMPT_SHOW_VISUAL) }, { "<C-b>", ALIAS("<PageUp>") }, { "<C-f>", ALIAS("<PageDown>") }, - { "<C-u>", ALIAS("<S-PageUp>") }, - { "<C-d>", ALIAS("<S-PageDown>") }, + { "<C-u>", ACTION(CURSORS_PREV) }, + { "<C-d>", ACTION(CURSORS_NEXT) }, { "x", ALIAS("d") }, { "r", ALIAS("c") }, { "s", ALIAS("c") }, diff --git a/main.c b/main.c @@ -48,6 +48,8 @@ static const char *cursors_align_indent(Vis*, const char *keys, const Arg *arg); static const char *cursors_clear(Vis*, const char *keys, const Arg *arg); /* remove the least recently added cursor */ static const char *cursors_remove(Vis*, const char *keys, const Arg *arg); +/* move to the previous (arg->i < 0) or next (arg->i > 0) cursor */ +static const char *cursors_navigate(Vis*, const char *keys, const Arg *arg); /* select the word the cursor is currently over */ static const char *cursors_select(Vis*, const char *keys, const Arg *arg); /* select the next region matching the current selection */ @@ -244,6 +246,8 @@ enum { VIS_ACTION_CURSORS_ALIGN_INDENT, VIS_ACTION_CURSORS_REMOVE_ALL, VIS_ACTION_CURSORS_REMOVE_LAST, + VIS_ACTION_CURSORS_PREV, + VIS_ACTION_CURSORS_NEXT, VIS_ACTION_TEXT_OBJECT_WORD_OUTER, VIS_ACTION_TEXT_OBJECT_WORD_INNER, VIS_ACTION_TEXT_OBJECT_LONGWORD_OUTER, @@ -929,6 +933,16 @@ static const KeyAction vis_action[] = { "Remove least recently created cursor", cursors_remove, }, + [VIS_ACTION_CURSORS_PREV] = { + "cursors-prev", + "Move to the previous cursor", + cursors_navigate, { .i = -PAGE_HALF } + }, + [VIS_ACTION_CURSORS_NEXT] = { + "cursors-next", + "Move to the next cursor", + cursors_navigate, { .i = +PAGE_HALF } + }, [VIS_ACTION_TEXT_OBJECT_WORD_OUTER] = { "text-object-word-outer", "A word leading and trailing whitespace included", @@ -1301,6 +1315,28 @@ static const char *cursors_remove(Vis *vis, const char *keys, const Arg *arg) { return keys; } +static const char *cursors_navigate(Vis *vis, const char *keys, const Arg *arg) { + View *view = vis_view(vis); + bool multiple_cursors = view_cursors_next(view_cursors(view)); + if (!multiple_cursors) + return wscroll(vis, keys, arg); + Cursor *c = view_cursors_primary_get(view); + if (arg->i < 0) { + c = view_cursors_next(c); + if (!c) + c = view_cursors(view); + } else { + c = view_cursors_prev(c); + if (!c) { + c = view_cursors(view); + for (Cursor *n = c; n; n = view_cursors_next(n)) + c = n; + } + } + view_cursors_primary_set(c); + return keys; +} + static const char *replace(Vis *vis, const char *keys, const Arg *arg) { if (!keys[0]) return NULL;