console: grideditor keybindings for r, R and e

This commit is contained in:
Aldo Cortesi 2017-06-11 11:47:04 +12:00
parent f804495fd8
commit d7cc7e62a2
3 changed files with 72 additions and 70 deletions

View File

@ -1,15 +1,11 @@
import abc
import copy
from typing import Any
from typing import Callable
from typing import Container
from typing import Iterable
from typing import Optional
from typing import Sequence
from typing import Tuple
from typing import Set # noqa
import os
import typing
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
@ -24,6 +20,21 @@ FOOTER_EDITING = [
]
def read_file(filename: str, escaped: bool) -> typing.AnyStr:
filename = os.path.expanduser(filename)
try:
with open(filename, "r" if escaped else "rb") as f:
d = f.read()
except IOError as v:
raise exceptions.CommandError(v)
if escaped:
try:
d = strutils.escaped_str_to_bytes(d)
except ValueError:
raise exceptions.CommandError("Invalid Python-style string encoding.")
return d
class Cell(urwid.WidgetWrap):
def get_data(self):
"""
@ -51,10 +62,10 @@ class Column(metaclass=abc.ABCMeta):
pass
@abc.abstractmethod
def blank(self) -> Any:
def blank(self) -> typing.Any:
pass
def keypress(self, key: str, editor: "GridEditor") -> Optional[str]:
def keypress(self, key: str, editor: "GridEditor") -> typing.Optional[str]:
return key
@ -62,10 +73,10 @@ class GridRow(urwid.WidgetWrap):
def __init__(
self,
focused: Optional[int],
focused: typing.Optional[int],
editing: bool,
editor: "GridEditor",
values: Tuple[Iterable[bytes], Container[int]]
values: typing.Tuple[typing.Iterable[bytes], typing.Container[int]]
) -> None:
self.focused = focused
self.editor = editor
@ -118,7 +129,7 @@ class GridWalker(urwid.ListWalker):
def __init__(
self,
lst: Iterable[list],
lst: typing.Iterable[list],
editor: "GridEditor"
) -> None:
self.lst = [(i, set()) for i in lst] # type: Sequence[Tuple[Any, Set]]
@ -262,8 +273,8 @@ class BaseGridEditor(urwid.WidgetWrap):
master: "mitmproxy.tools.console.master.ConsoleMaster",
title,
columns,
value: Any,
callback: Callable[..., None],
value: typing.Any,
callback: typing.Callable[..., None],
*cb_args,
**cb_kwargs
) -> None:
@ -352,20 +363,20 @@ class BaseGridEditor(urwid.WidgetWrap):
elif column.keypress(key, self) and not self.handle_key(key):
return self._w.keypress(size, key)
def data_out(self, data: Sequence[list]) -> Any:
def data_out(self, data: typing.Sequence[list]) -> typing.Any:
"""
Called on raw list data, before data is returned through the
callback.
"""
return data
def data_in(self, data: Any) -> Iterable[list]:
def data_in(self, data: typing.Any) -> typing.Iterable[list]:
"""
Called to prepare provided data.
"""
return data
def is_error(self, col: int, val: Any) -> Optional[str]:
def is_error(self, col: int, val: typing.Any) -> typing.Optional[str]:
"""
Return None, or a string error message.
"""
@ -415,6 +426,19 @@ class BaseGridEditor(urwid.WidgetWrap):
def cmd_delete(self):
self.walker.delete_focus()
def cmd_read_file(self, path):
self.walker.set_current_value(read_file(path, False))
def cmd_read_file_escaped(self, path):
self.walker.set_current_value(read_file(path, True))
def cmd_spawn_editor(self):
o = self.walker.get_current_value()
if o is not None:
n = self.master.spawn_editor(o)
n = strutils.clean_hanging_newline(n)
self.walker.set_current_value(n)
class GridEditor(BaseGridEditor):
title = None # type: str
@ -424,8 +448,8 @@ class GridEditor(BaseGridEditor):
def __init__(
self,
master: "mitmproxy.tools.console.master.ConsoleMaster",
value: Any,
callback: Callable[..., None],
value: typing.Any,
callback: typing.Callable[..., None],
*cb_args,
**cb_kwargs
) -> None:
@ -480,7 +504,7 @@ class FocusEditor(urwid.WidgetWrap, layoutwidget.LayoutWidget):
def focus_changed(self):
if self.master.view.focus.flow:
self._w = BaseGridEditor(
self.master.view.focus.flow,
self.master,
self.title,
self.columns,
self.get_data(self.master.view.focus.flow),

View File

@ -1,34 +1,9 @@
import os
from typing import Callable, Optional
import urwid
from mitmproxy.tools.console import signals
from mitmproxy.tools.console.grideditor import base
from mitmproxy.utils import strutils
def read_file(filename: str, callback: Callable[..., None], escaped: bool) -> Optional[str]:
if not filename:
return None
filename = os.path.expanduser(filename)
try:
with open(filename, "r" if escaped else "rb") as f:
d = f.read()
except IOError as v:
return str(v)
if escaped:
try:
d = strutils.escaped_str_to_bytes(d)
except ValueError:
return "Invalid Python-style string encoding."
# TODO: Refactor the status_prompt_path signal so that we
# can raise exceptions here and return the content instead.
callback(d)
return None
class Column(base.Column):
def Display(self, data):
return Display(data)
@ -40,29 +15,7 @@ class Column(base.Column):
return b""
def keypress(self, key, editor):
if key == "r":
if editor.walker.get_current_value() is not None:
signals.status_prompt_path.send(
self,
prompt="Read file",
callback=read_file,
args=(editor.walker.set_current_value, True)
)
elif key == "R":
if editor.walker.get_current_value() is not None:
signals.status_prompt_path.send(
self,
prompt="Read unescaped file",
callback=read_file,
args=(editor.walker.set_current_value, False)
)
elif key == "e":
o = editor.walker.get_current_value()
if o is not None:
n = editor.master.spawn_editor(o)
n = strutils.clean_hanging_newline(n)
editor.walker.set_current_value(n)
elif key in ["enter"]:
if key in ["enter"]:
editor.walker.start_edit()
else:
return key

View File

@ -356,6 +356,28 @@ class ConsoleAddon:
"""
self._grideditor().cmd_delete()
@command.command("console.grideditor.readfile")
def grideditor_readfile(self, path: str) -> None:
"""
Read a file into the currrent cell.
"""
self._grideditor().cmd_read_file(path)
@command.command("console.grideditor.readfile_escaped")
def grideditor_readfile_escaped(self, path: str) -> None:
"""
Read a file containing a Python-style escaped stringinto the
currrent cell.
"""
self._grideditor().cmd_read_file_escaped(path)
@command.command("console.grideditor.editor")
def grideditor_editor(self) -> None:
"""
Spawn an external editor on the current cell.
"""
self._grideditor().cmd_spawn_editor()
@command.command("console.flowview.mode.set")
def flowview_mode_set(self) -> None:
"""
@ -514,6 +536,9 @@ def default_keymap(km):
km.add("A", "console.grideditor.insert", ["grideditor"])
km.add("tab", "console.grideditor.next", ["grideditor"])
km.add("d", "console.grideditor.delete", ["grideditor"])
km.add("r", "console.command console.grideditor.readfile", ["grideditor"])
km.add("R", "console.command console.grideditor.readfile_escaped", ["grideditor"])
km.add("e", "console.grideditor.editor", ["grideditor"])
class ConsoleMaster(master.Master):