From 2536766cacdd5a38c56fd852e75f830328c84a8f Mon Sep 17 00:00:00 2001 From: Ryan Roden-Corrent Date: Mon, 2 May 2016 22:54:47 -0400 Subject: [PATCH 1/5] Run :bind to print the current binding. The arg is now optional. If omitted, :bind prints the current binding as a message. If --mode is given, the binding for that mode is printed. --- qutebrowser/config/parsers/keyconf.py | 21 +++++++++++++++++---- tests/integration/features/keyinput.feature | 14 ++++++++++++++ 2 files changed, 31 insertions(+), 4 deletions(-) diff --git a/qutebrowser/config/parsers/keyconf.py b/qutebrowser/config/parsers/keyconf.py index 487659984..74252cc92 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 class KeyConfigError(Exception): @@ -150,19 +150,32 @@ 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') + 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/tests/integration/features/keyinput.feature b/tests/integration/features/keyinput.feature index 1d930da24..656391de5 100644 --- a/tests/integration/features/keyinput.feature +++ b/tests/integration/features/keyinput.feature @@ -31,6 +31,20 @@ Feature: Keyboard input And I press the keys "test5" Then the message "test5-2" should be shown + Scenario: Printing an unbound key + When I run :bind test6 + Then the message "test6 is not bound in normal mode" should be shown + + Scenario: Printing a bound key + When I run :bind test6 message-info foo + And I run :bind test6 + Then the message "test6 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 test6 message-info bar + And I run :bind --mode=caret test6 + Then the message "test6 is bound to 'message-info bar' in caret mode" should be shown + # :unbind Scenario: Binding and unbinding a keychain From b8a593cac557f567a26614acebb4bbeab550f5a6 Mon Sep 17 00:00:00 2001 From: Ryan Roden-Corrent Date: Sat, 23 Apr 2016 00:24:53 -0400 Subject: [PATCH 2/5] Show command completions for :bind. All commands will be offered as completions for the argument of :bind. Due to the way completers parse the command line, the following bind --mode caret j will throw off completions as 'caret' is treated as a positional arg in terms of the argument count for completions. In the above example, completion will be triggered for 'j' and no completions will be given for the actual command. bind --mode=caret j will complete correctly, though completions are not filtered by the given mode. I attempted an approach to filter the commands based on the mode but it ended up being messy and flaky. --- qutebrowser/completion/models/instances.py | 11 ++++++++++- qutebrowser/config/parsers/keyconf.py | 6 ++++-- qutebrowser/utils/usertypes.py | 3 ++- 3 files changed, 16 insertions(+), 4 deletions(-) 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 74252cc92..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, message +from qutebrowser.utils import log, utils, qtutils, message, usertypes class KeyConfigError(Exception): @@ -151,7 +151,9 @@ class KeyConfigParser(QObject): f.write(data) @cmdutils.register(instance='key-config', maxsplit=1, no_cmd_split=True, - win_id='win_id') + 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. 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. From 90c42ff2e27752e7699d12ae055d98d554f27519 Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Tue, 10 May 2016 23:39:48 +0200 Subject: [PATCH 3/5] Regenerate docs --- README.asciidoc | 2 +- doc/help/commands.asciidoc | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) 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`). From ea243ae022d359b59a2cefb4fd0ddd41ac400101 Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Tue, 10 May 2016 23:46:02 +0200 Subject: [PATCH 4/5] Renumber keybindings in keyinput.feature An unique keybinding for each test means we have some level of isolation and can understand error messages more easily. As we're >10 now, let's use a leading zero to avoid shadowed keybindings. --- tests/integration/features/keyinput.feature | 64 ++++++++++----------- 1 file changed, 32 insertions(+), 32 deletions(-) diff --git a/tests/integration/features/keyinput.feature b/tests/integration/features/keyinput.feature index 656391de5..acc0fa62c 100644 --- a/tests/integration/features/keyinput.feature +++ b/tests/integration/features/keyinput.feature @@ -6,60 +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 test6 - Then the message "test6 is not bound in normal mode" should be shown + When I run :bind test06 + Then the message "test06 is not bound in normal mode" should be shown Scenario: Printing a bound key - When I run :bind test6 message-info foo - And I run :bind test6 - Then the message "test6 is bound to 'message-info foo' in normal mode" should be shown + 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 test6 message-info bar - And I run :bind --mode=caret test6 - Then the message "test6 is bound to 'message-info bar' in caret mode" should be shown + 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 @@ -70,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 From cb27dbbfb50981e44dd8de363088bdcecb157219 Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Tue, 10 May 2016 23:47:16 +0200 Subject: [PATCH 5/5] Fix error message check for :bind test --- tests/integration/features/keyinput.feature | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/integration/features/keyinput.feature b/tests/integration/features/keyinput.feature index acc0fa62c..4385c2357 100644 --- a/tests/integration/features/keyinput.feature +++ b/tests/integration/features/keyinput.feature @@ -33,7 +33,7 @@ Feature: Keyboard input Scenario: Printing an unbound key When I run :bind test06 - Then the message "test06 is not bound in normal mode" should be shown + 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