More work on evmenu helper
This commit is contained in:
parent
b89d188c32
commit
84e26566ae
2 changed files with 73 additions and 61 deletions
|
|
@ -170,5 +170,4 @@ GOTO_CALLABLES = {
|
||||||
def testmenu(caller):
|
def testmenu(caller):
|
||||||
menutree = parse_menu_template(caller, MENU_TEMPLATE, GOTO_CALLABLES)
|
menutree = parse_menu_template(caller, MENU_TEMPLATE, GOTO_CALLABLES)
|
||||||
# we'll use a custom EvMenu child later
|
# we'll use a custom EvMenu child later
|
||||||
EvMenu(caller, menutree, auto_help=False)
|
EvMenu(caller, menutree)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -329,6 +329,19 @@ class EvMenuError(RuntimeError):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class EvMenuGotoAbortMessage(RuntimeError):
|
||||||
|
"""
|
||||||
|
This can be raised by a goto-callable to abort the goto flow. The message
|
||||||
|
stored with the executable will be sent to the caller who will remain on
|
||||||
|
the current node. This can be used to pass single-line returns without
|
||||||
|
re-running the entire node with text and options.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
raise EvMenuGotoMessage("That makes no sense.")
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
# -------------------------------------------------------------
|
# -------------------------------------------------------------
|
||||||
#
|
#
|
||||||
# Menu command and command set
|
# Menu command and command set
|
||||||
|
|
@ -795,6 +808,8 @@ class EvMenu:
|
||||||
|
|
||||||
def run_exec(self, nodename, raw_string, **kwargs):
|
def run_exec(self, nodename, raw_string, **kwargs):
|
||||||
"""
|
"""
|
||||||
|
NOTE: This is deprecated. Use `goto` directly instead.
|
||||||
|
|
||||||
Run a function or node as a callback (with the 'exec' option key).
|
Run a function or node as a callback (with the 'exec' option key).
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
|
|
@ -1100,24 +1115,29 @@ class EvMenu:
|
||||||
"""
|
"""
|
||||||
cmd = strip_ansi(raw_string.strip().lower())
|
cmd = strip_ansi(raw_string.strip().lower())
|
||||||
|
|
||||||
if self.options and cmd in self.options:
|
try:
|
||||||
# this will take precedence over the default commands
|
if self.options and cmd in self.options:
|
||||||
# below
|
# this will take precedence over the default commands
|
||||||
goto, goto_kwargs, execfunc, exec_kwargs = self.options[cmd]
|
# below
|
||||||
self.run_exec_then_goto(execfunc, goto, raw_string, exec_kwargs, goto_kwargs)
|
goto, goto_kwargs, execfunc, exec_kwargs = self.options[cmd]
|
||||||
elif self.auto_look and cmd in ("look", "l"):
|
self.run_exec_then_goto(execfunc, goto, raw_string, exec_kwargs, goto_kwargs)
|
||||||
self.display_nodetext()
|
elif self.auto_look and cmd in ("look", "l"):
|
||||||
elif self.auto_help and cmd in ("help", "h"):
|
self.display_nodetext()
|
||||||
self.display_helptext()
|
elif self.auto_help and cmd in ("help", "h"):
|
||||||
elif self.auto_quit and cmd in ("quit", "q", "exit"):
|
self.display_helptext()
|
||||||
self.close_menu()
|
elif self.auto_quit and cmd in ("quit", "q", "exit"):
|
||||||
elif self.debug_mode and cmd.startswith("menudebug"):
|
self.close_menu()
|
||||||
self.print_debug_info(cmd[9:].strip())
|
elif self.debug_mode and cmd.startswith("menudebug"):
|
||||||
elif self.default:
|
self.print_debug_info(cmd[9:].strip())
|
||||||
goto, goto_kwargs, execfunc, exec_kwargs = self.default
|
elif self.default:
|
||||||
self.run_exec_then_goto(execfunc, goto, raw_string, exec_kwargs, goto_kwargs)
|
goto, goto_kwargs, execfunc, exec_kwargs = self.default
|
||||||
else:
|
self.run_exec_then_goto(execfunc, goto, raw_string, exec_kwargs, goto_kwargs)
|
||||||
self.caller.msg(_HELP_NO_OPTION_MATCH, session=self._session)
|
else:
|
||||||
|
self.caller.msg(_HELP_NO_OPTION_MATCH, session=self._session)
|
||||||
|
except EvMenuGotoAbortMessage as err:
|
||||||
|
# custom interrupt from inside a goto callable - print the message and
|
||||||
|
# stay on the current node.
|
||||||
|
self.caller.msg(str(err), session=self._session)
|
||||||
|
|
||||||
def display_nodetext(self):
|
def display_nodetext(self):
|
||||||
self.caller.msg(self.nodetext, session=self._session)
|
self.caller.msg(self.nodetext, session=self._session)
|
||||||
|
|
@ -1603,20 +1623,37 @@ _OPTION_COMMENT_START = "#"
|
||||||
# Input/option/goto handler functions that allows for dynamically generated
|
# Input/option/goto handler functions that allows for dynamically generated
|
||||||
# nodes read from the menu template.
|
# nodes read from the menu template.
|
||||||
|
|
||||||
|
def _process_callable(caller, goto, goto_callables, raw_string,
|
||||||
|
current_nodename, kwargs):
|
||||||
|
match = _RE_CALLABLE.match(goto)
|
||||||
|
if match:
|
||||||
|
gotofunc = match.group("funcname")
|
||||||
|
gotokwargs = match.group("kwargs") or ""
|
||||||
|
if gotofunc in goto_callables:
|
||||||
|
for kwarg in gotokwargs.split(","):
|
||||||
|
if kwarg and "=" in kwarg:
|
||||||
|
key, value = [part.strip() for part in kwarg.split("=", 1)]
|
||||||
|
try:
|
||||||
|
key = literal_eval(key)
|
||||||
|
except ValueError:
|
||||||
|
pass
|
||||||
|
try:
|
||||||
|
value = literal_eval(value)
|
||||||
|
except ValueError:
|
||||||
|
pass
|
||||||
|
kwargs[key] = value
|
||||||
|
goto = goto_callables[gotofunc](caller, raw_string, **kwargs)
|
||||||
|
if goto is None:
|
||||||
|
return goto, {"generated_nodename": current_nodename}
|
||||||
|
return goto, {"generated_nodename": goto}
|
||||||
|
|
||||||
|
|
||||||
def _generated_goto_func(caller, raw_string, **kwargs):
|
def _generated_goto_func(caller, raw_string, **kwargs):
|
||||||
goto = kwargs["goto"]
|
goto = kwargs["goto"]
|
||||||
goto_callables = kwargs["goto_callables"]
|
goto_callables = kwargs["goto_callables"]
|
||||||
current_nodename = kwargs["current_nodename"]
|
current_nodename = kwargs["current_nodename"]
|
||||||
|
return _process_callable(caller, goto, goto_callables, raw_string,
|
||||||
if _RE_CALLABLE.match(goto):
|
current_nodename, kwargs)
|
||||||
gotofunc = goto.strip()[:-2]
|
|
||||||
if gotofunc in goto_callables:
|
|
||||||
goto = goto_callables[gotofunc](caller, raw_string, **kwargs)
|
|
||||||
if goto is None:
|
|
||||||
return goto, {"generated_nodename": current_nodename}
|
|
||||||
caller.msg(_HELP_NO_OPTION_MATCH)
|
|
||||||
return goto, {"generated_nodename": goto}
|
|
||||||
|
|
||||||
|
|
||||||
def _generated_input_goto_func(caller, raw_string, **kwargs):
|
def _generated_input_goto_func(caller, raw_string, **kwargs):
|
||||||
|
|
@ -1627,40 +1664,16 @@ def _generated_input_goto_func(caller, raw_string, **kwargs):
|
||||||
# start with glob patterns
|
# start with glob patterns
|
||||||
for pattern, goto in gotomap.items():
|
for pattern, goto in gotomap.items():
|
||||||
if fnmatch(raw_string.lower(), pattern):
|
if fnmatch(raw_string.lower(), pattern):
|
||||||
match = _RE_CALLABLE.match(goto)
|
return _process_callable(caller, goto, goto_callables, raw_string,
|
||||||
if match:
|
current_nodename, kwargs)
|
||||||
gotofunc = match.group("funcname")
|
|
||||||
gotokwargs = match.group("kwargs") or ""
|
|
||||||
if gotofunc in goto_callables:
|
|
||||||
for kwarg in gotokwargs.split(","):
|
|
||||||
if kwarg and "=" in kwarg:
|
|
||||||
key, value = [part.strip() for part in kwarg.split("=", 1)]
|
|
||||||
try:
|
|
||||||
key = literal_eval(key)
|
|
||||||
except ValueError:
|
|
||||||
pass
|
|
||||||
try:
|
|
||||||
value = literal_eval(value)
|
|
||||||
except ValueError:
|
|
||||||
pass
|
|
||||||
kwargs[key] = value
|
|
||||||
goto = goto_callables[gotofunc](caller, raw_string, **kwargs)
|
|
||||||
if goto is None:
|
|
||||||
return goto, {"generated_nodename": current_nodename}
|
|
||||||
return goto, {"generated_nodename": goto}
|
|
||||||
# no glob pattern match; try regex
|
# no glob pattern match; try regex
|
||||||
for pattern, goto in gotomap.items():
|
for pattern, goto in gotomap.items():
|
||||||
if pattern and re.match(pattern, raw_string.lower(), flags=re.I + re.M):
|
if pattern and re.match(pattern, raw_string.lower(), flags=re.I + re.M):
|
||||||
if _RE_CALLABLE.match(goto):
|
return _process_callable(caller, goto, goto_callables, raw_string,
|
||||||
gotofunc = goto.strip()[:-2]
|
current_nodename, kwargs)
|
||||||
if gotofunc in goto_callables:
|
# no match, show error
|
||||||
goto = goto_callables[gotofunc](caller, raw_string, **kwargs)
|
|
||||||
if goto is None:
|
raise EvMenuGotoAbortMessage(_HELP_NO_OPTION_MATCH)
|
||||||
return goto, {"generated_nodename": current_nodename}
|
|
||||||
return goto, {"generated_nodename": goto}
|
|
||||||
# no match, rerun current node
|
|
||||||
caller.msg(_HELP_NO_OPTION_MATCH)
|
|
||||||
return None, {"generated_nodename": current_nodename}
|
|
||||||
|
|
||||||
|
|
||||||
def _generated_node(caller, raw_string, **kwargs):
|
def _generated_node(caller, raw_string, **kwargs):
|
||||||
|
|
@ -1715,6 +1728,7 @@ def parse_menu_template(caller, menu_template, goto_callables=None):
|
||||||
# if we have a pattern, build the arguments for _default later
|
# if we have a pattern, build the arguments for _default later
|
||||||
pattern = main_key[len(_OPTION_INPUT_MARKER):].strip()
|
pattern = main_key[len(_OPTION_INPUT_MARKER):].strip()
|
||||||
inputparsemap[pattern] = goto
|
inputparsemap[pattern] = goto
|
||||||
|
print(f"main_key {main_key} {pattern} {goto}")
|
||||||
else:
|
else:
|
||||||
# a regular goto string/callable target
|
# a regular goto string/callable target
|
||||||
option = {
|
option = {
|
||||||
|
|
@ -1748,7 +1762,6 @@ def parse_menu_template(caller, menu_template, goto_callables=None):
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
print(f"nodename: {nodename}, options: {options}")
|
|
||||||
return options
|
return options
|
||||||
|
|
||||||
def _parse(caller, menu_template, goto_callables):
|
def _parse(caller, menu_template, goto_callables):
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue