Repository: qutebrowser/qutebrowser

Issue:
Incremental search + Enter jumps to the next match
When I write `/search term` and press `Enter` to finish the prompt, qutebrowser jumps to the _second_ occurrence while the first occurrence is highlighted even before pressing `Enter`.

```
$ qutebrowser --version
[0121/170550.774588:WARNING:stack_trace_posix.cc(648)] Failed to open file: /tmp/.glhjvleX (deleted)
  Error: No such file or directory
[0121/170550.774652:WARNING:stack_trace_posix.cc(648)] Failed to open file: /home/lahwaacz/#7081286 (deleted)
  Error: No such file or directory
qutebrowser v1.1.0
Git commit: 
Backend: QtWebEngine (Chromium 61.0.3163.140)

CPython: 3.6.4
Qt: 5.10.0
PyQt: 5.9.2

sip: 4.19.6
colorama: no
pypeg2: 2.15
jinja2: 2.10
pygments: 2.2.0
yaml: 3.12
cssutils: no
attr: 17.4.0
PyQt5.QtWebEngineWidgets: yes
PyQt5.QtWebKitWidgets: no
pdf.js: 1.9.426 (/usr/share/pdf.js/build/pdf.js)
sqlite: 3.21.0
QtNetwork SSL: OpenSSL 1.1.0g  2 Nov 2017

Style: QFusionStyle
Platform: Linux-4.14.13-1-ARCH-x86_64-with-arch, 64bit
Linux distribution: Arch Linux (arch)
Frozen: False
Imported from /usr/lib/python3.6/site-packages/qutebrowser
Qt library executable path: /usr/lib/qt/libexec, data path: /usr/share/qt

Paths:
cache: /home/lahwaacz/.cache/qutebrowser
config: /home/lahwaacz/.config/qutebrowser
data: /home/lahwaacz/.local/share/qutebrowser
runtime: /run/user/1000/qutebrowser
system data: /usr/share/qutebrowser

Uptime: 0:00:00
```


Discussion:
I've seen this as well but can't reliably reproduce it.

cc @jupart 
Hmm, on my machine I can reproduce this every time. I'm still on qt5.7.1 though...
I'll check this out soon.
I've been looking at this off and on, comparing to Vim search functionality. We could eat an Enter key press after incremental search, but it seems kind of hacky to me. I noticed that in Neovim (maybe Vim too), while typing the search term with incremental search set, 

1. it searches to the first matched term and highlights it as you type. After you press the Enter key, 
2. it searches for all matching words in the buffer (all the open buffers actually I think) and highlights them in a different color. 

I'd like to make incremental search in qutebrowser work this way, as I think it's a good design.

My idea was to add a `search_once` browser command that accomplishes 1. that incremental search can use. Then on an Enter key press, we `search` as usual.
In Vim 8.0.1427 there is a `hlsearch` option which highlights all search matches when in normal mode (i.e. after pressing Enter in the search prompt) and an `incsearch` option which highlights _all_ matches as soon as you type them in the prompt. IIRC this is how the searching in qutebrowser used to work at some point. I'd like this issue to be about fixing the problem, not changing the behaviour to Neovim's - it's simpler as it doesn't need `search_once` and personally I find the Vim's behaviour better than Neovim's.
I've noticed this issue as well, and just wanted to make two quick comments.

1. This is specific to `<enter>`. If you hit `<esc>` instead, the search highlight remains, and the currently focused search is the first match. So, as a workaround, you can (train yourself to) hit `<esc>` (or `<ctrl-[>`) instead of `<enter>`.
2. One motivation (in case anyone needed one) for staying on the first match, instead of jumping to the second, is so that, if the first match is a link, then you can just hit `<enter>` a second time to follow the link. Obviously, hitting `<enter>` twice in quick succesion is way more comfortable than hitting `<esc>` then `<enter>` (and I myself have this bound to muscle memory from previous versions of qutebrowser and others).
Indeed, the second issue you mentioned is really bugging me, so I want to try to fix this before the next release, unless someone beats me to it.

Resolving patch:
diff --git a/qutebrowser/browser/commands.py b/qutebrowser/browser/commands.py
--- a/qutebrowser/browser/commands.py
+++ b/qutebrowser/browser/commands.py
@@ -1778,10 +1778,10 @@ def search(self, text="", reverse=False):
         """
         self.set_mark("'")
         tab = self._current_widget()
-        if tab.search.search_displayed:
-            tab.search.clear()
 
         if not text:
+            if tab.search.search_displayed:
+                tab.search.clear()
             return
 
         options = {
diff --git a/qutebrowser/browser/webengine/webenginetab.py b/qutebrowser/browser/webengine/webenginetab.py
--- a/qutebrowser/browser/webengine/webenginetab.py
+++ b/qutebrowser/browser/webengine/webenginetab.py
@@ -183,6 +183,12 @@ def wrapped_callback(found):
 
     def search(self, text, *, ignore_case='never', reverse=False,
                result_cb=None):
+        # Don't go to next entry on duplicate search
+        if self.text == text and self.search_displayed:
+            log.webview.debug("Ignoring duplicate search request"
+                              " for {}".format(text))
+            return
+
         self.text = text
         self._flags = QWebEnginePage.FindFlags(0)
         if self._is_case_sensitive(ignore_case):
diff --git a/qutebrowser/browser/webkit/webkittab.py b/qutebrowser/browser/webkit/webkittab.py
--- a/qutebrowser/browser/webkit/webkittab.py
+++ b/qutebrowser/browser/webkit/webkittab.py
@@ -146,8 +146,14 @@ def clear(self):
 
     def search(self, text, *, ignore_case='never', reverse=False,
                result_cb=None):
-        self.search_displayed = True
+        # Don't go to next entry on duplicate search
+        if self.text == text and self.search_displayed:
+            log.webview.debug("Ignoring duplicate search request"
+                              " for {}".format(text))
+            return
+
         self.text = text
+        self.search_displayed = True
         self._flags = QWebPage.FindWrapsAroundDocument
         if self._is_case_sensitive(ignore_case):
             self._flags |= QWebPage.FindCaseSensitively


Test patch:
diff --git a/tests/end2end/features/search.feature b/tests/end2end/features/search.feature
--- a/tests/end2end/features/search.feature
+++ b/tests/end2end/features/search.feature
@@ -52,6 +52,12 @@ Feature: Searching on a page
         And I wait for "search didn't find blub" in the log
         Then the warning "Text 'blub' not found on page!" should be shown
 
+    Scenario: Searching text duplicates
+        When I run :search foo
+        And I wait for "search found foo" in the log
+        And I run :search foo
+        Then "Ignoring duplicate search request for foo" should be logged
+
     ## search.ignore_case
 
     Scenario: Searching text with search.ignore_case = always