From cdd5a53767e51a6d992bf8d08df2733e7af916b8 Mon Sep 17 00:00:00 2001 From: Aldo Cortesi Date: Tue, 7 Feb 2012 16:39:37 +1300 Subject: Refactor console. Split the console implementation out into logical components. --- libmproxy/console/connlist.py | 100 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 100 insertions(+) create mode 100644 libmproxy/console/connlist.py (limited to 'libmproxy/console/connlist.py') diff --git a/libmproxy/console/connlist.py b/libmproxy/console/connlist.py new file mode 100644 index 00000000..3fdfb0ed --- /dev/null +++ b/libmproxy/console/connlist.py @@ -0,0 +1,100 @@ +import urwid +import common + +class ConnectionItem(common.WWrap): + def __init__(self, master, state, flow, focus): + self.master, self.state, self.flow = master, state, flow + self.focus = focus + w = self.get_text() + common.WWrap.__init__(self, w) + + def get_text(self): + return urwid.Text(common.format_flow(self.flow, self.focus)) + + def selectable(self): + return True + + def keypress(self, (maxcol,), key): + key = common.shortcuts(key) + if key == "a": + self.flow.accept_intercept() + self.master.sync_list_view() + elif key == "d": + self.flow.kill(self.master) + self.state.delete_flow(self.flow) + self.master.sync_list_view() + elif key == "r": + r = self.master.replay_request(self.flow) + if r: + self.master.statusbar.message(r) + self.master.sync_list_view() + elif key == "R": + self.state.revert(self.flow) + self.master.sync_list_view() + elif key == "W": + self.master.path_prompt( + "Save this flow: ", + self.state.last_saveload, + self.master.save_one_flow, + self.flow + ) + elif key == "X": + self.flow.kill(self.master) + elif key == "v": + self.master.toggle_eventlog() + elif key == "enter": + if self.flow.request: + self.master.view_flow(self.flow) + elif key == "|": + self.master.path_prompt( + "Send flow to script: ", self.state.last_script, + self.master.run_script_once, self.flow + ) + return key + + +class ConnectionListView(urwid.ListWalker): + def __init__(self, master, state): + self.master, self.state = master, state + if self.state.flow_count(): + self.set_focus(0) + + def get_focus(self): + f, i = self.state.get_focus() + f = ConnectionItem(self.master, self.state, f, True) if f else None + return f, i + + def set_focus(self, focus): + ret = self.state.set_focus(focus) + self._modified() + return ret + + def get_next(self, pos): + f, i = self.state.get_next(pos) + f = ConnectionItem(self.master, self.state, f, False) if f else None + return f, i + + def get_prev(self, pos): + f, i = self.state.get_prev(pos) + f = ConnectionItem(self.master, self.state, f, False) if f else None + return f, i + + +class ConnectionListBox(urwid.ListBox): + def __init__(self, master): + self.master = master + urwid.ListBox.__init__(self, master.conn_list_view) + + def keypress(self, size, key): + key = common.shortcuts(key) + if key == "A": + self.master.accept_all() + self.master.sync_list_view() + key = None + elif key == "C": + self.master.clear_connections() + key = None + elif key == "v": + self.master.toggle_eventlog() + key = None + return urwid.ListBox.keypress(self, size, key) -- cgit v1.2.3 From 7e6196511f5dc761d5361ac89ff4e6641881d05c Mon Sep 17 00:00:00 2001 From: Aldo Cortesi Date: Wed, 8 Feb 2012 14:07:17 +1300 Subject: Editable fields for KVEditor. --- libmproxy/console/connlist.py | 55 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) (limited to 'libmproxy/console/connlist.py') diff --git a/libmproxy/console/connlist.py b/libmproxy/console/connlist.py index 3fdfb0ed..319963e8 100644 --- a/libmproxy/console/connlist.py +++ b/libmproxy/console/connlist.py @@ -1,6 +1,61 @@ import urwid import common +class EventListBox(urwid.ListBox): + def __init__(self, master): + self.master = master + urwid.ListBox.__init__(self, master.eventlist) + + def keypress(self, size, key): + key = common.shortcuts(key) + if key == "C": + self.master.clear_events() + key = None + return urwid.ListBox.keypress(self, size, key) + + +class BodyPile(urwid.Pile): + def __init__(self, master): + h = urwid.Text("Event log") + h = urwid.Padding(h, align="left", width=("relative", 100)) + + self.inactive_header = urwid.AttrWrap(h, "inactive_heading") + self.active_header = urwid.AttrWrap(h, "heading") + + urwid.Pile.__init__( + self, + [ + ConnectionListBox(master), + urwid.Frame(EventListBox(master), header = self.inactive_header) + ] + ) + self.master = master + self.focus = 0 + + def keypress(self, size, key): + if key == "tab": + self.focus = (self.focus + 1)%len(self.widget_list) + self.set_focus(self.focus) + if self.focus == 1: + self.widget_list[1].header = self.active_header + else: + self.widget_list[1].header = self.inactive_header + key = None + elif key == "v": + self.master.toggle_eventlog() + key = None + + # This is essentially a copypasta from urwid.Pile's keypress handler. + # So much for "closed for modification, but open for extension". + item_rows = None + if len(size)==2: + item_rows = self.get_item_rows( size, focus=True ) + i = self.widget_list.index(self.focus_item) + tsize = self.get_item_size(size,i,True,item_rows) + return self.focus_item.keypress( tsize, key ) + + + class ConnectionItem(common.WWrap): def __init__(self, master, state, flow, focus): self.master, self.state, self.flow = master, state, flow -- cgit v1.2.3 From e3f28e1c06093147660e2857adce24b441d6530f Mon Sep 17 00:00:00 2001 From: Aldo Cortesi Date: Wed, 8 Feb 2012 21:47:39 +1300 Subject: Move to context-dependent help model. The all-in-one page was just getting too unwieldy. --- libmproxy/console/connlist.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'libmproxy/console/connlist.py') diff --git a/libmproxy/console/connlist.py b/libmproxy/console/connlist.py index 319963e8..1d34fba9 100644 --- a/libmproxy/console/connlist.py +++ b/libmproxy/console/connlist.py @@ -1,6 +1,21 @@ import urwid import common +def _mkhelp(): + text = [] + keys = [ + ("C", "clear connection list or eventlog"), + ("d", "delete connection from view"), + ("v", "toggle eventlog"), + ("X", "kill and delete connection, even if it's mid-intercept"), + ("tab", "tab between eventlog and connection list"), + ("enter", "view connection"), + ] + text.extend(common.format_keyvals(keys, key="key", val="text", indent=4)) + return text +help_context = _mkhelp() + + class EventListBox(urwid.ListBox): def __init__(self, master): self.master = master -- cgit v1.2.3 From 866a93a8bc28fed47dde04f49c13592a7163bff4 Mon Sep 17 00:00:00 2001 From: Aldo Cortesi Date: Wed, 8 Feb 2012 22:28:15 +1300 Subject: Start consolidating keybindings. I want each view to have a more coherent set of bindings. This means minimizing the global bindings, and making some bindings accessible only from screens related to their functionality. --- libmproxy/console/connlist.py | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'libmproxy/console/connlist.py') diff --git a/libmproxy/console/connlist.py b/libmproxy/console/connlist.py index 1d34fba9..d9ef258b 100644 --- a/libmproxy/console/connlist.py +++ b/libmproxy/console/connlist.py @@ -4,12 +4,15 @@ import common def _mkhelp(): text = [] keys = [ + ("A", "accept all intercepted connections"), + ("a", "accept this intercepted connection"), ("C", "clear connection list or eventlog"), ("d", "delete connection from view"), ("v", "toggle eventlog"), ("X", "kill and delete connection, even if it's mid-intercept"), ("tab", "tab between eventlog and connection list"), ("enter", "view connection"), + ("|", "run script on this flow"), ] text.extend(common.format_keyvals(keys, key="key", val="text", indent=4)) return text @@ -117,10 +120,13 @@ class ConnectionItem(common.WWrap): self.master.view_flow(self.flow) elif key == "|": self.master.path_prompt( - "Send flow to script: ", self.state.last_script, - self.master.run_script_once, self.flow + "Send flow to script: ", + self.state.last_script, + self.master.run_script_once, + self.flow ) - return key + else: + return key class ConnectionListView(urwid.ListWalker): -- cgit v1.2.3 From 5df0b9e9610b803241f8c4870ddfe3afb450a048 Mon Sep 17 00:00:00 2001 From: Aldo Cortesi Date: Wed, 8 Feb 2012 22:55:48 +1300 Subject: Further keybinding consolidation. Also, move KVEditor's "i" binding to "A" to avoid clashes with global bindings. --- libmproxy/console/connlist.py | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) (limited to 'libmproxy/console/connlist.py') diff --git a/libmproxy/console/connlist.py b/libmproxy/console/connlist.py index d9ef258b..0f238322 100644 --- a/libmproxy/console/connlist.py +++ b/libmproxy/console/connlist.py @@ -8,7 +8,13 @@ def _mkhelp(): ("a", "accept this intercepted connection"), ("C", "clear connection list or eventlog"), ("d", "delete connection from view"), + ("l", "set limit filter pattern"), + ("L", "load saved flows"), + ("r", "replay request"), + ("R", "revert changes to request"), ("v", "toggle eventlog"), + ("w", "save all flows matching current limit"), + ("W", "save this flow"), ("X", "kill and delete connection, even if it's mid-intercept"), ("tab", "tab between eventlog and connection list"), ("enter", "view connection"), @@ -96,6 +102,15 @@ class ConnectionItem(common.WWrap): self.flow.kill(self.master) self.state.delete_flow(self.flow) self.master.sync_list_view() + elif key == "l": + self.master.prompt("Limit: ", self.state.limit_txt, self.master.set_limit) + self.master.sync_list_view() + elif key == "L": + self.master.path_prompt( + "Load flows: ", + self.state.last_saveload, + self.master.load_flows_callback + ) elif key == "r": r = self.master.replay_request(self.flow) if r: @@ -104,6 +119,12 @@ class ConnectionItem(common.WWrap): elif key == "R": self.state.revert(self.flow) self.master.sync_list_view() + elif key == "w": + self.master.path_prompt( + "Save flows: ", + self.state.last_saveload, + self.master.save_flows + ) elif key == "W": self.master.path_prompt( "Save this flow: ", @@ -120,9 +141,9 @@ class ConnectionItem(common.WWrap): self.master.view_flow(self.flow) elif key == "|": self.master.path_prompt( - "Send flow to script: ", + "Send flow to script: ", self.state.last_script, - self.master.run_script_once, + self.master.run_script_once, self.flow ) else: -- cgit v1.2.3