[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]
[tor-commits] [nyx/master] Proper handler chaining
commit ec9788b0fbca919e250d4c7ce1dc10dc4c8e9fb5
Author: Damian Johnson <atagar@xxxxxxxxxxxxxx>
Date: Tue Jul 19 09:43:20 2016 -0700
Proper handler chaining
Our tab completion handler was hardcoded to call the history handler. Fine if
tab and history completion are always done together (as they are at the moment)
but clearly a bug. Fixing this so any combination of handlers can be used.
---
nyx/curses.py | 33 +++++++++++++++++++--------------
test/subwindow.py | 14 ++++++++------
2 files changed, 27 insertions(+), 20 deletions(-)
diff --git a/nyx/curses.py b/nyx/curses.py
index 3767cd3..a6a8b2d 100644
--- a/nyx/curses.py
+++ b/nyx/curses.py
@@ -86,6 +86,7 @@ import collections
import curses
import curses.ascii
import curses.textpad
+import functools
import os
import threading
@@ -280,12 +281,15 @@ def str_input(x, y, initial_text = '', backlog = None, tab_completion = None):
curses_subwindow.addstr(0, 0, initial_text[:width - 1])
textbox = curses.textpad.Textbox(curses_subwindow, insert_mode = True)
- if tab_completion is not None:
- user_input = textbox.edit(lambda key: _handle_tab_completion(textbox, key, backlog, tab_completion)).strip()
- elif backlog is not None:
- user_input = textbox.edit(lambda key: _handle_history_key(textbox, key, backlog)).strip()
- else:
- user_input = textbox.edit(lambda key: _handle_key(textbox, key)).strip()
+ handler = _handle_key
+
+ if backlog:
+ handler = functools.partial(_handle_history_key, handler, backlog)
+
+ if tab_completion:
+ handler = functools.partial(_handle_tab_completion, handler, tab_completion)
+
+ user_input = textbox.edit(lambda key: handler(textbox, key)).strip()
try:
curses.curs_set(0) # hide cursor
@@ -328,14 +332,15 @@ def _handle_key(textbox, key):
return key
-def _handle_history_key(textbox, key, backlog):
+def _handle_history_key(next_handler, backlog, textbox, key):
"""
Handles history validation. When the up/down arrow keys are pressed,
the relative previous/next commands are shown.
+ :param func next_handler: handler to invoke after this
+ :param list backlog: backlog of all previous commands entered
:param Textbox textbox: current textbox context
:param int key: key pressed
- :param list backlog: backlog of all previous commands entered
:returns: **None** if up/down arrow key is pressed or calls function
to write key to the textbox
@@ -370,19 +375,19 @@ def _handle_history_key(textbox, key, backlog):
HISTORY_DICT['selection_index'] = new_selection
return None
- return _handle_key(textbox, key)
+ return next_handler(textbox, key)
-def _handle_tab_completion(textbox, key, backlog, tab_completion):
+def _handle_tab_completion(next_handler, tab_completion, textbox, key):
"""
Handles tab completion. If the tab key is pressed, the current textbox
contents are checked for probable commands.
- :param Textbox textbox: current textbox context
- :param int key: key pressed
- :param list backlog: backlog of all previous commands entered
+ :param func next_handler: handler to invoke after this
:param Autocompleter.matches tab_completion: function to suggest probable
commands based on current content
+ :param Textbox textbox: current textbox context
+ :param int key: key pressed
:returns: **None** when tab key is pressed or calls function to handle
history validation
@@ -409,7 +414,7 @@ def _handle_tab_completion(textbox, key, backlog, tab_completion):
return None
- return _handle_history_key(textbox, key, backlog)
+ return next_handler(textbox, key)
def curses_attr(*attributes):
diff --git a/test/subwindow.py b/test/subwindow.py
index 3f58278..559c451 100644
--- a/test/subwindow.py
+++ b/test/subwindow.py
@@ -68,6 +68,8 @@ EXPECTED_SCROLLBAR_BOTTOM = """
-+
""".strip()
+NO_OP_HANDLER = lambda key, textbox: None
+
class TestCurses(unittest.TestCase):
@require_curses
@@ -156,21 +158,20 @@ class TestCurses(unittest.TestCase):
key_pressed = ord('a')
self.assertEqual(key_pressed, nyx.curses._handle_key(textbox, key_pressed))
- @patch('nyx.curses._handle_key')
- def test_handle_history_key(self, mock_handle_key):
+ def test_handle_history_key(self):
backlog = ['GETINFO version']
dimensions = (40, 80)
textbox = Mock()
textbox.win.getyx.return_value = dimensions
- self.assertIsNone(nyx.curses._handle_history_key(textbox, curses.KEY_UP, []))
+ self.assertIsNone(nyx.curses._handle_history_key(NO_OP_HANDLER, [], textbox, curses.KEY_UP))
textbox = Mock()
textbox.win.getyx.return_value = dimensions
textbox.win.getmaxyx.return_value = dimensions
textbox.win.addstr = Mock()
textbox.win.move = Mock()
- nyx.curses._handle_history_key(textbox, curses.KEY_UP, backlog)
+ nyx.curses._handle_history_key(NO_OP_HANDLER, backlog, textbox, curses.KEY_UP)
self.assertTrue(textbox.win.clear.called)
expected_addstr_call = call(dimensions[0], 0, backlog[0])
self.assertEqual(expected_addstr_call, textbox.win.addstr.call_args)
@@ -178,7 +179,8 @@ class TestCurses(unittest.TestCase):
self.assertEqual(expected_move_call, textbox.win.move.call_args)
textbox = Mock()
- nyx.curses._handle_history_key(textbox, curses.KEY_LEFT, [])
+ mock_handle_key = Mock()
+ nyx.curses._handle_history_key(mock_handle_key, [], textbox, curses.KEY_LEFT)
self.assertTrue(mock_handle_key.called)
@patch('nyx.curses._handle_history_key')
@@ -193,7 +195,7 @@ class TestCurses(unittest.TestCase):
textbox.win.move = Mock()
tab_completion = Mock()
tab_completion.return_value = [tab_completion_content]
- nyx.curses._handle_tab_completion(textbox, 9, [], tab_completion)
+ nyx.curses._handle_tab_completion(NO_OP_HANDLER, tab_completion, textbox, 9)
self.assertTrue(textbox.win.clear.called)
expected_addstr_call = call(dimensions[0], 0, tab_completion_content)
self.assertEqual(expected_addstr_call, textbox.win.addstr.call_args)
_______________________________________________
tor-commits mailing list
tor-commits@xxxxxxxxxxxxxxxxxxxx
https://lists.torproject.org/cgi-bin/mailman/listinfo/tor-commits