summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormathieui <mathieui@mathieui.net>2019-09-28 18:35:23 +0200
committermathieui <mathieui@mathieui.net>2020-05-09 19:46:17 +0200
commit80ce8453f50ccaad4d71fda8811ee33f5ffa3624 (patch)
tree6e4b7f86f97a82c5fd4cebc6a61349283dee2a36
parenta5ef6ec9105f22d14b7d7ec3b634796fc3466e93 (diff)
downloadpoezio-80ce8453f50ccaad4d71fda8811ee33f5ffa3624.tar.gz
poezio-80ce8453f50ccaad4d71fda8811ee33f5ffa3624.tar.bz2
poezio-80ce8453f50ccaad4d71fda8811ee33f5ffa3624.tar.xz
poezio-80ce8453f50ccaad4d71fda8811ee33f5ffa3624.zip
Rewrite part of the message handling/rendering
-rw-r--r--poezio/core/core.py5
-rw-r--r--poezio/mam.py1
-rw-r--r--poezio/tabs/basetabs.py11
-rw-r--r--poezio/tabs/xmltab.py5
-rw-r--r--poezio/text_buffer.py32
-rw-r--r--poezio/ui/consts.py10
-rw-r--r--poezio/ui/funcs.py10
-rw-r--r--poezio/ui/render.py234
-rw-r--r--poezio/ui/types.py172
-rw-r--r--poezio/windows/text_win.py204
10 files changed, 374 insertions, 310 deletions
diff --git a/poezio/core/core.py b/poezio/core/core.py
index 14852ac2..2b8252b1 100644
--- a/poezio/core/core.py
+++ b/poezio/core/core.py
@@ -1349,7 +1349,10 @@ class Core:
colors = get_theme().INFO_COLORS
color = colors.get(typ.lower(), colors.get('default', None))
nb_lines = self.information_buffer.add_message(
- msg, nickname=typ, nick_color=color)
+ txt=msg,
+ nickname=typ,
+ nick_color=color
+ )
popup_on = config.get('information_buffer_popup_on').split()
if isinstance(self.tabs.current_tab, tabs.RosterInfoTab):
self.refresh_window()
diff --git a/poezio/mam.py b/poezio/mam.py
index 0f745f30..6e13c074 100644
--- a/poezio/mam.py
+++ b/poezio/mam.py
@@ -72,7 +72,6 @@ def add_line(
highlight=False,
top=top,
identifier=None,
- str_time=None,
jid=None,
)
diff --git a/poezio/tabs/basetabs.py b/poezio/tabs/basetabs.py
index 40868e2f..eadc9a3f 100644
--- a/poezio/tabs/basetabs.py
+++ b/poezio/tabs/basetabs.py
@@ -45,7 +45,8 @@ from poezio.decorators import command_args_parser, refresh_wrapper
from poezio.logger import logger
from poezio.text_buffer import TextBuffer
from poezio.theming import get_theme, dump_tuple
-from poezio.windows.funcs import truncate_nick
+from poezio.ui.funcs import truncate_nick
+from poezio.ui.consts import LONG_FORMAT_LENGTH
from slixmpp import JID, InvalidJID, Message
@@ -839,12 +840,8 @@ class ChatTab(Tab):
if message.me:
offset += 1
if timestamp:
- if message.str_time:
- offset += 1 + len(message.str_time)
- if theme.CHAR_TIME_LEFT and message.str_time:
- offset += 1
- if theme.CHAR_TIME_RIGHT and message.str_time:
- offset += 1
+ if message.history:
+ offset += 1 + LONG_FORMAT_LENGTH
lines = poopt.cut_text(txt, self.text_win.width - offset - 1)
for line in lines:
built_lines.append(line)
diff --git a/poezio/tabs/xmltab.py b/poezio/tabs/xmltab.py
index c4a50df8..c73eddd0 100644
--- a/poezio/tabs/xmltab.py
+++ b/poezio/tabs/xmltab.py
@@ -262,7 +262,10 @@ class XMLTab(Tab):
else:
xml = self.core_buffer.messages[:]
text = '\n'.join(
- ('%s %s %s' % (msg.str_time, msg.nickname, clean_text(msg.txt))
+ ('%s %s %s' % (
+ msg.time.strftime('%H:%M:%S'),
+ msg.nickname,
+ clean_text(msg.txt))
for msg in xml))
filename = os.path.expandvars(os.path.expanduser(args[0]))
try:
diff --git a/poezio/text_buffer.py b/poezio/text_buffer.py
index 1667f0dc..c03f84f5 100644
--- a/poezio/text_buffer.py
+++ b/poezio/text_buffer.py
@@ -63,7 +63,6 @@ class TextBuffer:
highlight: bool = False,
top: Optional[bool] = False,
identifier: Optional[str] = None,
- str_time: Optional[str] = None,
jid: Optional[str] = None,
ack: int = 0) -> int:
"""
@@ -71,14 +70,13 @@ class TextBuffer:
"""
msg = Message(
txt,
- time,
- nickname,
- nick_color,
- history,
- user,
- identifier,
- top,
- str_time=str_time,
+ time=time,
+ nickname=nickname,
+ nick_color=nick_color,
+ history=history,
+ user=user,
+ identifier=identifier,
+ top=top,
highlight=highlight,
jid=jid,
ack=ack)
@@ -180,7 +178,7 @@ class TextBuffer:
if msg.user and msg.user is not user:
raise CorrectionError("Different users")
- elif len(msg.str_time) > 8: # ugly
+ elif msg.history:
raise CorrectionError("Delayed message")
elif not msg.user and (msg.jid is None or jid is None):
raise CorrectionError('Could not check the '
@@ -195,13 +193,13 @@ class TextBuffer:
self.correction_ids[new_id] = orig_id
message = Message(
- txt,
- time,
- msg.nickname,
- msg.nick_color,
- False,
- msg.user,
- orig_id,
+ txt=txt,
+ time=time,
+ nickname=msg.nickname,
+ nick_color=msg.nick_color,
+ history=False,
+ user=msg.user,
+ identifier=orig_id,
highlight=highlight,
old_message=msg,
revisions=msg.revisions + 1,
diff --git a/poezio/ui/consts.py b/poezio/ui/consts.py
index 91f19a82..0838d953 100644
--- a/poezio/ui/consts.py
+++ b/poezio/ui/consts.py
@@ -1,4 +1,14 @@
+from datetime import datetime
+
FORMAT_CHAR = '\x19'
# These are non-printable chars, so they should never appear in the input,
# I guess. But maybe we can find better chars that are even less risky.
FORMAT_CHARS = '\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x1A'
+
+# Short date format (only show time)
+SHORT_FORMAT = '%H:%M:%S'
+SHORT_FORMAT_LENGTH = len(datetime.now().strftime(SHORT_FORMAT))
+
+# Long date format (show date and time)
+LONG_FORMAT = '%Y-%m-%d %H:%M:%S'
+LONG_FORMAT_LENGTH = len(datetime.now().strftime(LONG_FORMAT))
diff --git a/poezio/ui/funcs.py b/poezio/ui/funcs.py
index 260cc037..023432ee 100644
--- a/poezio/ui/funcs.py
+++ b/poezio/ui/funcs.py
@@ -22,12 +22,14 @@ def find_first_format_char(text: str,
return pos
-def truncate_nick(nick: Optional[str], size=10) -> Optional[str]:
+def truncate_nick(nick: Optional[str], size=10) -> str:
if size < 1:
size = 1
- if nick and len(nick) > size:
- return nick[:size] + '…'
- return nick
+ if nick:
+ if len(nick) > size:
+ return nick[:size] + '…'
+ return nick
+ return ''
def parse_attrs(text: str, previous: Optional[List[str]] = None) -> List[str]:
diff --git a/poezio/ui/render.py b/poezio/ui/render.py
new file mode 100644
index 00000000..64b480a9
--- /dev/null
+++ b/poezio/ui/render.py
@@ -0,0 +1,234 @@
+import logging
+import curses
+
+from datetime import datetime
+from functools import singledispatch
+from typing import List, Optional, Tuple
+from math import ceil, log10
+
+from poezio import poopt
+from poezio.ui.consts import (
+ FORMAT_CHAR,
+ LONG_FORMAT,
+ SHORT_FORMAT,
+)
+from poezio.ui.funcs import (
+ truncate_nick,
+ parse_attrs,
+)
+from poezio.theming import (
+ get_theme,
+)
+from poezio.ui.types import (
+ BaseMessage,
+ Message,
+ XMLLog,
+)
+
+# 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: BaseMessage, 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
+
+ def __repr__(self):
+ return '(%s, %s)' % (self.start_pos, self.end_pos)
+
+
+LinePos = Tuple[int, int]
+
+def generate_lines(lines: List[LinePos], msg: BaseMessage, default_color: str = '') -> List[Line]:
+ line_objects = []
+ attrs = [] # type: List[str]
+ prepend = default_color if default_color else ''
+ for line in lines:
+ saved = Line(
+ msg=msg,
+ start_pos=line[0],
+ end_pos=line[1],
+ prepend=prepend)
+ attrs = parse_attrs(msg.txt[line[0]:line[1]], attrs)
+ if attrs:
+ prepend = FORMAT_CHAR + FORMAT_CHAR.join(attrs)
+ else:
+ if default_color:
+ prepend = default_color
+ else:
+ prepend = ''
+ line_objects.append(saved)
+ return line_objects
+
+
+@singledispatch
+def build_lines(msg: BaseMessage, width: int, timestamp: bool, nick_size: int = 10) -> List[Line]:
+ offset = msg.compute_offset(timestamp, nick_size)
+ lines = poopt.cut_text(msg.txt, width - offset - 1)
+ return generate_lines(lines, msg, default_color='')
+
+
+@build_lines.register(type(None))
+def build_separator(*args, **kwargs):
+ return [None]
+
+
+@build_lines.register(Message)
+def build_message(msg: Message, width: int, timestamp: bool, nick_size: int = 10) -> List[Line]:
+ """
+ Build a list of lines from this message.
+ """
+ txt = msg.txt
+ if not txt:
+ return []
+ offset = msg.compute_offset(timestamp, nick_size)
+ lines = poopt.cut_text(txt, width - offset - 1)
+ return generate_lines(lines, msg, default_color='')
+
+
+@build_lines.register(XMLLog)
+def build_xmllog(msg: XMLLog, width: int, timestamp: bool, nick_size: int = 10) -> List[Line]:
+ offset = msg.compute_offset(timestamp, nick_size)
+ lines = poopt.cut_text(msg.txt, width - offset - 1)
+ return generate_lines(lines, msg, default_color='')
+
+
+@singledispatch
+def write_pre(msg: BaseMessage, win, with_timestamps: bool, nick_size: int) -> int:
+ """Write the part before text (only the timestamp)"""
+ if with_timestamps:
+ return 1 + PreMessageHelpers.write_time(win, False, msg.time)
+ return 0
+
+
+@write_pre.register(Message)
+def write_pre_message(msg: Message, win, with_timestamps: bool, nick_size: int) -> int:
+ """Write the part before the body:
+ - timestamp (short or long)
+ - ack/nack
+ - nick (with a "* " for /me)
+ - LMC number if present
+ """
+ offset = 0
+ if with_timestamps:
+ logging.debug(msg)
+ offset += PreMessageHelpers.write_time(win, msg.history, msg.time)
+
+ if not msg.nickname: # not a message, nothing to do afterwards
+ return offset
+
+ nick = truncate_nick(msg.nickname, nick_size)
+ offset += poopt.wcswidth(nick)
+ if msg.nick_color:
+ color = msg.nick_color
+ elif msg.user:
+ color = msg.user.color
+ else:
+ color = None
+ if msg.ack:
+ if msg.ack > 0:
+ offset += PreMessageHelpers.write_ack(win)
+ else:
+ offset += PreMessageHelpers.write_nack(win)
+ if msg.me:
+ with win.colored_text(color=get_theme().COLOR_ME_MESSAGE):
+ win.addstr('* ')
+ PreMessageHelpers.write_nickname(win, nick, color, msg.highlight)
+ offset += PreMessageHelpers.write_revisions(win, msg)
+ win.addstr(' ')
+ offset += 3
+ else:
+ PreMessageHelpers.write_nickname(win, nick, color, msg.highlight)
+ offset += PreMessageHelpers.write_revisions(win, msg)
+ win.addstr('> ')
+ offset += 2
+ return offset
+
+
+@write_pre.register(XMLLog)
+def write_pre_xmllog(msg: XMLLog, win, with_timestamps: bool, nick_size: int) -> int:
+ """Write the part before the stanza (timestamp + IN/OUT)"""
+ offset = 0
+ if with_timestamps:
+ offset += PreMessageHelpers.write_time(win, False, msg.time)
+ theme = get_theme()
+ if msg.incoming:
+ char = theme.CHAR_XML_IN
+ color = theme.COLOR_XML_IN
+ else:
+ char = theme.CHAR_XML_OUT
+ color = theme.COLOR_XML_OUT
+ nick = truncate_nick(char, nick_size)
+ offset += poopt.wcswidth(nick)
+ PreMessageHelpers.write_nickname(win, char, color)
+ win.addstr(' ')
+ return offset
+
+class PreMessageHelpers:
+
+ @staticmethod
+ def write_revisions(buffer, msg: Message) -> int:
+ if msg.revisions:
+ color = get_theme().COLOR_REVISIONS_MESSAGE
+ with buffer.colored_text(color=color):
+ buffer.addstr('%d' % msg.revisions)
+ return ceil(log10(msg.revisions + 1))
+ return 0
+
+ @staticmethod
+ def write_ack(buffer) -> int:
+ theme = get_theme()
+ color = theme.COLOR_CHAR_ACK
+ with buffer.colored_text(color=color):
+ buffer.addstr(theme.CHAR_ACK_RECEIVED)
+ buffer.addstr(' ')
+ return poopt.wcswidth(theme.CHAR_ACK_RECEIVED) + 1
+
+ @staticmethod
+ def write_nack(buffer) -> int:
+ theme = get_theme()
+ color = theme.COLOR_CHAR_NACK
+ with buffer.colored_text(color=color):
+ buffer.addstr(theme.CHAR_NACK)
+ buffer.addstr(' ')
+ return poopt.wcswidth(theme.CHAR_NACK) + 1
+
+ @staticmethod
+ def write_nickname(buffer, nickname: str, color, highlight=False) -> None:
+ """
+ Write the nickname, using the user's color
+ and return the number of written characters
+ """
+ if not nickname:
+ return
+ attr = None
+ if highlight:
+ hl_color = get_theme().COLOR_HIGHLIGHT_NICK
+ if hl_color == "reverse":
+ attr = curses.A_REVERSE
+ else:
+ color = hl_color
+ with buffer.colored_text(color=color, attr=attr):
+ buffer.addstr(nickname)
+
+ @staticmethod
+ def write_time(buffer, history: bool, time: datetime) -> int:
+ """
+ Write the date on the yth line of the window
+ """
+ if time:
+ if history:
+ format = LONG_FORMAT
+ else:
+ format = SHORT_FORMAT
+ logging.debug(time)
+ time_str = time.strftime(format)
+ color = get_theme().COLOR_TIME_STRING
+ with buffer.colored_text(color=color):
+ buffer.addstr(time_str)
+ buffer.addstr(' ')
+ return poopt.wcswidth(time_str) + 1
+ return 0
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
diff --git a/poezio/windows/text_win.py b/poezio/windows/text_win.py
index bba66d60..904a709b 100644
--- a/poezio/windows/text_win.py
+++ b/poezio/windows/text_win.py
@@ -14,7 +14,8 @@ from poezio.ui.funcs import truncate_nick, parse_attrs
from poezio import poopt
from poezio.config import config
from poezio.theming import to_curses_attr, get_theme, dump_tuple
-from poezio.ui.types import Line, Message
+from poezio.ui.types import Message
+from poezio.ui.render import Line, build_lines, write_pre
log = logging.getLogger(__name__)
@@ -106,7 +107,7 @@ class BaseTextWin(Win):
Build a list of lines from a message, without adding it
to a list
"""
- return []
+ return build_lines(message, self.width, timestamp, nick_size)
def refresh(self) -> None:
pass
@@ -117,20 +118,6 @@ class BaseTextWin(Win):
"""
self.addstr_colored(txt, y, x)
- def write_time(self, time: str) -> int:
- """
- Write the date on the yth line of the window
- """
- if time:
- color = get_theme().COLOR_TIME_STRING
- curses_color = to_curses_attr(color)
- self._win.attron(curses_color)
- self.addstr(time)
- self._win.attroff(curses_color)
- self.addstr(' ')
- return poopt.wcswidth(time) + 1
- return 0
-
# TODO: figure out the type of room.
def resize(self, height: int, width: int, y: int, x: int, room=None) -> None:
if hasattr(self, 'width'):
@@ -341,15 +328,6 @@ class TextWin(BaseTextWin):
self.built_lines.pop(0)
return len(lines)
- def build_message(self, message: Optional[Message], timestamp: bool = False, nick_size: int = 10) -> List[Union[None, Line]]:
- """
- Build a list of lines from a message, without adding it
- to a list
- """
- if message is None: # line separator
- return [None]
- return message.render(self.width, timestamp, nick_size)
-
def refresh(self) -> None:
log.debug('Refresh: %s', self.__class__.__name__)
if self.height <= 0:
@@ -367,11 +345,10 @@ class TextWin(BaseTextWin):
if line:
msg = line.msg
if line.start_pos == 0:
- offset = self.write_pre_msg(msg, with_timestamps,
- nick_size)
+ offset = write_pre(msg, self, with_timestamps, nick_size)
elif y == 0:
- offset = self.compute_offset(msg, with_timestamps,
- nick_size)
+ offset = msg.compute_offset(with_timestamps,
+ nick_size)
self.write_text(
y, offset,
line.prepend + line.msg.txt[line.start_pos:line.end_pos])
@@ -382,120 +359,11 @@ class TextWin(BaseTextWin):
self._win.attrset(0)
self._refresh()
- def compute_offset(self, msg, with_timestamps, nick_size) -> int:
- offset = 0
- if with_timestamps and msg.str_time:
- offset += poopt.wcswidth(msg.str_time) + 1
-
- if not msg.nickname: # not a message, nothing to do afterwards
- return offset
-
- nick = truncate_nick(msg.nickname, nick_size)
- offset += poopt.wcswidth(nick)
- if msg.ack:
- theme = get_theme()
- if msg.ack > 0:
- offset += poopt.wcswidth(theme.CHAR_ACK_RECEIVED) + 1
- else:
- offset += poopt.wcswidth(theme.CHAR_NACK) + 1
- if msg.me:
- offset += 3
- else:
- offset += 2
- if msg.revisions:
- offset += ceil(log10(msg.revisions + 1))
- offset += self.write_revisions(msg)
- return offset
-
- def write_pre_msg(self, msg, with_timestamps, nick_size) -> int:
- offset = 0
- if with_timestamps:
- offset += self.write_time(msg.str_time)
-
- if not msg.nickname: # not a message, nothing to do afterwards
- return offset
-
- nick = truncate_nick(msg.nickname, nick_size)
- offset += poopt.wcswidth(nick)
- if msg.nick_color:
- color = msg.nick_color
- elif msg.user:
- color = msg.user.color
- else:
- color = None
- if msg.ack:
- if msg.ack > 0:
- offset += self.write_ack()
- else:
- offset += self.write_nack()
- if msg.me:
- self._win.attron(to_curses_attr(get_theme().COLOR_ME_MESSAGE))
- self.addstr('* ')
- self.write_nickname(nick, color, msg.highlight)
- offset += self.write_revisions(msg)
- self.addstr(' ')
- offset += 3
- else:
- self.write_nickname(nick, color, msg.highlight)
- offset += self.write_revisions(msg)
- self.addstr('> ')
- offset += 2
- return offset
-
- def write_revisions(self, msg) -> int:
- if msg.revisions:
- self._win.attron(
- to_curses_attr(get_theme().COLOR_REVISIONS_MESSAGE))
- self.addstr('%d' % msg.revisions)
- self._win.attrset(0)
- return ceil(log10(msg.revisions + 1))
- return 0
-
def write_line_separator(self, y) -> None:
theme = get_theme()
char = theme.CHAR_NEW_TEXT_SEPARATOR
self.addnstr(y, 0, char * (self.width // len(char) - 1), self.width,
to_curses_attr(theme.COLOR_NEW_TEXT_SEPARATOR))
-
- def write_ack(self) -> int:
- theme = get_theme()
- color = theme.COLOR_CHAR_ACK
- self._win.attron(to_curses_attr(color))
- self.addstr(theme.CHAR_ACK_RECEIVED)
- self._win.attroff(to_curses_attr(color))
- self.addstr(' ')
- return poopt.wcswidth(theme.CHAR_ACK_RECEIVED) + 1
-
- def write_nack(self) -> int:
- theme = get_theme()
- color = theme.COLOR_CHAR_NACK
- self._win.attron(to_curses_attr(color))
- self.addstr(theme.CHAR_NACK)
- self._win.attroff(to_curses_attr(color))
- self.addstr(' ')
- return poopt.wcswidth(theme.CHAR_NACK) + 1
-
- def write_nickname(self, nickname, color, highlight=False) -> None:
- """
- Write the nickname, using the user's color
- and return the number of written characters
- """
- if not nickname:
- return
- if highlight:
- hl_color = get_theme().COLOR_HIGHLIGHT_NICK
- if hl_color == "reverse":
- self._win.attron(curses.A_REVERSE)
- else:
- color = hl_color
- if color:
- self._win.attron(to_curses_attr(color))
- self.addstr(nickname)
- if color:
- self._win.attroff(to_curses_attr(color))
- if highlight and hl_color == "reverse":
- self._win.attroff(curses.A_REVERSE)
-
def modify_message(self, old_id, message) -> None:
"""
Find a message, and replace it with a new one
@@ -544,28 +412,12 @@ class XMLTextWin(BaseTextWin):
if line:
msg = line.msg
if line.start_pos == 0:
- if msg.nickname == theme.CHAR_XML_OUT:
- color = theme.COLOR_XML_OUT
- elif msg.nickname == theme.CHAR_XML_IN:
- color = theme.COLOR_XML_IN
- self.write_time(msg.str_time)
- self.write_prefix(msg.nickname, color)
- self.addstr(' ')
+ offset = write_pre(msg, self, True, 10)
if y != self.height - 1:
self.addstr('\n')
self._win.attrset(0)
for y, line in enumerate(lines):
- offset = 0
- # Offset for the timestamp (if any) plus a space after it
- offset += len(line.msg.str_time)
- # space
- offset += 1
-
- # Offset for the prefix
- offset += poopt.wcswidth(truncate_nick(line.msg.nickname))
- # space
- offset += 1
-
+ offset = msg.compute_offset(True, 10)
self.write_text(
y, offset,
line.prepend + line.msg.txt[line.start_pos:line.end_pos])
@@ -573,43 +425,3 @@ class XMLTextWin(BaseTextWin):
self.addstr('\n')
self._win.attrset(0)
self._refresh()
-
- def build_message(self, message: Message, timestamp: bool = False, nick_size: int = 10) -> List[Line]:
- txt = message.txt
- ret = []
- default_color = None
- nick = truncate_nick(message.nickname, nick_size)
- offset = 0
- if nick:
- offset += poopt.wcswidth(nick) + 1 # + nick + ' ' length
- if message.str_time:
- offset += 1 + len(message.str_time)
- theme = get_theme()
- if theme.CHAR_TIME_LEFT and message.str_time:
- offset += 1
- if theme.CHAR_TIME_RIGHT and message.str_time:
- offset += 1
- lines = poopt.cut_text(txt, self.width - offset - 1)
- prepend = default_color if default_color else ''
- attrs = [] # type: List[str]
- for line in lines:
- saved = Line(
- msg=message,
- start_pos=line[0],
- end_pos=line[1],
- prepend=prepend)
- attrs = parse_attrs(message.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
-
- def write_prefix(self, nickname, color) -> None:
- self._win.attron(to_curses_attr(color))
- self.addstr(truncate_nick(nickname))
- self._win.attroff(to_curses_attr(color))