mirror of
https://github.com/Grasscutters/mitmproxy.git
synced 2024-11-23 00:01:36 +00:00
console: key binding viewer
Read-only for now.
This commit is contained in:
parent
88832f92a3
commit
ba49b55684
@ -6,16 +6,6 @@ from mitmproxy.tools.console import signals
|
||||
|
||||
HELP_HEIGHT = 5
|
||||
|
||||
|
||||
def fcol(s, width, attr):
|
||||
s = str(s)
|
||||
return (
|
||||
"fixed",
|
||||
width,
|
||||
urwid.Text((attr, s))
|
||||
)
|
||||
|
||||
|
||||
command_focus_change = blinker.Signal()
|
||||
|
||||
|
||||
|
@ -3,6 +3,7 @@ def map(km):
|
||||
km.add(":", "console.command ''", ["global"], "Command prompt")
|
||||
km.add("?", "console.view.help", ["global"], "View help")
|
||||
km.add("C", "console.view.commands", ["global"], "View commands")
|
||||
km.add("K", "console.view.keybindings", ["global"], "View key bindings")
|
||||
km.add("O", "console.view.options", ["global"], "View options")
|
||||
km.add("E", "console.view.eventlog", ["global"], "View event log")
|
||||
km.add("Q", "console.exit", ["global"], "Exit immediately")
|
||||
|
@ -30,7 +30,7 @@ class FlowItem(urwid.WidgetWrap):
|
||||
self.master.commands.call("console.view.flow @focus")
|
||||
return True
|
||||
|
||||
def keypress(self, xxx_todo_changeme, key):
|
||||
def keypress(self, size, key):
|
||||
return key
|
||||
|
||||
|
||||
|
146
mitmproxy/tools/console/keybindings.py
Normal file
146
mitmproxy/tools/console/keybindings.py
Normal file
@ -0,0 +1,146 @@
|
||||
import urwid
|
||||
import blinker
|
||||
import textwrap
|
||||
from mitmproxy.tools.console import layoutwidget
|
||||
|
||||
HELP_HEIGHT = 5
|
||||
|
||||
|
||||
keybinding_focus_change = blinker.Signal()
|
||||
|
||||
|
||||
class KeyItem(urwid.WidgetWrap):
|
||||
def __init__(self, walker, binding, focused):
|
||||
self.walker, self.binding, self.focused = walker, binding, focused
|
||||
super().__init__(None)
|
||||
self._w = self.get_widget()
|
||||
|
||||
def get_widget(self):
|
||||
cmd = textwrap.dedent(self.binding.command).strip()
|
||||
parts = [
|
||||
(4, urwid.Text([("focus", ">> " if self.focused else " ")])),
|
||||
(10, urwid.Text([("title", self.binding.key)])),
|
||||
(12, urwid.Text([("highlight", "\n".join(self.binding.contexts))])),
|
||||
urwid.Text([("text", cmd)]),
|
||||
]
|
||||
return urwid.Columns(parts)
|
||||
|
||||
def get_edit_text(self):
|
||||
return self._w[1].get_edit_text()
|
||||
|
||||
def selectable(self):
|
||||
return True
|
||||
|
||||
def keypress(self, size, key):
|
||||
return key
|
||||
|
||||
|
||||
class KeyListWalker(urwid.ListWalker):
|
||||
def __init__(self, master):
|
||||
self.master = master
|
||||
|
||||
self.index = 0
|
||||
self.focusobj = None
|
||||
self.bindings = list(master.keymap.list("all"))
|
||||
self.set_focus(0)
|
||||
|
||||
def get_edit_text(self):
|
||||
return self.focus_obj.get_edit_text()
|
||||
|
||||
def _get(self, pos):
|
||||
binding = self.bindings[pos]
|
||||
return KeyItem(self, binding, pos == self.index)
|
||||
|
||||
def get_focus(self):
|
||||
return self.focus_obj, self.index
|
||||
|
||||
def set_focus(self, index):
|
||||
binding = self.bindings[index]
|
||||
self.index = index
|
||||
self.focus_obj = self._get(self.index)
|
||||
keybinding_focus_change.send(binding.help or "")
|
||||
|
||||
def get_next(self, pos):
|
||||
if pos >= len(self.bindings) - 1:
|
||||
return None, None
|
||||
pos = pos + 1
|
||||
return self._get(pos), pos
|
||||
|
||||
def get_prev(self, pos):
|
||||
pos = pos - 1
|
||||
if pos < 0:
|
||||
return None, None
|
||||
return self._get(pos), pos
|
||||
|
||||
|
||||
class KeyList(urwid.ListBox):
|
||||
def __init__(self, master):
|
||||
self.master = master
|
||||
self.walker = KeyListWalker(master)
|
||||
super().__init__(self.walker)
|
||||
|
||||
def keypress(self, size, key):
|
||||
if key == "m_select":
|
||||
foc, idx = self.get_focus()
|
||||
# Act here
|
||||
elif key == "m_start":
|
||||
self.set_focus(0)
|
||||
self.walker._modified()
|
||||
elif key == "m_end":
|
||||
self.set_focus(len(self.walker.bindings) - 1)
|
||||
self.walker._modified()
|
||||
return super().keypress(size, key)
|
||||
|
||||
|
||||
class KeyHelp(urwid.Frame):
|
||||
def __init__(self, master):
|
||||
self.master = master
|
||||
super().__init__(self.widget(""))
|
||||
self.set_active(False)
|
||||
keybinding_focus_change.connect(self.sig_mod)
|
||||
|
||||
def set_active(self, val):
|
||||
h = urwid.Text("Key Binding Help")
|
||||
style = "heading" if val else "heading_inactive"
|
||||
self.header = urwid.AttrWrap(h, style)
|
||||
|
||||
def widget(self, txt):
|
||||
cols, _ = self.master.ui.get_cols_rows()
|
||||
return urwid.ListBox(
|
||||
[urwid.Text(i) for i in textwrap.wrap(txt, cols)]
|
||||
)
|
||||
|
||||
def sig_mod(self, txt):
|
||||
self.set_body(self.widget(txt))
|
||||
|
||||
|
||||
class KeyBindings(urwid.Pile, layoutwidget.LayoutWidget):
|
||||
title = "Key Bindings"
|
||||
keyctx = "keybindings"
|
||||
|
||||
def __init__(self, master):
|
||||
oh = KeyHelp(master)
|
||||
super().__init__(
|
||||
[
|
||||
KeyList(master),
|
||||
(HELP_HEIGHT, oh),
|
||||
]
|
||||
)
|
||||
self.master = master
|
||||
|
||||
def keypress(self, size, key):
|
||||
if key == "m_next":
|
||||
self.focus_position = (
|
||||
self.focus_position + 1
|
||||
) % len(self.widget_list)
|
||||
self.widget_list[1].set_active(self.focus_position == 1)
|
||||
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)
|
@ -54,7 +54,7 @@ class Keymap:
|
||||
return None
|
||||
|
||||
def list(self, context: str) -> typing.Sequence[Binding]:
|
||||
b = [b for b in self.bindings if context in b.contexts]
|
||||
b = [b for b in self.bindings if context in b.contexts or context == "all"]
|
||||
b.sort(key=lambda x: x.key)
|
||||
return b
|
||||
|
||||
|
@ -240,6 +240,11 @@ class ConsoleAddon:
|
||||
"""
|
||||
signals.status_prompt_command.send(partial=" ".join(partial)) # type: ignore
|
||||
|
||||
@command.command("console.view.keybindings")
|
||||
def view_keybindings(self) -> None:
|
||||
"""View the commands list."""
|
||||
self.master.switch_view("keybindings")
|
||||
|
||||
@command.command("console.view.commands")
|
||||
def view_commands(self) -> None:
|
||||
"""View the commands list."""
|
||||
|
@ -4,6 +4,7 @@ from mitmproxy.tools.console import statusbar
|
||||
from mitmproxy.tools.console import flowlist
|
||||
from mitmproxy.tools.console import flowview
|
||||
from mitmproxy.tools.console import commands
|
||||
from mitmproxy.tools.console import keybindings
|
||||
from mitmproxy.tools.console import options
|
||||
from mitmproxy.tools.console import overlay
|
||||
from mitmproxy.tools.console import help
|
||||
@ -29,6 +30,7 @@ class WindowStack:
|
||||
flowlist = flowlist.FlowListBox(master),
|
||||
flowview = flowview.FlowView(master),
|
||||
commands = commands.Commands(master),
|
||||
keybindings = keybindings.KeyBindings(master),
|
||||
options = options.Options(master),
|
||||
help = help.HelpView(master),
|
||||
eventlog = eventlog.EventLog(master),
|
||||
|
@ -265,7 +265,7 @@ def test_duplicate():
|
||||
def test_remove():
|
||||
v = view.View()
|
||||
with taddons.context():
|
||||
f = [tflow.tflow(), tflow.tflow() ]
|
||||
f = [tflow.tflow(), tflow.tflow()]
|
||||
v.add(f)
|
||||
assert len(v) == 2
|
||||
v.remove(f)
|
||||
|
Loading…
Reference in New Issue
Block a user