[tor-commits] [nyx/master] Move raw curses usage behind raw_screen()
atagar at torproject.org
atagar at torproject.org
Sun Mar 20 00:17:45 UTC 2016
commit 5d9c3dde6315b1ceb9ba9017823ea036501b909c
Author: Damian Johnson <atagar at torproject.org>
Date: Thu Mar 17 09:53:18 2016 -0700
Move raw curses usage behind raw_screen()
Providing a function for raw access to the curses screen rather than passing a
reference around. This is an intermediate step since we want to abstract this
all away but for now better to have them go through nyx.curses to get this.
---
nyx/controller.py | 46 +++++++++++++++++-----------------------------
nyx/curses.py | 35 ++++++++++++++++++++++++++++++++---
nyx/panel/__init__.py | 14 ++++++++------
nyx/panel/config.py | 4 ++--
nyx/panel/connection.py | 4 ++--
nyx/panel/graph.py | 4 ++--
nyx/panel/header.py | 4 ++--
nyx/panel/log.py | 4 ++--
nyx/panel/torrc.py | 4 ++--
nyx/popups.py | 2 +-
10 files changed, 70 insertions(+), 51 deletions(-)
diff --git a/nyx/controller.py b/nyx/controller.py
index 602c85e..32f4db5 100644
--- a/nyx/controller.py
+++ b/nyx/controller.py
@@ -63,8 +63,8 @@ class LabelPanel(nyx.panel.Panel):
Panel that just displays a single line of text.
"""
- def __init__(self, stdscr):
- nyx.panel.Panel.__init__(self, stdscr, 'msg', 0, height=1)
+ def __init__(self):
+ nyx.panel.Panel.__init__(self, 'msg', 0, height=1)
self.msg_text = ''
self.msg_attr = NORMAL
@@ -92,41 +92,36 @@ class Controller:
Tracks the global state of the interface
"""
- def __init__(self, stdscr):
+ def __init__(self):
"""
Creates a new controller instance. Panel lists are ordered as they appear,
top to bottom on the page.
-
- Arguments:
- stdscr - curses window
"""
- self._screen = stdscr
-
self._sticky_panels = [
- nyx.panel.header.HeaderPanel(stdscr),
- LabelPanel(stdscr),
+ nyx.panel.header.HeaderPanel(),
+ LabelPanel(),
]
self._page_panels, first_page_panels = [], []
if CONFIG['features.panels.show.graph']:
- first_page_panels.append(nyx.panel.graph.GraphPanel(stdscr))
+ first_page_panels.append(nyx.panel.graph.GraphPanel())
if CONFIG['features.panels.show.log']:
- first_page_panels.append(nyx.panel.log.LogPanel(stdscr))
+ first_page_panels.append(nyx.panel.log.LogPanel())
if first_page_panels:
self._page_panels.append(first_page_panels)
if CONFIG['features.panels.show.connection']:
- self._page_panels.append([nyx.panel.connection.ConnectionPanel(stdscr)])
+ self._page_panels.append([nyx.panel.connection.ConnectionPanel()])
if CONFIG['features.panels.show.config']:
- self._page_panels.append([nyx.panel.config.ConfigPanel(stdscr)])
+ self._page_panels.append([nyx.panel.config.ConfigPanel()])
if CONFIG['features.panels.show.torrc']:
- self._page_panels.append([nyx.panel.torrc.TorrcPanel(stdscr)])
+ self._page_panels.append([nyx.panel.torrc.TorrcPanel()])
self.quit_signal = False
self._page = 0
@@ -135,13 +130,6 @@ class Controller:
self._last_drawn = 0
self.set_msg() # initializes our control message
- def get_screen(self):
- """
- Provides our curses window.
- """
-
- return self._screen
-
def get_page_count(self):
"""
Provides the number of pages the interface has. This may be zero if all
@@ -306,7 +294,8 @@ class Controller:
# https://trac.torproject.org/projects/tor/ticket/2830#comment:9
if force:
- self._screen.clear()
+ with nyx.curses.raw_screen() as stdscr:
+ stdscr.clear()
for panel_impl in display_panels:
panel_impl.redraw(force)
@@ -365,17 +354,14 @@ class Controller:
return halt_thread
-def start_nyx(stdscr):
+def start_nyx():
"""
Main draw loop context.
-
- Arguments:
- stdscr - curses window
"""
global NYX_CONTROLLER
- NYX_CONTROLLER = Controller(stdscr)
+ NYX_CONTROLLER = Controller()
control = get_controller()
if not CONFIG['features.acsSupport']:
@@ -411,7 +397,9 @@ def start_nyx(stdscr):
# redraws the interface if it's needed
control.redraw(False)
- stdscr.refresh()
+
+ with nyx.curses.raw_screen() as stdscr:
+ stdscr.refresh()
# wait for user keyboard input until timeout, unless an override was set
diff --git a/nyx/curses.py b/nyx/curses.py
index 97ad02a..4d9571b 100644
--- a/nyx/curses.py
+++ b/nyx/curses.py
@@ -9,6 +9,7 @@ if we want Windows support in the future too.
::
start - initializes curses with the given function
+ raw_screen - provides direct access to the curses screen
key_input - get keypress by user
curses_attr - curses encoded text attribute
@@ -139,8 +140,7 @@ CONFIG = stem.util.conf.config_dict('nyx', {
def start(function, transparent_background = False, cursor = True):
"""
- Starts a curses interface, delegating to the given function. The function
- should accept a single argument for the curses screen.
+ Starts a curses interface, delegating to the given function.
:param funtion: function to invoke when curses starts
:param bool transparent_background: allows background transparency
@@ -164,11 +164,40 @@ def start(function, transparent_background = False, cursor = True):
except curses.error:
pass
- function(stdscr)
+ function()
curses.wrapper(_wrapper)
+def raw_screen():
+ """
+ Provides the curses screen. This can only be called after
+ :func:`~nyx.curses.start`, and is used as follows...
+
+ ::
+
+ with nyx.curses.raw_screen() as stdscr:
+ ... work with curses...
+
+ In the future this will never be called directly. This is just an
+ intermediate function as we migrate.
+ """
+
+ class _Wrapper(object):
+ def __enter__(self):
+ # TODO: We should be wrapping this with CURSES_LOCK.acquire/release(),
+ # but doing so seems to be causing frequent terminal gliches when
+ # shutting down. Strange since this should be strictly safer. Oh well -
+ # something to dig into later.
+
+ return CURSES_SCREEN
+
+ def __exit__(self, exit_type, value, traceback):
+ pass
+
+ return _Wrapper()
+
+
def key_input(input_timeout = None):
"""
Gets a key press from the user.
diff --git a/nyx/panel/__init__.py b/nyx/panel/__init__.py
index 176eea9..bab0cc7 100644
--- a/nyx/panel/__init__.py
+++ b/nyx/panel/__init__.py
@@ -122,12 +122,11 @@ class Panel(object):
redraw().
"""
- def __init__(self, parent, name, top, left = 0, height = -1, width = -1):
+ def __init__(self, name, top, left = 0, height = -1, width = -1):
"""
Creates a durable wrapper for a curses subwindow in the given parent.
Arguments:
- parent - parent curses window
name - identifier for the panel
top - positioning of top within parent
left - positioning of the left edge within the parent
@@ -140,7 +139,6 @@ class Panel(object):
# might chose their height based on its parent's current width).
self.panel_name = name
- self.parent = parent
self.visible = False
self.title_visible = True
@@ -358,7 +356,9 @@ class Panel(object):
returns a tuple of (height, width).
"""
- new_height, new_width = self.parent.getmaxyx()
+ with nyx.curses.raw_screen() as stdscr:
+ new_height, new_width = stdscr.getmaxyx()
+
set_height, set_width = self.get_height(), self.get_width()
new_height = max(0, new_height - self.top)
new_width = max(0, new_width - self.left)
@@ -601,7 +601,8 @@ class Panel(object):
display_width = self.get_preferred_size()[1]
- input_subwindow = self.parent.subwin(1, display_width - x, self.top + y, self.left + x)
+ with nyx.curses.raw_screen() as stdscr:
+ input_subwindow = stdscr.subwin(1, display_width - x, self.top + y, self.left + x)
# blanks the field's area, filling it with the font in case it's hilighting
@@ -744,7 +745,8 @@ class Panel(object):
# would mean far more complicated code and no more selective refreshing)
if recreate:
- self.win = self.parent.subwin(new_height, new_width, self.top, self.left)
+ with nyx.curses.raw_screen() as stdscr:
+ self.win = stdscr.subwin(new_height, new_width, self.top, self.left)
# note: doing this log before setting win produces an infinite loop
stem.util.log.debug("recreating panel '%s' with the dimensions of %i/%i" % (self.get_name(), new_height, new_width))
diff --git a/nyx/panel/config.py b/nyx/panel/config.py
index 5b8a636..fc6dad1 100644
--- a/nyx/panel/config.py
+++ b/nyx/panel/config.py
@@ -118,8 +118,8 @@ class ConfigPanel(nyx.panel.Panel):
Editor for tor's configuration.
"""
- def __init__(self, stdscr):
- nyx.panel.Panel.__init__(self, stdscr, 'configuration', 0)
+ def __init__(self):
+ nyx.panel.Panel.__init__(self, 'configuration', 0)
self._contents = []
self._scroller = nyx.curses.CursorScroller()
diff --git a/nyx/panel/connection.py b/nyx/panel/connection.py
index e3124d9..09efafb 100644
--- a/nyx/panel/connection.py
+++ b/nyx/panel/connection.py
@@ -259,8 +259,8 @@ class ConnectionPanel(nyx.panel.Panel, threading.Thread):
the current consensus and other data sources.
"""
- def __init__(self, stdscr):
- nyx.panel.Panel.__init__(self, stdscr, 'connections', 0)
+ def __init__(self):
+ nyx.panel.Panel.__init__(self, 'connections', 0)
threading.Thread.__init__(self)
self.setDaemon(True)
diff --git a/nyx/panel/graph.py b/nyx/panel/graph.py
index 20a64c0..e4a0ce7 100644
--- a/nyx/panel/graph.py
+++ b/nyx/panel/graph.py
@@ -381,8 +381,8 @@ class GraphPanel(nyx.panel.Panel):
Panel displaying graphical information of GraphCategory instances.
"""
- def __init__(self, stdscr):
- nyx.panel.Panel.__init__(self, stdscr, 'graph', 0)
+ def __init__(self):
+ nyx.panel.Panel.__init__(self, 'graph', 0)
self._displayed_stat = None if CONFIG['features.graph.type'] == 'none' else CONFIG['features.graph.type']
self._update_interval = CONFIG['features.graph.interval']
diff --git a/nyx/panel/header.py b/nyx/panel/header.py
index 51245ee..c3bba36 100644
--- a/nyx/panel/header.py
+++ b/nyx/panel/header.py
@@ -37,8 +37,8 @@ class HeaderPanel(nyx.panel.Panel, threading.Thread):
Top area containing tor settings and system information.
"""
- def __init__(self, stdscr):
- nyx.panel.Panel.__init__(self, stdscr, 'header', 0)
+ def __init__(self):
+ nyx.panel.Panel.__init__(self, 'header', 0)
threading.Thread.__init__(self)
self.setDaemon(True)
diff --git a/nyx/panel/log.py b/nyx/panel/log.py
index 3ab53f3..d6e00de 100644
--- a/nyx/panel/log.py
+++ b/nyx/panel/log.py
@@ -64,8 +64,8 @@ class LogPanel(nyx.panel.Panel, threading.Thread):
from tor's log file if it exists.
"""
- def __init__(self, stdscr):
- nyx.panel.Panel.__init__(self, stdscr, 'log', 0)
+ def __init__(self):
+ nyx.panel.Panel.__init__(self, 'log', 0)
threading.Thread.__init__(self)
self.setDaemon(True)
diff --git a/nyx/panel/torrc.py b/nyx/panel/torrc.py
index 033fd94..f52b6fb 100644
--- a/nyx/panel/torrc.py
+++ b/nyx/panel/torrc.py
@@ -20,8 +20,8 @@ class TorrcPanel(panel.Panel):
area.
"""
- def __init__(self, stdscr):
- panel.Panel.__init__(self, stdscr, 'torrc', 0)
+ def __init__(self):
+ panel.Panel.__init__(self, 'torrc', 0)
self._scroller = nyx.curses.Scroller()
self._show_line_numbers = True # shows left aligned line numbers
diff --git a/nyx/popups.py b/nyx/popups.py
index f29c9c8..6190a09 100644
--- a/nyx/popups.py
+++ b/nyx/popups.py
@@ -54,7 +54,7 @@ def popup_window(height = -1, width = -1, top = 0, left = 0, below_static = True
else:
sticky_height = 0
- popup = nyx.panel.Panel(control.get_screen(), 'popup', top + sticky_height, left, height, width)
+ popup = nyx.panel.Panel('popup', top + sticky_height, left, height, width)
popup.set_visible(True)
# Redraws the popup to prepare a subwindow instance. If none is spawned then
More information about the tor-commits
mailing list