Merge pull request #2388 from cortesi/consolebits

A few console-related bits and bobs
This commit is contained in:
Aldo Cortesi 2017-06-11 22:35:05 +12:00 committed by GitHub
commit c03f14cba6
19 changed files with 70 additions and 246 deletions

View File

@ -1,2 +1,3 @@
def original_addr(csock):
return csock.getsockname()

View File

@ -99,7 +99,7 @@ class CommandsList(urwid.ListBox):
super().__init__(self.walker)
def keypress(self, size, key):
if key == "enter":
if key == "m_select":
foc, idx = self.get_focus()
signals.status_prompt_command.send(partial=foc.cmd.path + " ")
elif key == "m_start":
@ -148,7 +148,7 @@ class Commands(urwid.Pile, layoutwidget.LayoutWidget):
self.master = master
def keypress(self, size, key):
if key == "tab":
if key == "m_next":
self.focus_position = (
self.focus_position + 1
) % len(self.widget_list)

View File

@ -17,6 +17,8 @@ def map(km):
km.add("j", "console.nav.down", ["global"], "Down")
km.add("l", "console.nav.right", ["global"], "Right")
km.add("h", "console.nav.left", ["global"], "Left")
km.add("tab", "console.nav.next", ["global"], "Next")
km.add("enter", "console.nav.select", ["global"], "Select")
km.add(" ", "console.nav.pagedown", ["global"], "Page down")
km.add("ctrl f", "console.nav.pagedown", ["global"], "Page down")
km.add("ctrl b", "console.nav.pageup", ["global"], "Page up")
@ -78,7 +80,6 @@ def map(km):
["flowlist", "flowview"],
"Run a script on this flow"
)
km.add("enter", "console.view.flow @focus", ["flowlist"], "View this flow")
km.add(
"e",
@ -105,7 +106,6 @@ def map(km):
)
km.add("p", "view.focus.prev", ["flowview"], "Go to previous flow")
km.add("m", "console.flowview.mode.set", ["flowview"], "Set flow view mode")
km.add("tab", "console.nav.right", ["flowview"], "Go to next tab")
km.add(
"z",
"console.choose \"Part\" request,response "
@ -121,7 +121,6 @@ def map(km):
km.add("a", "console.grideditor.add", ["grideditor"], "Add a row after cursor")
km.add("A", "console.grideditor.insert", ["grideditor"], "Insert a row before cursor")
km.add("tab", "console.grideditor.next", ["grideditor"], "Go to next field")
km.add("d", "console.grideditor.delete", ["grideditor"], "Delete this row")
km.add(
"r",
@ -136,3 +135,5 @@ def map(km):
"Read a Python-style escaped string from file"
)
km.add("e", "console.grideditor.editor", ["grideditor"], "Edit in external editor")
km.add("z", "console.eventlog.clear", ["eventlog"], "Clear")

View File

@ -18,16 +18,14 @@ class EventLog(urwid.ListBox, layoutwidget.LayoutWidget):
self.master = master
urwid.ListBox.__init__(self, self.walker)
signals.sig_add_log.connect(self.sig_add_log)
signals.sig_clear_log.connect(self.sig_clear_log)
def set_focus(self, index):
if 0 <= index < len(self.walker):
super().set_focus(index)
def keypress(self, size, key):
if key == "z":
self.clear_events()
key = None
elif key == "m_end":
if key == "m_end":
self.set_focus(len(self.walker) - 1)
elif key == "m_start":
self.set_focus(0)
@ -45,5 +43,5 @@ class EventLog(urwid.ListBox, layoutwidget.LayoutWidget):
if self.master.options.console_focus_follow:
self.walker.set_focus(len(self.walker) - 1)
def clear_events(self):
def sig_clear_log(self, sender):
self.walker[:] = []

View File

@ -82,6 +82,8 @@ class FlowListBox(urwid.ListBox, layoutwidget.LayoutWidget):
self.master.commands.call("view.go 0")
elif key == "m_end":
self.master.commands.call("view.go -1")
elif key == "m_select":
self.master.commands.call("console.view.flow @focus")
return urwid.ListBox.keypress(self, size, key)
def view_changed(self):

View File

@ -194,10 +194,6 @@ class FlowDetails(tabs.Tabs):
]
return searchable.Searchable(txt)
def keypress(self, size, key):
key = super().keypress(size, key)
return self._w.keypress(size, key)
class FlowView(urwid.Frame, layoutwidget.LayoutWidget):
keyctx = "flowview"

View File

@ -6,19 +6,10 @@ import urwid
from mitmproxy.utils import strutils
from mitmproxy import exceptions
from mitmproxy.tools.console import common
from mitmproxy.tools.console import signals
from mitmproxy.tools.console import layoutwidget
import mitmproxy.tools.console.master # noqa
FOOTER = [
('heading_key', "enter"), ":edit ",
('heading_key', "q"), ":back ",
]
FOOTER_EDITING = [
('heading_key', "esc"), ":stop editing ",
]
def read_file(filename: str, escaped: bool) -> typing.AnyStr:
filename = os.path.expanduser(filename)
@ -197,12 +188,10 @@ class GridWalker(urwid.ListWalker):
self.edit_row = GridRow(
self.focus_col, True, self.editor, self.lst[self.focus]
)
signals.footer_help.send(self, helptext=FOOTER_EDITING)
self._modified()
def stop_edit(self):
if self.edit_row:
signals.footer_help.send(self, helptext=FOOTER)
try:
val = self.edit_row.edit_col.get_data()
except ValueError:
@ -262,7 +251,6 @@ class GridListBox(urwid.ListBox):
FIRST_WIDTH_MAX = 40
FIRST_WIDTH_MIN = 20
class BaseGridEditor(urwid.WidgetWrap):
@ -315,7 +303,6 @@ class BaseGridEditor(urwid.WidgetWrap):
w = urwid.Frame(self.lb, header=h)
super().__init__(w)
signals.footer_help.send(self, helptext="")
self.show_empty_msg()
def layout_popping(self):
@ -344,7 +331,7 @@ class BaseGridEditor(urwid.WidgetWrap):
def keypress(self, size, key):
if self.walker.edit_row:
if key in ["esc"]:
if key == "esc":
self.walker.stop_edit()
elif key == "tab":
pf, pfc = self.walker.focus, self.walker.focus_col
@ -358,6 +345,8 @@ class BaseGridEditor(urwid.WidgetWrap):
column = self.columns[self.walker.focus_col]
if key == "m_start":
self.walker.set_focus(0)
elif key == "m_next":
self.walker.tab_next()
elif key == "m_end":
self.walker.set_focus(len(self.walker.lst) - 1)
elif key == "left":
@ -389,38 +378,6 @@ class BaseGridEditor(urwid.WidgetWrap):
def handle_key(self, key):
return False
def make_help(self):
text = [
urwid.Text([("text", "Editor control:\n")])
]
keys = [
("A", "insert row before cursor"),
("a", "add row after cursor"),
("d", "delete row"),
("e", "spawn external editor on current field"),
("q", "save changes and exit editor"),
("r", "read value from file"),
("R", "read unescaped value from file"),
("esc", "save changes and exit editor"),
("tab", "next field"),
("enter", "edit field"),
]
text.extend(
common.format_keyvals(keys, key="key", val="text", indent=4)
)
text.append(
urwid.Text(
[
"\n",
("text", "Values are escaped Python-style strings.\n"),
]
)
)
return text
def cmd_next(self):
self.walker.tab_next()
def cmd_add(self):
self.walker.add()

View File

@ -15,7 +15,7 @@ class Column(base.Column):
return b""
def keypress(self, key, editor):
if key in ["enter"]:
if key in ["m_select"]:
editor.walker.start_edit()
else:
return key

View File

@ -26,7 +26,7 @@ class Column(base.Column):
expire=1000
)
return
elif key in ["enter"]:
elif key == "m_select":
editor.master.view_grideditor(
self.subeditor(
editor.master,

View File

@ -1,8 +1,5 @@
import urwid
from mitmproxy import exceptions
from mitmproxy.tools.console import common
from mitmproxy.tools.console import layoutwidget
from mitmproxy.tools.console.grideditor import base
from mitmproxy.tools.console.grideditor import col_text
@ -32,20 +29,6 @@ class HeaderEditor(base.FocusEditor):
col_bytes.Column("Value")
]
def make_help(self):
h = super().make_help()
text = [
urwid.Text([("text", "Special keys:\n")])
]
keys = [
]
text.extend(
common.format_keyvals(keys, key="key", val="text", indent=4)
)
text.append(urwid.Text([("text", "\n")]))
text.extend(h)
return text
class RequestHeaderEditor(HeaderEditor):
title = "Edit Request Headers"

View File

@ -6,6 +6,21 @@ from mitmproxy.tools.console import layoutwidget
from mitmproxy.tools.console import tabs
class CListBox(urwid.ListBox):
def __init__(self, contents):
self.length = len(contents)
contents = contents[:] + [urwid.Text(["\n"])] * 5
super().__init__(contents)
def keypress(self, size, key):
if key == "m_end":
self.set_focus(self.length - 1)
elif key == "m_start":
self.set_focus(0)
else:
return super().keypress(size, key)
class HelpView(tabs.Tabs, layoutwidget.LayoutWidget):
title = "Help"
keyctx = "help"
@ -54,7 +69,7 @@ class HelpView(tabs.Tabs, layoutwidget.LayoutWidget):
text.extend(self.format_keys(self.master.keymap.list("global")))
return urwid.ListBox(text)
return CListBox(text)
def filtexp_title(self):
return "Filter Expressions"
@ -83,7 +98,7 @@ class HelpView(tabs.Tabs, layoutwidget.LayoutWidget):
text.extend(
common.format_keyvals(examples, key="key", val="text", indent=4)
)
return urwid.ListBox(text)
return CListBox(text)
def layout_pushed(self, prev):
"""

View File

@ -6,6 +6,7 @@ from mitmproxy.tools.console import commandeditor
SupportedContexts = {
"chooser",
"commands",
"eventlog",
"flowlist",
"flowview",
"global",

View File

@ -131,6 +131,20 @@ class ConsoleAddon:
"""
self.master.inject_key("m_end")
@command.command("console.nav.next")
def nav_next(self) -> None:
"""
Go to the next navigatable item.
"""
self.master.inject_key("m_next")
@command.command("console.nav.select")
def nav_select(self) -> None:
"""
Select a navigable item for viewing or editing.
"""
self.master.inject_key("m_select")
@command.command("console.nav.up")
def nav_up(self) -> None:
"""
@ -343,13 +357,6 @@ class ConsoleAddon:
"""
self._grideditor().cmd_insert()
@command.command("console.grideditor.next")
def grideditor_next(self) -> None:
"""
Go to next cell.
"""
self._grideditor().cmd_next()
@command.command("console.grideditor.delete")
def grideditor_delete(self) -> None:
"""
@ -419,6 +426,13 @@ class ConsoleAddon:
]
)
@command.command("console.eventlog.clear")
def eventlog_clear(self) -> None:
"""
Clear the event log.
"""
signals.sig_clear_log.send(self)
def running(self):
self.started = True

View File

@ -176,8 +176,10 @@ class OptionsList(urwid.ListBox):
except exceptions.OptionsError as v:
signals.status_message.send(message=str(v))
self.walker.stop_editing()
return None
elif key == "esc":
self.walker.stop_editing()
return None
else:
if key == "m_start":
self.set_focus(0)
@ -185,7 +187,7 @@ class OptionsList(urwid.ListBox):
elif key == "m_end":
self.set_focus(len(self.walker.opts) - 1)
self.walker._modified()
elif key == "enter":
elif key == "m_select":
foc, idx = self.get_focus()
if foc.opt.typespec == bool:
self.master.options.toggler(foc.opt.name)()
@ -261,7 +263,7 @@ class Options(urwid.Pile, layoutwidget.LayoutWidget):
return foc.opt.name
def keypress(self, size, key):
if key == "tab":
if key == "m_next":
self.focus_position = (
self.focus_position + 1
) % len(self.widget_list)

View File

@ -2,7 +2,6 @@ import math
import urwid
from mitmproxy.tools.console import common
from mitmproxy.tools.console import signals
from mitmproxy.tools.console import grideditor
from mitmproxy.tools.console import layoutwidget
@ -116,20 +115,13 @@ class Chooser(urwid.WidgetWrap, layoutwidget.LayoutWidget):
def keypress(self, size, key):
key = self.master.keymap.handle("chooser", key)
if key == "enter":
if key == "m_select":
self.callback(self.choices[self.walker.index])
signals.pop_view_state.send(self)
elif key == "esc":
signals.pop_view_state.send(self)
return super().keypress(size, key)
def make_help(self):
text = []
keys = [
("enter", "choose option"),
("esc", "exit chooser"),
]
text.extend(common.format_keyvals(keys, key="key", val="text", indent=4))
return text
class OptionsOverlay(urwid.WidgetWrap, layoutwidget.LayoutWidget):
keyctx = "grideditor"
@ -151,9 +143,6 @@ class OptionsOverlay(urwid.WidgetWrap, layoutwidget.LayoutWidget):
)
self.width = math.ceil(cols * 0.8)
def make_help(self):
return self.ge.make_help()
def key_responder(self):
return self.ge.key_responder()

View File

@ -1,120 +0,0 @@
import urwid
from mitmproxy.tools.console import common
class _OptionWidget(urwid.WidgetWrap):
def __init__(self, option, text, shortcut, active, focus):
self.option = option
textattr = "text"
keyattr = "key"
if focus and active:
textattr = "option_active_selected"
keyattr = "option_selected_key"
elif focus:
textattr = "option_selected"
keyattr = "option_selected_key"
elif active:
textattr = "option_active"
if shortcut:
text = common.highlight_key(
text,
shortcut,
textattr = textattr,
keyattr = keyattr
)
opt = urwid.Text(text, align="left")
opt = urwid.AttrWrap(opt, textattr)
opt = urwid.Padding(opt, align = "center", width = 40)
urwid.WidgetWrap.__init__(self, opt)
def keypress(self, size, key):
return key
def selectable(self):
return True
class OptionWalker(urwid.ListWalker):
def __init__(self, options):
urwid.ListWalker.__init__(self)
self.options = options
self.focus = 0
def set_focus(self, pos):
self.focus = pos
def get_focus(self):
return self.options[self.focus].render(True), self.focus
def get_next(self, pos):
if pos >= len(self.options) - 1:
return None, None
return self.options[pos + 1].render(False), pos + 1
def get_prev(self, pos):
if pos <= 0:
return None, None
return self.options[pos - 1].render(False), pos - 1
class Heading:
def __init__(self, text):
self.text = text
def render(self, focus):
opt = urwid.Text("\n" + self.text, align="left")
opt = urwid.AttrWrap(opt, "title")
opt = urwid.Padding(opt, align = "center", width = 40)
return opt
def _neg(*args):
return False
class Option:
def __init__(self, text, shortcut, getstate=None, activate=None):
self.text = text
self.shortcut = shortcut
self.getstate = getstate or _neg
self.activate = activate or _neg
def render(self, focus):
return _OptionWidget(
self,
self.text,
self.shortcut,
self.getstate(),
focus)
class Select(urwid.ListBox):
def __init__(self, options):
self.walker = OptionWalker(options)
urwid.ListBox.__init__(
self,
self.walker
)
self.options = options
self.keymap = {}
for i in options:
if hasattr(i, "shortcut") and i.shortcut:
if i.shortcut in self.keymap:
raise ValueError("Duplicate shortcut key: %s" % i.shortcut)
self.keymap[i.shortcut] = i
def keypress(self, size, key):
if key == "enter" or key == " ":
self.get_focus()[0].option.activate()
return None
if key in self.keymap:
self.keymap[key].activate()
self.set_focus(self.options.index(self.keymap[key]))
return None
return super().keypress(size, key)

View File

@ -1,6 +1,9 @@
import blinker
# Show a status message in the action bar
# Clear the eventlog
sig_clear_log = blinker.Signal()
# Add an entry to the eventlog
sig_add_log = blinker.Signal()
@ -33,9 +36,6 @@ call_in = blinker.Signal()
# Focus the body, footer or header of the main window
focus = blinker.Signal()
# Set the mini help text in the footer of the main window
footer_help = blinker.Signal()
# Fired when settings change
update_settings = blinker.Signal()

View File

@ -3,7 +3,6 @@ import os.path
import urwid
from mitmproxy.tools.console import common
from mitmproxy.tools.console import pathedit
from mitmproxy.tools.console import signals
from mitmproxy.tools.console import commandeditor
import mitmproxy.tools.console.master # noqa
@ -39,16 +38,12 @@ class ActionBar(urwid.WidgetWrap):
self.clear()
signals.status_message.connect(self.sig_message)
signals.status_prompt.connect(self.sig_prompt)
signals.status_prompt_path.connect(self.sig_path_prompt)
signals.status_prompt_onekey.connect(self.sig_prompt_onekey)
signals.status_prompt_command.connect(self.sig_prompt_command)
self.last_path = ""
self.prompting = None
self.onekey = False
self.pathprompt = False
def sig_message(self, sender, message, expire=1):
if self.prompting:
@ -74,15 +69,6 @@ class ActionBar(urwid.WidgetWrap):
self._w = commandeditor.CommandEdit(partial)
self.prompting = commandeditor.CommandExecutor(self.master)
def sig_path_prompt(self, sender, prompt, callback, args=()):
signals.focus.send(self, section="footer")
self._w = pathedit.PathEdit(
self.prep_prompt(prompt),
os.path.dirname(self.last_path)
)
self.pathprompt = True
self.prompting = PromptPath(callback, args)
def sig_prompt_onekey(self, sender, prompt, keys, callback, args=()):
"""
Keys are a set of (word, key) tuples. The appropriate key in the
@ -128,13 +114,10 @@ class ActionBar(urwid.WidgetWrap):
def prompt_done(self):
self.prompting = None
self.onekey = False
self.pathprompt = False
signals.status_message.send(message="")
signals.focus.send(self, section="body")
def prompt_execute(self, txt):
if self.pathprompt:
self.last_path = txt
p = self.prompting
self.prompt_done()
msg = p(txt)

View File

@ -35,7 +35,9 @@ class Tabs(urwid.WidgetWrap):
def keypress(self, size, key):
n = len(self.tabs)
if key == "right":
if key == "m_next":
self.change_tab((self.tab_offset + 1) % n)
elif key == "right":
self.change_tab((self.tab_offset + 1) % n)
elif key == "left":
self.change_tab((self.tab_offset - 1) % n)