fixes incsearch history handling
authorRobert Timm <mail@rtti.de>
Sat, 22 Apr 2017 22:55:48 +0000 (00:55 +0200)
committerRobert Timm <mail@rtti.de>
Sun, 23 Apr 2017 10:21:16 +0000 (12:21 +0200)
Refactores parts of command_search() (closes #372)
Fixes search using "/ register (type "/<enter>")

src/command.c
src/command.h
src/ex.c
src/main.c
src/main.h
src/normal.c

index 1ffb109..204bf05 100644 (file)
 #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);
-            };
+            }
         }
     }
 
index ba2ba46..16a5d25 100644 (file)
@@ -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
index 0949f55..7b154a5 100644 (file)
--- 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 */
index 8e38de2..9059a82 100644 (file)
@@ -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;
 
index 36fac57..5124c99 100644 (file)
@@ -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;
 };
 
index 31cdaa4..a951b6c 100644 (file)
@@ -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;