Start add edit_node decorator (untested)
This commit is contained in:
parent
02b9654f1c
commit
ed3e57edd0
2 changed files with 331 additions and 106 deletions
|
|
@ -175,7 +175,7 @@ from evennia import Command, CmdSet
|
||||||
from evennia.utils import logger
|
from evennia.utils import logger
|
||||||
from evennia.utils.evtable import EvTable
|
from evennia.utils.evtable import EvTable
|
||||||
from evennia.utils.ansi import strip_ansi
|
from evennia.utils.ansi import strip_ansi
|
||||||
from evennia.utils.utils import mod_import, make_iter, pad, m_len
|
from evennia.utils.utils import mod_import, make_iter, pad, m_len, is_iter
|
||||||
from evennia.commands import cmdhandler
|
from evennia.commands import cmdhandler
|
||||||
|
|
||||||
# read from protocol NAWS later?
|
# read from protocol NAWS later?
|
||||||
|
|
@ -683,6 +683,43 @@ class EvMenu(object):
|
||||||
return ret, kwargs
|
return ret, kwargs
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
def extract_goto_exec(self, nodename, option_dict):
|
||||||
|
"""
|
||||||
|
Helper: Get callables and their eventual kwargs.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
nodename (str): The current node name (used for error reporting).
|
||||||
|
option_dict (dict): The seleted option's dict.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
goto (str, callable or None): The goto directive in the option.
|
||||||
|
goto_kwargs (dict): Kwargs for `goto` if the former is callable, otherwise empty.
|
||||||
|
execute (callable or None): Executable given by the `exec` directive.
|
||||||
|
exec_kwargs (dict): Kwargs for `execute` if it's callable, otherwise empty.
|
||||||
|
|
||||||
|
"""
|
||||||
|
goto_kwargs, exec_kwargs = {}, {}
|
||||||
|
goto, execute = option_dict.get("goto", None), option_dict.get("exec", None)
|
||||||
|
if goto and isinstance(goto, (tuple, list)):
|
||||||
|
if len(goto) > 1:
|
||||||
|
goto, goto_kwargs = goto[:2] # ignore any extra arguments
|
||||||
|
if not hasattr(goto_kwargs, "__getitem__"):
|
||||||
|
# not a dict-like structure
|
||||||
|
raise EvMenuError("EvMenu node {}: goto kwargs is not a dict: {}".format(
|
||||||
|
nodename, goto_kwargs))
|
||||||
|
else:
|
||||||
|
goto = goto[0]
|
||||||
|
if execute and isinstance(execute, (tuple, list)):
|
||||||
|
if len(execute) > 1:
|
||||||
|
execute, exec_kwargs = execute[:2] # ignore any extra arguments
|
||||||
|
if not hasattr(exec_kwargs, "__getitem__"):
|
||||||
|
# not a dict-like structure
|
||||||
|
raise EvMenuError("EvMenu node {}: exec kwargs is not a dict: {}".format(
|
||||||
|
nodename, goto_kwargs))
|
||||||
|
else:
|
||||||
|
execute = execute[0]
|
||||||
|
return goto, goto_kwargs, execute, exec_kwargs
|
||||||
|
|
||||||
def goto(self, nodename, raw_string, **kwargs):
|
def goto(self, nodename, raw_string, **kwargs):
|
||||||
"""
|
"""
|
||||||
Run a node by name, optionally dynamically generating that name first.
|
Run a node by name, optionally dynamically generating that name first.
|
||||||
|
|
@ -696,29 +733,6 @@ class EvMenu(object):
|
||||||
argument)
|
argument)
|
||||||
|
|
||||||
"""
|
"""
|
||||||
def _extract_goto_exec(option_dict):
|
|
||||||
"Helper: Get callables and their eventual kwargs"
|
|
||||||
goto_kwargs, exec_kwargs = {}, {}
|
|
||||||
goto, execute = option_dict.get("goto", None), option_dict.get("exec", None)
|
|
||||||
if goto and isinstance(goto, (tuple, list)):
|
|
||||||
if len(goto) > 1:
|
|
||||||
goto, goto_kwargs = goto[:2] # ignore any extra arguments
|
|
||||||
if not hasattr(goto_kwargs, "__getitem__"):
|
|
||||||
# not a dict-like structure
|
|
||||||
raise EvMenuError("EvMenu node {}: goto kwargs is not a dict: {}".format(
|
|
||||||
nodename, goto_kwargs))
|
|
||||||
else:
|
|
||||||
goto = goto[0]
|
|
||||||
if execute and isinstance(execute, (tuple, list)):
|
|
||||||
if len(execute) > 1:
|
|
||||||
execute, exec_kwargs = execute[:2] # ignore any extra arguments
|
|
||||||
if not hasattr(exec_kwargs, "__getitem__"):
|
|
||||||
# not a dict-like structure
|
|
||||||
raise EvMenuError("EvMenu node {}: exec kwargs is not a dict: {}".format(
|
|
||||||
nodename, goto_kwargs))
|
|
||||||
else:
|
|
||||||
execute = execute[0]
|
|
||||||
return goto, goto_kwargs, execute, exec_kwargs
|
|
||||||
|
|
||||||
if callable(nodename):
|
if callable(nodename):
|
||||||
# run the "goto" callable, if possible
|
# run the "goto" callable, if possible
|
||||||
|
|
@ -764,12 +778,12 @@ class EvMenu(object):
|
||||||
desc = dic.get("desc", dic.get("text", None))
|
desc = dic.get("desc", dic.get("text", None))
|
||||||
if "_default" in keys:
|
if "_default" in keys:
|
||||||
keys = [key for key in keys if key != "_default"]
|
keys = [key for key in keys if key != "_default"]
|
||||||
goto, goto_kwargs, execute, exec_kwargs = _extract_goto_exec(dic)
|
goto, goto_kwargs, execute, exec_kwargs = self.extract_goto_exec(nodename, dic)
|
||||||
self.default = (goto, goto_kwargs, execute, exec_kwargs)
|
self.default = (goto, goto_kwargs, execute, exec_kwargs)
|
||||||
else:
|
else:
|
||||||
# use the key (only) if set, otherwise use the running number
|
# use the key (only) if set, otherwise use the running number
|
||||||
keys = list(make_iter(dic.get("key", str(inum + 1).strip())))
|
keys = list(make_iter(dic.get("key", str(inum + 1).strip())))
|
||||||
goto, goto_kwargs, execute, exec_kwargs = _extract_goto_exec(dic)
|
goto, goto_kwargs, execute, exec_kwargs = self.extract_goto_exec(nodename, dic)
|
||||||
if keys:
|
if keys:
|
||||||
display_options.append((keys[0], desc))
|
display_options.append((keys[0], desc))
|
||||||
for key in keys:
|
for key in keys:
|
||||||
|
|
@ -975,11 +989,143 @@ class EvMenu(object):
|
||||||
|
|
||||||
# -----------------------------------------------------------
|
# -----------------------------------------------------------
|
||||||
#
|
#
|
||||||
# List node
|
# Edit node (decorator turning a node into an editing
|
||||||
|
# point for a given resource
|
||||||
#
|
#
|
||||||
# -----------------------------------------------------------
|
# -----------------------------------------------------------
|
||||||
|
|
||||||
def list_node(option_generator, examine_processor, goto_processor, pagesize=10):
|
def edit_node(edit_text, add_text, edit_callback, add_callback, get_choices=None):
|
||||||
|
"""
|
||||||
|
Decorator for turning an EvMenu node into an editing
|
||||||
|
page. Will add new options, prepending those options
|
||||||
|
added in the node.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
edit_text (str or callable): Will be used as text for the edit node. If
|
||||||
|
callable, it will be called as edittext(selection)
|
||||||
|
and should return the node text for the edit-node, probably listing
|
||||||
|
the current value of all editable propnames, if possible.
|
||||||
|
add_text (str) or callable: Gives text for node in add-mode. If a callable,
|
||||||
|
called as add_text() and should return the text for the node.
|
||||||
|
edit_callback (callable): Will be called as edit_callback(editable, raw_string)
|
||||||
|
and should return a boolean True/False if the setting of the property
|
||||||
|
succeeded or not. The value will always be a string and should be
|
||||||
|
converted as needed.
|
||||||
|
add_callback (callable): Will be called as add_callback(raw_string) and
|
||||||
|
should return a boolean True/False if the addition succeded.
|
||||||
|
|
||||||
|
get_choices (callable): Produce the available editable choices. If this
|
||||||
|
is not given, the `goto` callable must have been provided with the
|
||||||
|
kwarg `available_choices` by the decorated node.
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
def decorator(func):
|
||||||
|
|
||||||
|
def _setter_goto(caller, raw_string, **kwargs):
|
||||||
|
editable = kwargs.get("editable")
|
||||||
|
mode = kwargs.get("edit_node_mode")
|
||||||
|
try:
|
||||||
|
if mode == 'edit':
|
||||||
|
is_ok = edit_callback(editable, raw_string)
|
||||||
|
else:
|
||||||
|
is_ok = add_callback(raw_string)
|
||||||
|
except Exception:
|
||||||
|
logger.log_trace()
|
||||||
|
if not is_ok:
|
||||||
|
caller.msg("|rValue could not be set.")
|
||||||
|
return None
|
||||||
|
|
||||||
|
def _patch_goto(caller, raw_string, **kwargs):
|
||||||
|
|
||||||
|
# parse incoming string to figure out if there is a match to edit/add
|
||||||
|
match = re.search(r"(^[a-zA-Z]*)\s*([0-9]*)$", raw_string)
|
||||||
|
cmd, number = match.groups()
|
||||||
|
edit_mode = None
|
||||||
|
available_choices = None
|
||||||
|
selection = None
|
||||||
|
|
||||||
|
if get_choices:
|
||||||
|
available_choices = make_iter(get_choices(caller, raw_string, **kwargs))
|
||||||
|
if not available_choices:
|
||||||
|
available_choices = kwargs.get("available_choices", [])
|
||||||
|
|
||||||
|
if available_choices and cmd.startswith("e"):
|
||||||
|
try:
|
||||||
|
index = int(cmd) - 1
|
||||||
|
selection = available_choices[index]
|
||||||
|
edit_mode = 'edit'
|
||||||
|
except (IndexError, TypeError):
|
||||||
|
caller.msg("|rNot a valid 'edit' command.")
|
||||||
|
|
||||||
|
if cmd.startswith("a") and not number:
|
||||||
|
# add mode
|
||||||
|
edit_mode = "add"
|
||||||
|
|
||||||
|
if edit_mode:
|
||||||
|
# replace with edit text/options
|
||||||
|
text = edit_text(selection) if edit_mode == "edit" else add_text()
|
||||||
|
options = ({"key": "_default",
|
||||||
|
"goto": (_setter_goto,
|
||||||
|
{"selection": selection,
|
||||||
|
"edit_node_mode": edit_mode})})
|
||||||
|
return text, options
|
||||||
|
|
||||||
|
# no matches - pass through to the original decorated goto instruction
|
||||||
|
|
||||||
|
decorated_opt = kwargs.get("decorated_opt")
|
||||||
|
|
||||||
|
if decorated_opt:
|
||||||
|
# use EvMenu's parser to get the goto/goto-kwargs out of
|
||||||
|
# the decorated option structure
|
||||||
|
dec_goto, dec_goto_kwargs, _, _ = \
|
||||||
|
caller.ndb._menutree.extract_goto_exec("edit-node", decorated_opt)
|
||||||
|
|
||||||
|
if callable(dec_goto):
|
||||||
|
try:
|
||||||
|
return dec_goto(caller, raw_string,
|
||||||
|
**{dec_goto_kwargs if dec_goto_kwargs else {}})
|
||||||
|
except Exception:
|
||||||
|
caller.msg("|rThere was an error in the edit node.")
|
||||||
|
logger.log_trace()
|
||||||
|
return None
|
||||||
|
|
||||||
|
def _edit_node(caller, raw_string, **kwargs):
|
||||||
|
|
||||||
|
text, options = func(caller, raw_string, **kwargs)
|
||||||
|
|
||||||
|
if options:
|
||||||
|
# find eventual _default in options and patch it with a handler for
|
||||||
|
# catching editing
|
||||||
|
|
||||||
|
decorated_opt = None
|
||||||
|
iopt = 0
|
||||||
|
for iopt, optdict in enumerate(options):
|
||||||
|
if optdict.get('key') == "_default":
|
||||||
|
decorated_opt = optdict
|
||||||
|
break
|
||||||
|
|
||||||
|
if decorated_opt:
|
||||||
|
# inject our wrapper over the original goto instruction for the
|
||||||
|
# _default action (save the original)
|
||||||
|
options[iopt]["goto"] = (_patch_goto,
|
||||||
|
{"decorated_opt": decorated_opt})
|
||||||
|
|
||||||
|
return text, options
|
||||||
|
|
||||||
|
return _edit_node
|
||||||
|
return decorator
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# -----------------------------------------------------------
|
||||||
|
#
|
||||||
|
# List node (decorator turning a node into a list with
|
||||||
|
# look/edit/add functionality for the elements)
|
||||||
|
#
|
||||||
|
# -----------------------------------------------------------
|
||||||
|
|
||||||
|
def list_node(option_generator, select=None, examine=None, edit=None, add=None, pagesize=10):
|
||||||
"""
|
"""
|
||||||
Decorator for making an EvMenu node into a multi-page list node. Will add new options,
|
Decorator for making an EvMenu node into a multi-page list node. Will add new options,
|
||||||
prepending those options added in the node.
|
prepending those options added in the node.
|
||||||
|
|
@ -987,17 +1133,25 @@ def list_node(option_generator, examine_processor, goto_processor, pagesize=10):
|
||||||
Args:
|
Args:
|
||||||
option_generator (callable or list): A list of strings indicating the options, or a callable
|
option_generator (callable or list): A list of strings indicating the options, or a callable
|
||||||
that is called without any arguments to produce such a list.
|
that is called without any arguments to produce such a list.
|
||||||
examine_processor (callable, optional): Will be called with the caller and the chosen option
|
select (callable, option): Will be called as select(caller, menuchoice)
|
||||||
when examining said option. Should return a text string to display in the node.
|
|
||||||
goto_processor (callable, optional): Will be called as goto_processor(caller, menuchoice)
|
|
||||||
where menuchoice is the chosen option as a string. Should return the target node to
|
where menuchoice is the chosen option as a string. Should return the target node to
|
||||||
goto after this selection.
|
goto after this selection. Note that if this is not given, the decorated node must itself
|
||||||
|
provide a way to continue from the node!
|
||||||
|
examine (callable, optional): If given, allows for examining options in detail. Will
|
||||||
|
be called with examine(caller, menuchoice) and should return a text string to
|
||||||
|
display in-place in the node.
|
||||||
|
edit (callable, optional): If given, this callable will be called as edit(caller, menuchoice).
|
||||||
|
It should return the node-key to a node decorated with the `edit_node` decorator. The
|
||||||
|
menuchoice will automatically be stored on the menutree as `list_node_edit`.
|
||||||
|
add (tuple, optional): If given, this callable will be called as add(caller, menuchoice).
|
||||||
|
It should return the node-key to a node decorated with the `edit_node` decorator. The
|
||||||
|
menuchoice will automatically be stored on the menutree as `list_node_add`.
|
||||||
|
|
||||||
pagesize (int): How many options to show per page.
|
pagesize (int): How many options to show per page.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
@list_node(['foo', 'bar'], examine_processor, goto_processor)
|
@list_node(['foo', 'bar'], examine, select)
|
||||||
def node_index(caller):
|
def node_index(caller):
|
||||||
text = "describing the list"
|
text = "describing the list"
|
||||||
return text, []
|
return text, []
|
||||||
|
|
@ -1006,27 +1160,63 @@ def list_node(option_generator, examine_processor, goto_processor, pagesize=10):
|
||||||
|
|
||||||
def decorator(func):
|
def decorator(func):
|
||||||
|
|
||||||
def _input_parser(caller, raw_string, **kwargs):
|
def _select_parser(caller, raw_string, **kwargs):
|
||||||
"Parse which input was given, select from option_list"
|
"""
|
||||||
|
Parse the select action
|
||||||
|
"""
|
||||||
available_choices = kwargs.get("available_choices", [])
|
available_choices = kwargs.get("available_choices", [])
|
||||||
processor = kwargs.get("selection_processor")
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
match_ind = int(re.search(r"[0-9]+$", raw_string).group()) - 1
|
index = int(raw_string.strip()) - 1
|
||||||
selection = available_choices[match_ind]
|
selection = available_choices[index]
|
||||||
except (AttributeError, KeyError, IndexError, ValueError):
|
except Exception:
|
||||||
return None
|
caller.msg("|rInvalid choice.|n")
|
||||||
|
else:
|
||||||
if processor:
|
|
||||||
try:
|
try:
|
||||||
return processor(caller, selection)
|
return select(caller, selection)
|
||||||
except Exception:
|
except Exception:
|
||||||
logger.log_trace()
|
logger.log_trace()
|
||||||
return selection
|
return None
|
||||||
|
|
||||||
|
def _input_parser(caller, raw_string, **kwargs):
|
||||||
|
"""
|
||||||
|
Parse which input was given, select from option_list.
|
||||||
|
|
||||||
|
Understood input is [cmd]<num>, where [cmd] is either empty (`select`)
|
||||||
|
or one of the supported actions `look`, `edit` or `add` depending on
|
||||||
|
which processors are available.
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
available_choices = kwargs.get("available_choices", [])
|
||||||
|
match = re.search(r"(^[a-zA-Z]*)\s*([0-9]*)$", raw_string)
|
||||||
|
cmd, number = match.groups()
|
||||||
|
mode, selection = None, None
|
||||||
|
|
||||||
|
if number:
|
||||||
|
number = int(number) - 1
|
||||||
|
cmd = cmd.lower().strip()
|
||||||
|
if cmd.startswith("e") or cmd.startswith("a") and edit:
|
||||||
|
mode = "edit"
|
||||||
|
elif examine:
|
||||||
|
mode = "examine"
|
||||||
|
|
||||||
|
try:
|
||||||
|
selection = available_choices[number]
|
||||||
|
except IndexError:
|
||||||
|
caller.msg("|rInvalid index")
|
||||||
|
mode = None
|
||||||
|
else:
|
||||||
|
caller.msg("|rMust supply a number.")
|
||||||
|
|
||||||
|
return mode, selection
|
||||||
|
|
||||||
|
def _relay_to_edit_or_add(caller, raw_string, **kwargs):
|
||||||
|
pass
|
||||||
|
|
||||||
def _list_node(caller, raw_string, **kwargs):
|
def _list_node(caller, raw_string, **kwargs):
|
||||||
|
|
||||||
|
mode = kwargs.get("list_mode", None)
|
||||||
option_list = option_generator() if callable(option_generator) else option_generator
|
option_list = option_generator() if callable(option_generator) else option_generator
|
||||||
|
|
||||||
nall_options = len(option_list)
|
nall_options = len(option_list)
|
||||||
|
|
@ -1035,71 +1225,104 @@ def list_node(option_generator, examine_processor, goto_processor, pagesize=10):
|
||||||
|
|
||||||
page_index = max(0, min(npages - 1, kwargs.get("optionpage_index", 0)))
|
page_index = max(0, min(npages - 1, kwargs.get("optionpage_index", 0)))
|
||||||
page = pages[page_index]
|
page = pages[page_index]
|
||||||
|
entry = None
|
||||||
|
extra_text = None
|
||||||
|
|
||||||
# dynamic, multi-page option list. We use _input_parser as a goto-callable,
|
if mode == "arbitrary":
|
||||||
# with the `goto_processor` redirecting when we leave the node.
|
# freeform input, we must parse it for the allowed commands (look/edit)
|
||||||
options = [{"desc": opt,
|
mode, entry = _input_parser(caller, raw_string,
|
||||||
"goto": (_input_parser,
|
**{"available_choices": page})
|
||||||
{"available_choices": page,
|
|
||||||
"selection_processor": goto_processor})} for opt in page]
|
|
||||||
|
|
||||||
if npages > 1:
|
if examine and mode: # == "look":
|
||||||
# if the goto callable returns None, the same node is rerun, and
|
# look mode - we are examining a given entry
|
||||||
# kwargs not used by the callable are passed on to the node. This
|
|
||||||
# allows us to call ourselves over and over, using different kwargs.
|
|
||||||
options.append({"key": ("|Wcurrent|n", "c"),
|
|
||||||
"desc": "|W({}/{})|n".format(page_index + 1, npages),
|
|
||||||
"goto": (lambda caller: None,
|
|
||||||
{"optionpage_index": page_index})})
|
|
||||||
if page_index > 0:
|
|
||||||
options.append({"key": ("|wp|Wrevious page|n", "p"),
|
|
||||||
"goto": (lambda caller: None,
|
|
||||||
{"optionpage_index": page_index - 1})})
|
|
||||||
if page_index < npages - 1:
|
|
||||||
options.append({"key": ("|wn|Wext page|n", "n"),
|
|
||||||
"goto": (lambda caller: None,
|
|
||||||
{"optionpage_index": page_index + 1})})
|
|
||||||
|
|
||||||
|
|
||||||
# this catches arbitrary input, notably to examine entries ('look 4' or 'l4' etc)
|
|
||||||
options.append({"key": "_default",
|
|
||||||
"goto": (lambda caller: None,
|
|
||||||
{"show_detail": True, "optionpage_index": page_index})})
|
|
||||||
|
|
||||||
# update text with detail, if set. Here we call _input_parser like a normal function
|
|
||||||
text_detail = None
|
|
||||||
if raw_string and 'show_detail' in kwargs:
|
|
||||||
text_detail = _input_parser(
|
|
||||||
caller, raw_string, **{"available_choices": page,
|
|
||||||
"selection_processor": examine_processor})
|
|
||||||
if text_detail is None:
|
|
||||||
text_detail = "|rThat's not a valid command or option.|n"
|
|
||||||
|
|
||||||
# add data from the decorated node
|
|
||||||
|
|
||||||
text = ''
|
|
||||||
extra_options = []
|
|
||||||
try:
|
|
||||||
text, extra_options = func(caller, raw_string)
|
|
||||||
except TypeError:
|
|
||||||
try:
|
try:
|
||||||
text, extra_options = func(caller)
|
text = examine(caller, entry)
|
||||||
except Exception:
|
except Exception:
|
||||||
raise
|
logger.log_trace()
|
||||||
except Exception:
|
text = "|rCould not view."
|
||||||
logger.log_trace()
|
options = [{"key": ("|wb|Wack|n", "b"),
|
||||||
print("extra_options:", extra_options)
|
"goto": (lambda caller: None,
|
||||||
|
{"optionpage_index": page_index})},
|
||||||
|
{"key": "_default",
|
||||||
|
"goto": (lambda caller: None,
|
||||||
|
{"optionpage_index": page_index})}]
|
||||||
|
return text, options
|
||||||
|
|
||||||
|
# if edit and mode == "edit":
|
||||||
|
# pass
|
||||||
|
# elif add and mode == "add":
|
||||||
|
# # add mode - we are adding a new entry
|
||||||
|
# pass
|
||||||
|
|
||||||
else:
|
else:
|
||||||
if isinstance(extra_options, {}):
|
# normal mode - list
|
||||||
extra_options = [extra_options]
|
pass
|
||||||
|
|
||||||
|
if select:
|
||||||
|
# We have a processor to handle selecting an entry
|
||||||
|
|
||||||
|
# dynamic, multi-page option list. Each selection leads to the `select`
|
||||||
|
# callback being called with a result from the available choices
|
||||||
|
options = [{"desc": opt,
|
||||||
|
"goto": (_select_parser,
|
||||||
|
{"available_choices": page})} for opt in page]
|
||||||
|
|
||||||
|
if add:
|
||||||
|
# We have a processor to handle adding a new entry. Re-run this node
|
||||||
|
# in the 'add' mode
|
||||||
|
options.append({"key": ("|wadd|Wdd new|n", "a"),
|
||||||
|
"goto": (lambda caller: None,
|
||||||
|
{"optionpage_index": page_index,
|
||||||
|
"list_mode": "add"})})
|
||||||
|
if npages > 1:
|
||||||
|
# if the goto callable returns None, the same node is rerun, and
|
||||||
|
# kwargs not used by the callable are passed on to the node. This
|
||||||
|
# allows us to call ourselves over and over, using different kwargs.
|
||||||
|
options.append({"key": ("|Wcurrent|n", "c"),
|
||||||
|
"desc": "|W({}/{})|n".format(page_index + 1, npages),
|
||||||
|
"goto": (lambda caller: None,
|
||||||
|
{"optionpage_index": page_index})})
|
||||||
|
if page_index > 0:
|
||||||
|
options.append({"key": ("|wp|Wrevious page|n", "p"),
|
||||||
|
"goto": (lambda caller: None,
|
||||||
|
{"optionpage_index": page_index - 1})})
|
||||||
|
if page_index < npages - 1:
|
||||||
|
options.append({"key": ("|wn|Wext page|n", "n"),
|
||||||
|
"goto": (lambda caller: None,
|
||||||
|
{"optionpage_index": page_index + 1})})
|
||||||
|
|
||||||
|
# this catches arbitrary input and reruns this node with the 'arbitrary' mode
|
||||||
|
# this could mean input on the form 'look <num>' or 'edit <num>'
|
||||||
|
options.append({"key": "_default",
|
||||||
|
"goto": (lambda caller: None,
|
||||||
|
{"optionpage_index": page_index,
|
||||||
|
"available_choices": page,
|
||||||
|
"list_mode": "arbitrary"})})
|
||||||
|
|
||||||
|
# add data from the decorated node
|
||||||
|
|
||||||
|
extra_options = []
|
||||||
|
try:
|
||||||
|
text, extra_options = func(caller, raw_string)
|
||||||
|
except TypeError:
|
||||||
|
try:
|
||||||
|
text, extra_options = func(caller)
|
||||||
|
except Exception:
|
||||||
|
raise
|
||||||
|
except Exception:
|
||||||
|
logger.log_trace()
|
||||||
|
print("extra_options:", extra_options)
|
||||||
else:
|
else:
|
||||||
extra_options = make_iter(extra_options)
|
if isinstance(extra_options, {}):
|
||||||
|
extra_options = [extra_options]
|
||||||
|
else:
|
||||||
|
extra_options = make_iter(extra_options)
|
||||||
|
|
||||||
options.extend(extra_options)
|
options.extend(extra_options)
|
||||||
text = text + "\n\n" + text_detail if text_detail else text
|
text = text + "\n\n" + extra_text if extra_text else text
|
||||||
text += "\n\n(Make a choice or enter 'look <num>' to examine an option closer)"
|
text += "\n\n(Make a choice or enter 'look <num>' to examine an option closer)"
|
||||||
|
|
||||||
return text, options
|
return text, options
|
||||||
|
|
||||||
return _list_node
|
return _list_node
|
||||||
return decorator
|
return decorator
|
||||||
|
|
|
||||||
|
|
@ -690,9 +690,11 @@ def spawn(*prototypes, **kwargs):
|
||||||
# Helper functions
|
# Helper functions
|
||||||
|
|
||||||
def _get_menu_metaprot(caller):
|
def _get_menu_metaprot(caller):
|
||||||
|
|
||||||
|
metaproto = None
|
||||||
if hasattr(caller.ndb._menutree, "olc_metaprot"):
|
if hasattr(caller.ndb._menutree, "olc_metaprot"):
|
||||||
return caller.ndb._menutree.olc_metaprot
|
metaproto = caller.ndb._menutree.olc_metaprot
|
||||||
else:
|
if not metaproto:
|
||||||
metaproto = build_metaproto(None, '', [], [], None)
|
metaproto = build_metaproto(None, '', [], [], None)
|
||||||
caller.ndb._menutree.olc_metaprot = metaproto
|
caller.ndb._menutree.olc_metaprot = metaproto
|
||||||
caller.ndb._menutree.olc_new = True
|
caller.ndb._menutree.olc_new = True
|
||||||
|
|
@ -931,7 +933,7 @@ def _prototype_select(caller, prototype):
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
|
||||||
@list_node(_all_prototypes, _prototype_examine, _prototype_select)
|
@list_node(_all_prototypes, _prototype_select, examine=_prototype_examine)
|
||||||
def node_prototype(caller):
|
def node_prototype(caller):
|
||||||
metaprot = _get_menu_metaprot(caller)
|
metaprot = _get_menu_metaprot(caller)
|
||||||
prot = metaprot.prototype
|
prot = metaprot.prototype
|
||||||
|
|
@ -979,7 +981,7 @@ def _typeclass_select(caller, typeclass):
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
|
||||||
@list_node(_all_typeclasses, _typeclass_examine, _typeclass_select)
|
@list_node(_all_typeclasses, _typeclass_select, examine=_typeclass_examine)
|
||||||
def node_typeclass(caller):
|
def node_typeclass(caller):
|
||||||
metaprot = _get_menu_metaprot(caller)
|
metaprot = _get_menu_metaprot(caller)
|
||||||
prot = metaprot.prototype
|
prot = metaprot.prototype
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue