diff --git a/README.asciidoc b/README.asciidoc index 90ab8bcee..839b80c1f 100644 --- a/README.asciidoc +++ b/README.asciidoc @@ -149,8 +149,8 @@ Contributors, sorted by the number of commits in descending order: * Felix Van der Jeugt * Martin Tournoij * Raphael Pierzina -* Joel Torstensson * Ryan Roden-Corrent +* Joel Torstensson * Patric Schmitz * Claude * Corentin Julé diff --git a/doc/help/commands.asciidoc b/doc/help/commands.asciidoc index 10dda0517..97896ae64 100644 --- a/doc/help/commands.asciidoc +++ b/doc/help/commands.asciidoc @@ -94,13 +94,14 @@ How many pages to go back. [[bind]] === bind -Syntax: +:bind [*--mode* 'MODE'] [*--force*] 'key' 'command'+ +Syntax: +:bind [*--mode* 'MODE'] [*--force*] 'key' ['command']+ Bind a key to a command. ==== positional arguments * +'key'+: The keychain or special key (inside `<...>`) to bind. -* +'command'+: The command to execute, with optional args. +* +'command'+: The command to execute, with optional args, or not given to print the current binding. + ==== optional arguments * +*-m*+, +*--mode*+: A comma-separated list of modes to bind the key in (default: `normal`). diff --git a/qutebrowser/completion/models/instances.py b/qutebrowser/completion/models/instances.py index 002a8a815..1a3a95d3f 100644 --- a/qutebrowser/completion/models/instances.py +++ b/qutebrowser/completion/models/instances.py @@ -29,7 +29,8 @@ import functools from PyQt5.QtCore import pyqtSlot -from qutebrowser.completion.models import miscmodels, urlmodel, configmodel +from qutebrowser.completion.models import (miscmodels, urlmodel, configmodel, + base) from qutebrowser.utils import objreg, usertypes, log, debug from qutebrowser.config import configdata @@ -119,6 +120,13 @@ def init_session_completion(): _instances[usertypes.Completion.sessions] = model +def _init_empty_completion(): + """Initialize empty completion model.""" + log.completion.debug("Initializing empty completion.") + if usertypes.Completion.empty not in _instances: + _instances[usertypes.Completion.empty] = base.BaseCompletionModel() + + INITIALIZERS = { usertypes.Completion.command: _init_command_completion, usertypes.Completion.helptopic: _init_helptopic_completion, @@ -130,6 +138,7 @@ INITIALIZERS = { usertypes.Completion.quickmark_by_name: init_quickmark_completions, usertypes.Completion.bookmark_by_url: init_bookmark_completions, usertypes.Completion.sessions: init_session_completion, + usertypes.Completion.empty: _init_empty_completion, } diff --git a/qutebrowser/config/parsers/keyconf.py b/qutebrowser/config/parsers/keyconf.py index 487659984..5d9e3fc0d 100644 --- a/qutebrowser/config/parsers/keyconf.py +++ b/qutebrowser/config/parsers/keyconf.py @@ -27,7 +27,7 @@ from PyQt5.QtCore import pyqtSignal, QObject from qutebrowser.config import configdata, textwrapper from qutebrowser.commands import cmdutils, cmdexc -from qutebrowser.utils import log, utils, qtutils +from qutebrowser.utils import log, utils, qtutils, message, usertypes class KeyConfigError(Exception): @@ -150,19 +150,34 @@ class KeyConfigParser(QObject): data = str(self) f.write(data) - @cmdutils.register(instance='key-config', maxsplit=1, no_cmd_split=True) - def bind(self, key, command, *, mode=None, force=False): + @cmdutils.register(instance='key-config', maxsplit=1, no_cmd_split=True, + win_id='win_id', + completion=[usertypes.Completion.empty, + usertypes.Completion.command]) + def bind(self, key, win_id, command=None, *, mode=None, force=False): """Bind a key to a command. Args: key: The keychain or special key (inside `<...>`) to bind. - command: The command to execute, with optional args. + command: The command to execute, with optional args, or None to + print the current binding. mode: A comma-separated list of modes to bind the key in (default: `normal`). force: Rebind the key if it is already bound. """ if mode is None: mode = 'normal' + + if command is None: + cmd = self.get_bindings_for(mode).get(key, None) + if cmd is None: + message.info(win_id, "{} is unbound in {} mode".format( + key, mode)) + else: + message.info(win_id, "{} is bound to '{}' in {} mode".format( + key, cmd, mode)) + return + mode = self._normalize_sectname(mode) for m in mode.split(','): if m not in configdata.KEY_DATA: diff --git a/qutebrowser/utils/usertypes.py b/qutebrowser/utils/usertypes.py index 0af42b291..accbe9448 100644 --- a/qutebrowser/utils/usertypes.py +++ b/qutebrowser/utils/usertypes.py @@ -238,7 +238,8 @@ KeyMode = enum('KeyMode', ['normal', 'hint', 'command', 'yesno', 'prompt', # Available command completions Completion = enum('Completion', ['command', 'section', 'option', 'value', 'helptopic', 'quickmark_by_name', - 'bookmark_by_url', 'url', 'tab', 'sessions']) + 'bookmark_by_url', 'url', 'tab', 'sessions', + 'empty']) # Exit statuses for errors. Needs to be an int for sys.exit. diff --git a/tests/integration/features/keyinput.feature b/tests/integration/features/keyinput.feature index 1d930da24..4385c2357 100644 --- a/tests/integration/features/keyinput.feature +++ b/tests/integration/features/keyinput.feature @@ -6,46 +6,60 @@ Feature: Keyboard input # :bind Scenario: Binding a keychain - When I run :bind test1 message-info test1 - And I press the keys "test1" - Then the message "test1" should be shown + When I run :bind test01 message-info test01 + And I press the keys "test01" + Then the message "test01" should be shown Scenario: Binding an invalid command - When I run :bind test2 abcd + When I run :bind test02 abcd Then the error "Invalid command 'abcd'!" should be shown Scenario: Binding with invalid mode. - When I run :bind --mode abcd test3 message-info test3 + When I run :bind --mode abcd test03 message-info test03 Then the error "Invalid mode abcd!" should be shown Scenario: Double-binding a key - When I run :bind test4 message-info test4 - And I run :bind test4 message-info test4-2 - And I press the keys "test4" - Then the error "Duplicate keychain test4 - use --force to override!" should be shown - And the message "test4" should be shown + When I run :bind test04 message-info test04 + And I run :bind test04 message-info test04-2 + And I press the keys "test04" + Then the error "Duplicate keychain test04 - use --force to override!" should be shown + And the message "test04" should be shown Scenario: Double-binding with --force - When I run :bind test5 message-info test5 - And I run :bind --force test5 message-info test5-2 - And I press the keys "test5" - Then the message "test5-2" should be shown + When I run :bind test05 message-info test05 + And I run :bind --force test05 message-info test05-2 + And I press the keys "test05" + Then the message "test05-2" should be shown + + Scenario: Printing an unbound key + When I run :bind test06 + Then the message "test06 is unbound in normal mode" should be shown + + Scenario: Printing a bound key + When I run :bind test07 message-info foo + And I run :bind test07 + Then the message "test07 is bound to 'message-info foo' in normal mode" should be shown + + Scenario: Printing a bound key in a given mode + When I run :bind --mode=caret test08 message-info bar + And I run :bind --mode=caret test08 + Then the message "test08 is bound to 'message-info bar' in caret mode" should be shown # :unbind Scenario: Binding and unbinding a keychain - When I run :bind test6 message-error test6 - And I run :unbind test6 - And I press the keys "test6" - Then "test6" should not be logged + When I run :bind test09 message-error test09 + And I run :unbind test09 + And I press the keys "test09" + Then "test09" should not be logged Scenario: Unbinding with invalid mode. - When I run :unbind test7 abcd + When I run :unbind test10 abcd Then the error "Invalid mode abcd!" should be shown Scenario: Unbinding with invalid keychain. - When I run :unbind test8 - Then the error "Can't find binding 'test8' in section 'normal'!" should be shown + When I run :unbind test11 + Then the error "Can't find binding 'test11' in section 'normal'!" should be shown Scenario: Unbinding a built-in binding When I run :unbind o @@ -56,12 +70,12 @@ Feature: Keyboard input # :clear-keychain Scenario: Clearing the keychain - When I run :bind foo message-error test9 - And I run :bind bar message-info test9-2 + When I run :bind foo message-error test12 + And I run :bind bar message-info test12-2 And I press the keys "fo" And I run :clear-keychain And I press the keys "bar" - Then the message "test9-2" should be shown + Then the message "test12-2" should be shown # input -> forward-unbound-keys