codekingpro/portable-devtools
114k
1import textwrap2 3import urwid4 5from mitmproxy import command6from mitmproxy.tools.console import layoutwidget7from mitmproxy.tools.console import signals8from mitmproxy.utils import signals as utils_signals9 10HELP_HEIGHT = 511 12command_focus_change = utils_signals.SyncSignal(lambda text: None)13 14 15class CommandItem(urwid.WidgetWrap):16 def __init__(self, walker, cmd: command.Command, focused: bool):17 self.walker, self.cmd, self.focused = walker, cmd, focused18 super().__init__(self.get_widget())19 20 def get_widget(self):21 parts = [("focus", ">> " if self.focused else " "), ("title", self.cmd.name)]22 if self.cmd.parameters:23 parts += [24 ("text", " "),25 ("text", " ".join(str(param) for param in self.cmd.parameters)),26 ]27 if self.cmd.return_type:28 parts += [29 ("title", " -> "),30 ("text", command.typename(self.cmd.return_type)),31 ]32 33 return urwid.AttrMap(urwid.Padding(urwid.Text(parts)), "text")34 35 def get_edit_text(self):36 return self._w[1].get_edit_text()37 38 def selectable(self):39 return True40 41 def keypress(self, size, key):42 return key43 44 45class CommandListWalker(urwid.ListWalker):46 def __init__(self, master):47 self.master = master48 self.index = 049 self.refresh()50 51 def refresh(self):52 self.cmds = list(self.master.commands.commands.values())53 self.cmds.sort(key=lambda x: x.signature_help())54 self.set_focus(self.index)55 56 def get_edit_text(self):57 return self.focus_obj.get_edit_text()58 59 def _get(self, pos):60 cmd = self.cmds[pos]61 return CommandItem(self, cmd, pos == self.index)62 63 def get_focus(self):64 return self.focus_obj, self.index65 66 def set_focus(self, index: int) -> None:67 cmd = self.cmds[index]68 self.index = index69 self.focus_obj = self._get(self.index)70 command_focus_change.send(cmd.help or "")71 72 def get_next(self, pos):73 if pos >= len(self.cmds) - 1:74 return None, None75 pos = pos + 176 return self._get(pos), pos77 78 def get_prev(self, pos):79 pos = pos - 180 if pos < 0:81 return None, None82 return self._get(pos), pos83 84 85class CommandsList(urwid.ListBox):86 def __init__(self, master):87 self.master = master88 self.walker = CommandListWalker(master)89 super().__init__(self.walker)90 91 def keypress(self, size: int, key: str):92 if key == "m_select":93 foc, idx = self.get_focus()94 signals.status_prompt_command.send(partial=foc.cmd.name + " ")95 elif key == "m_start":96 self.set_focus(0)97 self.walker._modified()98 elif key == "m_end":99 self.set_focus(len(self.walker.cmds) - 1)100 self.walker._modified()101 return super().keypress(size, key)102 103 104class CommandHelp(urwid.Frame):105 def __init__(self, master):106 self.master = master107 super().__init__(self.widget(""))108 self.set_active(False)109 command_focus_change.connect(self.sig_mod)110 111 def set_active(self, val):112 h = urwid.Text("Command Help")113 style = "heading" if val else "heading_inactive"114 self.header = urwid.AttrMap(h, style)115 116 def widget(self, txt):117 cols, _ = self.master.ui.get_cols_rows()118 return urwid.ListBox([urwid.Text(i) for i in textwrap.wrap(txt, cols)])119 120 def sig_mod(self, txt):121 self.body = self.widget(txt)122 123 124class Commands(urwid.Pile, layoutwidget.LayoutWidget):125 title = "Command Reference"126 keyctx = "commands"127 128 focus_position: int129 130 def __init__(self, master):131 oh = CommandHelp(master)132 super().__init__(133 [134 CommandsList(master),135 (HELP_HEIGHT, oh),136 ]137 )138 self.master = master139 140 def layout_pushed(self, prev):141 self.widget_list[0].walker.refresh()142 143 def keypress(self, size, key):144 if key == "m_next":145 self.focus_position = (self.focus_position + 1) % len(self.widget_list)146 self.widget_list[1].set_active(self.focus_position == 1)147 key = None148 149 # This is essentially a copypasta from urwid.Pile's keypress handler.150 # So much for "closed for modification, but open for extension".151 item_rows = None152 if len(size) == 2:153 item_rows = self.get_item_rows(size, focus=True)154 i = self.widget_list.index(self.focus_item)155 tsize = self.get_item_size(size, i, True, item_rows)156 return self.focus_item.keypress(tsize, key)157 