diff options
author | Florent Le Coz <louiz@louiz.org> | 2011-05-29 00:35:11 +0200 |
---|---|---|
committer | Florent Le Coz <louiz@louiz.org> | 2011-05-29 00:35:11 +0200 |
commit | 8d3053bd93db2e976f49a3a32038712083d411a7 (patch) | |
tree | 8f65efeb61a6676fef0e6ca9d8469985b0b068c0 | |
parent | 3af88ff8d620791e4d4969e913b46fe34857f9c3 (diff) | |
download | poezio-8d3053bd93db2e976f49a3a32038712083d411a7.tar.gz poezio-8d3053bd93db2e976f49a3a32038712083d411a7.tar.bz2 poezio-8d3053bd93db2e976f49a3a32038712083d411a7.tar.xz poezio-8d3053bd93db2e976f49a3a32038712083d411a7.zip |
fixes #2164. Restore multiline messages on paste of big text. That’s now faster and works ~100% of the time (no more message cut in two part for no reason, I think)
-rw-r--r-- | src/core.py | 40 | ||||
-rw-r--r-- | src/keyboard.py | 79 |
2 files changed, 68 insertions, 51 deletions
diff --git a/src/core.py b/src/core.py index 14cb4857..f4cca7e3 100644 --- a/src/core.py +++ b/src/core.py @@ -670,23 +670,31 @@ class Core(object): """ # curses.ungetch(0) # FIXME while self.running: - char = self.read_keyboard() + char_list = self.read_keyboard() # Special case for M-x where x is a number - 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() + 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 - if char in self.key_func: - self.key_func[char]() + if self.current_tab().nb == nb: + self.go_to_previous_tab() + else: + self.command_win('%d' % nb) + # search for keyboard shortcut + if char in self.key_func: + self.key_func[char]() + else: + res = self.do_command(char) + if res: + self.refresh_window() else: - self.do_command(char) + for char in char_list: + self.do_command(char) + self.refresh_window() self.doupdate() def current_tab(self): @@ -1419,9 +1427,7 @@ class Core(object): def do_command(self, key): if not key: return - res = self.current_tab().on_input(key) - if res: - self.refresh_window() + return self.current_tab().on_input(key) def on_roster_enter_key(self, roster_row): """ diff --git a/src/keyboard.py b/src/keyboard.py index 27edca5f..f3dd14db 100644 --- a/src/keyboard.py +++ b/src/keyboard.py @@ -24,8 +24,6 @@ shortcut, like ^A, M-a or KEY_RESIZE) import time -last_timeout = time.time() - def get_next_byte(s): """ Read the next byte of the utf-8 char @@ -41,44 +39,57 @@ def get_next_byte(s): return (None, c) return (ord(c), c.encode('latin-1')) # returns a number and a bytes object -def read_char(s): +def read_char(s, timeout=1000): """ Read one utf-8 char see http://en.wikipedia.org/wiki/UTF-8#Description """ - global last_timeout - s.timeout(1000) + s.timeout(timeout) # The timeout for timed events to be checked every second + ret_list = [] + # The list of all chars. For example if you paste a text, the list the chars pasted + # so that they can be handled at once. (first, char) = get_next_byte(s) - if first is None and char is None: - last_timeout = time.time() - return None - if not isinstance(first, int): # Keyboard special, like KEY_HOME etc - return char - if first == 127 or first == 8: - return "KEY_BACKSPACE" - if first < 127: # ASCII char on one byte - if first <= 26: # transform Ctrl+* keys - char = chr(first + 64) - # if char == 'M' and time.time() - last_char_time < 0.0005: - # char = 'J' - return "^"+char - if first == 27: - second = read_char(s) - res = 'M-%s' % (second,) - return res - if 194 <= first: - (code, c) = get_next_byte(s) # 2 bytes char - char += c - if 224 <= first: - (code, c) = get_next_byte(s) # 3 bytes char - char += c - if 240 <= first: - (code, c) = get_next_byte(s) # 4 bytes char - char += c - try: - return char.decode('utf-8') # return all the concatened byte objets, decoded - except UnicodeDecodeError: + while first is not None or char is not None: + if not isinstance(first, int): # Keyboard special, like KEY_HOME etc + return [char] + if first == 127 or first == 8: + return ["KEY_BACKSPACE"] + s.timeout(0) # we are now getting the missing utf-8 bytes to get a whole char + if first < 127: # ASCII char on one byte + if first <= 26: # transform Ctrl+* keys + char = chr(first + 64) + ret_list.append("^"+char) + (first, char) = get_next_byte(s) + continue + if first == 27: + second = read_char(s, 0) + res = 'M-%s' % (second[0],) + ret_list.append(res) + (first, char) = get_next_byte(s) + continue + if 194 <= first: + (code, c) = get_next_byte(s) # 2 bytes char + char += c + if 224 <= first: + (code, c) = get_next_byte(s) # 3 bytes char + char += c + if 240 <= first: + (code, c) = get_next_byte(s) # 4 bytes char + char += c + try: + ret_list.append(char.decode('utf-8')) # return all the concatened byte objets, decoded + except UnicodeDecodeError: + return None + # s.timeout(1) # timeout to detect a paste of many chars + (first, char) = get_next_byte(s) + if not ret_list: + # nothing at all was read, that’s a timed event timeout return None + if len(ret_list) != 1: + if ret_list[-1] == '^M': + ret_list.pop(-1) + return [char if char != '^M' else '^J' for char in ret_list] + return ret_list if __name__ == '__main__': import curses |