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: 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): 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. Call the command with a set of arguments. At this point, all argumets are strings.
""" """
if len(self.paramtypes) != len(args): 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))] 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): def keypress(self, size, key):
key = common.shortcuts(key) key = common.shortcuts(key)
if key == "A": if key == ":":
signals.status_prompt_command.send()
elif key == "A":
for f in self.master.view: for f in self.master.view:
if f.intercepted: if f.intercepted:
f.resume() f.resume()

View File

@ -288,7 +288,7 @@ class ConsoleMaster(master.Master):
screen = self.ui, screen = self.ui,
handle_mouse = self.options.console_mouse, 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(0.01, self.ticker)
self.loop.set_alarm_in( self.loop.set_alarm_in(

View File

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

View File

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