[tor-commits] [nyx/master] Line wrap interpreter content

atagar at torproject.org atagar at torproject.org
Fri Jan 4 20:28:48 UTC 2019


commit 75052e8d3f07771c10e0a886d25a31038bb75fbd
Author: Damian Johnson <atagar at torproject.org>
Date:   Fri Jan 4 12:26:57 2019 -0800

    Line wrap interpreter content
    
    When lines exceed our terminal width we cropped the content. Clearly this sucks
    since it makes that content impossible to... well, get.
    
    Wrapping lines that exceed our panel width with a two space indentation.
    
      https://trac.torproject.org/projects/tor/ticket/28297
---
 nyx/panel/interpreter.py | 59 +++++++++++++++++++++++++++++++++++++++++-------
 web/changelog/index.html |  2 ++
 2 files changed, 53 insertions(+), 8 deletions(-)

diff --git a/nyx/panel/interpreter.py b/nyx/panel/interpreter.py
index 0a4209d..2687888 100644
--- a/nyx/panel/interpreter.py
+++ b/nyx/panel/interpreter.py
@@ -7,6 +7,7 @@ information, tab completion, and other usability features.
 """
 
 import curses
+import threading
 import nyx.curses
 import nyx.panel
 
@@ -53,6 +54,12 @@ class InterpreterPanel(nyx.panel.Panel):
     self._lines = []
     self._user_inputs = []  # previous user inputs
 
+    # cache for the line wrapped content we display
+
+    self._wrapped_lines = []
+    self._wrapped_line_lock = threading.RLock()
+    self._wrapped_line_width = 80
+
     controller = tor_controller()
     self._autocompleter = stem.interpreter.autocomplete.Autocompleter(controller)
     self._interpreter = stem.interpreter.commands.ControlInterpreter(controller)
@@ -60,7 +67,7 @@ class InterpreterPanel(nyx.panel.Panel):
   def key_handlers(self):
     def _scroll(key):
       page_height = self.get_height() - 1
-      is_changed = self._scroller.handle_key(key, len(self._lines) + 1, page_height)
+      is_changed = self._scroller.handle_key(key, len(self._get_lines()) + 1, page_height)
 
       if is_changed:
         self.redraw()
@@ -71,7 +78,7 @@ class InterpreterPanel(nyx.panel.Panel):
 
       return nyx.curses.str_input(
         4 + self._x_offset,
-        self.get_top() + max(1, min(len(self._lines) + 1, self.get_height() - 1)),
+        self.get_top() + max(1, min(len(self._get_lines()) + 1, self.get_height() - 1)),
         backlog = self._user_inputs,
         tab_completion = self._autocompleter.matches
       )
@@ -98,11 +105,11 @@ class InterpreterPanel(nyx.panel.Panel):
           self._is_input_mode = False
           break
 
-        self._lines.append(_format_prompt_input(user_input, prompt))
+        self._add_line(_format_prompt_input(user_input, prompt))
 
         if response:
           for line in response.split('\n'):
-            self._lines.append([(text, attr) for text, attr in nyx.curses.asci_to_curses(line)])
+            self._add_line([(text, attr) for text, attr in nyx.curses.asci_to_curses(line)])
 
       self.redraw()
 
@@ -111,13 +118,49 @@ class InterpreterPanel(nyx.panel.Panel):
       nyx.panel.KeyHandler('arrows', 'scroll up and down', _scroll, key_func = lambda key: key.is_scroll()),
     )
 
+  def _add_line(self, line):
+    with self._wrapped_line_lock:
+      self._lines.append(line)
+
+      wrapped_line = []
+
+      for text, attr in line:
+        while text:
+          wrapped_line.append((text[:self._wrapped_line_width], attr))
+          text = text[self._wrapped_line_width:]
+
+          if text:
+            text = '  ' + text  # indent wrapped lines
+            self._wrapped_lines.append(wrapped_line)
+            wrapped_line = []
+
+      self._wrapped_lines.append(wrapped_line)
+
+  def _get_lines(self, width = None):
+    with self._wrapped_line_lock:
+      if width and width != self._wrapped_line_width:
+        # Our panel size has changed. As such, line wrapping needs to be re-cached.
+
+        lines = self._lines
+
+        self._lines = []
+        self._wrapped_lines = []
+        self._wrapped_line_width = width
+
+        for line in lines:
+          self._add_line(line)
+
+      return self._wrapped_lines
+
   def _draw(self, subwindow):
     if self._is_input_mode:
       subwindow.addstr(0, 0, 'Control Interpreter (enter "/help" for usage or a blank line to stop):', HIGHLIGHT)
     else:
       subwindow.addstr(0, 0, 'Control Interpreter:', HIGHLIGHT)
 
-    scroll = self._scroller.location(len(self._lines) + 1, subwindow.height - 1)
+    lines = self._get_lines(subwindow.width - self._x_offset)
+
+    scroll = self._scroller.location(len(lines) + 1, subwindow.height - 1)
 
     if self._interpreter.is_multiline_context:
       prompt = [MULTILINE_PROMPT]
@@ -126,11 +169,11 @@ class InterpreterPanel(nyx.panel.Panel):
     else:
       prompt = [PROMPT, PROMPT_USAGE]
 
-    if len(self._lines) > subwindow.height - 2:
+    if len(lines) > subwindow.height - 2:
       self._x_offset = 2
-      subwindow.scrollbar(1, scroll, len(self._lines) + 1)
+      subwindow.scrollbar(1, scroll, len(lines) + 1)
 
-    visible_lines = self._lines[scroll:scroll + subwindow.height - 1]
+    visible_lines = lines[scroll:scroll + subwindow.height - 1]
 
     if len(visible_lines) < subwindow.height - 1:
       visible_lines.append(prompt)
diff --git a/web/changelog/index.html b/web/changelog/index.html
index 8041655..1700466 100644
--- a/web/changelog/index.html
+++ b/web/changelog/index.html
@@ -96,6 +96,7 @@
           <ul>
             <li>Geoip information unavailable for inbound connections</li>
             <li>Dialog showing exit statistics crashed when no data was available (<a href="https://trac.torproject.org/projects/tor/ticket/25801">ticket</a>)</li>
+            <li>More strictly scrub sensitive connection information (<a href="https://trac.torproject.org/projects/tor/ticket/27475">ticket</a>)</li>
           </ul>
         </li>
 
@@ -114,6 +115,7 @@
 
         <li><span class="component">Interpreter</span>
           <ul>
+            <li>Line wrap content (<b><a href="https://trac.torproject.org/projects/tor/ticket/28297">ticket</a></b>)</li>
             <li>Large amounts of content made panel sluggish (<b><a href="https://trac.torproject.org/projects/tor/ticket/28902">ticket</a></b>)</li>
           </ul>
         </li>



More information about the tor-commits mailing list