console options: add an overlay grid editor for sequence options
This commit is contained in:
parent
4e24c95a61
commit
49b0a67eb9
|
@ -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,6 +276,8 @@ class GridEditor(urwid.WidgetWrap):
|
|||
first_width = max(len(r), first_width)
|
||||
self.first_width = min(first_width, FIRST_WIDTH_MAX)
|
||||
|
||||
title = None
|
||||
if self.title:
|
||||
title = urwid.Text(self.title)
|
||||
title = urwid.Padding(title, align="left", width=("relative", 100))
|
||||
title = urwid.AttrWrap(title, "heading")
|
||||
|
@ -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):
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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):
|
||||
|
@ -98,3 +104,21 @@ class Chooser(urwid.WidgetWrap):
|
|||
self.callback(self.choices[self.walker.index])
|
||||
signals.pop_view_state.send(self)
|
||||
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)
|
||||
|
|
|
@ -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()
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue