summaryrefslogtreecommitdiff
path: root/poezio/ui/types.py
diff options
context:
space:
mode:
Diffstat (limited to 'poezio/ui/types.py')
-rw-r--r--poezio/ui/types.py172
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