summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorent Le Coz <louiz@louiz.org>2014-08-07 23:20:21 +0200
committerFlorent Le Coz <louiz@louiz.org>2014-08-07 23:20:21 +0200
commit3ef9228211df46ada9bb5b851682a9c7d833de56 (patch)
tree3bf40a1f43c97577f5cf317c937f55023c0bb186
parent0e2bba640e1ffcfaa7ce4bc6782f24b0f10b8c08 (diff)
downloadpoezio-3ef9228211df46ada9bb5b851682a9c7d833de56.tar.gz
poezio-3ef9228211df46ada9bb5b851682a9c7d833de56.tar.bz2
poezio-3ef9228211df46ada9bb5b851682a9c7d833de56.tar.xz
poezio-3ef9228211df46ada9bb5b851682a9c7d833de56.zip
Continuation keys (like after M-j or Ctrl-c) are handled without blocking
-rw-r--r--src/core/core.py61
-rwxr-xr-xsrc/keyboard.py9
-rw-r--r--src/windows/input_placeholders.py13
-rw-r--r--src/windows/inputs.py12
4 files changed, 65 insertions, 30 deletions
diff --git a/src/core/core.py b/src/core/core.py
index fe9efdd5..f4da11d0 100644
--- a/src/core/core.py
+++ b/src/core/core.py
@@ -39,13 +39,13 @@ from config import config, firstrun
from contact import Contact, Resource
from daemon import Executor
from fifo import Fifo
-from keyboard import Keyboard
from logger import logger
from plugin_manager import PluginManager
from roster import roster
from size_manager import SizeManager
from text_buffer import TextBuffer
from theming import get_theme
+import keyboard
from . import completions
from . import commands
@@ -72,7 +72,7 @@ class Core(object):
self.running = True
self.xmpp = singleton.Singleton(connection.Connection)
self.xmpp.core = self
- self.keyboard = Keyboard()
+ self.keyboard = keyboard.Keyboard()
roster.set_node(self.xmpp.client_roster)
decorators.refresh_wrapper.core = self
self.paused = False
@@ -131,6 +131,11 @@ class Core(object):
del self.commands['status']
del self.commands['show']
+ # A list of integers. For example if the user presses Alt+j, 2, 1,
+ # we will insert 2, then 1 in that list, and we will finally build
+ # the number 21 and use it with command_win, before clearing the
+ # list.
+ self.room_number_jump = []
self.key_func = KeyDict()
# Key bindings associated with handlers
# and pseudo-keys used to map actions below.
@@ -742,10 +747,21 @@ class Core(object):
def do_command(self, key, raw):
"""
Execute the action associated with a key
+
+ Or if keyboard.continuation_keys_callback is set, call it instead. See
+ the comment of this variable.
"""
if not key:
return
- return self.current_tab().on_input(key, raw)
+ if keyboard.continuation_keys_callback is not None:
+ # Reset the callback to None BEFORE calling it, because this
+ # callback MAY set a new callback itself, and we don’t want to
+ # erase it in that case
+ cb = keyboard.continuation_keys_callback
+ keyboard.continuation_keys_callback = None
+ cb(key)
+ else:
+ self.current_tab().on_input(key, raw)
def try_execute(self, line):
@@ -1060,17 +1076,24 @@ class Core(object):
Read 2 more chars and go to the tab
with the given number
"""
- char = self.read_keyboard()[0]
- try:
- nb1 = int(char)
- except ValueError:
- return
- char = self.read_keyboard()[0]
- try:
- nb2 = int(char)
- except ValueError:
- return
- self.command_win('%s%s' % (nb1, nb2))
+ def read_next_digit(digit):
+ try:
+ nb = int(digit)
+ except ValueError:
+ # If it is not a number, we do nothing. If it was the first
+ # one, we do not wait for a second one by re-setting the
+ # callback
+ pass
+ else:
+ self.room_number_jump.append(digit)
+ if len(self.room_number_jump) == 2:
+ arg = "".join(self.room_number_jump)
+ self.room_number_jump.clear()
+ self.command_win(arg)
+ else:
+ # We need to read more digits
+ keyboard.continuation_keys_callback = read_next_digit
+ keyboard.continuation_keys_callback = read_next_digit
def go_to_roster(self):
"Select the roster as the current tab"
@@ -1623,13 +1646,11 @@ class Core(object):
def read_keyboard(self):
"""
- Get the next keyboard key pressed and returns it.
- get_user_input() has a timeout: it returns None when the timeout
- occurs. In that case we do not return (we loop until we get
- a non-None value), but we check for timed events instead.
+ Get the next keyboard key pressed and returns it. It blocks until
+ something can be read on stdin, this function must be called only if
+ there is something to read. No timeout ever occurs.
"""
- res = self.keyboard.get_user_input(self.stdscr)
- return res
+ return self.keyboard.get_user_input(self.stdscr)
def escape_next_key(self):
"""
diff --git a/src/keyboard.py b/src/keyboard.py
index 0a1391ea..f88a030c 100755
--- a/src/keyboard.py
+++ b/src/keyboard.py
@@ -18,6 +18,15 @@ import curses.ascii
import logging
log = logging.getLogger(__name__)
+# A callback that will handle the next key entered by the user. For
+# example if the user presses Ctrl+j, we set a callbacks, and the
+# next key pressed by the user will be passed to this callback
+# instead of the normal process of executing global keybard
+# shortcuts or inserting text in the current output. The callback
+# is always reset to None afterwards (to resume the normal
+# processing of keys)
+continuation_keys_callback = None
+
def get_next_byte(s):
"""
Read the next byte of the utf-8 char
diff --git a/src/windows/input_placeholders.py b/src/windows/input_placeholders.py
index 6fd7975a..0887cfc5 100644
--- a/src/windows/input_placeholders.py
+++ b/src/windows/input_placeholders.py
@@ -68,9 +68,12 @@ class YesNoInput(Win):
def prompt(self):
"""Monopolizes the input while waiting for a recognized keypress"""
- cl = []
- while self.value is None:
- if len(cl) == 1 and cl[0] in self.key_func:
- self.key_func[cl[0]]()
- cl = self.core.read_keyboard()
+ def cb(key):
+ if key in self.key_func:
+ self.key_func[key]()
+ if self.value is None:
+ # We didn’t finish with this prompt, continue monopolizing
+ # it again until value is set
+ keyboard.continuation_keys_callback = cb
+ keyboard.continuation_keys_callback = cb
diff --git a/src/windows/inputs.py b/src/windows/inputs.py
index ff13a562..afce3dd8 100644
--- a/src/windows/inputs.py
+++ b/src/windows/inputs.py
@@ -8,6 +8,7 @@ log = logging.getLogger(__name__)
import curses
import string
+import keyboard
import common
import poopt
from . import Win
@@ -655,11 +656,12 @@ class MessageInput(HistoryInput):
"""
Read one more char (c), add the corresponding char from formats_char to the text string
"""
- attr_char = self.core.read_keyboard()[0]
- if attr_char in self.text_attributes:
- char = format_chars[self.text_attributes.index(attr_char)]
- self.do_command(char, False)
- self.rewrite_text()
+ def cb(attr_char):
+ if attr_char in self.text_attributes:
+ char = format_chars[self.text_attributes.index(attr_char)]
+ self.do_command(char, False)
+ self.rewrite_text()
+ keyboard.continuation_keys_callback = cb
def key_enter(self):
if self.history_enter():