aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAldo Cortesi <aldo@nullcube.com>2017-03-19 10:25:07 +1300
committerAldo Cortesi <aldo@corte.si>2017-03-19 10:32:22 +1300
commit49b0a67eb95a5f55bace24c73e458c2eb224f1b7 (patch)
tree70d17f5486ce4c12e87259eb60dd2d70aa29987a
parent4e24c95a61802fd6fb9a03fdffd0380d90c46e0c (diff)
downloadmitmproxy-49b0a67eb95a5f55bace24c73e458c2eb224f1b7.tar.gz
mitmproxy-49b0a67eb95a5f55bace24c73e458c2eb224f1b7.tar.bz2
mitmproxy-49b0a67eb95a5f55bace24c73e458c2eb224f1b7.zip
console options: add an overlay grid editor for sequence options
-rw-r--r--mitmproxy/tools/console/grideditor/base.py16
-rw-r--r--mitmproxy/tools/console/grideditor/editors.py17
-rw-r--r--mitmproxy/tools/console/options.py13
-rw-r--r--mitmproxy/tools/console/overlay.py30
-rw-r--r--mitmproxy/tools/console/signals.py3
-rw-r--r--mitmproxy/tools/console/statusbar.py11
-rw-r--r--test/mitmproxy/test_optmanager.py12
7 files changed, 84 insertions, 18 deletions
diff --git a/mitmproxy/tools/console/grideditor/base.py b/mitmproxy/tools/console/grideditor/base.py
index 4505bb97..d2ba47c3 100644
--- a/mitmproxy/tools/console/grideditor/base.py
+++ b/mitmproxy/tools/console/grideditor/base.py
@@ -182,12 +182,12 @@ class GridWalker(urwid.ListWalker):
self.edit_row = GridRow(
self.focus_col, True, self.editor, self.lst[self.focus]
)
- self.editor.master.loop.widget.footer.update(FOOTER_EDITING)
+ signals.footer_help.send(self, helptext=FOOTER_EDITING)
self._modified()
def stop_edit(self):
if self.edit_row:
- self.editor.master.loop.widget.footer.update(FOOTER)
+ signals.footer_help.send(self, helptext=FOOTER)
try:
val = self.edit_row.edit_col.get_data()
except ValueError:
@@ -276,9 +276,11 @@ class GridEditor(urwid.WidgetWrap):
first_width = max(len(r), first_width)
self.first_width = min(first_width, FIRST_WIDTH_MAX)
- title = urwid.Text(self.title)
- title = urwid.Padding(title, align="left", width=("relative", 100))
- title = urwid.AttrWrap(title, "heading")
+ title = None
+ if self.title:
+ title = urwid.Text(self.title)
+ title = urwid.Padding(title, align="left", width=("relative", 100))
+ title = urwid.AttrWrap(title, "heading")
headings = []
for i, col in enumerate(self.columns):
@@ -297,10 +299,10 @@ class GridEditor(urwid.WidgetWrap):
self.lb = GridListBox(self.walker)
w = urwid.Frame(
self.lb,
- header=urwid.Pile([title, h])
+ header=urwid.Pile([title, h]) if title else None
)
super().__init__(w)
- self.master.loop.widget.footer.update("")
+ signals.footer_help.send(self, helptext="")
self.show_empty_msg()
def show_empty_msg(self):
diff --git a/mitmproxy/tools/console/grideditor/editors.py b/mitmproxy/tools/console/grideditor/editors.py
index 0d9929ae..39e51b2b 100644
--- a/mitmproxy/tools/console/grideditor/editors.py
+++ b/mitmproxy/tools/console/grideditor/editors.py
@@ -245,3 +245,20 @@ class SetCookieEditor(base.GridEditor):
]
)
return vals
+
+
+class OptionsEditor(base.GridEditor):
+ title = None
+ columns = [
+ col_text.Column("")
+ ]
+
+ def __init__(self, master, name, vals):
+ self.name = name
+ super().__init__(master, [[i] for i in vals], self.callback)
+
+ def callback(self, vals):
+ setattr(self.master.options, self.name, [i[0] for i in vals])
+
+ def is_error(self, col, val):
+ pass
diff --git a/mitmproxy/tools/console/options.py b/mitmproxy/tools/console/options.py
index 479d3918..706605fc 100644
--- a/mitmproxy/tools/console/options.py
+++ b/mitmproxy/tools/console/options.py
@@ -1,7 +1,7 @@
import urwid
import blinker
import textwrap
-from typing import Optional
+from typing import Optional, Sequence
from mitmproxy import exceptions
from mitmproxy.tools.console import common
@@ -213,6 +213,16 @@ class OptionsList(urwid.ListBox):
self.master.options.setter(foc.opt.name)
)
)
+ elif foc.opt.typespec == Sequence[str]:
+ self.master.overlay(
+ overlay.OptionsOverlay(
+ self.master,
+ foc.opt.name,
+ foc.opt.current()
+ )
+ )
+ else:
+ raise NotImplementedError()
return super().keypress(size, key)
@@ -269,4 +279,3 @@ class Options(urwid.Pile):
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)
-
diff --git a/mitmproxy/tools/console/overlay.py b/mitmproxy/tools/console/overlay.py
index cf7fdfcb..e1dc50bf 100644
--- a/mitmproxy/tools/console/overlay.py
+++ b/mitmproxy/tools/console/overlay.py
@@ -1,6 +1,10 @@
+import math
+
+import urwid
+
from mitmproxy.tools.console import common
from mitmproxy.tools.console import signals
-import urwid
+from mitmproxy.tools.console import grideditor
class SimpleOverlay(urwid.Overlay):
@@ -15,9 +19,11 @@ class SimpleOverlay(urwid.Overlay):
)
def keypress(self, size, key):
+ key = super().keypress(size, key)
if key == "esc":
signals.pop_view_state.send(self)
- return super().keypress(size, key)
+ else:
+ return key
class Choice(urwid.WidgetWrap):
@@ -97,4 +103,22 @@ class Chooser(urwid.WidgetWrap):
if key == "enter":
self.callback(self.choices[self.walker.index])
signals.pop_view_state.send(self)
- return super().keypress(size, key) \ No newline at end of file
+ return super().keypress(size, key)
+
+
+class OptionsOverlay(urwid.WidgetWrap):
+ def __init__(self, master, name, vals):
+ cols, rows = master.ui.get_cols_rows()
+ super().__init__(
+ urwid.AttrWrap(
+ urwid.LineBox(
+ urwid.BoxAdapter(
+ grideditor.OptionsEditor(master, name, vals),
+ math.ceil(rows * 0.5)
+ ),
+ title="text"
+ ),
+ "background"
+ )
+ )
+ self.width = math.ceil(cols * 0.8)
diff --git a/mitmproxy/tools/console/signals.py b/mitmproxy/tools/console/signals.py
index cb71c5c1..ad2c2962 100644
--- a/mitmproxy/tools/console/signals.py
+++ b/mitmproxy/tools/console/signals.py
@@ -30,6 +30,9 @@ call_in = blinker.Signal()
# Focus the body, footer or header of the main window
focus = blinker.Signal()
+# Focus the body, footer or header of the main window
+footer_help = blinker.Signal()
+
# Fired when settings change
update_settings = blinker.Signal()
diff --git a/mitmproxy/tools/console/statusbar.py b/mitmproxy/tools/console/statusbar.py
index f8fe53ed..3f18bbb3 100644
--- a/mitmproxy/tools/console/statusbar.py
+++ b/mitmproxy/tools/console/statusbar.py
@@ -5,7 +5,6 @@ import urwid
from mitmproxy.tools.console import common
from mitmproxy.tools.console import pathedit
from mitmproxy.tools.console import signals
-from mitmproxy.utils import human
class PromptPath:
@@ -143,10 +142,15 @@ class StatusBar(urwid.WidgetWrap):
super().__init__(urwid.Pile([self.ib, self.master.ab]))
signals.update_settings.connect(self.sig_update)
signals.flowlist_change.connect(self.sig_update)
+ signals.footer_help.connect(self.sig_footer_help)
master.options.changed.connect(self.sig_update)
master.view.focus.sig_change.connect(self.sig_update)
self.redraw()
+ def sig_footer_help(self, sender, helptext):
+ self.helptext = helptext
+ self.redraw()
+
def sig_update(self, sender, updated=None):
self.redraw()
@@ -281,10 +285,5 @@ class StatusBar(urwid.WidgetWrap):
]), "heading")
self.ib._w = status
- def update(self, text):
- self.helptext = text
- self.redraw()
- self.master.loop.draw_screen()
-
def selectable(self):
return True
diff --git a/test/mitmproxy/test_optmanager.py b/test/mitmproxy/test_optmanager.py
index 6f87ac06..4dc2e9ca 100644
--- a/test/mitmproxy/test_optmanager.py
+++ b/test/mitmproxy/test_optmanager.py
@@ -140,6 +140,18 @@ class Rec():
def test_subscribe():
o = TO()
r = Rec()
+
+ # pytest.raises keeps a reference here that interferes with the cleanup test
+ # further down.
+ try:
+ o.subscribe(r, ["unknown"])
+ except exceptions.OptionsError:
+ pass
+ else:
+ raise AssertionError
+
+ assert len(o.changed.receivers) == 0
+
o.subscribe(r, ["two"])
o.one = 2
assert not r.called