vis

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

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

commit 2266bcb8841c9f61feec280c7545799b9b20328c
parent 20b7c994fe52b631e58fe9f332d84ce35b0acb0e
Author: Marc André Tanner <mat@brain-dump.org>
Date:   Wed, 22 Feb 2017 09:28:40 +0100

vis: add exact count motion flag

Some motions should fail (i.e. keep the initial position) when
the specified count can not be satisfied exactly.

Examples include t, f, T, and F.

Fix #497

Diffstat:
Mvis-core.h | 1+
Mvis-motions.c | 6++++--
Mvis.c | 10+++++++++-
3 files changed, 14 insertions(+), 3 deletions(-)

diff --git a/vis-core.h b/vis-core.h @@ -69,6 +69,7 @@ typedef struct { /* Motion implementation, takes a cursor postion and returns a LINEWISE_INCLUSIVE = 1 << 3, /* inclusive, but only if motion is linewise? */ IDEMPOTENT = 1 << 4, /* does the returned postion remain the same if called multiple times? */ JUMP = 1 << 5, /* should the resulting position of the motion be recorded in the jump list? */ + COUNT_EXACT = 1 << 6, /* fail (keep initial position) if count can not be satisfied exactly */ } type; void *data; } Movement; diff --git a/vis-motions.c b/vis-motions.c @@ -502,17 +502,19 @@ const Movement vis_motions[] = { }, [VIS_MOVE_LEFT_TO] = { .vis = to_left, + .type = COUNT_EXACT, }, [VIS_MOVE_RIGHT_TO] = { .vis = to, - .type = INCLUSIVE, + .type = INCLUSIVE|COUNT_EXACT, }, [VIS_MOVE_LEFT_TILL] = { .vis = till_left, + .type = COUNT_EXACT, }, [VIS_MOVE_RIGHT_TILL] = { .vis = till, - .type = INCLUSIVE, + .type = INCLUSIVE|COUNT_EXACT, }, [VIS_MOVE_MARK] = { .file = mark_goto, diff --git a/vis.c b/vis.c @@ -710,6 +710,7 @@ void vis_do(Vis *vis) { .arg = &a->arg, }; + bool err = false; if (a->movement) { size_t start = pos; for (int i = 0; i < count; i++) { @@ -728,8 +729,15 @@ void vis_do(Vis *vis) { pos = a->movement->win(vis, win, pos); else if (a->movement->user) pos = a->movement->user(vis, win, a->movement->data, pos); - if (pos == EPOS || a->movement->type & IDEMPOTENT || pos == pos_prev) + if (pos == EPOS || a->movement->type & IDEMPOTENT || pos == pos_prev) { + err = a->movement->type & COUNT_EXACT; break; + } + } + + if (err) { + repeatable = false; + continue; // break? } if (pos == EPOS) {