-
-
Notifications
You must be signed in to change notification settings - Fork 1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Map keychains in passthrough-keymodes #1044
Comments
This isn't possible right now, sorry - but let's add it to the TODO 😉 #319 is somewhat related. |
👍 |
Partial work on this from @MichaelMackus in #3075: From 77b7d2287fe906229412255a06afdbe1b4564f02 Mon Sep 17 00:00:00 2001
From: Michael Mackus <michaelmackus@gmail.com>
Date: Sat, 30 Sep 2017 11:30:09 -0700
Subject: [PATCH 1/6] Add base KeyChainParser for passthrough modes
---
qutebrowser/keyinput/keyparser.py | 52 +++++++++++++++++++++++++++++++++++--
qutebrowser/keyinput/modeparsers.py | 32 +++--------------------
2 files changed, 53 insertions(+), 31 deletions(-)
diff --git a/qutebrowser/keyinput/keyparser.py b/qutebrowser/keyinput/keyparser.py
index 8fcb53035c..76c099a106 100644
--- a/qutebrowser/keyinput/keyparser.py
+++ b/qutebrowser/keyinput/keyparser.py
@@ -21,12 +21,61 @@
import traceback
+from PyQt5.QtCore import pyqtSlot
+
from qutebrowser.keyinput.basekeyparser import BaseKeyParser
from qutebrowser.utils import message, utils
from qutebrowser.commands import runners, cmdexc
+class KeyChainParser(BaseKeyParser):
+ """KeyChainParser which implements chaining of multiple keys."""
+ def __init__(self, win_id, parent=None):
+ super().__init__(win_id, parent, supports_count=True,
+ supports_chains=True)
+ self._partial_timer = usertypes.Timer(self, 'partial-match')
+ self._partial_timer.setSingleShot(True)
+
+ def __repr__(self):
+ return utils.get_repr(self)
+
+ def _handle_single_key(self, e):
+ """Override _handle_single_key to abort if the key is a startchar.
-class CommandKeyParser(BaseKeyParser):
+ Args:
+ e: the KeyPressEvent from Qt.
+
+ Return:
+ A self.Match member.
+ """
+ match = super()._handle_single_key(e)
+ if match == self.Match.partial:
+ timeout = config.val.input.partial_timeout
+ if timeout != 0:
+ self._partial_timer.setInterval(timeout)
+ self._partial_timer.timeout.connect(self._clear_partial_match)
+ self._partial_timer.start()
+ return match
+
+ @pyqtSlot()
+ def _clear_partial_match(self):
+ """Clear a partial keystring after a timeout."""
+ self._debug_log("Clearing partial keystring {}".format(
+ self._keystring))
+ self._keystring = ''
+ self.keystring_updated.emit(self._keystring)
+
+ @pyqtSlot()
+ def _stop_timers(self):
+ super()._stop_timers()
+ self._partial_timer.stop()
+ try:
+ self._partial_timer.timeout.disconnect(self._clear_partial_match)
+ except TypeError:
+ # no connections
+ pass
+
+
+class CommandKeyParser(KeyChainParser):
"""KeyChainParser for command bindings.
@@ -45,7 +94,6 @@ def execute(self, cmdstr, _keytype, count=None):
except cmdexc.Error as e:
message.error(str(e), stack=traceback.format_exc())
-
class PassthroughKeyParser(CommandKeyParser):
"""KeyChainParser which passes through normal keys.
diff --git a/qutebrowser/keyinput/modeparsers.py b/qutebrowser/keyinput/modeparsers.py
index 7aa8ca3716..dd809f90c3 100644
--- a/qutebrowser/keyinput/modeparsers.py
+++ b/qutebrowser/keyinput/modeparsers.py
@@ -39,18 +39,12 @@
class NormalKeyParser(keyparser.CommandKeyParser):
- """KeyParser for normal mode with added STARTCHARS detection and more.
-
- Attributes:
- _partial_timer: Timer to clear partial keypresses.
- """
+ """KeyParser for normal mode with added STARTCHARS detection and more."""
def __init__(self, win_id, parent=None):
super().__init__(win_id, parent, supports_count=True,
supports_chains=True)
self._read_config('normal')
- self._partial_timer = usertypes.Timer(self, 'partial-match')
- self._partial_timer.setSingleShot(True)
self._inhibited = False
self._inhibited_timer = usertypes.Timer(self, 'normal-inhibited')
self._inhibited_timer.setSingleShot(True)
@@ -72,14 +66,8 @@ def _handle_single_key(self, e):
self._debug_log("Ignoring key '{}', because the normal mode is "
"currently inhibited.".format(txt))
return self.Match.none
- match = super()._handle_single_key(e)
- if match == self.Match.partial:
- timeout = config.val.input.partial_timeout
- if timeout != 0:
- self._partial_timer.setInterval(timeout)
- self._partial_timer.timeout.connect(self._clear_partial_match)
- self._partial_timer.start()
- return match
+
+ return super()._handle_single_key(e)
def set_inhibited_timeout(self, timeout):
if timeout != 0:
@@ -91,14 +79,6 @@ def set_inhibited_timeout(self, timeout):
self._inhibited_timer.start()
@pyqtSlot()
- def _clear_partial_match(self):
- """Clear a partial keystring after a timeout."""
- self._debug_log("Clearing partial keystring {}".format(
- self._keystring))
- self._keystring = ''
- self.keystring_updated.emit(self._keystring)
-
- @pyqtSlot()
def _clear_inhibited(self):
"""Reset inhibition state after a timeout."""
self._debug_log("Releasing inhibition state of normal mode.")
@@ -107,12 +87,6 @@ def _clear_inhibited(self):
@pyqtSlot()
def _stop_timers(self):
super()._stop_timers()
- self._partial_timer.stop()
- try:
- self._partial_timer.timeout.disconnect(self._clear_partial_match)
- except TypeError:
- # no connections
- pass
self._inhibited_timer.stop()
try:
self._inhibited_timer.timeout.disconnect(self._clear_inhibited)
From ccf1616eb34d612ba86963b223f801b44c9572f3 Mon Sep 17 00:00:00 2001
From: Michael Mackus <michaelmackus@gmail.com>
Date: Tue, 3 Oct 2017 10:15:58 -0700
Subject: [PATCH 2/6] Add arguments and imports
---
qutebrowser/keyinput/keyparser.py | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/qutebrowser/keyinput/keyparser.py b/qutebrowser/keyinput/keyparser.py
index 76c099a106..99e7abaf9e 100644
--- a/qutebrowser/keyinput/keyparser.py
+++ b/qutebrowser/keyinput/keyparser.py
@@ -24,14 +24,14 @@
from PyQt5.QtCore import pyqtSlot
from qutebrowser.keyinput.basekeyparser import BaseKeyParser
-from qutebrowser.utils import message, utils
+from qutebrowser.utils import message, usertypes, utils
from qutebrowser.commands import runners, cmdexc
+from qutebrowser.config import config
class KeyChainParser(BaseKeyParser):
"""KeyChainParser which implements chaining of multiple keys."""
- def __init__(self, win_id, parent=None):
- super().__init__(win_id, parent, supports_count=True,
- supports_chains=True)
+ def __init__(self, win_id, parent=None, supports_count=True, supports_chains=True):
+ super().__init__(win_id, parent, supports_count=supports_count, supports_chains=supports_chains)
self._partial_timer = usertypes.Timer(self, 'partial-match')
self._partial_timer.setSingleShot(True)
From 8adf859220305a0d692bf2a3af41de2315185d0c Mon Sep 17 00:00:00 2001
From: Michael Mackus <michaelmackus@gmail.com>
Date: Tue, 3 Oct 2017 10:17:16 -0700
Subject: [PATCH 3/6] Don't warn on keychains
---
qutebrowser/keyinput/keyparser.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/qutebrowser/keyinput/keyparser.py b/qutebrowser/keyinput/keyparser.py
index 99e7abaf9e..c0fdf60586 100644
--- a/qutebrowser/keyinput/keyparser.py
+++ b/qutebrowser/keyinput/keyparser.py
@@ -32,6 +32,7 @@ class KeyChainParser(BaseKeyParser):
"""KeyChainParser which implements chaining of multiple keys."""
def __init__(self, win_id, parent=None, supports_count=True, supports_chains=True):
super().__init__(win_id, parent, supports_count=supports_count, supports_chains=supports_chains)
+ self._warn_on_keychains = False
self._partial_timer = usertypes.Timer(self, 'partial-match')
self._partial_timer.setSingleShot(True)
@@ -116,7 +117,6 @@ def __init__(self, win_id, mode, parent=None, warn=True):
warn: Whether to warn if an ignored key was bound.
"""
super().__init__(win_id, parent, supports_chains=False)
- self._warn_on_keychains = warn
self._read_config(mode)
self._mode = mode
From 25321af5cb63244ce127bfc97bab25584b98b4ad Mon Sep 17 00:00:00 2001
From: Michael Mackus <michaelmackus@gmail.com>
Date: Tue, 3 Oct 2017 16:00:28 -0700
Subject: [PATCH 4/6] Fix keychains in insert & command modes
---
qutebrowser/keyinput/keyparser.py | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/qutebrowser/keyinput/keyparser.py b/qutebrowser/keyinput/keyparser.py
index c0fdf60586..5a8d0eb44a 100644
--- a/qutebrowser/keyinput/keyparser.py
+++ b/qutebrowser/keyinput/keyparser.py
@@ -32,7 +32,7 @@ class KeyChainParser(BaseKeyParser):
"""KeyChainParser which implements chaining of multiple keys."""
def __init__(self, win_id, parent=None, supports_count=True, supports_chains=True):
super().__init__(win_id, parent, supports_count=supports_count, supports_chains=supports_chains)
- self._warn_on_keychains = False
+ self._warn_on_keychains = not supports_chains
self._partial_timer = usertypes.Timer(self, 'partial-match')
self._partial_timer.setSingleShot(True)
@@ -84,8 +84,8 @@ class CommandKeyParser(KeyChainParser):
_commandrunner: CommandRunner instance.
"""
- def __init__(self, win_id, parent=None, supports_count=None,
- supports_chains=False):
+ def __init__(self, win_id, parent=None, supports_count=True,
+ supports_chains=True):
super().__init__(win_id, parent, supports_count, supports_chains)
self._commandrunner = runners.CommandRunner(win_id)
@@ -116,7 +116,7 @@ def __init__(self, win_id, mode, parent=None, warn=True):
parent: Qt parent.
warn: Whether to warn if an ignored key was bound.
"""
- super().__init__(win_id, parent, supports_chains=False)
+ super().__init__(win_id, parent)
self._read_config(mode)
self._mode = mode
From 59ad095faca93984de7b58bebd7c7c865c4258e8 Mon Sep 17 00:00:00 2001
From: Michael Mackus <michaelmackus@gmail.com>
Date: Tue, 3 Oct 2017 16:09:50 -0700
Subject: [PATCH 5/6] Remove supports_chains arg
Everything that extends KeyChainParser is assumed to support keychains
now. Also dropped the "warn" arg since it wasn't being used.
---
qutebrowser/keyinput/keyparser.py | 16 ++++++----------
qutebrowser/keyinput/modeman.py | 3 +--
qutebrowser/keyinput/modeparsers.py | 15 +++++----------
3 files changed, 12 insertions(+), 22 deletions(-)
diff --git a/qutebrowser/keyinput/keyparser.py b/qutebrowser/keyinput/keyparser.py
index 5a8d0eb44a..6ebb91b860 100644
--- a/qutebrowser/keyinput/keyparser.py
+++ b/qutebrowser/keyinput/keyparser.py
@@ -30,9 +30,8 @@
class KeyChainParser(BaseKeyParser):
"""KeyChainParser which implements chaining of multiple keys."""
- def __init__(self, win_id, parent=None, supports_count=True, supports_chains=True):
- super().__init__(win_id, parent, supports_count=supports_count, supports_chains=supports_chains)
- self._warn_on_keychains = not supports_chains
+ def __init__(self, win_id, parent=None, supports_count=None):
+ super().__init__(win_id, parent, supports_count, supports_chains=True)
self._partial_timer = usertypes.Timer(self, 'partial-match')
self._partial_timer.setSingleShot(True)
@@ -84,9 +83,8 @@ class CommandKeyParser(KeyChainParser):
_commandrunner: CommandRunner instance.
"""
- def __init__(self, win_id, parent=None, supports_count=True,
- supports_chains=True):
- super().__init__(win_id, parent, supports_count, supports_chains)
+ def __init__(self, win_id, parent=None, supports_count=True):
+ super().__init__(win_id, parent, supports_count)
self._commandrunner = runners.CommandRunner(win_id)
def execute(self, cmdstr, _keytype, count=None):
@@ -108,18 +106,16 @@ class PassthroughKeyParser(CommandKeyParser):
do_log = False
passthrough = True
- def __init__(self, win_id, mode, parent=None, warn=True):
+ def __init__(self, win_id, mode, parent=None):
"""Constructor.
Args:
mode: The mode this keyparser is for.
parent: Qt parent.
- warn: Whether to warn if an ignored key was bound.
"""
super().__init__(win_id, parent)
self._read_config(mode)
self._mode = mode
def __repr__(self):
- return utils.get_repr(self, mode=self._mode,
- warn=self._warn_on_keychains)
+ return utils.get_repr(self, mode=self._mode)
diff --git a/qutebrowser/keyinput/modeman.py b/qutebrowser/keyinput/modeman.py
index 6a6dd5459c..c5c091ad25 100644
--- a/qutebrowser/keyinput/modeman.py
+++ b/qutebrowser/keyinput/modeman.py
@@ -72,8 +72,7 @@ def init(win_id, parent):
KM.passthrough: keyparser.PassthroughKeyParser(win_id, 'passthrough',
modeman),
KM.command: keyparser.PassthroughKeyParser(win_id, 'command', modeman),
- KM.prompt: keyparser.PassthroughKeyParser(win_id, 'prompt', modeman,
- warn=False),
+ KM.prompt: keyparser.PassthroughKeyParser(win_id, 'prompt', modeman),
KM.yesno: modeparsers.PromptKeyParser(win_id, modeman),
KM.caret: modeparsers.CaretKeyParser(win_id, modeman),
KM.set_mark: modeparsers.RegisterKeyParser(win_id, KM.set_mark,
diff --git a/qutebrowser/keyinput/modeparsers.py b/qutebrowser/keyinput/modeparsers.py
index dd809f90c3..e09337bf53 100644
--- a/qutebrowser/keyinput/modeparsers.py
+++ b/qutebrowser/keyinput/modeparsers.py
@@ -42,8 +42,7 @@ class NormalKeyParser(keyparser.CommandKeyParser):
"""KeyParser for normal mode with added STARTCHARS detection and more."""
def __init__(self, win_id, parent=None):
- super().__init__(win_id, parent, supports_count=True,
- supports_chains=True)
+ super().__init__(win_id, parent, supports_count=True)
self._read_config('normal')
self._inhibited = False
self._inhibited_timer = usertypes.Timer(self, 'normal-inhibited')
@@ -100,8 +99,7 @@ class PromptKeyParser(keyparser.CommandKeyParser):
"""KeyParser for yes/no prompts."""
def __init__(self, win_id, parent=None):
- super().__init__(win_id, parent, supports_count=False,
- supports_chains=True)
+ super().__init__(win_id, parent, supports_count=False)
# We don't want an extra section for this in the config, so we just
# abuse the prompt section.
self._read_config('prompt')
@@ -120,8 +118,7 @@ class HintKeyParser(keyparser.CommandKeyParser):
"""
def __init__(self, win_id, parent=None):
- super().__init__(win_id, parent, supports_count=False,
- supports_chains=True)
+ super().__init__(win_id, parent, supports_count=False)
self._filtertext = ''
self._last_press = LastPress.none
self._read_config('hint')
@@ -236,8 +233,7 @@ class CaretKeyParser(keyparser.CommandKeyParser):
passthrough = True
def __init__(self, win_id, parent=None):
- super().__init__(win_id, parent, supports_count=True,
- supports_chains=True)
+ super().__init__(win_id, parent, supports_count=True)
self._read_config('caret')
@@ -251,8 +247,7 @@ class RegisterKeyParser(keyparser.CommandKeyParser):
"""
def __init__(self, win_id, mode, parent=None):
- super().__init__(win_id, parent, supports_count=False,
- supports_chains=False)
+ super().__init__(win_id, parent, supports_count=False)
self._mode = mode
self._read_config('register')
From 652d92b3b91ecb33ef6510f76c7b5d549d4e6a49 Mon Sep 17 00:00:00 2001
From: Michael Mackus <michaelmackus@gmail.com>
Date: Tue, 3 Oct 2017 16:53:58 -0700
Subject: [PATCH 6/6] Turn off count for passthrough modes
This was breaking number keys in input modes.
---
qutebrowser/keyinput/keyparser.py | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/qutebrowser/keyinput/keyparser.py b/qutebrowser/keyinput/keyparser.py
index 6ebb91b860..fd55d47ec8 100644
--- a/qutebrowser/keyinput/keyparser.py
+++ b/qutebrowser/keyinput/keyparser.py
@@ -30,7 +30,7 @@
class KeyChainParser(BaseKeyParser):
"""KeyChainParser which implements chaining of multiple keys."""
- def __init__(self, win_id, parent=None, supports_count=None):
+ def __init__(self, win_id, parent=None, supports_count=False):
super().__init__(win_id, parent, supports_count, supports_chains=True)
self._partial_timer = usertypes.Timer(self, 'partial-match')
self._partial_timer.setSingleShot(True)
@@ -83,7 +83,7 @@ class CommandKeyParser(KeyChainParser):
_commandrunner: CommandRunner instance.
"""
- def __init__(self, win_id, parent=None, supports_count=True):
+ def __init__(self, win_id, parent=None, supports_count=False):
super().__init__(win_id, parent, supports_count)
self._commandrunner = runners.CommandRunner(win_id)
@@ -113,7 +113,7 @@ def __init__(self, win_id, mode, parent=None):
mode: The mode this keyparser is for.
parent: Qt parent.
"""
- super().__init__(win_id, parent)
+ super().__init__(win_id, parent, supports_count=False)
self._read_config(mode)
self._mode = mode |
With #319 now done, you can |
Just my 2 cents that this isn't fixed yet. The-Compiler's comment on March 4, 2018 is still correct. It will let you type 'j', but you have to press 'j' twice to get that letter, and nothing new is saved to key.conf when you bind it. (I wish we could up-vote issues on Github. I'd love to have this fixed. I just learned Python, so I may give it a shot. |
@bearcatsandor You can upvote issues on GitHub, that's what reactions are for. Also, note that |
Wow. That was a fast response. Thank you. I'll check all that out. For anyone that may have tried this and wants to revert, the command is unbind --mode=insert jk |
Is there any way to map a sequence such as 'jk' to 'leave-mode'? Unfortunately, only combinations are supported.
Thanks for the excellent work!
The text was updated successfully, but these errors were encountered: