def build_message(self, message, timestamp=False, nick_size=10): """ 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 [] if len(message.str_time) > 8: default_color = (FORMAT_CHAR + dump_tuple(get_theme().COLOR_LOG_MSG) + '}') else: default_color = None ret = [] nick = truncate_nick(message.nickname, nick_size) offset = 0 if message.ack: if message.ack > 0: offset += poopt.wcswidth(get_theme().CHAR_ACK_RECEIVED) + 1 else: offset += poopt.wcswidth(get_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 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
def build_message(self, message, timestamp=False): """ 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 [] if len(message.str_time) > 8: default_color = (FORMAT_CHAR + dump_tuple(get_theme().COLOR_LOG_MSG) + '}') else: default_color = None ret = [] nick = truncate_nick(message.nickname) offset = 0 if message.ack: if message.ack > 0: offset += poopt.wcswidth(get_theme().CHAR_ACK_RECEIVED) + 1 else: offset += poopt.wcswidth(get_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 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
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()
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 assert (self.pos >= self.view_pos and self.pos <= self.view_pos + max(self.width, 3))
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
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
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()
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 assert(self.pos >= self.view_pos and self.pos <= self.view_pos + max(self.width, 3))
def build_message(self, message, timestamp=False): txt = message.txt ret = [] default_color = None nick = truncate_nick(message.nickname) 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
def build_message(self, message, timestamp=False): txt = message.txt ret = [] default_color = None nick = truncate_nick(message.nickname) 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
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
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
def refresh(self): 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()
def refresh(self): 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()
def refresh(self): log.debug('Refresh: %s', self.__class__.__name__) 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] with_timestamps = config.get("show_timestamps") 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.nick_color: color = msg.nick_color elif msg.user: color = msg.user.color else: color = None if with_timestamps: self.write_time(msg.str_time) if msg.ack: if msg.ack > 0: self.write_ack() else: self.write_nack() if msg.me: self._win.attron(to_curses_attr(get_theme().COLOR_ME_MESSAGE)) self.addstr('* ') self.write_nickname(msg.nickname, color, msg.highlight) if msg.revisions: self._win.attron(to_curses_attr(get_theme().COLOR_REVISIONS_MESSAGE)) self.addstr('%d' % msg.revisions) self._win.attrset(0) self.addstr(' ') else: self.write_nickname(msg.nickname, color, msg.highlight) if msg.revisions: self._win.attron(to_curses_attr(get_theme().COLOR_REVISIONS_MESSAGE)) self.addstr('%d' % msg.revisions) self._win.attrset(0) self.addstr('> ') if y != self.height-1: self.addstr('\n') self._win.attrset(0) for y, line in enumerate(lines): if not line: self.write_line_separator(y) else: offset = 0 # Offset for the timestamp (if any) plus a space after it if with_timestamps: offset += len(line.msg.str_time) if offset: offset += 1 # Offset for the nickname (if any) # plus a space and a > after it if line.msg.nickname: offset += poopt.wcswidth( truncate_nick(line.msg.nickname)) if line.msg.me: offset += 3 else: offset += 2 offset += ceil(log10(line.msg.revisions + 1)) if line.msg.ack: if msg.ack > 0: offset += 1 + poopt.wcswidth( get_theme().CHAR_ACK_RECEIVED) else: offset += 1 + poopt.wcswidth(get_theme().CHAR_NACK) 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()
def refresh(self): log.debug('Refresh: %s', self.__class__.__name__) 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] with_timestamps = config.get("show_timestamps") 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.nick_color: color = msg.nick_color elif msg.user: color = msg.user.color else: color = None if with_timestamps: self.write_time(msg.str_time) if msg.ack: self.write_ack() if msg.me: self._win.attron( to_curses_attr(get_theme().COLOR_ME_MESSAGE)) self.addstr('* ') self.write_nickname(msg.nickname, color, msg.highlight) if msg.revisions: self._win.attron( to_curses_attr( get_theme().COLOR_REVISIONS_MESSAGE)) self.addstr('%d' % msg.revisions) self._win.attrset(0) self.addstr(' ') else: self.write_nickname(msg.nickname, color, msg.highlight) if msg.revisions: self._win.attron( to_curses_attr( get_theme().COLOR_REVISIONS_MESSAGE)) self.addstr('%d' % msg.revisions) self._win.attrset(0) self.addstr('> ') if y != self.height - 1: self.addstr('\n') self._win.attrset(0) for y, line in enumerate(lines): if not line: self.write_line_separator(y) else: offset = 0 # Offset for the timestamp (if any) plus a space after it if with_timestamps: offset += len(line.msg.str_time) if offset: offset += 1 # Offset for the nickname (if any) # plus a space and a > after it if line.msg.nickname: offset += poopt.wcswidth(truncate_nick(line.msg.nickname)) if line.msg.me: offset += 3 else: offset += 2 offset += ceil(log10(line.msg.revisions + 1)) if line.msg.ack: offset += 1 + poopt.wcswidth( get_theme().CHAR_ACK_RECEIVED) 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()