internlm/SWE-Fixer-Train-110K huggingface dataset:
Repository: qutebrowser/qutebrowser

Issue:
q<Fn> tries to record macro
I'm not sure if this is solved in #2113, but currently when doing `q<Fn>` I get `Recording macro ''...`

cc @blyxxyz


Discussion:
I can't reproduce it on either branch. I remember that another laptop got a `XF86WakeUp` KeyPress event when pressing Fn, though. Can you use `xev` to check what kind of X events Fn sends?

I can record macros for other weird keys, like `XF86AudioMute`. Ignoring them would be better.

Yep, `XF86WakeUp` indeed.


Resolving patch:
diff --git a/qutebrowser/keyinput/modeparsers.py b/qutebrowser/keyinput/modeparsers.py
--- a/qutebrowser/keyinput/modeparsers.py
+++ b/qutebrowser/keyinput/modeparsers.py
@@ -294,12 +294,12 @@ def handle(self, e):
         if super().handle(e):
             return True
 
-        if utils.keyevent_to_string(e) is None:
-            # this is a modifier key, let it pass and keep going
-            return False
-
         key = e.text()
 
+        if key == '' or utils.keyevent_to_string(e) is None:
+            # this is not a proper register key, let it pass and keep going
+            return False
+
         tabbed_browser = objreg.get('tabbed-browser', scope='window',
                                     window=self._win_id)
         macro_recorder = objreg.get('macro-recorder')


Test patch:
diff --git a/tests/end2end/features/keyinput.feature b/tests/end2end/features/keyinput.feature
--- a/tests/end2end/features/keyinput.feature
+++ b/tests/end2end/features/keyinput.feature
@@ -260,3 +260,19 @@ Feature: Keyboard input
         When I run :record-macro
         And I press the key "<Escape>"
         Then "Leaving mode KeyMode.record_macro (reason: leave current)" should be logged
+
+    Scenario: Ignoring non-register keys
+        Given I open data/scroll/simple.html
+        And I run :tab-only
+        When I run :scroll down with count 2
+        And I wait until the scroll position changed
+        And I run :record-macro
+        And I press the key "<Menu>"
+        And I press the key "c"
+        And I run :scroll up
+        And I wait until the scroll position changed
+        And I run :record-macro
+        And I run :run-macro
+        And I press the key "c"
+        And I wait until the scroll position changed to 0/0
+        Then the page should not be scrolled
Repository: qutebrowser/qutebrowser

Issue:
When copying link location for mails, `mailto:` should be removed.
In the crash dialog and on web pages.



Discussion:

Resolving patch:
diff --git a/qutebrowser/browser/hints.py b/qutebrowser/browser/hints.py
--- a/qutebrowser/browser/hints.py
+++ b/qutebrowser/browser/hints.py
@@ -235,7 +235,10 @@ def yank(self, url, context):
         sel = (context.target == Target.yank_primary and
                utils.supports_selection())
 
-        urlstr = url.toString(QUrl.FullyEncoded | QUrl.RemovePassword)
+        flags = QUrl.FullyEncoded | QUrl.RemovePassword
+        if url.scheme() == 'mailto':
+            flags |= QUrl.RemoveScheme
+        urlstr = url.toString(flags)
         utils.set_clipboard(urlstr, selection=sel)
 
         msg = "Yanked URL to {}: {}".format(


Test patch:
diff --git a/tests/end2end/data/email_address.html b/tests/end2end/data/email_address.html
new file mode 100644
--- /dev/null
+++ b/tests/end2end/data/email_address.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+
+<html>
+    <head>
+        <meta charset="utf-8">
+        <title>Email address</title>
+    </head>
+    <body>
+        <a href="mailto:nobody">Email address</a>
+    </body>
+</html>
diff --git a/tests/end2end/features/hints.feature b/tests/end2end/features/hints.feature
--- a/tests/end2end/features/hints.feature
+++ b/tests/end2end/features/hints.feature
@@ -110,6 +110,12 @@ Feature: Using hints
         And I hint with args "links yank-primary" and follow a
         Then the clipboard should contain "http://localhost:(port)/data/hello.txt"
 
+    Scenario: Yanking email address to clipboard
+        When I run :debug-set-fake-clipboard
+        And I open data/email_address.html
+        And I hint with args "links yank" and follow a
+        Then the clipboard should contain "nobody"
+
     Scenario: Rapid hinting
         When I open data/hints/rapid.html in a new tab
         And I run :tab-only
Repository: qutebrowser/qutebrowser

Issue:
Disable the automatic "Run :adblock-update" info message on startup
Every time I start qutebrowser I got a message:

> Run :adblock-update to get adblock lists

I've set `host-blocking-enabled = false` in the config, because I have my own hosts file in /etc + I have privoxy.

I couldn't find a way to disable this message. I searched in the config, in the man page, in the help, here through the issues... Am I missing something? :confused: 


Discussion:
A `touch ~/.local/share/qutebrowser/blocked-hosts` should make it go away, but I agree it should be hidden when host blocking is disabled.
I created the file, it's okay now, thanks.

Resolving patch:
diff --git a/qutebrowser/browser/adblock.py b/qutebrowser/browser/adblock.py
--- a/qutebrowser/browser/adblock.py
+++ b/qutebrowser/browser/adblock.py
@@ -165,7 +165,8 @@ def read_hosts(self):
         if not found:
             args = objreg.get('args')
             if (config.get('content', 'host-block-lists') is not None and
-                    args.basedir is None):
+                    args.basedir is None and
+                    config.get('content', 'host-blocking-enabled')):
                 message.info("Run :adblock-update to get adblock lists.")
 
     @cmdutils.register(instance='host-blocker')


Test patch:
Repository: qutebrowser/qutebrowser

Issue:
Add -s argument to `open` to use HTTPS instead of HTTP
I really want to open HTTPS by default. I always hit `t` or `o` and put `https://` manually after `:open `. But this is too much work (still nothing compared to using the mouse, which requires moving my entire arm! But nonetheless it is relatively too much work, at least unncessary).

So far I worked around this by defining `t` and `o` to map to `:open -t https://` and `:open https://`, respectively (thanks to The-Compiler for suggesting this quick workaround). So when I type `t` or `o`, I get something like `:open -t https://` pre-filled. This is very nice.

But the problem is when I want to use search engine keywords. `:open -t https://ddgo lol`, where `ddgo` is a search engine keyword to search keyword `lol` in search engine DuckDuckGo, will not work as expected. This is why I think mapping `t` (or `o`) to `:open -t https://` is not a perfect solution, as it causes me to delete the prefixed `https://` every time I want to use a search keyword (which partly defeats the purpose of using a search keyword which is to save time to begin with, as I end up wasting time deleting the `https://`).

I think the real solution is to introduce a new argument to `:open`, perhaps `-s` to force the potocol to be HTTPS. Then, I can map `t` to `:open -t -s` and everything would work peacefully, including my search engine keywords, without needing to delete `https://`.


Discussion:

Resolving patch:
diff --git a/qutebrowser/browser/commands.py b/qutebrowser/browser/commands.py
--- a/qutebrowser/browser/commands.py
+++ b/qutebrowser/browser/commands.py
@@ -236,7 +236,7 @@ def tab_close(self, prev=False, next_=False, opposite=False, count=None):
     @cmdutils.argument('url', completion=usertypes.Completion.url)
     @cmdutils.argument('count', count=True)
     def openurl(self, url=None, implicit=False,
-                bg=False, tab=False, window=False, count=None):
+                bg=False, tab=False, window=False, count=None, secure=False):
         """Open a URL in the current/[count]th tab.
 
         If the URL contains newlines, each line gets opened in its own tab.
@@ -249,6 +249,7 @@ def openurl(self, url=None, implicit=False,
             implicit: If opening a new tab, treat the tab as implicit (like
                       clicking on a link).
             count: The tab index to open the URL in, or None.
+            secure: Force HTTPS.
         """
         if url is None:
             urls = [config.get('general', 'default-page')]
@@ -256,6 +257,8 @@ def openurl(self, url=None, implicit=False,
             urls = self._parse_url_input(url)
 
         for i, cur_url in enumerate(urls):
+            if secure:
+                cur_url.setScheme('https')
             if not window and i > 0:
                 tab = False
                 bg = True


Test patch:
Repository: qutebrowser/qutebrowser

Issue:
Crash with invalid PAC file
With this PAC file:

```js
function FindProxyForURL(url, host) {
  return 'SOCKS5 172.26.133.85:1080';
}
```

we get:

```
13:29:34 ERROR: Error in PAC resolution: Unknown proxy type: SOCKS5.
Traceback (most recent call last):
  File "/home/florian/proj/qutebrowser/git/qutebrowser/browser/network/pac.py", line 306, in resolve
    return self._pac.resolve(query, from_file=from_file)
  File "/home/florian/proj/qutebrowser/git/qutebrowser/browser/network/pac.py", line 225, in resolve
    return self._parse_proxy_string(result_str)
  File "/home/florian/proj/qutebrowser/git/qutebrowser/browser/network/pac.py", line 170, in _parse_proxy_string
    return [PACResolver._parse_proxy_entry(x) for x in proxies]
  File "/home/florian/proj/qutebrowser/git/qutebrowser/browser/network/pac.py", line 170, in <listcomp>
    return [PACResolver._parse_proxy_entry(x) for x in proxies]
  File "/home/florian/proj/qutebrowser/git/qutebrowser/browser/network/pac.py", line 165, in _parse_proxy_entry
    raise ParseProxyError(err.format(config[0]))
qutebrowser.browser.network.pac.ParseProxyError: Unknown proxy type: SOCKS5
```

```
13:29:34 ERROR: Uncaught exception
Traceback (most recent call last):
  File "/home/florian/proj/qutebrowser/git/qutebrowser/browser/network/proxy.py", line 69, in queryProxy
    for p in proxies:
TypeError: 'QNetworkProxy' object is not iterable
```

Also, maybe that file should be parsable? I'm told it works in other browsers.

cc @abbradar @amosbird


Discussion:

Resolving patch:
diff --git a/qutebrowser/browser/network/pac.py b/qutebrowser/browser/network/pac.py
--- a/qutebrowser/browser/network/pac.py
+++ b/qutebrowser/browser/network/pac.py
@@ -155,7 +155,7 @@ def _parse_proxy_entry(proxy_str):
                 raise ParseProxyError("Invalid number of parameters for PROXY")
             host, port = PACResolver._parse_proxy_host(config[1])
             return QNetworkProxy(QNetworkProxy.HttpProxy, host, port)
-        elif config[0] == "SOCKS":
+        elif config[0] in ["SOCKS", "SOCKS5"]:
             if len(config) != 2:
                 raise ParseProxyError("Invalid number of parameters for SOCKS")
             host, port = PACResolver._parse_proxy_host(config[1])


Test patch:
Repository: qutebrowser/qutebrowser

Issue:
AttributeError: 'NoneType' object has no attribute 'column_widths'
Someone has reported this 5 times in a row, unfortunately without any contact information. I'm not sure how it happens, but it seems to be a fresh first-time start of qutebrowser, with `quickstart.html` being opened and all.

```
[...]
17:18:41 DEBUG    webview    tabbedbrowser:on_title_changed:561 Changing title for idx 0 to 'qutebrowser quickstart | qutebrowser'
17:18:41 ERROR    misc       crashsignal:exception_hook:210 Uncaught exception
Traceback (most recent call last):
  File "/usr/lib/python3.6/site-packages/qutebrowser/completion/completionwidget.py", line 359, in resizeEvent
    self._resize_columns()
  File "/usr/lib/python3.6/site-packages/qutebrowser/completion/completionwidget.py", line 154, in _resize_columns
    column_widths = self.model().column_widths
AttributeError: 'NoneType' object has no attribute 'column_widths'
```

This is on Qt 5.9.1 and 630e9ebd6. I don't know why their completion widget would ever get a `resizeEvent` while hidden (because there's no model) - but if it's not reproducable, I guess we should just abort there if there's no model.

cc @rcorre 


Discussion:

Resolving patch:
diff --git a/qutebrowser/completion/completionwidget.py b/qutebrowser/completion/completionwidget.py
--- a/qutebrowser/completion/completionwidget.py
+++ b/qutebrowser/completion/completionwidget.py
@@ -148,6 +148,8 @@ def _on_config_changed(self, section, option):
 
     def _resize_columns(self):
         """Resize the completion columns based on column_widths."""
+        if self.model() is None:
+            return
         width = self.size().width()
         column_widths = self.model().column_widths
         pixel_widths = [(width * perc // 100) for perc in column_widths]


Test patch:
diff --git a/tests/unit/completion/test_completionwidget.py b/tests/unit/completion/test_completionwidget.py
--- a/tests/unit/completion/test_completionwidget.py
+++ b/tests/unit/completion/test_completionwidget.py
@@ -240,3 +240,8 @@ def test_completion_item_del_no_selection(completionview):
     with pytest.raises(cmdexc.CommandError, match='No item selected!'):
         completionview.completion_item_del()
     assert not func.called
+
+
+def test_resize_no_model(completionview, qtbot):
+    """Ensure no crash if resizeEvent is triggered with no model (#2854)."""
+    completionview.resizeEvent(None)
Repository: qutebrowser/qutebrowser

Issue:
Shift-tab and ctrl-d hides preloaded items
Like mentioned by @pkillnine in #2842, doing `shift-tab` then `ctrl-d` in the `:open` completion hides the items below the current one.

cc @rcorre 


Discussion:

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
@@ -93,10 +93,12 @@ def set_pattern(self, pattern):
             self._query.run(pat=pattern)
         self.setQuery(self._query)
 
-    def removeRows(self, _row, _count, _parent=None):
+    def removeRows(self, row, _count, _parent=None):
         """Override QAbstractItemModel::removeRows to re-run sql query."""
         # re-run query to reload updated table
         with debug.log_time('sql', 'Re-running completion query post-delete'):
             self._query.run()
         self.setQuery(self._query)
+        while self.rowCount() < row:
+            self.fetchMore()
         return True


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
@@ -22,7 +22,6 @@
 import datetime
 
 import pytest
-from PyQt5.QtCore import QModelIndex
 
 from qutebrowser.misc import sql
 from qutebrowser.completion.models import histcategory
@@ -147,6 +146,22 @@ def test_remove_rows(hist, model_validator):
     model_validator.set_model(cat)
     cat.set_pattern('')
     hist.delete('url', 'foo')
-    # histcategory does not care which index was removed, it just regenerates
-    cat.removeRows(QModelIndex(), 1)
+    cat.removeRows(0, 1)
     model_validator.validate([('bar', 'Bar', '')])
+
+
+def test_remove_rows_fetch(hist):
+    """removeRows should fetch enough data to make the current index valid."""
+    # we cannot use model_validator as it will fetch everything up front
+    hist.insert_batch({'url': [str(i) for i in range(300)]})
+    cat = histcategory.HistoryCategory()
+    cat.set_pattern('')
+
+    # sanity check that we didn't fetch everything up front
+    assert cat.rowCount() < 300
+    cat.fetchMore()
+    assert cat.rowCount() == 300
+
+    hist.delete('url', '298')
+    cat.removeRows(297, 1)
+    assert cat.rowCount() == 299
Repository: qutebrowser/qutebrowser

Issue:
:session-save option -o should imply -p
<!-- If this is a bug report, please remember to mention your version info from
`:open qute:version` or `qutebrowser --version` -->
The current behavior of the `:session-save` command with the `-o`/`--only-active-window` option on a private window is to save no tabs. It should still save tabs if a private window is selected, i.e. automatically imply the `-p`/`--with-private` option.


Discussion:

Resolving patch:
diff --git a/qutebrowser/misc/sessions.py b/qutebrowser/misc/sessions.py
--- a/qutebrowser/misc/sessions.py
+++ b/qutebrowser/misc/sessions.py
@@ -485,7 +485,7 @@ def session_save(self, name: str = default, current=False, quiet=False,
         try:
             if only_active_window:
                 name = self.save(name, only_window=win_id,
-                                 with_private=with_private)
+                                 with_private=True)
             else:
                 name = self.save(name, with_private=with_private)
         except SessionError as e:


Test patch:
diff --git a/tests/end2end/features/private.feature b/tests/end2end/features/private.feature
--- a/tests/end2end/features/private.feature
+++ b/tests/end2end/features/private.feature
@@ -153,3 +153,26 @@ Feature: Using private browsing
               - history:
                 - url: http://localhost:*/data/numbers/1.txt
                 - url: http://localhost:*/data/numbers/2.txt
+
+
+  Scenario: Saving a private session with only-active-window
+        When I open data/numbers/1.txt
+        And I open data/numbers/2.txt in a new tab
+        And I open data/numbers/3.txt in a private window
+        And I open data/numbers/4.txt in a new tab
+        And I open data/numbers/5.txt in a new tab
+        And I run :session-save --only-active-window window_session_name
+        And I run :window-only
+        And I run :tab-only
+        And I run :session-load -c window_session_name
+        And I wait until data/numbers/5.txt is loaded
+        Then the session should look like:
+            windows:
+                - tabs:
+                    - history:
+                        - url: http://localhost:*/data/numbers/3.txt
+                    - history:
+                        - url: http://localhost:*/data/numbers/4.txt
+                    - history:
+                        - active: true
+                          url: http://localhost:*/data/numbers/5.txt
Repository: qutebrowser/qutebrowser

Issue:
Use CommandParser for configmodel.bind
In the `new-config` branch, there's a `CommandParser` in `commands/runners.py` which got split off from `CommandRunner` and can be used standalone. Various places doing their own command parsing got updated accordingly, but `configmodel.bind` is still doing its own parsing. An example how it's used, from `:bind`:

https://github.com/qutebrowser/qutebrowser/blob/2117824cf9fdc47ea6fd9457c12cecbac117202e/qutebrowser/config/config.py#L179-L189

Split off from #2779, cc @rcorre - if you want to take a look at this, feel free to do a PR against `new-config`, or wait until that's merged and then do one against `master`.


Discussion:

Resolving patch:
diff --git a/qutebrowser/completion/models/configmodel.py b/qutebrowser/completion/models/configmodel.py
--- a/qutebrowser/completion/models/configmodel.py
+++ b/qutebrowser/completion/models/configmodel.py
@@ -21,7 +21,7 @@
 
 from qutebrowser.config import configdata, configexc
 from qutebrowser.completion.models import completionmodel, listcategory, util
-from qutebrowser.commands import cmdutils
+from qutebrowser.commands import runners
 
 
 def option(*, info):
@@ -71,8 +71,8 @@ def bind(key, *, info):
     cmd_text = info.keyconf.get_command(key, 'normal')
 
     if cmd_text:
-        cmd_name = cmd_text.split(' ')[0]
-        cmd = cmdutils.cmd_dict.get(cmd_name)
+        parser = runners.CommandParser()
+        cmd = parser.parse(cmd_text).cmd
         data = [(cmd_text, cmd.desc, key)]
         model.add_category(listcategory.ListCategory("Current", data))
 


Test patch:
diff --git a/tests/unit/completion/test_models.py b/tests/unit/completion/test_models.py
--- a/tests/unit/completion/test_models.py
+++ b/tests/unit/completion/test_models.py
@@ -573,6 +573,24 @@ def test_bind_completion(qtmodeltester, cmdutils_stub, config_stub,
     })
 
 
+def test_bind_completion_no_current(qtmodeltester, cmdutils_stub, config_stub,
+                                    key_config_stub, configdata_stub, info):
+    """Test keybinding completion with no current binding. """
+    model = configmodel.bind('x', info=info)
+    model.set_pattern('')
+    qtmodeltester.data_display_may_return_none = True
+    qtmodeltester.check(model)
+
+    _check_completions(model, {
+        "Commands": [
+            ('open', 'open a url', ''),
+            ('q', "Alias for 'quit'", ''),
+            ('quit', 'quit qutebrowser', 'ZQ, <ctrl+q>'),
+            ('scroll', 'Scroll the current tab in the given direction.', '')
+        ],
+    })
+
+
 def test_url_completion_benchmark(benchmark, info,
                                   quickmark_manager_stub,
                                   bookmark_manager_stub,
Repository: qutebrowser/qutebrowser

Issue:
Add small delay before updating completion
A small delay before updating the completion might help to reduce load when an user is e.g. holding backspace.



Discussion:

Resolving patch:
diff --git a/qutebrowser/completion/completer.py b/qutebrowser/completion/completer.py
--- a/qutebrowser/completion/completer.py
+++ b/qutebrowser/completion/completer.py
@@ -196,14 +196,25 @@ def schedule_completion_update(self):
 
         For performance reasons we don't want to block here, instead we do this
         in the background.
+
+        We delay the update only if we've already input some text and ignore
+        updates if the text is shorter than completion.min_chars (unless we're
+        hitting backspace in which case updates won't be ignored).
         """
-        if (self._cmd.cursorPosition() == self._last_cursor_pos and
+        _cmd, _sep, rest = self._cmd.text().partition(' ')
+        input_length = len(rest)
+        if (0 < input_length < config.val.completion.min_chars and
+                self._cmd.cursorPosition() > self._last_cursor_pos):
+            log.completion.debug("Ignoring update because the length of "
+                                 "the text is less than completion.min_chars.")
+        elif (self._cmd.cursorPosition() == self._last_cursor_pos and
                 self._cmd.text() == self._last_text):
             log.completion.debug("Ignoring update because there were no "
                                  "changes.")
         else:
             log.completion.debug("Scheduling completion update.")
-            self._timer.start()
+            start_delay = config.val.completion.delay if self._last_text else 0
+            self._timer.start(start_delay)
         self._last_cursor_pos = self._cmd.cursorPosition()
         self._last_text = self._cmd.text()
 


Test patch:
diff --git a/tests/helpers/stubs.py b/tests/helpers/stubs.py
--- a/tests/helpers/stubs.py
+++ b/tests/helpers/stubs.py
@@ -377,7 +377,9 @@ def setSingleShot(self, singleshot):
     def isSingleShot(self):
         return self._singleshot
 
-    def start(self):
+    def start(self, interval=None):
+        if interval:
+            self._interval = interval
         self._started = True
 
     def stop(self):
@@ -396,7 +398,7 @@ class InstaTimer(QObject):
 
     timeout = pyqtSignal()
 
-    def start(self):
+    def start(self, interval=None):
         self.timeout.emit()
 
     def setSingleShot(self, yes):