commands: add a Cmd argument type

This represents a command passed as an argument. Also split arguments from
command values themselves, making the command help for meta-commands much
clearer.
This commit is contained in:
Aldo Cortesi 2017-12-14 15:43:15 +13:00 committed by Aldo Cortesi
parent 04e19f9171
commit e64d5c6bb9
8 changed files with 35 additions and 20 deletions

View File

@ -37,7 +37,7 @@ class ClientPlayback:
ctx.master.addons.trigger("update", [])
@command.command("replay.client.file")
def load_file(self, path: str) -> None:
def load_file(self, path: command.Path) -> None:
try:
flows = io.read_flows_from_paths([path])
except exceptions.FlowReadException as e:

View File

@ -31,7 +31,7 @@ class ServerPlayback:
ctx.master.addons.trigger("update", [])
@command.command("replay.server.file")
def load_file(self, path: str) -> None:
def load_file(self, path: command.Path) -> None:
try:
flows = io.read_flows_from_paths([path])
except exceptions.FlowReadException as e:

View File

@ -23,6 +23,10 @@ class Path(str):
pass
class Cmd(str):
pass
def typename(t: type, ret: bool) -> str:
"""
Translates a type to an explanatory string. If ret is True, we're
@ -172,6 +176,8 @@ def parsearg(manager: CommandManager, spec: str, argtype: type) -> typing.Any:
"Invalid choice: see %s for options" % cmd
)
return spec
if argtype in (Path, Cmd):
return spec
elif issubclass(argtype, str):
return spec
elif argtype == bool:

View File

@ -3,18 +3,18 @@ from urwid.text_layout import calc_coords
class CommandBuffer():
def __init__(self, start: str = ""):
def __init__(self, start: str = "") -> None:
self.buf = start
# This is the logical cursor position - the display cursor is one
# character further on. Cursor is always within the range [0:len(buffer)].
self._cursor = len(self.buf)
@property
def cursor(self):
def cursor(self) -> int:
return self._cursor
@cursor.setter
def cursor(self, x):
def cursor(self, x) -> None:
if x < 0:
self._cursor = 0
elif x > len(self.buf):
@ -25,19 +25,19 @@ class CommandBuffer():
def render(self):
return self.buf
def left(self):
def left(self) -> None:
self.cursor = self.cursor - 1
def right(self):
def right(self) -> None:
self.cursor = self.cursor + 1
def backspace(self):
def backspace(self) -> None:
if self.cursor == 0:
return
self.buf = self.buf[:self.cursor - 1] + self.buf[self.cursor:]
self.cursor = self.cursor - 1
def insert(self, k: str):
def insert(self, k: str) -> None:
"""
Inserts text at the cursor.
"""
@ -48,7 +48,7 @@ class CommandBuffer():
class CommandEdit(urwid.WidgetWrap):
leader = ": "
def __init__(self, text):
def __init__(self, text) -> None:
self.cbuf = CommandBuffer(text)
self._w = urwid.Text(self.leader)
self.update()
@ -82,4 +82,3 @@ class CommandEdit(urwid.WidgetWrap):
def get_value(self):
return self.cbuf.buf

View File

@ -224,7 +224,11 @@ class ConsoleAddon:
@command.command("console.choose")
def console_choose(
self, prompt: str, choices: typing.Sequence[str], *cmd: str
self,
prompt: str,
choices: typing.Sequence[str],
cmd: command.Cmd,
*args: str,
) -> None:
"""
Prompt the user to choose from a specified list of strings, then
@ -233,7 +237,7 @@ class ConsoleAddon:
"""
def callback(opt):
# We're now outside of the call context...
repl = " ".join(cmd)
repl = cmd + " " + " ".join(args)
repl = repl.replace("{choice}", opt)
try:
self.master.commands.call(repl)
@ -246,7 +250,7 @@ class ConsoleAddon:
@command.command("console.choose.cmd")
def console_choose_cmd(
self, prompt: str, choicecmd: str, *cmd: str
self, prompt: str, choicecmd: command.Cmd, *cmd: str
) -> None:
"""
Prompt the user to choose from a list of strings returned by a
@ -492,14 +496,20 @@ class ConsoleAddon:
return list(sorted(keymap.Contexts))
@command.command("console.key.bind")
def key_bind(self, contexts: typing.Sequence[str], key: str, *command: str) -> None:
def key_bind(
self,
contexts: typing.Sequence[str],
key: str,
cmd: command.Cmd,
*args: str,
) -> None:
"""
Bind a shortcut key.
"""
try:
self.master.keymap.add(
key,
" ".join(command),
cmd + " " + " ".join(args),
contexts,
""
)

View File

@ -100,6 +100,7 @@ def test_typename():
assert command.typename(command.Choice("foo"), False) == "choice"
assert command.typename(command.Path, False) == "path"
assert command.typename(command.Cmd, False) == "cmd"
class DummyConsole:
@ -162,6 +163,9 @@ def test_parsearg():
assert command.parsearg(
tctx.master.commands, "foo", command.Path
) == "foo"
assert command.parsearg(
tctx.master.commands, "foo", command.Cmd
) == "foo"
class TDec:

View File

@ -32,6 +32,3 @@ class TestCommandBuffer:
cb.insert("x")
assert cb.buf == output[0]
assert cb.cursor == output[1]