From 9e36e729cee27f2b13c2b72cd600968c2c5e874f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc=20Andr=C3=A9=20Tanner?= Date: Mon, 3 Feb 2020 14:25:02 +0100 Subject: vis: improve 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 --- main.c | 38 +++++++++++++++++++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) 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; -- cgit v1.2.3