From 92e63829a699ec68e7dcc2185fb7393255342dd2 Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Wed, 30 Mar 2011 04:34:45 +0200 Subject: Finish colors support with xhtml (clean the elinks dump, handle the input etc) --- src/tabs.py | 10 ++++++++-- src/windows.py | 20 ++++++++++++++++++- src/xhtml.py | 63 +++++++++++++++++++++++++++++++++++++++++++++++++++++----- 3 files changed, 85 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/tabs.py b/src/tabs.py index b7624c2b..53115716 100644 --- a/src/tabs.py +++ b/src/tabs.py @@ -39,6 +39,7 @@ import string import common import core import singleton +import xhtml import multiuserchat as muc @@ -270,7 +271,8 @@ class ChatTab(Tab): def on_enter(self): txt = self.input.key_enter() - if not self.execute_command(txt): + clean_text = xhtml.clean_text(txt) + if not self.execute_command(clean_text): if txt.startswith('//'): txt = txt[1:] self.command_say(txt) @@ -556,7 +558,11 @@ class MucTab(ChatTab): def command_say(self, line): msg = self.core.xmpp.make_message(self.get_name()) msg['type'] = 'groupchat' - msg['body'] = line + if line.find('\x19') == -1: + msg['body'] = line + else: + msg['body'] = xhtml.clean_text(line) + msg['xhtml_im'] = xhtml.poezio_colors_to_html(line) if config.get('send_chat_states', 'true') == 'true' and self.remote_wants_chatstates is not False: msg['chat_state'] = 'active' msg.send() diff --git a/src/windows.py b/src/windows.py index 7051bf2d..48cfc7ba 100644 --- a/src/windows.py +++ b/src/windows.py @@ -1103,7 +1103,8 @@ class MessageInput(Input): """ attr_char = read_char(self.core.stdscr) if attr_char in self.text_attributes or attr_char.isdigit(): - self.do_command('\x19%s' % attr_char) + self.do_command('\x19', False) + self.do_command(attr_char) def key_down(self): """ @@ -1131,6 +1132,23 @@ class MessageInput(Input): self.clear_text() return txt + def rewrite_text(self): + """ + Refresh the line onscreen, from the pos and pos_line, with colors + """ + with g_lock: + text = self.text.replace('\n', '|') + self._win.erase() + if self.color: + self._win.attron(common.curses_color_pair(self.color)) + displayed_text = text[self.line_pos:self.line_pos+self.width-1] + self._win.attrset(0) + self.addstr_colored(displayed_text) + self.addstr(0, wcwidth.wcswidth(displayed_text[:self.pos]), '') + if self.color: + self._win.attroff(common.curses_color_pair(self.color)) + self._refresh() + class CommandInput(Input): """ An input with an help message in the left, with three given callbacks: diff --git a/src/xhtml.py b/src/xhtml.py index be09442b..aa2643f5 100644 --- a/src/xhtml.py +++ b/src/xhtml.py @@ -32,6 +32,8 @@ log = logging.getLogger(__name__) shell_colors_re = re.compile(r'(\[(?:\d+;)*(?:\d+m))') +start_indent_re = re.compile(r'\[0;30m\[0;37m ') +newline_indent_re = re.compile('\n\[0;37m ') def get_body_from_message_stanza(message): """ @@ -49,9 +51,24 @@ def get_body_from_message_stanza(message): return shell_colors_to_poezio_colors(shell_body) return message['body'] +def clean_text(string): + """ + Remove all \x19 from the string + """ + pos = string.find('\x19') + while pos != -1: + string = string[:pos] + string[pos+2:] + pos = string.find('\x19') + return string + number_to_color_names = { 1: 'red', 2: 'green', + 3: 'yellow', + 4: 'blue', + 5: 'violet', + 6: 'turquoise', + 7: 'white' } def poezio_colors_to_html(string): @@ -64,7 +81,7 @@ def poezio_colors_to_html(string): # a list of all opened elements, e.g. ['strong', 'span'] # So that we know what we need to close opened_elements = [] - res = "

" + res = "

" next_attr_char = string.find('\x19') while next_attr_char != -1: attr_char = string[next_attr_char+1].lower() @@ -101,6 +118,7 @@ def shell_colors_to_poezio_colors(string): The current understanding of this syntax is: n = 0: reset all attributes to defaults + n = 1: activate bold n >= 30 and n <= 37: set the foreground to n-30 """ @@ -110,11 +128,20 @@ def shell_colors_to_poezio_colors(string): res = '' for num in numbers: if num == 0: - res += r'\x19o' - elif num >= 30 and num <= 37: - res += r'\x19%s' % (num-30,) + res += '\x19o' + elif num == 1: + res += '\x19b' + elif num >= 31 and num <= 37: + res += '\x19%s' % (num-30,) return res - return shell_colors_re.sub(repl, string) + def remove_elinks_indent(string): + lines = string.split('\n') + for i, line in enumerate(lines): + lines[i] = re.sub(' ', '', line, 1) + return '\n'.join(lines) + res = shell_colors_re.sub(repl, string).strip() + res = remove_elinks_indent(res) + return res def xhtml_code_to_shell_colors(string): """ @@ -125,6 +152,32 @@ def xhtml_code_to_shell_colors(string): result = process.communicate(input=string.encode('utf-8'))[0] return result.decode('utf-8').strip() +def poezio_colors_to_xhtml(string): + """ + Generate a valid xhtml string from + the poezio colors in the given string + """ + res = "" + next_attr_char = string.find('\x19') + open_elements = [] + while next_attr_char != -1: + attr_char = string[next_attr_char+1].lower() + if next_attr_char != 0: + res += string[:next_attr_char] + string = string[next_attr_char+2:] + if attr_char == 'o': + # close all opened elements + for elem in open_elements: + res += '' + open_elements = [] + elif attr_char == 'b': + if 'strong' not in open_elements: + res += '' + open_elements.append('strong') + elif attr_char.isdigit(): + self._win.attron(common.curses_color_pair(int(attr_char))) + next_attr_char = string.find('\x19') + if __name__ == '__main__': # print(xhtml_code_to_shell_colors(""" # -- cgit v1.2.3