diff options
Diffstat (limited to 'poezio/ui/types.py')
-rw-r--r-- | poezio/ui/types.py | 172 |
1 files changed, 89 insertions, 83 deletions
diff --git a/poezio/ui/types.py b/poezio/ui/types.py index 69d77a07..18e51427 100644 --- a/poezio/ui/types.py +++ b/poezio/ui/types.py @@ -2,28 +2,78 @@ from datetime import datetime from math import ceil, log10 from typing import Union, Optional, List, Tuple - -from poezio.theming import get_theme, dump_tuple -from poezio.ui.funcs import truncate_nick, parse_attrs +from poezio.ui.funcs import truncate_nick from poezio import poopt -from poezio.ui.consts import FORMAT_CHAR +from poezio.user import User +from poezio.theming import dump_tuple, get_theme +from poezio.ui.consts import ( + SHORT_FORMAT_LENGTH, + LONG_FORMAT_LENGTH, +) + + +class BaseMessage: + __slots__ = ('txt', 'time', 'identifier') + + def __init__(self, txt: str, identifier: str = '', time: Optional[datetime] = None): + self.txt = txt + self.identifier = identifier + if time is not None: + self.time = time + else: + self.time = datetime.now() + + def compute_offset(self, with_timestamps: bool, nick_size: int) -> int: + return SHORT_FORMAT_LENGTH + 1 + + +class XMLLog(BaseMessage): + """XML Log message""" + __slots__ = ('txt', 'time', 'identifier', 'incoming') + + def __init__( + self, + txt: str, + incoming: bool, + ): + BaseMessage.__init__( + self, + txt=txt, + identifier='', + ) + self.txt = txt + self.identifier = '' + self.incoming = incoming + + def compute_offset(self, with_timestamps: bool, nick_size: int) -> int: + offset = 0 + theme = get_theme() + IN, OUT = theme.CHAR_XML_IN, theme.CHAR_XML_OUT + if with_timestamps: + offset += 1 + SHORT_FORMAT_LENGTH + if self.incoming: + nick = IN + else: + nick = OUT + nick = truncate_nick(nick, nick_size) or '' + offset += 1 + len(nick) + return offset -class Message: - __slots__ = ('txt', 'nick_color', 'time', 'str_time', 'nickname', 'user', +class Message(BaseMessage): + __slots__ = ('txt', 'nick_color', 'time', 'nickname', 'user', 'history', 'identifier', 'top', 'highlight', 'me', 'old_message', 'revisions', 'jid', 'ack') def __init__(self, txt: str, - time: Optional[datetime], nickname: Optional[str], - nick_color: Optional[Tuple], - history: bool, - user: Optional[str], - identifier: Optional[str], + time: Optional[datetime] = None, + nick_color: Optional[Tuple] = None, + history: bool = False, + user: Optional[User] = None, + identifier: Optional[str] = '', top: Optional[bool] = False, - str_time: Optional[str] = None, highlight: bool = False, old_message: Optional['Message'] = None, revisions: int = 0, @@ -33,27 +83,22 @@ class Message: Create a new Message object with parameters, check for /me messages, and delayed messages """ - time = time if time is not None else datetime.now() + BaseMessage.__init__( + self, + txt=txt.replace('\t', ' ') + '\x19o', + identifier=identifier or '', + time=time, + ) if txt.startswith('/me '): me = True txt = '\x19%s}%s\x19o' % (dump_tuple(get_theme().COLOR_ME_MESSAGE), txt[4:]) else: me = False - str_time = time.strftime("%H:%M:%S") - if history: - txt = txt.replace( - '\x19o', - '\x19o\x19%s}' % dump_tuple(get_theme().COLOR_LOG_MSG)) - str_time = time.strftime("%Y-%m-%d %H:%M:%S") - - self.txt = txt.replace('\t', ' ') + '\x19o' - self.nick_color = nick_color - self.time = time - self.str_time = str_time + self.history = history self.nickname = nickname + self.nick_color = nick_color self.user = user - self.identifier = identifier self.top = top self.highlight = highlight self.me = me @@ -91,68 +136,29 @@ class Message: rev -= 1 return ''.join(acc) - def render(self, width: int, timestamp: bool = False, nick_size: int = 10) -> List["Line"]: - """ - Build a list of lines from this message. - """ - txt = self.txt - if not txt: - return [] - theme = get_theme() - if len(self.str_time) > 8: - default_color = ( - FORMAT_CHAR + dump_tuple(theme.COLOR_LOG_MSG) + '}') # type: Optional[str] - else: - default_color = None - ret = [] # type: List[Union[None, Line]] - nick = truncate_nick(self.nickname, nick_size) + def compute_offset(self, with_timestamps: bool, nick_size: int) -> int: offset = 0 + if with_timestamps: + if self.history: + offset += 1 + LONG_FORMAT_LENGTH + else: + offset += 1 + SHORT_FORMAT_LENGTH + + if not self.nickname: # not a message, nothing to do afterwards + return offset + + nick = truncate_nick(self.nickname, nick_size) or '' + offset += poopt.wcswidth(nick) if self.ack: + theme = get_theme() if self.ack > 0: offset += poopt.wcswidth(theme.CHAR_ACK_RECEIVED) + 1 else: offset += poopt.wcswidth(theme.CHAR_NACK) + 1 - if nick: - offset += poopt.wcswidth(nick) + 2 # + nick + '> ' length - if self.revisions > 0: - offset += ceil(log10(self.revisions + 1)) if self.me: - offset += 1 # '* ' before and ' ' after - if timestamp: - if self.str_time: - offset += 1 + len(self.str_time) - if theme.CHAR_TIME_LEFT and self.str_time: - offset += 1 - if theme.CHAR_TIME_RIGHT and self.str_time: - offset += 1 - lines = poopt.cut_text(txt, width - offset - 1) - prepend = default_color if default_color else '' - attrs = [] # type: List[str] - for line in lines: - saved = Line( - msg=self, - start_pos=line[0], - end_pos=line[1], - prepend=prepend) - attrs = parse_attrs(self.txt[line[0]:line[1]], attrs) - if attrs: - prepend = FORMAT_CHAR + FORMAT_CHAR.join(attrs) - else: - if default_color: - prepend = default_color - else: - prepend = '' - ret.append(saved) - return ret - - -# msg is a reference to the corresponding Message object. text_start and -# text_end are the position delimiting the text in this line. -class Line: - __slots__ = ('msg', 'start_pos', 'end_pos', 'prepend') - - def __init__(self, msg: Message, start_pos: int, end_pos: int, prepend: str) -> None: - self.msg = msg - self.start_pos = start_pos - self.end_pos = end_pos - self.prepend = prepend + offset += 3 + else: + offset += 2 + if self.revisions: + offset += ceil(log10(self.revisions + 1)) + return offset |