Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes14kdownloads
options.py273 linesDownload Raw Back to console
1from __future__ import annotations2 3import pprint4import textwrap5import typing6from collections.abc import Sequence7from typing import Optional8 9import urwid10 11from mitmproxy import exceptions12from mitmproxy import optmanager13from mitmproxy.tools.console import layoutwidget14from mitmproxy.tools.console import overlay15from mitmproxy.tools.console import signals16 17HELP_HEIGHT = 518 19 20def can_edit_inplace(opt):21    if opt.choices:22        return False23    if opt.typespec in [str, int, Optional[str], Optional[int]]:24        return True25 26 27class OptionItem(urwid.WidgetWrap):28    def __init__(self, walker, opt, focused, namewidth, editing):29        self.walker, self.opt, self.focused = walker, opt, focused30        self.namewidth = namewidth31        self.editing = editing32        super().__init__(self.get_widget())33 34    def get_widget(self):35        val = self.opt.current()36        if self.opt.typespec is bool:37            displayval = "true" if val else "false"38        elif not val:39            displayval = ""40        elif self.opt.typespec == Sequence[str]:41            displayval = pprint.pformat(val, indent=1)42        else:43            displayval = str(val)44 45        changed = self.walker.master.options.has_changed(self.opt.name)46        if self.focused:47            valstyle = "option_active_selected" if changed else "option_selected"48        else:49            valstyle = "option_active" if changed else "text"50 51        if self.editing:52            valw = urwid.Edit(edit_text=displayval)53        else:54            valw = urwid.AttrMap(55                urwid.Padding(urwid.Text([(valstyle, displayval)])), valstyle56            )57 58        return urwid.Columns(59            [60                (61                    self.namewidth,62                    urwid.Text([("title", self.opt.name.ljust(self.namewidth))]),63                ),64                valw,65            ],66            dividechars=2,67            focus_column=1,68        )69 70    def get_edit_text(self):71        return self._w[1].get_edit_text()72 73    def selectable(self):74        return True75 76    def keypress(self, size, key):77        if self.editing:78            self._w[1].keypress(size, key)79            return80        return key81 82 83class OptionListWalker(urwid.ListWalker):84    def __init__(self, master, help_widget: OptionHelp):85        self.master = master86        self.help_widget = help_widget87 88        self.index = 089        self.focusobj = None90 91        self.opts = sorted(master.options.keys())92        self.maxlen = max(len(i) for i in self.opts)93        self.editing = False94        self.set_focus(0)95        self.master.options.changed.connect(self.sig_mod)96 97    def sig_mod(self, *args, **kwargs):98        self.opts = sorted(self.master.options.keys())99        self.maxlen = max(len(i) for i in self.opts)100        self._modified()101        self.set_focus(self.index)102 103    def start_editing(self):104        self.editing = True105        self.focus_obj = self._get(self.index, True)106        self._modified()107 108    def stop_editing(self):109        self.editing = False110        self.focus_obj = self._get(self.index, False)111        self.set_focus(self.index)112        self._modified()113 114    def get_edit_text(self):115        return self.focus_obj.get_edit_text()116 117    def _get(self, pos, editing):118        name = self.opts[pos]119        opt = self.master.options._options[name]120        return OptionItem(self, opt, pos == self.index, self.maxlen, editing)121 122    def get_focus(self):123        return self.focus_obj, self.index124 125    def set_focus(self, index):126        self.editing = False127        name = self.opts[index]128        opt = self.master.options._options[name]129        self.index = index130        self.focus_obj = self._get(self.index, self.editing)131        self.help_widget.update_help_text(opt.help)132        self._modified()133 134    def get_next(self, pos):135        if pos >= len(self.opts) - 1:136            return None, None137        pos = pos + 1138        return self._get(pos, False), pos139 140    def get_prev(self, pos):141        pos = pos - 1142        if pos < 0:143            return None, None144        return self._get(pos, False), pos145 146    def positions(self, reverse=False):147        if reverse:148            return reversed(range(len(self.opts)))149        else:150            return range(len(self.opts))151 152 153class OptionsList(urwid.ListBox):154    def __init__(self, master, help_widget: OptionHelp):155        self.master = master156        self.walker = OptionListWalker(master, help_widget)157        super().__init__(self.walker)158 159    def save_config(self, path):160        try:161            optmanager.save(self.master.options, path)162        except exceptions.OptionsError as e:163            signals.status_message.send(message=str(e))164 165    def keypress(self, size, key):166        if self.walker.editing:167            if key == "enter":168                foc, idx = self.get_focus()169                v = self.walker.get_edit_text()170                try:171                    self.master.options.set(f"{foc.opt.name}={v}")172                except exceptions.OptionsError as v:173                    signals.status_message.send(message=str(v))174                self.walker.stop_editing()175                return None176            elif key == "esc":177                self.walker.stop_editing()178                return None179        else:180            if key == "m_start":181                self.set_focus(0)182                self.walker._modified()183            elif key == "m_end":184                self.set_focus(len(self.walker.opts) - 1)185                self.walker._modified()186            elif key == "m_select":187                foc, idx = self.get_focus()188                if foc.opt.typespec is bool:189                    self.master.options.toggler(foc.opt.name)()190                    # Bust the focus widget cache191                    self.set_focus(self.walker.index)192                elif can_edit_inplace(foc.opt):193                    self.walker.start_editing()194                    self.walker._modified()195                elif foc.opt.choices:196                    self.master.overlay(197                        overlay.Chooser(198                            self.master,199                            foc.opt.name,200                            foc.opt.choices,201                            foc.opt.current(),202                            self.master.options.setter(foc.opt.name),203                        )204                    )205                elif foc.opt.typespec in (Sequence[str], typing.Sequence[str]):206                    self.master.overlay(207                        overlay.OptionsOverlay(208                            self.master,209                            foc.opt.name,210                            foc.opt.current(),211                            HELP_HEIGHT + 5,212                        ),213                        valign="top",214                    )215                else:216                    raise NotImplementedError()217        return super().keypress(size, key)218 219 220class OptionHelp(urwid.Frame):221    def __init__(self, master):222        self.master = master223        super().__init__(self.widget(""))224        self.set_active(False)225 226    def set_active(self, val):227        h = urwid.Text("Option Help")228        style = "heading" if val else "heading_inactive"229        self.header = urwid.AttrMap(h, style)230 231    def widget(self, txt):232        cols, _ = self.master.ui.get_cols_rows()233        return urwid.ListBox([urwid.Text(i) for i in textwrap.wrap(txt, cols)])234 235    def update_help_text(self, txt: str) -> None:236        self.body = self.widget(txt)237 238 239class Options(urwid.Pile, layoutwidget.LayoutWidget):240    title = "Options"241    keyctx = "options"242 243    focus_position: int244 245    def __init__(self, master):246        oh = OptionHelp(master)247        self.optionslist = OptionsList(master, oh)248        super().__init__(249            [250                self.optionslist,251                (HELP_HEIGHT, oh),252            ]253        )254        self.master = master255 256    def current_name(self):257        foc, idx = self.optionslist.get_focus()258        return foc.opt.name259 260    def keypress(self, size, key):261        if key == "m_next":262            self.focus_position = (self.focus_position + 1) % len(self.widget_list)263            self.widget_list[1].set_active(self.focus_position == 1)264            key = None265 266        # This is essentially a copypasta from urwid.Pile's keypress handler.267        # So much for "closed for modification, but open for extension".268        item_rows = None269        if len(size) == 2:270            item_rows = self.get_item_rows(size, focus=True)271        tsize = self.get_item_size(size, self.focus_position, True, item_rows)272        return self.focus.keypress(tsize, key)273 
codekingpro/portable-devtools · Team Ai