vis

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

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

commit 108e267e9b78e311921efa143491889f85c760ba
parent e8063265cd632eb6336791eea59c141ffddfc452
Author: Marc André Tanner <mat@brain-dump.org>
Date:   Fri,  6 Nov 2015 11:09:28 +0100

vis: fix operators to correctly handle multiple selections

Operators must not switch modes, they might be called multiple
times (once for every cursor/selection).

Closes #91. The concrete problem was that op_change for the
first cursor switched to insert mode, which cleared all the
remaining selections. Hence the other cursors had nothing to
operate on.

Reverts parts of e72b03a9.

Diffstat:
Mvis.c | 12++++++++----
1 file changed, 8 insertions(+), 4 deletions(-)

diff --git a/vis.c b/vis.c @@ -1135,7 +1135,6 @@ static size_t op_delete(Vis *vis, Text *txt, OperatorContext *c) { static size_t op_change(Vis *vis, Text *txt, OperatorContext *c) { op_delete(vis, txt, c); macro_operator_record(vis); - vis_mode_switch(vis, VIS_MODE_INSERT); return c->range.start; } @@ -1310,13 +1309,11 @@ static size_t op_join(Vis *vis, Text *txt, OperatorContext *c) { static size_t op_insert(Vis *vis, Text *txt, OperatorContext *c) { macro_operator_record(vis); - vis_mode_switch(vis, VIS_MODE_INSERT); return c->newpos != EPOS ? c->newpos : c->pos; } static size_t op_replace(Vis *vis, Text *txt, OperatorContext *c) { macro_operator_record(vis); - vis_mode_switch(vis, VIS_MODE_REPLACE); return c->newpos != EPOS ? c->newpos : c->pos; } @@ -1612,7 +1609,14 @@ static void action_do(Vis *vis, Action *a) { } if (a->op) { - if (vis->mode == &vis_modes[VIS_MODE_OPERATOR]) + /* operator implementations must not change the mode, + * they might get called multiple times (once for every cursor) + */ + if (a->op == &ops[OP_INSERT] || a->op == &ops[OP_CHANGE]) + vis_mode_switch(vis, VIS_MODE_INSERT); + else if (a->op == &ops[OP_REPLACE]) + vis_mode_switch(vis, VIS_MODE_REPLACE); + else if (vis->mode == &vis_modes[VIS_MODE_OPERATOR]) mode_set(vis, vis->mode_prev); else if (vis->mode->visual) vis_mode_switch(vis, VIS_MODE_NORMAL);