Repository: qutebrowser/qutebrowser

Issue:
History completion across fields
Versioning info:
https://paste.the-compiler.org/view/31238694

Running up to date Arch Linux 32, with qutebrowser from the repos.  I apologize for not tetsing the latest git version available, I don't have time to build right now.  The issue remains when using a new basedir.

When opening a webpage, the suggested results will include those whose URL ends with the beginning of the string you've typed and whose title begins with the rest of the string.

Steps to reproduce:
`$ qutebrowser -B /tmp/qutebrowsertmp/`
`:open https://qutebrowser.org/FAQ.html`
begin typing `:open mlfreq`

Expected behavior:
No results

Actual behavior:
qutebrowser FAQ is suggested

![image](https://user-images.githubusercontent.com/5490231/48035943-23cd3480-e134-11e8-8b35-370e75e91b08.png)

This only seems to apply to the history section, not bookmarks or quickmarks.


Discussion:
Debug log:

```
08:18:09 DEBUG    completion completionmodel:set_pattern:179 Setting completion pattern 'mlfreq'
08:18:09 DEBUG    sql        sql:run:207 Running SQL query: "SELECT url, title, strftime('%Y-%m-%d', last_atime, 'unixepoch', 'localtime') FROM CompletionHistory WHERE ((url || title) LIKE :0 escape '\')  ORDER BY last_atime DESC"
08:18:09 DEBUG    sql        sql:run:210 query bindings: {':0': '%mlfreq%'}
```

This is a side-effect of 636f9edff62fb121bb52a1c25ec5903d24a18074 and I'm not sure whether there's an easy solution for it... cc @rcorre.
It would be nice to be able to at least have highligting in that case. But it looks like the method that adds that styling only gets called per index, not per row. We could add some extra logic if the item text doesn't have the pattern in it to go fetch sibling items (that are also filter columns, which happen to coincide with the ones joined in the sql query for the history category) and concat the row and search in it and work the search match indices back to the individual items them hightlight them appropriately. And since that function should never (I assume) be called with a non empty pattern and rows that don't have a match it might even be reasonable. It seems like a yucky workaround though.

Resolving patch:
diff --git a/qutebrowser/completion/models/histcategory.py b/qutebrowser/completion/models/histcategory.py
--- a/qutebrowser/completion/models/histcategory.py
+++ b/qutebrowser/completion/models/histcategory.py
@@ -74,9 +74,10 @@ def set_pattern(self, pattern):
 
         # build a where clause to match all of the words in any order
         # given the search term "a b", the WHERE clause would be:
-        # ((url || title) LIKE '%a%') AND ((url || title) LIKE '%b%')
+        # ((url || ' ' || title) LIKE '%a%') AND
+        # ((url || ' ' || title) LIKE '%b%')
         where_clause = ' AND '.join(
-            "(url || title) LIKE :{} escape '\\'".format(i)
+            "(url || ' ' || title) LIKE :{} escape '\\'".format(i)
             for i in range(len(words)))
 
         # replace ' in timestamp-format to avoid breaking the query


Test patch:
diff --git a/tests/unit/completion/test_histcategory.py b/tests/unit/completion/test_histcategory.py
--- a/tests/unit/completion/test_histcategory.py
+++ b/tests/unit/completion/test_histcategory.py
@@ -82,6 +82,14 @@ def hist(init_sql, config_stub):
     ("ample itle",
      [('example.com', 'title'), ('example.com', 'nope')],
      [('example.com', 'title')]),
+
+    # https://github.com/qutebrowser/qutebrowser/issues/4411
+    ("mlfreq",
+     [('https://qutebrowser.org/FAQ.html', 'Frequently Asked Questions')],
+     []),
+    ("ml freq",
+     [('https://qutebrowser.org/FAQ.html', 'Frequently Asked Questions')],
+     [('https://qutebrowser.org/FAQ.html', 'Frequently Asked Questions')]),
 ])
 def test_set_pattern(pattern, before, after, model_validator, hist):
     """Validate the filtering and sorting results of set_pattern."""