Repository: qutebrowser/qutebrowser

Issue:
Cannot :bind to alias
`:bind` will fail with `invalid command` if you give it the name of an alias. However, you can bind to an alias by writing it in the config

Setting an alias does not update command completion
Run `set aliases qtb 'open -t qutebrowser.org'`. Press `:`. Note that `qtb` is not shown in command completion.



Discussion:

Resolving patch:
diff --git a/qutebrowser/completion/models/instances.py b/qutebrowser/completion/models/instances.py
--- a/qutebrowser/completion/models/instances.py
+++ b/qutebrowser/completion/models/instances.py
@@ -29,7 +29,7 @@
 
 from qutebrowser.completion.models import miscmodels, urlmodel, configmodel
 from qutebrowser.utils import objreg, usertypes, log, debug
-from qutebrowser.config import configdata
+from qutebrowser.config import configdata, config
 
 
 _instances = {}
@@ -155,6 +155,12 @@ def update(completions):
                 did_run.append(func)
 
 
+@config.change_filter('aliases', function=True)
+def _update_aliases():
+    """Update completions that include command aliases."""
+    update([usertypes.Completion.command])
+
+
 def init():
     """Initialize completions. Note this only connects signals."""
     quickmark_manager = objreg.get('quickmark-manager')
@@ -176,3 +182,5 @@ def init():
     keyconf = objreg.get('key-config')
     keyconf.changed.connect(
         functools.partial(update, [usertypes.Completion.command]))
+
+    objreg.get('config').changed.connect(_update_aliases)
diff --git a/qutebrowser/config/config.py b/qutebrowser/config/config.py
--- a/qutebrowser/config/config.py
+++ b/qutebrowser/config/config.py
@@ -36,7 +36,7 @@
 from PyQt5.QtCore import pyqtSignal, QObject, QUrl, QSettings
 
 from qutebrowser.config import configdata, configexc, textwrapper
-from qutebrowser.config.parsers import ini, keyconf
+from qutebrowser.config.parsers import ini
 from qutebrowser.commands import cmdexc, cmdutils
 from qutebrowser.utils import (message, objreg, utils, standarddir, log,
                                qtutils, error, usertypes)
@@ -178,6 +178,7 @@ def _init_key_config(parent):
     Args:
         parent: The parent to use for the KeyConfigParser.
     """
+    from qutebrowser.config.parsers import keyconf
     args = objreg.get('args')
     try:
         key_config = keyconf.KeyConfigParser(standarddir.config(), 'keys.conf',
diff --git a/qutebrowser/config/parsers/keyconf.py b/qutebrowser/config/parsers/keyconf.py
--- a/qutebrowser/config/parsers/keyconf.py
+++ b/qutebrowser/config/parsers/keyconf.py
@@ -25,7 +25,7 @@
 
 from PyQt5.QtCore import pyqtSignal, QObject
 
-from qutebrowser.config import configdata, textwrapper
+from qutebrowser.config import configdata, textwrapper, config
 from qutebrowser.commands import cmdutils, cmdexc
 from qutebrowser.utils import log, utils, qtutils, message, usertypes
 
@@ -352,7 +352,8 @@ def _validate_command(self, line):
                     line))
         commands = [c.split(maxsplit=1)[0].strip() for c in commands]
         for cmd in commands:
-            if cmd not in cmdutils.cmd_dict:
+            aliases = config.section('aliases')
+            if cmd not in cmdutils.cmd_dict and cmd not in aliases:
                 raise KeyConfigError("Invalid command '{}'!".format(cmd))
 
     def _read_command(self, line):


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
@@ -61,6 +61,18 @@ Feature: Keyboard input
         And I run :bind <ctrl-test23>
         Then the message "<ctrl-test23> is bound to 'message-info bar' in normal mode" should be shown
 
+    Scenario: Binding to an alias
+        When I run :set aliases 'mib' 'message-info baz'
+        And I run :bind test25 mib
+        And I press the keys "test25"
+        Then the message "baz" should be shown
+
+    Scenario: Printing a bound alias
+        When I run :set aliases 'mib' 'message-info baz'
+        And I run :bind <test26> mib
+        And I run :bind <test26>
+        Then the message "<test26> is bound to 'mib' in normal mode" should be shown
+
     # :unbind
 
     Scenario: Binding and unbinding a keychain
diff --git a/tests/unit/config/test_config.py b/tests/unit/config/test_config.py
--- a/tests/unit/config/test_config.py
+++ b/tests/unit/config/test_config.py
@@ -214,7 +214,7 @@ class TestKeyConfigParser:
 
     """Test config.parsers.keyconf.KeyConfigParser."""
 
-    def test_cmd_binding(self, cmdline_test):
+    def test_cmd_binding(self, cmdline_test, config_stub):
         """Test various command bindings.
 
         See https://github.com/The-Compiler/qutebrowser/issues/615
@@ -222,6 +222,7 @@ def test_cmd_binding(self, cmdline_test):
         Args:
             cmdline_test: A pytest fixture which provides testcases.
         """
+        config_stub.data = {'aliases': []}
         kcp = keyconf.KeyConfigParser(None, None)
         kcp._cur_section = 'normal'
         if cmdline_test.valid: