Ejemplo n.º 1
0
 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]
     txt = message.txt
     if not txt:
         return []
     theme = get_theme()
     if len(message.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(message.nickname, nick_size)
     offset = 0
     if message.ack:
         if message.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 message.revisions > 0:
         offset += ceil(log10(message.revisions + 1))
     if message.me:
         offset += 1  # '* ' before and ' ' after
     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
     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
Ejemplo n.º 2
0
 def build_message(self, message, timestamp=False, nick_size=10):
     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)
     if get_theme().CHAR_TIME_LEFT and message.str_time:
         offset += 1
     if get_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 = []
     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
Ejemplo n.º 3
0
    def write_pre_msg(self, msg, with_timestamps, nick_size):
        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
Ejemplo n.º 4
0
 def build_message(self, message, timestamp=False, nick_size=10):
     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)
     if get_theme().CHAR_TIME_LEFT and message.str_time:
         offset += 1
     if get_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 = []
     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
Ejemplo n.º 5
0
 def rewrite_text(self) -> None:
     """
     Refresh the line onscreen, but first, always adjust the
     view_pos.  Also, each FORMAT_CHAR+attr_char count only take
     one screen column (this is done in _addstr_colored_lite), we
     have to do some special calculations to find the correct
     length of text to display, and the position of the cursor.
     """
     self.adjust_view_pos()
     text = self.text
     self._win.erase()
     if self.color:
         self._win.attron(to_curses_attr(self.color))
     displayed_text = text[self.view_pos:self.view_pos + self.width -
                           1].replace('\t', '\x18')
     self._win.attrset(0)
     self._addstr_colored_lite(displayed_text)
     # Fill the rest of the line with the input color
     if self.color:
         (_, x) = self._win.getyx()
         size = self.width - x
         self.addnstr(' ' * size, size, to_curses_attr(self.color))
     self.addstr(0, poopt.wcswidth(
         displayed_text[:self.pos - self.view_pos]), '')
     if self.color:
         self._win.attroff(to_curses_attr(self.color))
     curses.curs_set(1)
     self._refresh()
Ejemplo n.º 6
0
    def write_pre_msg(self, msg, with_timestamps, nick_size):
        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
Ejemplo n.º 7
0
 def write_nack(self):
     color = get_theme().COLOR_CHAR_NACK
     self._win.attron(to_curses_attr(color))
     self.addstr(get_theme().CHAR_NACK)
     self._win.attroff(to_curses_attr(color))
     self.addstr(' ')
     return poopt.wcswidth(get_theme().CHAR_NACK) + 1
Ejemplo n.º 8
0
 def write_nack(self):
     color = get_theme().COLOR_CHAR_NACK
     self._win.attron(to_curses_attr(color))
     self.addstr(get_theme().CHAR_NACK)
     self._win.attroff(to_curses_attr(color))
     self.addstr(' ')
     return poopt.wcswidth(get_theme().CHAR_NACK) + 1
Ejemplo n.º 9
0
 def rewrite_text(self):
     """
     Refresh the line onscreen, but first, always adjust the
     view_pos.  Also, each FORMAT_CHAR+attr_char count only take
     one screen column (this is done in _addstr_colored_lite), we
     have to do some special calculations to find the correct
     length of text to display, and the position of the cursor.
     """
     self.adjust_view_pos()
     text = self.text
     self._win.erase()
     if self.color:
         self._win.attron(to_curses_attr(self.color))
     displayed_text = text[self.view_pos:self.view_pos+self.width-1].replace('\t', '\x18')
     self._win.attrset(0)
     self._addstr_colored_lite(displayed_text)
     # Fill the rest of the line with the input color
     if self.color:
         (_, x) = self._win.getyx()
         size = self.width - x
         self.addnstr(' ' * size, size, to_curses_attr(self.color))
     self.addstr(0,
             poopt.wcswidth(displayed_text[:self.pos-self.view_pos]), '')
     if self.color:
         self._win.attroff(to_curses_attr(self.color))
     curses.curs_set(1)
     self._refresh()
Ejemplo n.º 10
0
 def write_nack(buffer: 'Win') -> 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
Ejemplo n.º 11
0
 def write_ack(self) -> int:
     color = get_theme().COLOR_CHAR_ACK
     self._win.attron(to_curses_attr(color))
     self.addstr(get_theme().CHAR_ACK_RECEIVED)
     self._win.attroff(to_curses_attr(color))
     self.addstr(' ')
     return poopt.wcswidth(get_theme().CHAR_ACK_RECEIVED) + 1
Ejemplo n.º 12
0
 def goto_build_lines(self, new_date):
     text_buffer = self._text_buffer
     built_lines = []
     message_count = 0
     timestamp = config.get('show_timestamps')
     nick_size = config.get('max_nick_length')
     for message in text_buffer.messages:
         # Build lines of a message
         txt = message.txt
         nick = truncate_nick(message.nickname, nick_size)
         offset = 0
         theme = get_theme()
         if message.ack:
             if message.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
         if message.revisions > 0:
             offset += ceil(log10(message.revisions + 1))
         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
         lines = poopt.cut_text(txt, self.text_win.width - offset - 1)
         for line in lines:
             built_lines.append(line)
         # Find the message with timestamp less than or equal to the queried
         # timestamp and goto that location in the tab.
         if message.time <= new_date:
             message_count += 1
             if len(self.text_win.built_lines
                    ) - self.text_win.height >= len(built_lines):
                 self.text_win.pos = len(
                     self.text_win.built_lines
                 ) - self.text_win.height - len(built_lines) + 1
             else:
                 self.text_win.pos = 0
     if message_count == 0:
         self.text_win.scroll_up(len(self.text_win.built_lines))
     self.core.refresh_window()
Ejemplo n.º 13
0
 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
Ejemplo n.º 14
0
 def write_time(self, time):
     """
     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
Ejemplo n.º 15
0
    def compute_offset(self, msg, with_timestamps, nick_size):
        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:
            if msg.ack > 0:
                offset += poopt.wcswidth(get_theme().CHAR_ACK_RECEIVED) + 1
            else:
                offset += poopt.wcswidth(get_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
Ejemplo n.º 16
0
    def compute_offset(self, msg, with_timestamps, nick_size):
        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:
            if msg.ack > 0:
                offset += poopt.wcswidth(get_theme().CHAR_ACK_RECEIVED) + 1
            else:
                offset += poopt.wcswidth(get_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
Ejemplo n.º 17
0
 def write_time(buffer: 'Win', history: bool, time: datetime) -> int:
     """
     Write the date on the yth line of the window
     """
     theme = get_theme()
     if time:
         if history and time.date() != date.today():
             format = theme.LONG_TIME_FORMAT
         else:
             format = theme.SHORT_TIME_FORMAT
         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
Ejemplo n.º 18
0
def write_pre_xmllog(msg: XMLLog, win: 'Win', with_timestamps: bool,
                     nick_size: int) -> int:
    """Write the part before the stanza (timestamp + IN/OUT)"""
    offset = 0
    if with_timestamps:
        offset += 1 + 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
Ejemplo n.º 19
0
    def refresh(self) -> None:
        log.debug('Refresh: %s', self.__class__.__name__)
        theme = get_theme()
        if self.height <= 0:
            return
        if self.pos == 0:
            lines = self.built_lines[-self.height:]
        else:
            lines = self.built_lines[-self.height - self.pos:-self.pos]
        self._win.move(0, 0)
        self._win.erase()
        for y, line in enumerate(lines):
            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(' ')
            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

            self.write_text(
                y, offset,
                line.prepend + line.msg.txt[line.start_pos:line.end_pos])
            if y != self.height - 1:
                self.addstr('\n')
        self._win.attrset(0)
        self._refresh()
Ejemplo n.º 20
0
    def refresh(self) -> None:
        log.debug('Refresh: %s', self.__class__.__name__)
        theme = get_theme()
        if self.height <= 0:
            return
        if self.pos == 0:
            lines = self.built_lines[-self.height:]
        else:
            lines = self.built_lines[-self.height - self.pos:-self.pos]
        self._win.move(0, 0)
        self._win.erase()
        for y, line in enumerate(lines):
            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(' ')
            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

            self.write_text(
                y, offset,
                line.prepend + line.msg.txt[line.start_pos:line.end_pos])
            if y != self.height - 1:
                self.addstr('\n')
        self._win.attrset(0)
        self._refresh()
Ejemplo n.º 21
0
def write_pre_message(msg: Message, win: '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:
        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
Ejemplo n.º 22
0
    def adjust_view_pos(self) -> None:
        """
        Adjust the position of the View, if needed (for example if the
        cursor moved and would now be out of the view, we adapt the
        view_pos so that we can always see our cursor)
        """
        # start of the input
        if self.pos == 0:
            self.view_pos = 0
            return
        # cursor outside of the screen (left)
        if self.pos <= self.view_pos:
            self.view_pos = self.pos - max(1 * self.width // 3, 1)
        # cursor outside of the screen (right)
        elif self.pos >= self.view_pos + self.width - 1:
            self.view_pos = self.pos - max(2 * self.width // 3, 2)

        if self.view_pos < 0:
            self.view_pos = 0

        # text small enough to fit inside the window entirely:
        # remove scrolling if present
        if poopt.wcswidth(self.text) < self.width:
            self.view_pos = 0
Ejemplo n.º 23
0
    def adjust_view_pos(self):
        """
        Adjust the position of the View, if needed (for example if the
        cursor moved and would now be out of the view, we adapt the
        view_pos so that we can always see our cursor)
        """
        # start of the input
        if self.pos == 0:
            self.view_pos = 0
            return
        # cursor outside of the screen (left)
        if self.pos <= self.view_pos:
            self.view_pos = self.pos - max(1 * self.width // 3, 1)
        # cursor outside of the screen (right)
        elif self.pos >= self.view_pos + self.width - 1:
            self.view_pos = self.pos - max(2 * self.width // 3, 2)

        if self.view_pos < 0:
            self.view_pos = 0

        # text small enough to fit inside the window entirely:
        # remove scrolling if present
        if poopt.wcswidth(self.text) < self.width:
            self.view_pos = 0