From eb741c953d4b06bef6529f42641b3520ed992cd6 Mon Sep 17 00:00:00 2001 From: Robert Timm Date: Sun, 23 Apr 2017 00:55:48 +0200 Subject: [PATCH] fixes incsearch history handling Refactores parts of command_search() (closes #372) Fixes search using "/ register (type "/") --- src/command.c | 90 ++++++++++++++++++++++++++++++--------------------- src/command.h | 2 +- src/ex.c | 8 ++--- src/main.c | 2 +- src/main.h | 4 +-- src/normal.c | 11 +++---- 6 files changed, 64 insertions(+), 53 deletions(-) diff --git a/src/command.c b/src/command.c index 1ffb109..204bf05 100644 --- a/src/command.c +++ b/src/command.c @@ -31,67 +31,85 @@ #include "history.h" #include "main.h" -extern struct Vimb vb; - -gboolean command_search(Client *c, const Arg *arg) +gboolean command_search(Client *c, const Arg *arg, bool commit) { - const char *query; - gboolean forward; WebKitFindController *fc; + const char *query; + guint count; fc = webkit_web_view_get_find_controller(c->webview); + + g_assert(c); + g_assert(arg); + g_assert(fc); + if (arg->i == 0) { + webkit_find_controller_search_finish(fc); + /* Clear the input only if the search is active. */ if (c->state.search.active) { vb_echo(c, MSG_NORMAL, FALSE, ""); } - webkit_find_controller_search_finish(fc); + + c->state.search.active = FALSE; + c->state.search.direction = 0; c->state.search.matches = 0; - c->state.search.active = FALSE; + vb_statusbar_update(c); return TRUE; } - /* copy search query for later use */ - if (arg->s) { - /* set search direction only when the searching is started */ - c->state.search.direction = arg->i > 0 ? 1 : -1; - query = arg->s; - /* add new search query to history and search register */ - vb_register_add(c, '/', query); - history_add(c, HISTORY_SEARCH, query, NULL); - } else { - /* no search phrase given - continue a previous search */ - query = vb_register_get(c, '/'); - } + query = arg->s; + count = abs(arg->i); - forward = (arg->i * c->state.search.direction) > 0; + /* Only committed search strings adjust registers and are recorded in + * history, intermediate strings (while using incsearch) don't. */ + if (commit) { + if (query) { + history_add(c, HISTORY_SEARCH, query, NULL); + vb_register_add(c, '/', query); + } else { + /* Committed search without string re-searches last string. */ + query = vb_register_get(c, '/'); + } + } + /* Hand the query string to webkit's find controller. */ if (query) { - guint count = abs(arg->i); - - if (!c->state.search.active) { - webkit_find_controller_search(fc, query, - WEBKIT_FIND_OPTIONS_CASE_INSENSITIVE | - WEBKIT_FIND_OPTIONS_WRAP_AROUND | - (forward ? WEBKIT_FIND_OPTIONS_NONE : WEBKIT_FIND_OPTIONS_BACKWARDS), - G_MAXUINT); - /* TODO get the number of matches */ - c->state.search.active = TRUE; - /* Skip first search because the first match is already - * highlighted on search start. */ - count -= 1; + /* Force a fresh start in order to have webkit select the first match + * on the page. Without this workaround the first selected match + * depends on the most recent selection or caret position (even when + * caret browsing is disabled). */ + if(commit) { + webkit_find_controller_search(fc, "", WEBKIT_FIND_OPTIONS_NONE, G_MAXUINT); } - if (forward) { + webkit_find_controller_search(fc, query, + WEBKIT_FIND_OPTIONS_CASE_INSENSITIVE | + WEBKIT_FIND_OPTIONS_WRAP_AROUND | + (arg->i > 0 ? WEBKIT_FIND_OPTIONS_NONE : WEBKIT_FIND_OPTIONS_BACKWARDS), + G_MAXUINT); + + c->state.search.active = TRUE; + c->state.search.direction = arg->i > 0 ? 1 : -1; + /* TODO get the number of matches */ + + /* Skip first search because the first match is already + * highlighted on search start. */ + count -= 1; + } + + /* Step through searchs result focus according to arg->i. */ + if (c->state.search.active) { + if (arg->i * c->state.search.direction > 0) { while (count--) { webkit_find_controller_search_next(fc); - }; + } } else { while (count--) { webkit_find_controller_search_previous(fc); - }; + } } } diff --git a/src/command.h b/src/command.h index ba2ba46..16a5d25 100644 --- a/src/command.h +++ b/src/command.h @@ -43,7 +43,7 @@ enum { }; #endif -gboolean command_search(Client *c, const Arg *arg); +gboolean command_search(Client *c, const Arg *arg, bool commit); gboolean command_yank(Client *c, const Arg *arg, char buf); gboolean command_save(Client *c, const Arg *arg); #ifdef FEATURE_QUEUE diff --git a/src/ex.c b/src/ex.c index 0949f55..7b154a5 100644 --- a/src/ex.c +++ b/src/ex.c @@ -402,8 +402,7 @@ void ex_input_changed(Client *c, const char *text) case '/': /* fall through */ case '?': if (c->config.incsearch) { - command_search(c, &((Arg){0, NULL})); /* stop last search */ - command_search(c, &((Arg){*text == '/' ? 1 : -1, (char*)text + 1})); + command_search(c, &((Arg){*text == '/' ? 1 : -1, (char*)text + 1}), FALSE); } break; } @@ -511,10 +510,7 @@ static void input_activate(Client *c) case '?': vb_enter(c, 'n'); - /* start search, if incsearch, it's done while typing */ - if (!c->config.incsearch) { - command_search(c, &((Arg){count, cmd})); - } + command_search(c, &((Arg){count, strlen(cmd) ? cmd : NULL}), TRUE); break; case ';': /* fall through */ diff --git a/src/main.c b/src/main.c index 8e38de2..9059a82 100644 --- a/src/main.c +++ b/src/main.c @@ -1202,7 +1202,7 @@ static void on_webview_load_changed(WebKitWebView *webview, marks_clear(c); /* Unset possible last search. */ - command_search(c, &((Arg){0})); + command_search(c, &(Arg){0, NULL}, FALSE); break; diff --git a/src/main.h b/src/main.h index 36fac57..5124c99 100644 --- a/src/main.h +++ b/src/main.h @@ -173,9 +173,9 @@ struct State { WebKitHitTestResult *hit_test_result; struct { - gboolean active; /* indicate if there is a acitve search */ + gboolean active; /* indicate if there is a active search */ short direction; /* last direction 1 forward, -1 backward */ - int matches; /* number of matches search results */ + int matches; /* number of matching search results */ } search; }; diff --git a/src/normal.c b/src/normal.c index 31cdaa4..a951b6c 100644 --- a/src/normal.c +++ b/src/normal.c @@ -227,7 +227,7 @@ void normal_enter(Client *c) */ void normal_leave(Client *c) { - command_search(c, &((Arg){0})); + command_search(c, &((Arg){0, NULL}), FALSE); } /** @@ -344,7 +344,7 @@ static VbResult normal_clear_input(Client *c, const NormalCmdInfo *info) vb_echo(c, MSG_NORMAL, FALSE, ""); /* Unset search highlightning. */ - command_search(c, &((Arg){0})); + command_search(c, &((Arg){0, NULL}), FALSE); return RESULT_COMPLETE; } @@ -728,7 +728,7 @@ static VbResult normal_search(Client *c, const NormalCmdInfo *info) { int count = (info->count > 0) ? info->count : 1; - command_search(c, &((Arg){info->key == 'n' ? count : -count})); + command_search(c, &((Arg){info->key == 'n' ? count : -count, NULL}), FALSE); return RESULT_COMPLETE; } @@ -747,10 +747,7 @@ static VbResult normal_search_selection(Client *c, const NormalCmdInfo *info) } count = (info->count > 0) ? info->count : 1; - /* stopp possible existing search and the search highlights before - * starting the new search query */ - command_search(c, &((Arg){0})); - command_search(c, &((Arg){info->key == '*' ? count : -count, query})); + command_search(c, &((Arg){info->key == '*' ? count : -count, query}), TRUE); g_free(query); return RESULT_COMPLETE; -- 2.20.1