[tor-commits] [nyx/master] Function for drawing a log message

atagar at torproject.org atagar at torproject.org
Tue May 5 05:42:06 UTC 2015


commit eb090a9c2a9d985df4477136e682e89bc5905d04
Author: Damian Johnson <atagar at torproject.org>
Date:   Mon May 4 13:28:58 2015 -0700

    Function for drawing a log message
    
    Ick this draw function is a tricky, tangled mess! To be fair what it's trying
    to do isn't easy.
    
    Big chunk of this is rendering the content of a log message with line wrapping
    and deduplication. Rewritting this bit first in its own function.
---
 nyx/log_panel.py |  114 ++++++++++++++++++++++++------------------------------
 1 file changed, 51 insertions(+), 63 deletions(-)

diff --git a/nyx/log_panel.py b/nyx/log_panel.py
index 0a8e250..4211e09 100644
--- a/nyx/log_panel.py
+++ b/nyx/log_panel.py
@@ -331,7 +331,7 @@ class LogPanel(panel.Panel, threading.Thread):
 
       line_count = 1 - self._scroll
       seen_first_date_divider = False
-      divider_attr, duplicate_attr = (curses.A_BOLD, 'yellow'), (curses.A_BOLD, 'green')
+      divider_attr = (curses.A_BOLD, 'yellow')
 
       # determines if we have the minimum width to show date dividers
 
@@ -342,15 +342,10 @@ class LogPanel(panel.Panel, threading.Thread):
         entry = event_log[i]
         is_last = i == len(event_log) - 1
 
-        if CONFIG['features.log.showDuplicateEntries']:
-          duplicate_count = 0
-        elif entry.is_duplicate:
-          continue
-        else:
-          duplicate_count = len(entry.duplicates) if entry.duplicates else 0
-
-        if not self._filter.match(entry.display_message):
-          continue  # filter doesn't match log message - skip
+        if entry.is_duplicate and not CONFIG['features.log.showDuplicateEntries']:
+          continue  # deduplicated message
+        elif not self._filter.match(entry.display_message):
+          continue  # filter doesn't match log message
 
         # checks if we should be showing a divider with the date
 
@@ -380,60 +375,13 @@ class LogPanel(panel.Panel, threading.Thread):
           seen_first_date_divider = True
           line_count += 1
 
-        # entry contents to be displayed, tuples of the form:
-        # (msg, formatting, includeLinebreak)
-
-        display_queue = []
-
-        msg_comp = entry.display_message.split('\n')
-
-        for i in range(len(msg_comp)):
-          font = curses.A_BOLD if 'ERR' in entry.type else curses.A_NORMAL  # emphasizes ERR messages
-          display_queue.append((msg_comp[i].strip(), (font, CONFIG['attr.log_color'].get(entry.type, 'white')), i != len(msg_comp) - 1))
-
-        if duplicate_count:
-          plural_label = 's' if duplicate_count > 1 else ''
-          duplicate_msg = ' [%i duplicate%s hidden]' % (duplicate_count, plural_label)
-          display_queue.append((duplicate_msg, duplicate_attr, False))
-
-        # TODO: a fix made line_offset unused, and probably broke max_entries_per_line... not sure if we care
-
-        cursor_location, line_offset = msg_indent, 0
-        max_entries_per_line = CONFIG['features.log.max_lines_per_entry']
-
-        while display_queue:
-          msg, format, include_break = display_queue.pop(0)
-          draw_line = line_count + line_offset
-
-          if line_offset == max_entries_per_line:
-            break
-
-          max_msg_size = width - cursor_location - 1
-
-          if len(msg) > max_msg_size:
-            # message is too long - break it up
-            if line_offset == max_entries_per_line - 1:
-              msg = str_tools.crop(msg, max_msg_size)
-            else:
-              msg, remainder = str_tools.crop(msg, max_msg_size, 4, 4, str_tools.Ending.HYPHEN, True)
-              display_queue.insert(0, (remainder.strip(), format, include_break))
-
-            include_break = True
-
-          if draw_line < height and draw_line >= 1:
-            if seen_first_date_divider and width - divider_indent >= 3 and show_daybreaks:
-              self.addch(draw_line, divider_indent, curses.ACS_VLINE, *divider_attr)
-              self.addch(draw_line, width - 1, curses.ACS_VLINE, *divider_attr)
-
-            self.addstr(draw_line, cursor_location, msg, *format)
-
-          cursor_location += len(msg)
+        line_count_start = line_count
+        line_count = self._draw_entry(msg_indent, line_count, width, entry, height)
 
-          if include_break or not display_queue:
-            line_count += 1
-            cursor_location = msg_indent + 2  # indent following lines
-
-          line_count += line_offset
+        for y in range(line_count_start, line_count):
+          if seen_first_date_divider and width - divider_indent >= 3 and show_daybreaks:
+            self.addch(y, divider_indent, curses.ACS_VLINE, *divider_attr)
+            self.addch(y, width - 1, curses.ACS_VLINE, *divider_attr)
 
         # if this is the last line and there's room, then draw the bottom of the divider
 
@@ -473,6 +421,46 @@ class LogPanel(panel.Panel, threading.Thread):
         log.debug('redrawing the log panel with the corrected content height (%s)' % force_redraw_reason)
         self.redraw(True)
 
+  def _draw_entry(self, x, y, width, entry, height):
+    """
+    Presents a log entry with line wrapping.
+    """
+
+    def draw_line(x, y, width, msg, *attr):
+      msg, remaining_lines = msg.split('\n', 1) if ('\n' in msg) else (msg, '')
+      msg, cropped = str_tools.crop(msg, width - x - 1, min_crop = 4, ending = str_tools.Ending.HYPHEN, get_remainder = True)
+      x = self.addstr(y, x, msg, *attr) if y > 0 else 0  # draw unless it would cover the title
+      return x, (cropped + '\n' + remaining_lines).strip()
+
+    def draw_msg(min_x, x, y, width, msg, *attr):
+      orig_y = y
+
+      while msg:
+        x, msg = draw_line(x, y, width, msg, *attr)
+
+        if (y - orig_y + 1) >= CONFIG['features.log.max_lines_per_entry']:
+          break
+
+        if msg:
+          msg = '  ' + msg  # indent the next line
+          x, y = min_x, y + 1
+
+      return x, y
+
+    min_x, msg = x, entry.display_message
+    boldness = curses.A_BOLD if 'ERR' in entry.type else curses.A_NORMAL  # emphasize ERR messages
+    color = CONFIG['attr.log_color'].get(entry.type, 'white')
+
+    x, y = draw_msg(min_x, x, y, width, msg, boldness, color)
+
+    if entry.duplicates and not CONFIG['features.log.showDuplicateEntries']:
+      duplicate_count = len(entry.duplicates) - 1
+      plural = 's' if duplicate_count > 1 else ''
+      duplicate_msg = ' [%i duplicate%s hidden]' % (duplicate_count, plural)
+      x, y = draw_msg(min_x, x, y, width, duplicate_msg, curses.A_BOLD, 'green')
+
+    return y + 1
+
   def run(self):
     """
     Redraws the display, coalescing updates if events are rapidly logged (for





More information about the tor-commits mailing list