summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorent Le Coz <louiz@louiz.org>2012-10-09 04:35:02 +0000
committerFlorent Le Coz <louiz@louiz.org>2012-10-09 04:35:02 +0000
commit653695498aa334f3c34b0946162020fbae10839d (patch)
treecc2354bfb13e8f37daf9cce15d04ce2b3d3a544d
parent4965ee161896ccea6700485dc944db88947107c1 (diff)
downloadpoezio-653695498aa334f3c34b0946162020fbae10839d.tar.gz
poezio-653695498aa334f3c34b0946162020fbae10839d.tar.bz2
poezio-653695498aa334f3c34b0946162020fbae10839d.tar.xz
poezio-653695498aa334f3c34b0946162020fbae10839d.zip
Separate special keys from normal chars when receving a batch of chars.
In case of lags or paste of text, the input can yield a list of chars instead of just one char. In case of lags, keyboard special keys (KEY_BACKSPACE, ^W, etc) are mixed with other “normal” chars ('a', 'b', 'D', ' ' etc). Instead of handling that whole batch in one go (which requires us to ignore all the special keys, otherwise they would be displayed in the input, which are both bad ways to handle that), we separate special keys from the normal ones, and we handle that big batch as one or more smaller batches. This should make the input behave correctly in case of lag AND in case of paste of huge text (only one refresh per batch, respond instantly, no key lost or ignored, etc) fixed #2365
-rw-r--r--src/core.py95
1 files changed, 63 insertions, 32 deletions
diff --git a/src/core.py b/src/core.py
index 2accb4c4..700e6815 100644
--- a/src/core.py
+++ b/src/core.py
@@ -359,48 +359,79 @@ class Core(object):
return '\n'
elif key == '^I':
return ' '
- elif len(key) > 1:
- return ''
return key
def replace_line_breaks(key):
if key == '^J':
return '\n'
return key
-
+ def separate_chars_from_bindings(char_list):
+ """
+ returns a list of lists. For example if you give
+ ['a', 'b', 'KEY_BACKSPACE', 'n', 'u'], this function returns
+ [['a', 'b'], ['KEY_BACKSPACE'], ['n', 'u']]
+
+ This way, in case of lag (for example), we handle the typed text
+ by “batch” as much as possible (instead of one char at a time,
+ which implies a refresh after each char, which is very slow),
+ but we still handle the special chars (backspaces, arrows,
+ ctrl+x ou alt+x, etc) one by one, which avoids the issue of
+ printing them OR ignoring them in that case. This should
+ resolve the “my ^W are ignored when I lag ;(”.
+ """
+ res = []
+ current = []
+ for char in char_list:
+ assert(len(char) > 0)
+ if len(char) == 1:
+ current.append(char)
+ else:
+ res.append(current)
+ res.append([char])
+ current = []
+ if current:
+ res.append(current)
+ return res
while self.running:
if self.paused: continue
- char_list = [common.replace_key_with_bound(key)\
+ big_char_list = [common.replace_key_with_bound(key)\
for key in self.read_keyboard()]
- if self.paused:
- self.current_tab().input.do_command(char_list[0])
- self.current_tab().input.prompt()
- continue
- # Special case for M-x where x is a number
- if len(char_list) == 1:
- char = char_list[0]
- if char.startswith('M-') and len(char) == 3:
- try:
- nb = int(char[2])
- except ValueError:
- pass
- else:
- if self.current_tab().nb == nb:
- self.go_to_previous_tab()
+ log.debug(big_char_list)
+ log.debug(separate_chars_from_bindings(big_char_list))
+ # whether to refresh after ALL keys have been handled
+ do_refresh = True
+ for char_list in separate_chars_from_bindings(big_char_list):
+ if self.paused:
+ self.current_tab().input.do_command(char_list[0])
+ self.current_tab().input.prompt()
+ continue
+ # Special case for M-x where x is a number
+ if len(char_list) == 1:
+ char = char_list[0]
+ if char.startswith('M-') and len(char) == 3:
+ try:
+ nb = int(char[2])
+ except ValueError:
+ pass
else:
- self.command_win('%d' % nb)
- # search for keyboard shortcut
- func = self.key_func.get(char, None)
- if func:
- func()
+ if self.current_tab().nb == nb:
+ self.go_to_previous_tab()
+ else:
+ self.command_win('%d' % nb)
+ # search for keyboard shortcut
+ func = self.key_func.get(char, None)
+ if func:
+ func()
+ else:
+ res = self.do_command(replace_line_breaks(char), False)
+ if res:
+ do_refresh = True
else:
- res = self.do_command(replace_line_breaks(char), False)
- if res:
- self.refresh_window()
- else:
- self.do_command(''.join(map(
- lambda x: sanitize_input(x),
- char_list)
- ), True)
+ self.do_command(''.join(map(
+ lambda x: sanitize_input(x),
+ char_list)
+ ), True)
+ refresh = True
+ if refresh == True:
self.refresh_window()
self.doupdate()