aboutsummaryrefslogtreecommitdiff
path: root/main.c
diff options
context:
space:
mode:
authorMarc André Tanner <mat@brain-dump.org>2020-02-03 14:25:02 +0100
committerMarc André Tanner <mat@brain-dump.org>2020-02-03 14:25:02 +0100
commit9e36e729cee27f2b13c2b72cd600968c2c5e874f (patch)
tree72afd82051ea80fa94551c6f5f53f9d535ea8f25 /main.c
parentd04ab3a885428c10276ade0f0a5995a034330a1f (diff)
downloadvis-9e36e729cee27f2b13c2b72cd600968c2c5e874f.tar.gz
vis-9e36e729cee27f2b13c2b72cd600968c2c5e874f.tar.xz
vis: improve <C-n> in visual mode
If the existing primary selection is not a word, switch to a literal search. This should still avoid unwanted prefix matches (e.g. when renaming related variables) but allow searching for arbitrary regions. Fix #746
Diffstat (limited to 'main.c')
-rw-r--r--main.c38
1 files changed, 37 insertions, 1 deletions
diff --git a/main.c b/main.c
index 153ce94..80724d9 100644
--- a/main.c
+++ b/main.c
@@ -1397,6 +1397,37 @@ static const Selection *selection_new_primary(View *view, Filerange *r) {
return s;
}
+static const char *selections_match_next_literal(Vis *vis, const char *keys, const Arg *arg) {
+ Text *txt = vis_text(vis);
+ View *view = vis_view(vis);
+ Selection *s = view_selections_primary_get(view);
+ Filerange sel = view_selections_get(s);
+ size_t len = text_range_size(&sel);
+ if (!len)
+ return keys;
+
+ char *buf = text_bytes_alloc0(txt, sel.start, len);
+ if (!buf)
+ return keys;
+
+ size_t start = text_find_next(txt, sel.end, buf);
+ Filerange match = text_range_new(start, start+len);
+ if (start != sel.end && selection_new_primary(view, &match))
+ goto out;
+
+ sel = view_selections_get(view_selections(view));
+ start = text_find_prev(txt, sel.start, buf);
+ if (start == sel.start)
+ goto out;
+
+ match = text_range_new(start, start+len);
+ selection_new_primary(view, &match);
+
+out:
+ free(buf);
+ return keys;
+}
+
static const char *selections_match_next(Vis *vis, const char *keys, const Arg *arg) {
Text *txt = vis_text(vis);
View *view = vis_view(vis);
@@ -1405,10 +1436,15 @@ static const char *selections_match_next(Vis *vis, const char *keys, const Arg *
if (!text_range_valid(&sel))
return keys;
+ Filerange word = text_object_word(txt, view_cursors_pos(s));
+ if (!text_range_equal(&sel, &word))
+ return selections_match_next_literal(vis, keys, arg);
+
char *buf = text_bytes_alloc0(txt, sel.start, text_range_size(&sel));
if (!buf)
return keys;
- Filerange word = text_object_word_find_next(txt, sel.end, buf);
+
+ word = text_object_word_find_next(txt, sel.end, buf);
if (text_range_valid(&word) && selection_new_primary(view, &word))
goto out;