bowl/cheuph/euphoria/euph_renderer.py

150 lines
5 KiB
Python
Raw Blame History

import unicodedata
from typing import Set
import yaboli
from ..cursor_rendering import CursorRenderer
from ..element import Message, RenderedMessage
from ..markup import AT, AttributedText, Attributes
__all__ = ["EuphRenderer"]
class EuphRenderer(CursorRenderer):
YEAR_FORMAT = "%y-%m-%d "
YEAR_WIDTH = 11
TIME_FORMAT = "%H:%M"
TIME_WIDTH = 5
SECOND_FORMAT = ":%S"
SECOND_WIDTH = 3
NORMAL_WIDTH = {"N", "Na", "H", "A"}
def __init__(self,
nick: str,
replace_wide_unicode: bool = True,
replace_character_categories: Set[str] = {"Cf"},
unicode_placeholder: str = "<EFBFBD>",
# Meta settings
show_year: bool = False,
show_seconds: bool = False,
meta_attrs: Attributes = {},
# Surround settings
surround_left: str = "[",
surround_right: str = "]",
surround_attrs: Attributes = {},
# Cursor settings
cursor_surround_left: str = "<",
cursor_surround_right: str = ">",
cursor_surround_attrs: Attributes = {},
cursor_own_nick_attrs: Attributes = {},
cursor_fill: str = " ",
cursor_fill_attrs: Attributes = {},
# Various attributes
nick_attrs: Attributes = {},
own_nick_attrs: Attributes = {},
) -> None:
self.nick = nick
self._replace_wide_unicode = replace_wide_unicode
self._replace_character_categories = replace_character_categories
self._unicode_placeholder = unicode_placeholder
# Meta settings
self._show_year = show_year
self._show_seconds = show_seconds
self._meta_attrs = meta_attrs
# Surround settings
self._surround_left = surround_left
self._surround_right = surround_right
self._surround_attrs = surround_attrs
# Cursor settings
self._cursor_surround_left = cursor_surround_left
self._cursor_surround_right = cursor_surround_right
self._cursor_surround_attrs = cursor_surround_attrs
self._cursor_own_nick_attrs = cursor_own_nick_attrs
self._cursor_fill = cursor_fill
self._cursor_fill_attrs = cursor_fill_attrs
# Various attributes
self._nick_attrs = nick_attrs
self._own_nick_attrs = own_nick_attrs
@property
def meta_width(self) -> int:
width = self.TIME_WIDTH + 1 # One space at the end
if self._show_year:
width += self.YEAR_WIDTH
if self._show_seconds:
width += self.SECOND_WIDTH
return width
def _is_wide(self, char: str) -> bool:
return unicodedata.east_asian_width(char) not in self.NORMAL_WIDTH
def _filter_unicode(self, text: str) -> str:
new_chars = []
for char in text:
if self._replace_wide_unicode and self._is_wide(char):
new_chars.append(self._unicode_placeholder)
elif unicodedata.category(char) in self._replace_character_categories:
pass
else:
new_chars.append(char)
return "".join(new_chars)
def _render_meta(self, message: Message) -> AttributedText:
elements = [self.TIME_FORMAT]
if self._show_year:
elements.insert(0, self.YEAR_FORMAT)
if self._show_seconds:
elements.append(self.SECOND_FORMAT)
text = message.timestamp.strftime("".join(elements))
return AT(text, attributes=self._meta_attrs) + AT(" ")
def render_element(self, message: Message, width: int) -> RenderedMessage:
meta = self._render_meta(message)
if yaboli.similar(self.nick, message.nick):
nick_attrs = self._own_nick_attrs
else:
nick_attrs = self._nick_attrs
left = AT(self._surround_left, attributes=self._surround_attrs)
nick = AT(self._filter_unicode(message.nick),
attributes=nick_attrs)
right = AT(self._surround_right, attributes=self._surround_attrs)
nick_str = left + nick + right + AT(" ")
nick_spaces = AT(" " * len(nick))
content = self._filter_unicode(message.content)
lines = []
for i, line in enumerate(content.split("\n")):
text = (nick_str if i == 0 else nick_spaces) + AT(line)
lines.append(text)
return RenderedMessage(message.id, lines, meta)
def render_cursor(self, width: int) -> AttributedText:
left = AT(self._cursor_surround_left,
attributes=self._cursor_surround_attrs)
nick = AT(self._filter_unicode(self.nick),
attributes=self._cursor_own_nick_attrs)
right = AT(self._cursor_surround_right,
attributes=self._cursor_surround_attrs)
nick_str = left + nick + right
rest_width = max(0, width - len(nick_str))
rest_str = AT(self._cursor_fill * rest_width,
attributes=self._cursor_fill_attrs)
return nick_str + rest_str