aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarc André Tanner <mat@brain-dump.org>2020-12-28 15:17:36 +0100
committerMarc André Tanner <mat@brain-dump.org>2020-12-28 15:17:36 +0100
commitadf65e1dca8d3c0381133be8446eebddf412d772 (patch)
treed15dd7a68c597ca9be6ca92ea363578e501391cc
parent0b082239bc60f0a6a3cb743b38a63684652ae649 (diff)
downloadvis-adf65e1dca8d3c0381133be8446eebddf412d772.tar.gz
vis-adf65e1dca8d3c0381133be8446eebddf412d772.tar.xz
vis: implement multiline to/till motions
These are currently not mapped by default but can be enabled by mappings using their virtual key names.
-rw-r--r--main.c26
-rw-r--r--vis-motions.c58
-rw-r--r--vis.h4
3 files changed, 87 insertions, 1 deletions
diff --git a/main.c b/main.c
index 9719640..858af23 100644
--- a/main.c
+++ b/main.c
@@ -94,7 +94,7 @@ static const char *gotoline(Vis*, const char *keys, const Arg *arg);
/* make the current action use the operator indicated by arg->i */
static const char *operator(Vis*, const char *keys, const Arg *arg);
/* blocks to read a key and performs movement indicated by arg->i which
- * should be one of VIS_MOVE_{TO,TILL}_LINE_{RIGHT,LEFT}*/
+ * should be one of VIS_MOVE_{TO,TILL}_{,LINE}_{RIGHT,LEFT}*/
static const char *movement_key(Vis*, const char *keys, const Arg *arg);
/* perform the movement as indicated by arg->i */
static const char *movement(Vis*, const char *keys, const Arg *arg);
@@ -220,8 +220,12 @@ enum {
VIS_ACTION_TOTILL_REVERSE,
VIS_ACTION_PROMPT_SEARCH_FORWARD,
VIS_ACTION_PROMPT_SEARCH_BACKWARD,
+ VIS_ACTION_TILL_LEFT,
+ VIS_ACTION_TILL_RIGHT,
VIS_ACTION_TILL_LINE_LEFT,
VIS_ACTION_TILL_LINE_RIGHT,
+ VIS_ACTION_TO_LEFT,
+ VIS_ACTION_TO_RIGHT,
VIS_ACTION_TO_LINE_LEFT,
VIS_ACTION_TO_LINE_RIGHT,
VIS_ACTION_REGISTER,
@@ -718,6 +722,16 @@ static const KeyAction vis_action[] = {
VIS_HELP("Search backward")
prompt_show, { .s = "?" }
},
+ [VIS_ACTION_TILL_LEFT] = {
+ "vis-motion-till-left",
+ VIS_HELP("Till after the occurrence of character to the left")
+ movement_key, { .i = VIS_MOVE_TILL_LEFT }
+ },
+ [VIS_ACTION_TILL_RIGHT] = {
+ "vis-motion-till-right",
+ VIS_HELP("Till before the occurrence of character to the right")
+ movement_key, { .i = VIS_MOVE_TILL_RIGHT }
+ },
[VIS_ACTION_TILL_LINE_LEFT] = {
"vis-motion-till-line-left",
VIS_HELP("Till after the occurrence of character to the left on the current line")
@@ -728,6 +742,16 @@ static const KeyAction vis_action[] = {
VIS_HELP("Till before the occurrence of character to the right on the current line")
movement_key, { .i = VIS_MOVE_TILL_LINE_RIGHT }
},
+ [VIS_ACTION_TO_LEFT] = {
+ "vis-motion-to-left",
+ VIS_HELP("To the first occurrence of character to the left")
+ movement_key, { .i = VIS_MOVE_TO_LEFT }
+ },
+ [VIS_ACTION_TO_RIGHT] = {
+ "vis-motion-to-right",
+ VIS_HELP("To the first occurrence of character to the right")
+ movement_key, { .i = VIS_MOVE_TO_RIGHT }
+ },
[VIS_ACTION_TO_LINE_LEFT] = {
"vis-motion-to-line-left",
VIS_HELP("To the first occurrence of character to the left on the current line")
diff --git a/vis-motions.c b/vis-motions.c
index 9658f9f..6178f5a 100644
--- a/vis-motions.c
+++ b/vis-motions.c
@@ -112,6 +112,32 @@ static size_t longword_next(Vis *vis, Text *txt, size_t pos) {
VIS_MOVE_LONGWORD_END_NEXT, isspace);
}
+static size_t to_right(Vis *vis, Text *txt, size_t pos) {
+ char c;
+ size_t hit = text_find_next(txt, pos+1, vis->search_char);
+ if (!text_byte_get(txt, hit, &c) || c != vis->search_char[0])
+ return pos;
+ return hit;
+}
+
+static size_t till_right(Vis *vis, Text *txt, size_t pos) {
+ size_t hit = to_right(vis, txt, pos+1);
+ if (hit != pos)
+ return text_char_prev(txt, hit);
+ return pos;
+}
+
+static size_t to_left(Vis *vis, Text *txt, size_t pos) {
+ return text_find_prev(txt, pos, vis->search_char);
+}
+
+static size_t till_left(Vis *vis, Text *txt, size_t pos) {
+ size_t hit = to_left(vis, txt, pos-1);
+ if (hit != pos-1)
+ return text_char_next(txt, hit);
+ return pos;
+}
+
static size_t to_line_right(Vis *vis, Text *txt, size_t pos) {
char c;
if (pos == text_line_end(txt, pos))
@@ -294,8 +320,12 @@ bool vis_motion(Vis *vis, enum VisMotion motion, ...) {
}
break;
}
+ case VIS_MOVE_TO_RIGHT:
+ case VIS_MOVE_TO_LEFT:
case VIS_MOVE_TO_LINE_RIGHT:
case VIS_MOVE_TO_LINE_LEFT:
+ case VIS_MOVE_TILL_RIGHT:
+ case VIS_MOVE_TILL_LEFT:
case VIS_MOVE_TILL_LINE_RIGHT:
case VIS_MOVE_TILL_LINE_LEFT:
{
@@ -314,12 +344,24 @@ bool vis_motion(Vis *vis, enum VisMotion motion, ...) {
break;
case VIS_MOVE_TOTILL_REVERSE:
switch (vis->last_totill) {
+ case VIS_MOVE_TO_RIGHT:
+ motion = VIS_MOVE_TO_LEFT;
+ break;
+ case VIS_MOVE_TO_LEFT:
+ motion = VIS_MOVE_TO_RIGHT;
+ break;
case VIS_MOVE_TO_LINE_RIGHT:
motion = VIS_MOVE_TO_LINE_LEFT;
break;
case VIS_MOVE_TO_LINE_LEFT:
motion = VIS_MOVE_TO_LINE_RIGHT;
break;
+ case VIS_MOVE_TILL_RIGHT:
+ motion = VIS_MOVE_TILL_LEFT;
+ break;
+ case VIS_MOVE_TILL_LEFT:
+ motion = VIS_MOVE_TILL_RIGHT;
+ break;
case VIS_MOVE_TILL_LINE_RIGHT:
motion = VIS_MOVE_TILL_LINE_LEFT;
break;
@@ -515,6 +557,14 @@ const Movement vis_motions[] = {
.txt = lastline,
.type = LINEWISE|LINEWISE_INCLUSIVE|JUMP|IDEMPOTENT,
},
+ [VIS_MOVE_TO_LEFT] = {
+ .vis = to_left,
+ .type = COUNT_EXACT,
+ },
+ [VIS_MOVE_TO_RIGHT] = {
+ .vis = to_right,
+ .type = INCLUSIVE|COUNT_EXACT,
+ },
[VIS_MOVE_TO_LINE_LEFT] = {
.vis = to_line_left,
.type = COUNT_EXACT,
@@ -523,6 +573,14 @@ const Movement vis_motions[] = {
.vis = to_line_right,
.type = INCLUSIVE|COUNT_EXACT,
},
+ [VIS_MOVE_TILL_LEFT] = {
+ .vis = till_left,
+ .type = COUNT_EXACT,
+ },
+ [VIS_MOVE_TILL_RIGHT] = {
+ .vis = till_right,
+ .type = INCLUSIVE|COUNT_EXACT,
+ },
[VIS_MOVE_TILL_LINE_LEFT] = {
.vis = till_line_left,
.type = COUNT_EXACT,
diff --git a/vis.h b/vis.h
index 41fe6ae..b5a27fe 100644
--- a/vis.h
+++ b/vis.h
@@ -491,8 +491,12 @@ enum VisMotion {
VIS_MOVE_PARENTHESIS_START,
VIS_MOVE_PARENTHESIS_END,
VIS_MOVE_BRACKET_MATCH,
+ VIS_MOVE_TO_LEFT,
+ VIS_MOVE_TO_RIGHT,
VIS_MOVE_TO_LINE_LEFT,
VIS_MOVE_TO_LINE_RIGHT,
+ VIS_MOVE_TILL_LEFT,
+ VIS_MOVE_TILL_RIGHT,
VIS_MOVE_TILL_LINE_LEFT,
VIS_MOVE_TILL_LINE_RIGHT,
VIS_MOVE_FILE_BEGIN,