console: very basic interactive command executor

This commit is contained in:
Aldo Cortesi 2017-04-27 12:00:20 +12:00
parent 169baabcab
commit ee3dd3f3c5
7 changed files with 44 additions and 5 deletions

View File

@ -94,7 +94,7 @@ class Loader:
)
def add_command(self, path: str, func: typing.Callable) -> None:
self.master.commands.add_command(path, func)
self.master.commands.add(path, func)
def traverse(chain):

View File

@ -44,7 +44,7 @@ class Command:
Call the command with a set of arguments. At this point, all argumets are strings.
"""
if len(self.paramtypes) != len(args):
raise CommandError("SIGNATURE")
raise CommandError("Usage: %s" % self.signature_help())
args = [parsearg(args[i], self.paramtypes[i]) for i in range(len(args))]

View File

@ -0,0 +1,26 @@
import urwid
from mitmproxy import command
from mitmproxy.tools.console import signals
class CommandEdit(urwid.Edit):
def __init__(self):
urwid.Edit.__init__(self, ":", "")
def keypress(self, size, key):
return urwid.Edit.keypress(self, size, key)
class CommandExecutor:
def __init__(self, master):
self.master = master
def __call__(self, cmd):
try:
ret = self.master.commands.call(cmd)
except command.CommandError as v:
signals.status_message.send(message=str(v))
else:
if type(ret) == str:
signals.status_message.send(message=ret)

View File

@ -353,7 +353,9 @@ class FlowListBox(urwid.ListBox):
def keypress(self, size, key):
key = common.shortcuts(key)
if key == "A":
if key == ":":
signals.status_prompt_command.send()
elif key == "A":
for f in self.master.view:
if f.intercepted:
f.resume()

View File

@ -288,7 +288,7 @@ class ConsoleMaster(master.Master):
screen = self.ui,
handle_mouse = self.options.console_mouse,
)
self.ab = statusbar.ActionBar()
self.ab = statusbar.ActionBar(self)
self.loop.set_alarm_in(0.01, self.ticker)
self.loop.set_alarm_in(

View File

@ -24,6 +24,9 @@ status_prompt_path = blinker.Signal()
# Prompt for a single keystroke
status_prompt_onekey = blinker.Signal()
# Prompt for a command
status_prompt_command = blinker.Signal()
# Call a callback in N seconds
call_in = blinker.Signal()

View File

@ -5,6 +5,7 @@ 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 command
import mitmproxy.tools.console.master # noqa
@ -32,13 +33,15 @@ class PromptStub:
class ActionBar(urwid.WidgetWrap):
def __init__(self):
def __init__(self, master):
urwid.WidgetWrap.__init__(self, None)
self.master = master
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 = ""
@ -66,6 +69,11 @@ class ActionBar(urwid.WidgetWrap):
self._w = urwid.Edit(self.prep_prompt(prompt), text or "")
self.prompting = PromptStub(callback, args)
def sig_prompt_command(self, sender):
signals.focus.send(self, section="footer")
self._w = command.CommandEdit()
self.prompting = command.CommandExecutor(self.master)
def sig_path_prompt(self, sender, prompt, callback, args=()):
signals.focus.send(self, section="footer")
self._w = pathedit.PathEdit(