mirror of
https://github.com/evennia/evennia.git
synced 2025-10-29 19:35:56 +00:00
822 lines
23 KiB
Python
822 lines
23 KiB
Python
"""
|
|
Batch processors
|
|
|
|
These commands implements the 'batch-command' and 'batch-code'
|
|
processors, using the functionality in evennia.utils.batchprocessors.
|
|
They allow for offline world-building.
|
|
|
|
Batch-command is the simpler system. This reads a file (*.ev)
|
|
containing a list of in-game commands and executes them in sequence as
|
|
if they had been entered in the game (including permission checks
|
|
etc).
|
|
|
|
Batch-code is a full-fledged python code interpreter that reads blocks
|
|
of python code (*.py) and executes them in sequence. This allows for
|
|
much more power than Batch-command, but requires knowing Python and
|
|
the Evennia API. It is also a severe security risk and should
|
|
therefore always be limited to superusers only.
|
|
|
|
"""
|
|
import re
|
|
|
|
from django.conf import settings
|
|
|
|
from evennia.commands.cmdset import CmdSet
|
|
from evennia.utils import logger, utils
|
|
from evennia.utils.batchprocessors import BATCHCMD, BATCHCODE
|
|
|
|
_RE_COMMENT = re.compile(r"^#.*?$", re.MULTILINE + re.DOTALL)
|
|
_RE_CODE_START = re.compile(r"^# batchcode code:", re.MULTILINE)
|
|
_COMMAND_DEFAULT_CLASS = utils.class_from_module(settings.COMMAND_DEFAULT_CLASS)
|
|
|
|
# limit symbols for API inclusion
|
|
__all__ = ("CmdBatchCommands", "CmdBatchCode")
|
|
|
|
_HEADER_WIDTH = 70
|
|
_UTF8_ERROR = """
|
|
|rDecode error in '%s'.|n
|
|
|
|
This file contains non-ascii character(s). This is common if you
|
|
wrote some input in a language that has more letters and special
|
|
symbols than English; such as accents or umlauts. This is usually
|
|
fine and fully supported! But for Evennia to know how to decode such
|
|
characters in a universal way, the batchfile must be saved with the
|
|
international 'UTF-8' encoding. This file is not.
|
|
|
|
Please re-save the batchfile with the UTF-8 encoding (refer to the
|
|
documentation of your text editor on how to do this, or switch to a
|
|
better featured one) and try again.
|
|
|
|
Error reported was: '%s'
|
|
"""
|
|
|
|
|
|
# -------------------------------------------------------------
|
|
# Helper functions
|
|
# -------------------------------------------------------------
|
|
|
|
|
|
def format_header(caller, entry):
|
|
"""
|
|
Formats a header
|
|
"""
|
|
width = _HEADER_WIDTH - 10
|
|
# strip all comments for the header
|
|
if caller.ndb.batch_batchmode != "batch_commands":
|
|
# only do cleanup for batchcode
|
|
entry = _RE_CODE_START.split(entry, 1)[1]
|
|
entry = _RE_COMMENT.sub("", entry).strip()
|
|
header = utils.crop(entry, width=width)
|
|
ptr = caller.ndb.batch_stackptr + 1
|
|
stacklen = len(caller.ndb.batch_stack)
|
|
header = "|w%02i/%02i|G: %s|n" % (ptr, stacklen, header)
|
|
# add extra space to the side for padding.
|
|
header = "%s%s" % (header, " " * (width - len(header)))
|
|
header = header.replace("\n", "\\n")
|
|
|
|
return header
|
|
|
|
|
|
def format_code(entry):
|
|
"""
|
|
Formats the viewing of code and errors
|
|
"""
|
|
code = ""
|
|
for line in entry.split("\n"):
|
|
code += "\n|G>>>|n %s" % line
|
|
return code.strip()
|
|
|
|
|
|
def batch_cmd_exec(caller):
|
|
"""
|
|
Helper function for executing a single batch-command entry
|
|
"""
|
|
ptr = caller.ndb.batch_stackptr
|
|
stack = caller.ndb.batch_stack
|
|
command = stack[ptr]
|
|
caller.msg(format_header(caller, command))
|
|
try:
|
|
caller.execute_cmd(command)
|
|
except Exception:
|
|
logger.log_trace()
|
|
return False
|
|
return True
|
|
|
|
|
|
def batch_code_exec(caller):
|
|
"""
|
|
Helper function for executing a single batch-code entry
|
|
"""
|
|
ptr = caller.ndb.batch_stackptr
|
|
stack = caller.ndb.batch_stack
|
|
debug = caller.ndb.batch_debug
|
|
code = stack[ptr]
|
|
|
|
caller.msg(format_header(caller, code))
|
|
err = BATCHCODE.code_exec(code, extra_environ={"caller": caller}, debug=debug)
|
|
if err:
|
|
caller.msg(format_code(err))
|
|
return False
|
|
return True
|
|
|
|
|
|
def step_pointer(caller, step=1):
|
|
"""
|
|
Step in stack, returning the item located.
|
|
|
|
stackptr - current position in stack
|
|
stack - the stack of units
|
|
step - how many steps to move from stackptr
|
|
"""
|
|
ptr = caller.ndb.batch_stackptr
|
|
stack = caller.ndb.batch_stack
|
|
nstack = len(stack)
|
|
if ptr + step <= 0:
|
|
caller.msg("|RBeginning of batch file.")
|
|
if ptr + step >= nstack:
|
|
caller.msg("|REnd of batch file.")
|
|
caller.ndb.batch_stackptr = max(0, min(nstack - 1, ptr + step))
|
|
|
|
|
|
def show_curr(caller, showall=False):
|
|
"""
|
|
Show the current position in stack
|
|
"""
|
|
stackptr = caller.ndb.batch_stackptr
|
|
stack = caller.ndb.batch_stack
|
|
|
|
if stackptr >= len(stack):
|
|
caller.ndb.batch_stackptr = len(stack) - 1
|
|
show_curr(caller, showall)
|
|
return
|
|
|
|
entry = stack[stackptr]
|
|
|
|
string = format_header(caller, entry)
|
|
codeall = entry.strip()
|
|
string += "|G(hh for help)"
|
|
if showall:
|
|
for line in codeall.split("\n"):
|
|
string += "\n|G||n %s" % line
|
|
caller.msg(string)
|
|
|
|
|
|
def purge_processor(caller):
|
|
"""
|
|
This purges all effects running
|
|
on the caller.
|
|
"""
|
|
try:
|
|
del caller.ndb.batch_stack
|
|
del caller.ndb.batch_stackptr
|
|
del caller.ndb.batch_pythonpath
|
|
del caller.ndb.batch_batchmode
|
|
except Exception:
|
|
# something might have already been erased; it's not critical
|
|
pass
|
|
# clear everything back to the state before the batch call
|
|
if caller.ndb.batch_cmdset_backup:
|
|
caller.cmdset.cmdset_stack = caller.ndb.batch_cmdset_backup
|
|
caller.cmdset.update()
|
|
del caller.ndb.batch_cmdset_backup
|
|
else:
|
|
# something went wrong. Purge cmdset except default
|
|
caller.cmdset.clear()
|
|
|
|
# caller.scripts.validate() # this will purge interactive mode
|
|
|
|
|
|
# -------------------------------------------------------------
|
|
# main access commands
|
|
# -------------------------------------------------------------
|
|
|
|
|
|
class CmdBatchCommands(_COMMAND_DEFAULT_CLASS):
|
|
"""
|
|
build from batch-command file
|
|
|
|
Usage:
|
|
batchcommands[/interactive] <python.path.to.file>
|
|
|
|
Switch:
|
|
interactive - this mode will offer more control when
|
|
executing the batch file, like stepping,
|
|
skipping, reloading etc.
|
|
|
|
Runs batches of commands from a batch-cmd text file (*.ev).
|
|
|
|
"""
|
|
|
|
key = "batchcommands"
|
|
aliases = ["batchcommand", "batchcmd"]
|
|
switch_options = ("interactive",)
|
|
locks = "cmd:perm(batchcommands) or perm(Developer)"
|
|
help_category = "Building"
|
|
|
|
def func(self):
|
|
"""Starts the processor."""
|
|
|
|
caller = self.caller
|
|
|
|
args = self.args
|
|
if not args:
|
|
caller.msg("Usage: batchcommands[/interactive] <path.to.file>")
|
|
return
|
|
python_path = self.args
|
|
|
|
# parse indata file
|
|
|
|
try:
|
|
commands = BATCHCMD.parse_file(python_path)
|
|
except UnicodeDecodeError as err:
|
|
caller.msg(_UTF8_ERROR % (python_path, err))
|
|
return
|
|
except IOError as err:
|
|
if err:
|
|
err = "{}\n".format(str(err))
|
|
else:
|
|
err = ""
|
|
string = (
|
|
"%s'%s' could not load. You have to supply python paths "
|
|
"from one of the defined batch-file directories\n (%s)."
|
|
)
|
|
caller.msg(string % (err, python_path, ", ".join(settings.BASE_BATCHPROCESS_PATHS)))
|
|
return
|
|
if not commands:
|
|
caller.msg("File %s seems empty of valid commands." % python_path)
|
|
return
|
|
|
|
switches = self.switches
|
|
|
|
# Store work data in cache
|
|
caller.ndb.batch_stack = commands
|
|
caller.ndb.batch_stackptr = 0
|
|
caller.ndb.batch_pythonpath = python_path
|
|
caller.ndb.batch_batchmode = "batch_commands"
|
|
# we use list() here to create a new copy of the cmdset stack
|
|
caller.ndb.batch_cmdset_backup = list(caller.cmdset.cmdset_stack)
|
|
caller.cmdset.add(BatchSafeCmdSet)
|
|
|
|
if "inter" in switches or "interactive" in switches:
|
|
# Allow more control over how batch file is executed
|
|
|
|
# Set interactive state directly
|
|
caller.cmdset.add(BatchInteractiveCmdSet)
|
|
|
|
caller.msg("\nBatch-command processor - Interactive mode for %s ..." % python_path)
|
|
show_curr(caller)
|
|
else:
|
|
caller.msg(
|
|
"Running Batch-command processor - Automatic mode "
|
|
"for %s (this might take some time) ..." % python_path
|
|
)
|
|
|
|
# run in-process (might block)
|
|
for _ in range(len(commands)):
|
|
# loop through the batch file
|
|
if not batch_cmd_exec(caller):
|
|
return
|
|
step_pointer(caller, 1)
|
|
# clean out the safety cmdset and clean out all other
|
|
# temporary attrs.
|
|
string = " Batchfile '%s' applied." % python_path
|
|
caller.msg("|G%s" % string)
|
|
purge_processor(caller)
|
|
|
|
|
|
class CmdBatchCode(_COMMAND_DEFAULT_CLASS):
|
|
"""
|
|
build from batch-code file
|
|
|
|
Usage:
|
|
batchcode[/interactive] <python path to file>
|
|
|
|
Switch:
|
|
interactive - this mode will offer more control when
|
|
executing the batch file, like stepping,
|
|
skipping, reloading etc.
|
|
debug - auto-delete all objects that has been marked as
|
|
deletable in the script file (see example files for
|
|
syntax). This is useful so as to to not leave multiple
|
|
object copies behind when testing out the script.
|
|
|
|
Runs batches of commands from a batch-code text file (*.py).
|
|
|
|
"""
|
|
|
|
key = "batchcode"
|
|
aliases = ["batchcodes"]
|
|
switch_options = ("interactive", "debug")
|
|
locks = "cmd:superuser()"
|
|
help_category = "Building"
|
|
|
|
def func(self):
|
|
"""Starts the processor."""
|
|
|
|
caller = self.caller
|
|
|
|
args = self.args
|
|
if not args:
|
|
caller.msg("Usage: batchcode[/interactive/debug] <path.to.file>")
|
|
return
|
|
python_path = self.args
|
|
debug = "debug" in self.switches
|
|
|
|
# parse indata file
|
|
try:
|
|
codes = BATCHCODE.parse_file(python_path)
|
|
except UnicodeDecodeError as err:
|
|
caller.msg(_UTF8_ERROR % (python_path, err))
|
|
return
|
|
except IOError as err:
|
|
if err:
|
|
err = "{}\n".format(str(err))
|
|
else:
|
|
err = ""
|
|
string = (
|
|
"%s'%s' could not load. You have to supply python paths "
|
|
"from one of the defined batch-file directories\n (%s)."
|
|
)
|
|
caller.msg(string % (err, python_path, ", ".join(settings.BASE_BATCHPROCESS_PATHS)))
|
|
return
|
|
if not codes:
|
|
caller.msg("File %s seems empty of functional code." % python_path)
|
|
return
|
|
|
|
switches = self.switches
|
|
|
|
# Store work data in cache
|
|
caller.ndb.batch_stack = codes
|
|
caller.ndb.batch_stackptr = 0
|
|
caller.ndb.batch_pythonpath = python_path
|
|
caller.ndb.batch_batchmode = "batch_code"
|
|
caller.ndb.batch_debug = debug
|
|
# we use list() here to create a new copy of cmdset_stack
|
|
caller.ndb.batch_cmdset_backup = list(caller.cmdset.cmdset_stack)
|
|
caller.cmdset.add(BatchSafeCmdSet)
|
|
|
|
if "inter" in switches or "interactive" in switches:
|
|
# Allow more control over how batch file is executed
|
|
|
|
# Set interactive state directly
|
|
caller.cmdset.add(BatchInteractiveCmdSet)
|
|
|
|
caller.msg("\nBatch-code processor - Interactive mode for %s ..." % python_path)
|
|
show_curr(caller)
|
|
else:
|
|
caller.msg("Running Batch-code processor - Automatic mode for %s ..." % python_path)
|
|
|
|
for _ in range(len(codes)):
|
|
# loop through the batch file
|
|
if not batch_code_exec(caller):
|
|
return
|
|
step_pointer(caller, 1)
|
|
# clean out the safety cmdset and clean out all other
|
|
# temporary attrs.
|
|
string = " Batchfile '%s' applied." % python_path
|
|
caller.msg("|G%s" % string)
|
|
purge_processor(caller)
|
|
|
|
|
|
# -------------------------------------------------------------
|
|
# State-commands for the interactive batch processor modes
|
|
# (these are the same for both processors)
|
|
# -------------------------------------------------------------
|
|
|
|
|
|
class CmdStateAbort(_COMMAND_DEFAULT_CLASS):
|
|
"""
|
|
abort
|
|
|
|
This is a safety feature. It force-ejects us out of the processor and to
|
|
the default cmdset, regardless of what current cmdset the processor might
|
|
have put us in (e.g. when testing buggy scripts etc).
|
|
"""
|
|
|
|
key = "abort"
|
|
help_category = "BatchProcess"
|
|
locks = "cmd:perm(batchcommands)"
|
|
|
|
def func(self):
|
|
"""Exit back to default."""
|
|
purge_processor(self.caller)
|
|
self.caller.msg("Exited processor and reset out active cmdset back to the default one.")
|
|
|
|
|
|
class CmdStateLL(_COMMAND_DEFAULT_CLASS):
|
|
"""
|
|
ll
|
|
|
|
Look at the full source for the current
|
|
command definition.
|
|
"""
|
|
|
|
key = "ll"
|
|
help_category = "BatchProcess"
|
|
locks = "cmd:perm(batchcommands)"
|
|
|
|
def func(self):
|
|
show_curr(self.caller, showall=True)
|
|
|
|
|
|
class CmdStatePP(_COMMAND_DEFAULT_CLASS):
|
|
"""
|
|
pp
|
|
|
|
Process the currently shown command definition.
|
|
"""
|
|
|
|
key = "pp"
|
|
help_category = "BatchProcess"
|
|
locks = "cmd:perm(batchcommands)"
|
|
|
|
def func(self):
|
|
"""
|
|
This checks which type of processor we are running.
|
|
"""
|
|
caller = self.caller
|
|
if caller.ndb.batch_batchmode == "batch_code":
|
|
batch_code_exec(caller)
|
|
else:
|
|
batch_cmd_exec(caller)
|
|
|
|
|
|
class CmdStateRR(_COMMAND_DEFAULT_CLASS):
|
|
"""
|
|
rr
|
|
|
|
Reload the batch file, keeping the current
|
|
position in it.
|
|
"""
|
|
|
|
key = "rr"
|
|
help_category = "BatchProcess"
|
|
locks = "cmd:perm(batchcommands)"
|
|
|
|
def func(self):
|
|
caller = self.caller
|
|
if caller.ndb.batch_batchmode == "batch_code":
|
|
new_data = BATCHCODE.parse_file(caller.ndb.batch_pythonpath)
|
|
else:
|
|
new_data = BATCHCMD.parse_file(caller.ndb.batch_pythonpath)
|
|
caller.ndb.batch_stack = new_data
|
|
caller.msg(format_code("File reloaded. Staying on same command."))
|
|
show_curr(caller)
|
|
|
|
|
|
class CmdStateRRR(_COMMAND_DEFAULT_CLASS):
|
|
"""
|
|
rrr
|
|
|
|
Reload the batch file, starting over
|
|
from the beginning.
|
|
"""
|
|
|
|
key = "rrr"
|
|
help_category = "BatchProcess"
|
|
locks = "cmd:perm(batchcommands)"
|
|
|
|
def func(self):
|
|
caller = self.caller
|
|
if caller.ndb.batch_batchmode == "batch_code":
|
|
BATCHCODE.parse_file(caller.ndb.batch_pythonpath)
|
|
else:
|
|
BATCHCMD.parse_file(caller.ndb.batch_pythonpath)
|
|
caller.ndb.batch_stackptr = 0
|
|
caller.msg(format_code("File reloaded. Restarting from top."))
|
|
show_curr(caller)
|
|
|
|
|
|
class CmdStateNN(_COMMAND_DEFAULT_CLASS):
|
|
"""
|
|
nn
|
|
|
|
Go to next command. No commands are executed.
|
|
"""
|
|
|
|
key = "nn"
|
|
help_category = "BatchProcess"
|
|
locks = "cmd:perm(batchcommands)"
|
|
|
|
def func(self):
|
|
caller = self.caller
|
|
arg = self.args
|
|
if arg and arg.isdigit():
|
|
step = int(self.args)
|
|
else:
|
|
step = 1
|
|
step_pointer(caller, step)
|
|
show_curr(caller)
|
|
|
|
|
|
class CmdStateNL(_COMMAND_DEFAULT_CLASS):
|
|
"""
|
|
nl
|
|
|
|
Go to next command, viewing its full source.
|
|
No commands are executed.
|
|
"""
|
|
|
|
key = "nl"
|
|
help_category = "BatchProcess"
|
|
locks = "cmd:perm(batchcommands)"
|
|
|
|
def func(self):
|
|
caller = self.caller
|
|
arg = self.args
|
|
if arg and arg.isdigit():
|
|
step = int(self.args)
|
|
else:
|
|
step = 1
|
|
step_pointer(caller, step)
|
|
show_curr(caller, showall=True)
|
|
|
|
|
|
class CmdStateBB(_COMMAND_DEFAULT_CLASS):
|
|
"""
|
|
bb
|
|
|
|
Backwards to previous command. No commands
|
|
are executed.
|
|
"""
|
|
|
|
key = "bb"
|
|
help_category = "BatchProcess"
|
|
locks = "cmd:perm(batchcommands)"
|
|
|
|
def func(self):
|
|
caller = self.caller
|
|
arg = self.args
|
|
if arg and arg.isdigit():
|
|
step = -int(self.args)
|
|
else:
|
|
step = -1
|
|
step_pointer(caller, step)
|
|
show_curr(caller)
|
|
|
|
|
|
class CmdStateBL(_COMMAND_DEFAULT_CLASS):
|
|
"""
|
|
bl
|
|
|
|
Backwards to previous command, viewing its full
|
|
source. No commands are executed.
|
|
"""
|
|
|
|
key = "bl"
|
|
help_category = "BatchProcess"
|
|
locks = "cmd:perm(batchcommands)"
|
|
|
|
def func(self):
|
|
caller = self.caller
|
|
arg = self.args
|
|
if arg and arg.isdigit():
|
|
step = -int(self.args)
|
|
else:
|
|
step = -1
|
|
step_pointer(caller, step)
|
|
show_curr(caller, showall=True)
|
|
|
|
|
|
class CmdStateSS(_COMMAND_DEFAULT_CLASS):
|
|
"""
|
|
ss [steps]
|
|
|
|
Process current command, then step to the next
|
|
one. If steps is given,
|
|
process this many commands.
|
|
"""
|
|
|
|
key = "ss"
|
|
help_category = "BatchProcess"
|
|
locks = "cmd:perm(batchcommands)"
|
|
|
|
def func(self):
|
|
caller = self.caller
|
|
arg = self.args
|
|
if arg and arg.isdigit():
|
|
step = int(self.args)
|
|
else:
|
|
step = 1
|
|
|
|
for _ in range(step):
|
|
if caller.ndb.batch_batchmode == "batch_code":
|
|
batch_code_exec(caller)
|
|
else:
|
|
batch_cmd_exec(caller)
|
|
step_pointer(caller, 1)
|
|
show_curr(caller)
|
|
|
|
|
|
class CmdStateSL(_COMMAND_DEFAULT_CLASS):
|
|
"""
|
|
sl [steps]
|
|
|
|
Process current command, then step to the next
|
|
one, viewing its full source. If steps is given,
|
|
process this many commands.
|
|
"""
|
|
|
|
key = "sl"
|
|
help_category = "BatchProcess"
|
|
locks = "cmd:perm(batchcommands)"
|
|
|
|
def func(self):
|
|
caller = self.caller
|
|
arg = self.args
|
|
if arg and arg.isdigit():
|
|
step = int(self.args)
|
|
else:
|
|
step = 1
|
|
|
|
for _ in range(step):
|
|
if caller.ndb.batch_batchmode == "batch_code":
|
|
batch_code_exec(caller)
|
|
else:
|
|
batch_cmd_exec(caller)
|
|
step_pointer(caller, 1)
|
|
show_curr(caller)
|
|
|
|
|
|
class CmdStateCC(_COMMAND_DEFAULT_CLASS):
|
|
"""
|
|
cc
|
|
|
|
Continue to process all remaining
|
|
commands.
|
|
"""
|
|
|
|
key = "cc"
|
|
help_category = "BatchProcess"
|
|
locks = "cmd:perm(batchcommands)"
|
|
|
|
def func(self):
|
|
caller = self.caller
|
|
nstack = len(caller.ndb.batch_stack)
|
|
ptr = caller.ndb.batch_stackptr
|
|
step = nstack - ptr
|
|
|
|
for _ in range(step):
|
|
if caller.ndb.batch_batchmode == "batch_code":
|
|
batch_code_exec(caller)
|
|
else:
|
|
batch_cmd_exec(caller)
|
|
step_pointer(caller, 1)
|
|
show_curr(caller)
|
|
|
|
purge_processor(self)
|
|
caller.msg(format_code("Finished processing batch file."))
|
|
|
|
|
|
class CmdStateJJ(_COMMAND_DEFAULT_CLASS):
|
|
"""
|
|
jj <command number>
|
|
|
|
Jump to specific command number
|
|
"""
|
|
|
|
key = "jj"
|
|
help_category = "BatchProcess"
|
|
locks = "cmd:perm(batchcommands)"
|
|
|
|
def func(self):
|
|
caller = self.caller
|
|
arg = self.args
|
|
if arg and arg.isdigit():
|
|
number = int(self.args) - 1
|
|
else:
|
|
caller.msg(format_code("You must give a number index."))
|
|
return
|
|
ptr = caller.ndb.batch_stackptr
|
|
step = number - ptr
|
|
step_pointer(caller, step)
|
|
show_curr(caller)
|
|
|
|
|
|
class CmdStateJL(_COMMAND_DEFAULT_CLASS):
|
|
"""
|
|
jl <command number>
|
|
|
|
Jump to specific command number and view its full source.
|
|
"""
|
|
|
|
key = "jl"
|
|
help_category = "BatchProcess"
|
|
locks = "cmd:perm(batchcommands)"
|
|
|
|
def func(self):
|
|
caller = self.caller
|
|
arg = self.args
|
|
if arg and arg.isdigit():
|
|
number = int(self.args) - 1
|
|
else:
|
|
caller.msg(format_code("You must give a number index."))
|
|
return
|
|
ptr = caller.ndb.batch_stackptr
|
|
step = number - ptr
|
|
step_pointer(caller, step)
|
|
show_curr(caller, showall=True)
|
|
|
|
|
|
class CmdStateQQ(_COMMAND_DEFAULT_CLASS):
|
|
"""
|
|
qq
|
|
|
|
Quit the batchprocessor.
|
|
"""
|
|
|
|
key = "qq"
|
|
help_category = "BatchProcess"
|
|
locks = "cmd:perm(batchcommands)"
|
|
|
|
def func(self):
|
|
purge_processor(self.caller)
|
|
self.caller.msg("Aborted interactive batch mode.")
|
|
|
|
|
|
class CmdStateHH(_COMMAND_DEFAULT_CLASS):
|
|
"""Help command"""
|
|
|
|
key = "hh"
|
|
help_category = "BatchProcess"
|
|
locks = "cmd:perm(batchcommands)"
|
|
|
|
def func(self):
|
|
string = """
|
|
Interactive batch processing commands:
|
|
|
|
nn [steps] - next command (no processing)
|
|
nl [steps] - next & look
|
|
bb [steps] - back to previous command (no processing)
|
|
bl [steps] - back & look
|
|
jj <N> - jump to command nr N (no processing)
|
|
jl <N> - jump & look
|
|
pp - process currently shown command (no step)
|
|
ss [steps] - process & step
|
|
sl [steps] - process & step & look
|
|
ll - look at full definition of current command
|
|
rr - reload batch file (stay on current)
|
|
rrr - reload batch file (start from first)
|
|
hh - this help list
|
|
|
|
cc - continue processing to end, then quit.
|
|
qq - quit (abort all remaining commands)
|
|
|
|
abort - this is a safety command that always is available
|
|
regardless of what cmdsets gets added to us during
|
|
batch-command processing. It immediately shuts down
|
|
the processor and returns us to the default cmdset.
|
|
"""
|
|
self.caller.msg(string)
|
|
|
|
|
|
# -------------------------------------------------------------
|
|
#
|
|
# Defining the cmdsets for the interactive batchprocessor
|
|
# mode (same for both processors)
|
|
#
|
|
# -------------------------------------------------------------
|
|
|
|
|
|
class BatchSafeCmdSet(CmdSet):
|
|
"""
|
|
The base cmdset for the batch processor.
|
|
This sets a 'safe' abort command that will
|
|
always be available to get out of everything.
|
|
"""
|
|
|
|
key = "Batch_default"
|
|
priority = 150 # override other cmdsets.
|
|
|
|
def at_cmdset_creation(self):
|
|
"""Init the cmdset"""
|
|
self.add(CmdStateAbort())
|
|
|
|
|
|
class BatchInteractiveCmdSet(CmdSet):
|
|
"""
|
|
The cmdset for the interactive batch processor mode.
|
|
"""
|
|
|
|
key = "Batch_interactive"
|
|
priority = 104
|
|
|
|
def at_cmdset_creation(self):
|
|
"""init the cmdset"""
|
|
self.add(CmdStateAbort())
|
|
self.add(CmdStateLL())
|
|
self.add(CmdStatePP())
|
|
self.add(CmdStateRR())
|
|
self.add(CmdStateRRR())
|
|
self.add(CmdStateNN())
|
|
self.add(CmdStateNL())
|
|
self.add(CmdStateBB())
|
|
self.add(CmdStateBL())
|
|
self.add(CmdStateSS())
|
|
self.add(CmdStateSL())
|
|
self.add(CmdStateCC())
|
|
self.add(CmdStateJJ())
|
|
self.add(CmdStateJL())
|
|
self.add(CmdStateQQ())
|
|
self.add(CmdStateHH())
|