diff options
-rw-r--r-- | locale/poezio.pot | 571 | ||||
-rw-r--r-- | src/core.py | 40 | ||||
-rw-r--r-- | src/keyboard.py | 79 |
3 files changed, 488 insertions, 202 deletions
diff --git a/locale/poezio.pot b/locale/poezio.pot index 939adea1..fc66ac67 100644 --- a/locale/poezio.pot +++ b/locale/poezio.pot @@ -8,140 +8,135 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2010-06-13 16:13+0200\n" +"POT-Creation-Date: 2011-05-28 23:53+0200\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Language-Team: LANGUAGE <LL@li.org>\n" +"Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=CHARSET\n" "Content-Transfer-Encoding: 8bit\n" -#: src/connection.py:105 -#, python-format -msgid "" -"Error: Could not authenticate. Please make sure the server you chose (%s) " -"supports anonymous authentication" +#: src/core.py:59 +msgid "A password is required" +msgstr "" + +#: src/core.py:60 +msgid "Permission denied" +msgstr "" + +#: src/core.py:61 +msgid "The room does'nt exist" +msgstr "" + +#: src/core.py:62 +msgid "Your are not allowed to create a new room" +msgstr "" + +#: src/core.py:63 +msgid "A reserved nick must be used" +msgstr "" + +#: src/core.py:64 +msgid "You are not in the member list" +msgstr "" + +#: src/core.py:65 +msgid "This nickname is already in use or has been reserved" +msgstr "" + +#: src/core.py:66 +msgid "The maximum number of users has been reached" msgstr "" -#: src/gui.py:67 +#: src/core.py:113 msgid "" -"Usage: /join [room_name][/nick] [password]\n" +"Usage: /join [room_name][@server][/nick] [password]\n" "Join: Join the specified room. You can specify a nickname after a slash (/). " "If no nickname is specified, you will use the default_nick in the " "configuration file. You can omit the room name: you will then join the room " "you're looking at (useful if you were kicked). You can also provide a " -"password to join the room.\n" +"room_name without specifying a server, the server of the room you're " +"currently in will be used. You can also provide a password to join the " +"room.\n" "Examples:\n" "/join room@server.tld\n" -"/join room@server.tld/ John\n" +"/join room@server.tld/John\n" +"/join room2\n" "/join /me_again\n" "/join\n" "/join room@server.tld/my_nick password\n" -"/join / pass" +"/join / password" msgstr "" -#: src/gui.py:68 -msgid "" -"Usage: /quit\n" -"Quit: Just disconnect from the server and exit poezio." -msgstr "" - -#: src/gui.py:69 +#: src/core.py:114 msgid "" "Usage: /exit\n" "Exit: Just disconnect from the server and exit poezio." msgstr "" -#: src/gui.py:70 +#: src/core.py:115 msgid "" "Usage: /next\n" "Next: Go to the next room." msgstr "" -#: src/gui.py:71 -msgid "" -"Usage: /n\n" -"N: Go to the next room." -msgstr "" - -#: src/gui.py:72 +#: src/core.py:116 msgid "" "Usage: /prev\n" "Prev: Go to the previous room." msgstr "" -#: src/gui.py:73 -msgid "" -"Usage: /p\n" -"P: Go to the previous room." -msgstr "" - -#: src/gui.py:74 +#: src/core.py:117 msgid "" "Usage: /win <number>\n" "Win: Go to the specified room." msgstr "" -#: src/gui.py:75 +#: src/core.py:118 msgid "" "Usage: /w <number>\n" "W: Go to the specified room." msgstr "" -#: src/gui.py:76 -msgid "Usage: /ignore <nickname> \\Ignore: Ignore a specified nickname." -msgstr "" - -#: src/gui.py:77 +#: src/core.py:119 msgid "" -"Usage: /unignore <nickname>\\Unignore: Remove the specified nickname from " -"the ignore list." +"Usage: /show <availability> [status message]\n" +"Show: Sets your availability and (optionaly) your status message. The " +"<availability> argument is one of \"available, chat, away, afk, dnd, busy, xa" +"\" and the optional [status] argument will be your status message." msgstr "" -#: src/gui.py:78 +#: src/core.py:120 msgid "" -"Usage: /part [message]\n" -" Part: disconnect from a room. You can specify an optional message." +"Usage: /status <availability> [status message]\n" +"Status: Sets your availability and (optionaly) your status message. The " +"<availability> argument is one of \"available, chat, away, afk, dnd, busy, xa" +"\" and the optional [status] argument will be your status message." msgstr "" -#: src/gui.py:79 -msgid "" -"Usage: /show <availability> [status]\n" -"Show: Change your availability and (optionaly) your status. The " -"<availability> argument is one of \"avail, available, ok, here, chat, away, " -"afk, dnd, busy, xa\" and the optional [message] argument will be your status " -"message" -msgstr "" - -#: src/gui.py:80 +#: src/core.py:121 msgid "" "Usage: /away [message]\n" -"Away: Sets your availability to away and (optional) sets your status " -"message. This is equivalent to '/show away [message]'" +"Away: Sets your availability to away and (optionaly) your status message. " +"This is equivalent to '/status away [message]'" msgstr "" -#: src/gui.py:81 +#: src/core.py:122 msgid "" "Usage: /busy [message]\n" -"Busy: Sets your availability to busy and (optional) sets your status " -"message. This is equivalent to '/show busy [message]'" +"Busy: Sets your availability to busy and (optionaly) your status message. " +"This is equivalent to '/status busy [message]'" msgstr "" -#: src/gui.py:82 -msgid "" -"Usage: /avail [message]\n" -"Avail: Sets your availability to available and (optional) sets your status " -"message. This is equivalent to '/show available [message]'" -msgstr "" - -#: src/gui.py:83 +#: src/core.py:123 msgid "" "Usage: /available [message]\n" -"Available: Sets your availability to available and (optional) sets your " -"status message. This is equivalent to '/show available [message]'" +"Available: Sets your availability to available and (optionaly) your status " +"message. This is equivalent to '/status available [message]'" msgstr "" -#: src/gui.py:84 +#: src/core.py:124 msgid "" "Usage: /bookmark [roomname][/nick]\n" "Bookmark: Bookmark the specified room (you will then auto-join it on each " @@ -151,7 +146,7 @@ msgid "" "room (instead of default_nick)" msgstr "" -#: src/gui.py:85 +#: src/core.py:125 msgid "" "Usage: /set <option> [value]\n" "Set: Sets the value to the option in your configuration file. You can, for " @@ -160,197 +155,471 @@ msgid "" "(nothing) by providing no [value] after <option>." msgstr "" -#: src/gui.py:86 +#: src/core.py:126 msgid "" -"Usage: /kick <nick> [reason]\n" -"Kick: Kick the user with the specified nickname. You also can give an " -"optional reason." +"Usage: /theme\n" +"Theme: Reload the theme defined in the config file." msgstr "" -#: src/gui.py:87 +#: src/core.py:127 msgid "" -"Usage: /topic <subject> \n" -"Topic: Change the subject of the room" +"Usage: /list\n" +"List: get the list of public chatrooms on the specified server" msgstr "" -#: src/gui.py:88 +#: src/core.py:128 msgid "" -"Usage: /query <nick>\n" -"Query: Open a private conversation with <nick>. This nick has to be present " -"in the room you're currently in." +"Usage: /message <jid> [optional message]\n" +"Message: Open a conversation with the specified JID (even if it is not in " +"our roster), and send a message to it, if specified" msgstr "" -#: src/gui.py:90 +#: src/core.py:129 msgid "" -"Usage: /nick <nickname> \n" -"Nick: Change your nickname in the current room" +"Usage: /version <jid>\n" +"Version: get the software version of the given JID (usually its XMPP client " +"and Operating System)" +msgstr "" + +#: src/core.py:130 +msgid "" +"Usage: /connect\n" +"Connect: disconnect from the remote server if you are currently connected " +"and then connect to it again" +msgstr "" + +#: src/core.py:131 +msgid "" +"Usage: /server_cycle [domain] [message]\n" +"Server Cycle: disconnect and reconnects in all the rooms in domain." +msgstr "" + +#: src/core.py:192 +msgid "Welcome to poezio!" +msgstr "" + +#: src/core.py:391 +msgid "Connection to remote server failed" msgstr "" -#: src/gui.py:219 -msgid "Welcome on Poezio \\o/!" +#: src/core.py:400 +msgid "Disconnected from server." msgstr "" -#: src/gui.py:220 +#: src/core.py:406 +msgid "Authentication failed." +msgstr "" + +#: src/core.py:412 +msgid "Connected to server." +msgstr "" + +#: src/core.py:419 +msgid "Authentication success." +msgstr "" + +#: src/core.py:420 #, python-format msgid "Your JID is %s" msgstr "" -#: src/gui.py:281 +#: src/core.py:860 msgid "Unknown error" msgstr "" -#: src/gui.py:282 +#: src/core.py:862 src/tabs.py:1680 #, python-format -msgid "Error: %(code)s-%(msg)s: %(body)s" +msgid "Error: %(code)s - %(msg)s: %(body)s" msgstr "" -#: src/gui.py:285 +#: src/core.py:865 +#, python-format +msgid "Error: %(msg)s: %(body)s" +msgstr "" + +#: src/core.py:868 msgid "" "To provide a password in order to join the room, type \"/join / password" "\" (replace \"password\" by the real password)" msgstr "" -#: src/gui.py:345 +#: src/core.py:874 +msgid "" +"You can join the room with an other nick, by typing \"/join /other_nick\"" +msgstr "" + +#: src/core.py:923 +#, python-format +msgid "%(nick)s set the subject to: %(subject)s" +msgstr "" + +#: src/core.py:925 +#, python-format +msgid "The subject is: %(subject)s" +msgstr "" + +#: src/core.py:960 #, python-format msgid "message received for a non-existing room: %s" msgstr "" -#: src/gui.py:351 +#: src/core.py:986 +msgid "Available commands are: " +msgstr "" + +#: src/core.py:991 +msgid "" +"\n" +"Type /help <command_name> to know what each command does" +msgstr "" + +#: src/core.py:998 #, python-format -msgid "%(nick)s changed the subject to: %(subject)s" +msgid "Unknown command: %s" +msgstr "" + +#: src/core.py:1060 src/tabs.py:551 +msgid "an unknown software" +msgstr "" + +#: src/core.py:1061 src/tabs.py:552 +msgid "unknown" msgstr "" -#: src/gui.py:353 +#: src/core.py:1062 src/tabs.py:553 +msgid "on an unknown platform" +msgstr "" + +#: src/core.py:1215 +msgid "You didn't specify a server for the room you want to join" +msgstr "" + +#: src/core.py:1276 #, python-format -msgid "The subject is: %(subject)s" +msgid "Your bookmarks are now: %s" msgstr "" -#: src/gui.py:389 +#: src/core.py:1347 +msgid "No server specified" +msgstr "" + +#: src/core.py:1474 src/tabs.py:144 #, python-format -msgid "Your nickname is %s" +msgid "Unknown command (%s)" +msgstr "" + +#: src/core.py:1474 src/tabs.py:144 +msgid "Error" +msgstr "" + +#: src/tabs.py:59 +msgid "busy" +msgstr "" + +#: src/tabs.py:60 +msgid "away" +msgstr "" + +#: src/tabs.py:61 +msgid "not available" msgstr "" -#: src/gui.py:391 +#: src/tabs.py:62 +msgid "chatty" +msgstr "" + +#: src/tabs.py:63 +msgid "available" +msgstr "" + +#: src/tabs.py:263 +msgid "" +"Usage: /say <message>\n" +"Say: Just send the message.\n" +" Useful if you want your message to " +"begin with a '/'" +msgstr "" + +#: src/tabs.py:457 +msgid "" +"Usage: /ignore <nickname> \n" +"Ignore: Ignore a specified nickname." +msgstr "" + +#: src/tabs.py:458 +msgid "" +"Usage: /unignore <nickname>\n" +"Unignore: Remove the specified nickname from the ignore list." +msgstr "" + +#: src/tabs.py:459 +msgid "" +"Usage: /kick <nick> [reason]\n" +"Kick: Kick the user with the specified nickname. You also can give an " +"optional reason." +msgstr "" + +#: src/tabs.py:460 +msgid "" +"Usage: /topic <subject>\n" +"Topic: Change the subject of the room" +msgstr "" + +#: src/tabs.py:461 +msgid "" +"Usage: /query <nick> [message]\n" +"Query: Open a private conversation with <nick>. This nick has to be present " +"in the room you're currently in. If you specified a message after the " +"nickname, it will immediately be sent to this user" +msgstr "" + +#: src/tabs.py:462 +msgid "" +"Usage: /part [message]\n" +" Part: disconnect from a room. You can specify an optional message." +msgstr "" + +#: src/tabs.py:463 +msgid "" +"Usage: /nick <nickname>\n" +"Nick: Change your nickname in the current room" +msgstr "" + +#: src/tabs.py:464 +msgid "" +"Usage: /recolor\n" +"Recolor: Re-assign a color to all participants of the current room, based on " +"the last time they talked. Use this if the participants currently talking " +"have too many identical colors." +msgstr "" + +#: src/tabs.py:465 +msgid "" +"Usage: /cycle [message]\n" +"Cycle: Leaves the current room and rejoin it immediately" +msgstr "" + +#: src/tabs.py:466 +msgid "" +"Usage: /info <nickname>\n" +"Info: Display some information about the user in the MUC: his/here role, " +"affiliation, status and status message." +msgstr "" + +#: src/tabs.py:467 +msgid "" +"Usage: /configure\n" +"Configure: Configure the current room, through a form." +msgstr "" + +#: src/tabs.py:468 +msgid "" +"Usage: /version <jid or nick>\n" +"Version: get the software version of the given JID or nick in room (usually " +"its XMPP client and Operating System)" +msgstr "" + +#: src/tabs.py:602 +#, python-format +msgid "Cannot find user: %s" +msgstr "" + +#: src/tabs.py:610 #, python-format -msgid "%s is in the room" +msgid "The subject of the room is: %s" msgstr "" -#: src/gui.py:402 +#: src/tabs.py:664 src/tabs.py:682 #, python-format -msgid "%(nick)s joined the room %(roomname)s" +msgid "%s is not in the room" msgstr "" -#: src/gui.py:414 +#: src/tabs.py:666 #, python-format -msgid "%(old)s is now known as %(new)s" +msgid "%s is already ignored" msgstr "" -#: src/gui.py:418 +#: src/tabs.py:669 #, python-format -msgid "%(old_nick)s is now known as %(new_nick)s" +msgid "%s is now ignored" msgstr "" -#: src/gui.py:437 +#: src/tabs.py:684 #, python-format -msgid "You have been kicked by %(by)s. Reason: %(reason)s" +msgid "%s is not ignored" msgstr "" -#: src/gui.py:439 +#: src/tabs.py:687 #, python-format -msgid "You have been kicked. Reason: %s" +msgid "%s is now unignored" msgstr "" -#: src/gui.py:442 +#: src/tabs.py:822 #, python-format -msgid "%(nick)s has been kicked by %(by)s. Reason: %(reason)s" +msgid "5Your nickname is 3%s" msgstr "" -#: src/gui.py:444 +#: src/tabs.py:891 #, python-format -msgid "%(nick)s has been kicked. Reason: %(reason)s" +msgid "1%(spec)s 3You5 have been banned by 4%(by)s" msgstr "" -#: src/gui.py:450 src/gui.py:453 +#: src/tabs.py:893 #, python-format -msgid "%s has left the room" +msgid "1%(spec)s 3You5 have been banned." msgstr "" -#: src/gui.py:457 +#: src/tabs.py:896 #, python-format -msgid "%s changed his/her status: " +msgid "1%(spec)s 3%(nick)s5 has been banned by 4%(by)s" msgstr "" -#: src/gui.py:459 +#: src/tabs.py:898 #, python-format -msgid "affiliation: %s," +msgid "1%(spec)s 3%(nick)s5 has been banned" msgstr "" -#: src/gui.py:461 +#: src/tabs.py:900 #, python-format -msgid "role: %s," +msgid "5 Reason: 6%(reason)s5" msgstr "" -#: src/gui.py:463 +#: src/tabs.py:914 #, python-format -msgid "show: %s," +msgid "1%(spec)s 3You5 have been kicked by 3%(by)s" msgstr "" -#: src/gui.py:465 +#: src/tabs.py:916 #, python-format -msgid "status: %s," +msgid "1%(spec)s 3You5 have been kicked." msgstr "" -#: src/gui.py:518 +#: src/tabs.py:922 #, python-format -msgid "Error: unknown command (%s)" +msgid "1%(spec)s 3%(nick)s5 has been kicked by 3%(by)s" msgstr "" -#: src/gui.py:534 -msgid "Available commands are: " +#: src/tabs.py:924 +#, python-format +msgid "1%(spec)s 3%(nick)s5 has been kicked" msgstr "" -#: src/gui.py:537 -msgid "" -"\n" -"Type /help <command_name> to know what each command does" +#: src/tabs.py:926 +#, python-format +msgid "5 Reason: 6%(reason)s" msgstr "" -#: src/gui.py:542 +#: src/tabs.py:940 #, python-format -msgid "Unknown command: %s" +msgid "1%(spec)s 3%(nick)s5 has left the room" msgstr "" -#: src/gui.py:616 +#: src/tabs.py:942 #, python-format -msgid "already in room [%s]" +msgid "1%(spec)s 3%(nick)s5 (4%(jid)s5) has left the room" msgstr "" -#: src/gui.py:720 +#: src/tabs.py:955 #, python-format -msgid "%s is now ignored" +msgid "3%s5 changed: " msgstr "" -#: src/gui.py:722 +#: src/tabs.py:957 #, python-format -msgid "%s is already ignored" +msgid "affiliation: %s, " msgstr "" -#: src/gui.py:736 +#: src/tabs.py:960 #, python-format -msgid "%s was not ignored" +msgid "role: %s, " msgstr "" -#: src/gui.py:741 +#: src/tabs.py:963 #, python-format -msgid "%s is now unignored" +msgid "show: %s, " msgstr "" -#: src/gui.py:798 +#: src/tabs.py:966 #, python-format -msgid "The subject of the room is: %s" +msgid "status: %s, " +msgstr "" + +#: src/tabs.py:1002 src/tabs.py:1496 +msgid "" +"Usage: /unquery\n" +"Unquery: close the tab" +msgstr "" + +#: src/tabs.py:1003 src/tabs.py:1497 +msgid "Usage: /part\\Part: close the tab" +msgstr "" + +#: src/tabs.py:1113 +#, python-format +msgid "\"[%(old_nick)s]\" is now known as \"[%(new_nick)s]\"" +msgstr "" + +#: src/tabs.py:1122 +#, python-format +msgid "%(spec)s \"[%(nick)s]\" has left the room" msgstr "" -#: src/window.py:135 +#: src/tabs.py:1124 #, python-format -msgid "%(nick)s from room %(room)s" +msgid "%(spec)s \"[%(nick)s]\" has left the room \"(%(status)s)\"" +msgstr "" + +#: src/tabs.py:1155 +msgid "" +"Usage: /deny [jid]\n" +"Deny: Use this command to remove and deny your presence to the provided JID " +"(or the selected contact in your roster), who is asking you to be in his/" +"here roster" +msgstr "" + +#: src/tabs.py:1156 +msgid "" +"Usage: /accept [jid]\n" +"Accept: Use this command to authorize the provided JID (or the selected " +"contact in your roster), to see your presence, and to ask to subscribe to it " +"(mutual presence subscription)." +msgstr "" + +#: src/tabs.py:1157 +msgid "" +"Usage: /add <jid>\\Add: Use this command to add the specified JID to your " +"roster. The reverse authorization will automatically be accepted if the " +"remote JID accepts your subscription, leading to a mutual presence " +"subscription." +msgstr "" + +#: src/tabs.py:1158 +msgid "" +"Usage: /remove [jid]\\Remove: Use this command to remove the specified JID " +"from your roster. This wil unsubscribe you from its presence, cancel its " +"subscription to yours, and remove the item from your roster" +msgstr "" + +#: src/tabs.py:1159 +msgid "" +"Usage: /export [/path/to/file]\n" +"Export: Use this command to export your contacts into /path/to/file if " +"specified, or $HOME/poezio_contacts if not." +msgstr "" + +#: src/tabs.py:1160 +msgid "" +"Usage: /import [/path/to/file]\n" +"Import: Use this command to import your contacts from /path/to/file if " +"specified, or $HOME/poezio_contacts if not." +msgstr "" + +#: src/tabs.py:1206 +msgid "No JID specified" +msgstr "" + +#: src/tabs.py:1631 +msgid "" +"Usage: /close\n" +"Close: Just close this tab" msgstr "" diff --git a/src/core.py b/src/core.py index f96a61a8..44c967ca 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 |