evennia.utils.evmenu¶
The EvMenu is a full in-game menu system for Evennia.
To start the menu, just import the EvMenu class from this module.
Example usage:
from evennia.utils.evmenu import EvMenu
EvMenu(caller, menu_module_path,
startnode="node1",
cmdset_mergetype="Replace", cmdset_priority=1,
auto_quit=True, cmd_on_exit="look", persistent=True)
Where caller is the Object to use the menu on - it will get a new cmdset while using the Menu. The menu_module_path is the python path to a python module containing function definitions. By adjusting the keyword options of the Menu() initialization call you can start the menu at different places in the menu definition file, adjust if the menu command should overload the normal commands or not, etc.
The persistent keyword will make the menu survive a server reboot. It is False by default. Note that if using persistent mode, every node and callback in the menu must be possible to be pickled, this excludes e.g. callables that are class methods or functions defined dynamically or as part of another function. In non-persistent mode no such restrictions exist.
The menu is defined in a module (this can be the same module as the command definition too) with function definitions:
def node1(caller):
# (this is the start node if called like above)
# code
return text, options
def node_with_other_name(caller, input_string):
# code
return text, options
def another_node(caller, input_string, **kwargs):
# code
return text, options
Where caller is the object using the menu and input_string is the command entered by the user on the previous node (the command entered to get to this node). The node function code will only be executed once per node-visit and the system will accept nodes with both one or two arguments interchangeably. It also accepts nodes that takes **kwargs.
The menu tree itself is available on the caller as caller.ndb._evmenu. This makes it a convenient place to store temporary state variables between nodes, since this NAttribute is deleted when the menu is exited.
The return values must be given in the above order, but each can be returned as None as well. If the options are returned as None, the menu is immediately exited and the default “look” command is called.
text (str, tuple or None): Text shown at this node. If a tuple, the second element in the tuple is a help text to display at this node when the user enters the menu help command there.
options (tuple, dict or None): If None, this exits the menu. If a single dict, this is a single-option node. If a tuple, it should be a tuple of option dictionaries. Option dicts have the following keys:
- key (str or tuple, optional): What to enter to choose this option.
If a tuple, it must be a tuple of strings, where the first string is the key which will be shown to the user and the others are aliases. If unset, the options’ number will be used. The special key _default marks this option as the default fallback when no other option matches the user input. There can only be one _default option per node. It will not be displayed in the list.
desc (str, optional): This describes what choosing the option will do.
- goto (str, tuple or callable): If string, should be the name of node to go to
when this option is selected. If a callable, it has the signature callable(caller[,raw_input][,**kwargs]). If a tuple, the first element is the callable and the second is a dict with the kwargs to pass to the callable. Those kwargs will also be passed into the next node if possible. Such a callable should return either a str or a (str, dict), where the string is the name of the next node to go to and the dict is the new, (possibly modified) kwarg to pass into the next node. If the callable returns None or the empty string, the current node will be revisited.
- exec (str, callable or tuple, optional): This takes the same input as goto above
and runs before it. If given a node name, the node will be executed but will not be considered the next node. If node/callback returns str or (str, dict), these will replace the goto step (goto callbacks will not fire), with the string being the next node name and the optional dict acting as the kwargs-input for the next node. If an exec callable returns None, the current node is re-run.
If key is not given, the option will automatically be identified by its number 1..N.
Example:
# in menu_module.py
def node1(caller):
text = ("This is a node text",
"This is help text for this node")
options = ({"key": "testing",
"desc": "Select this to go to node 2",
"goto": ("node2", {"foo": "bar"}),
"exec": "callback1"},
{"desc": "Go to node 3.",
"goto": "node3"})
return text, options
def callback1(caller):
# this is called when choosing the "testing" option in node1
# (before going to node2). If it returned a string, say 'node3',
# then the next node would be node3 instead of node2 as specified
# by the normal 'goto' option key above.
caller.msg("Callback called!")
def node2(caller, **kwargs):
text = '''
This is node 2. It only allows you to go back
to the original node1. This extra indent will
be stripped. We don't include a help text but
here are the variables passed to us: {}
'''.format(kwargs)
options = {"goto": "node1"}
return text, options
def node3(caller):
text = "This ends the menu since there are no options."
return text, None
When starting this menu with Menu(caller, “path.to.menu_module”), the first node will look something like this:
This is a node text
______________________________________
testing: Select this to go to node 2
2: Go to node 3
Where you can both enter “testing” and “1” to select the first option. If the client supports MXP, they may also mouse-click on “testing” to do the same. When making this selection, a function “callback1” in the same Using help will show the help text, otherwise a list of available commands while in menu mode.
The menu tree is exited either by using the in-menu quit command or by reaching a node without any options.
For a menu demo, import CmdTestMenu from this module and add it to your default cmdset. Run it with this module, like testmenu evennia.utils.evmenu.
Menu generation from template string¶
In evmenu.py is a helper function parse_menu_template that parses a template-string and outputs a menu-tree dictionary suitable to pass into EvMenu:
menutree = evmenu.parse_menu_template(caller, menu_template, goto_callables)
EvMenu(caller, menutree)
For maximum flexibility you can inject normally-created nodes in the menu tree before passing it to EvMenu. If that’s not needed, you can also create a menu in one step with:
evmenu.template2menu(caller, menu_template, goto_callables)
The goto_callables is a mapping {“funcname”: callable, …}, where each callable must be a module-global function on the form funcname(caller, raw_string, **kwargs) (like any goto-callable). The menu_template is a multi-line string on the following form:
## node start
This is the text of the start node.
The text area can have multiple lines, line breaks etc.
Each option below is one of these forms
key: desc -> gotostr_or_func
key: gotostr_or_func
>: gotostr_or_func
> glob/regex: gotostr_or_func
## options
# comments are only allowed from beginning of line.
# Indenting is not necessary, but good for readability
1: Option number 1 -> node1
2: Option number 2 -> node2
next: This steps next -> go_back()
# the -> can be ignored if there is no desc
back: go_back(from_node=start)
abort: abort
## node node1
Text for Node1. Enter a message!
<return> to go back.
## options
# Starting the option-line with >
# allows to perform different actions depending on
# what is inserted.
# this catches everything starting with foo
> foo*: handle_foo_message()
# regex are also allowed (this catches number inputs)
> [0-9]+?: handle_numbers()
# this catches the empty return
>: start
# this catches everything else
> *: handle_message(from_node=node1)
## node node2
Text for Node2. Just go back.
## options
>: start
# node abort
This exits the menu since there is no **## options** section.
Each menu node is defined by a # node <name> containing the text of the node, followed by ## options Also ## NODE and ## OPTIONS work. No python code logics is allowed in the template, this code is not evaluated but parsed. More advanced dynamic usage requires a full node-function (which can be added to the generated dict, as said).
Adding (..) to a goto treats it as a callable and it must then be included in the goto_callable mapping. Only named keywords (or no args at all) are allowed, these will be added to the **kwargs going into the callable. Quoting strings is only needed if wanting to pass strippable spaces, otherwise the key:values will be converted to strings/numbers with literal_eval before passed into the callable.
The “> ” option takes a glob or regex to perform different actions depending on user input. Make sure to sort these in increasing order of generality since they will be tested in sequence.
-
exception
evennia.utils.evmenu.
EvMenuError
[source]¶ Bases:
RuntimeError
Error raised by menu when facing internal errors.
-
exception
evennia.utils.evmenu.
EvMenuGotoAbortMessage
[source]¶ Bases:
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.”)
-
class
evennia.utils.evmenu.
CmdEvMenuNode
(**kwargs)[source]¶ Bases:
evennia.commands.command.Command
Menu options.
-
key
= '__noinput_command'¶
-
aliases
= ['__nomatch_command']¶
-
locks
= 'cmd:all()'¶
-
help_category
= 'menu'¶
-
auto_help_display_key
= '<menu commands>'¶
-
get_help
()[source]¶ Return the help message for this command and this caller.
By default, return self.__doc__ (the docstring just under the class definition). You can override this behavior, though, and even customize it depending on the caller, or other commands the caller can use.
- Parameters
caller (Object or Account) – the caller asking for help on the command.
cmdset (CmdSet) – the command set (if you need additional commands).
- Returns
docstring (str) – the help text to provide the caller for this command.
-
lock_storage
= 'cmd:all()'¶
-
-
class
evennia.utils.evmenu.
EvMenuCmdSet
(cmdsetobj=None, key=None)[source]¶ Bases:
evennia.commands.cmdset.CmdSet
The Menu cmdset replaces the current cmdset.
-
key
= 'menu_cmdset'¶
-
priority
= 1¶
-
mergetype
= 'Replace'¶
-
no_objs
= True¶
-
no_exits
= True¶
-
no_channels
= False¶
-
path
= 'evennia.utils.evmenu.EvMenuCmdSet'¶
-
-
class
evennia.utils.evmenu.
EvMenu
(caller, menudata, startnode='start', cmdset_mergetype='Replace', cmdset_priority=1, auto_quit=True, auto_look=True, auto_help=True, cmd_on_exit='look', persistent=False, startnode_input='', session=None, debug=False, **kwargs)[source]¶ Bases:
object
This object represents an operational menu. It is initialized from a menufile.py instruction.
-
node_border_char
= '_'¶
-
__init__
(caller, menudata, startnode='start', cmdset_mergetype='Replace', cmdset_priority=1, auto_quit=True, auto_look=True, auto_help=True, cmd_on_exit='look', persistent=False, startnode_input='', session=None, debug=False, **kwargs)[source]¶ Initialize the menu tree and start the caller onto the first node.
- Parameters
caller (Object, Account or Session) – The user of the menu.
menudata (str, module or dict) – The full or relative path to the module holding the menu tree data. All global functions in this module whose name doesn’t start with ‘_ ‘ will be parsed as menu nodes. Also the module itself is accepted as input. Finally, a dictionary menu tree can be given directly. This must then be a mapping {“nodekey”:callable,…} where callable must be called as and return the data expected of a menu node. This allows for dynamic menu creation.
startnode (str, optional) – The starting node name in the menufile.
cmdset_mergetype (str, optional) – ‘Replace’ (default) means the menu commands will be exclusive - no other normal commands will be usable while the user is in the menu. ‘Union’ means the menu commands will be integrated with the existing commands (it will merge with merge_priority), if so, make sure that the menu’s command names don’t collide with existing commands in an unexpected way. Also the CMD_NOMATCH and CMD_NOINPUT will be overloaded by the menu cmdset. Other cmdser mergetypes has little purpose for the menu.
cmdset_priority (int, optional) – The merge priority for the menu command set. The default (1) is usually enough for most types of menus.
auto_quit (bool, optional) – Allow user to use “q”, “quit” or “exit” to leave the menu at any point. Recommended during development!
auto_look (bool, optional) – Automatically make “looK” or “l” to re-show the last node. Turning this off means you have to handle re-showing nodes yourself, but may be useful if you need to use “l” for some other purpose.
auto_help (bool, optional) – Automatically make “help” or “h” show the current help entry for the node. If turned off, eventual help must be handled manually, but it may be useful if you need ‘h’ for some other purpose, for example.
cmd_on_exit (callable, str or None, optional) – When exiting the menu (either by reaching a node with no options or by using the in-built quit command (activated with allow_quit), this callback function or command string will be executed. The callback function takes two parameters, the caller then the EvMenu object. This is called after cleanup is complete. Set to None to not call any command.
persistent (bool, optional) – Make the Menu persistent (i.e. it will survive a reload. This will make the Menu cmdset persistent. Use with caution - if your menu is buggy you may end up in a state you can’t get out of! Also note that persistent mode requires that all formatters, menu nodes and callables are possible to pickle. When the server is reloaded, the latest node shown will be completely re-run with the same input arguments - so be careful if you are counting up some persistent counter or similar - the counter may be run twice if reload happens on the node that does that. Note that if debug is True, this setting is ignored and assumed to be False.
startnode_input (str or (str, dict), optional) – Send an input text to startnode as if a user input text from a fictional previous node. If including the dict, this will be passed as kwargs to that node. When the server reloads, the latest visited node will be re-run as **node(caller, raw_string, **kwargs).
session (Session, optional) – This is useful when calling EvMenu from an account in multisession mode > 2. Note that this session only really relevant for the very first display of the first node - after that, EvMenu itself will keep the session updated from the command input. So a persistent menu will not be using this same session anymore after a reload.
debug (bool, optional) – If set, the ‘menudebug’ command will be made available by default in all nodes of the menu. This will print out the current state of the menu. Deactivate for production use! When the debug flag is active, the persistent flag is deactivated.
- Keyword Arguments
any (any) – All kwargs will become initialization variables on caller.ndb._evmenu, to be available at run.
- Raises
EvMenuError – If the start/end node is not found in menu tree.
Notes
While running, the menu is stored on the caller as caller.ndb._evmenu. Also the current Session (from the Command, so this is still valid in multisession environments) is available through caller.ndb._evmenu._session. The _evmenu property is a good one for storing intermediary data on between nodes since it will be automatically deleted when the menu closes.
In persistent mode, all nodes, formatters and callbacks in the menu must be possible to be pickled, this excludes e.g. callables that are class methods or functions defined dynamically or as part of another function. In non-persistent mode no such restrictions exist.
-
msg
(txt)[source]¶ This is a central point for sending return texts to the caller. It allows for a central point to add custom messaging when creating custom EvMenu overrides.
- Parameters
txt (str) – The text to send.
Notes
By default this will send to the same session provided to EvMenu (if session kwarg was provided to EvMenu.__init__). It will also send it with a type=menu for the benefit of OOB/webclient.
-
run_exec
(nodename, raw_string, **kwargs)[source]¶ NOTE: This is deprecated. Use goto directly instead.
Run a function or node as a callback (with the ‘exec’ option key).
- Parameters
nodename (callable or str) – A callable to run as callable(caller, raw_string), or the Name of an existing node to run as a callable. This may or may not return a string.
raw_string (str) – The raw default string entered on the previous node (only used if the node accepts it as an argument)
kwargs (any) – These are optional kwargs passed into goto
- Returns
new_goto (str or None) –
- A replacement goto location string or
None (no replacement).
Notes
Relying on exec callbacks to set the goto location is very powerful but will easily lead to spaghetti structure and hard-to-trace paths through the menu logic. So be careful with relying on this.
-
extract_goto_exec
(nodename, option_dict)[source]¶ Helper: Get callables and their eventual kwargs.
- Parameters
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
(nodename, raw_string, **kwargs)[source]¶ Run a node by name, optionally dynamically generating that name first.
- Parameters
nodename (str or callable) – Name of node or a callable to be called as function(caller, raw_string, **kwargs) or function(caller, **kwargs) to return the actual goto string or a (“nodename”, kwargs) tuple.
raw_string (str) – The raw default string entered on the previous node (only used if the node accepts it as an argument)
- Keyword Arguments
any – Extra arguments to goto callables.
-
run_exec_then_goto
(runexec, goto, raw_string, runexec_kwargs=None, goto_kwargs=None)[source]¶ Call ‘exec’ callback and goto (which may also be a callable) in sequence.
- Parameters
runexec (callable or str) – Callback to run before goto. If the callback returns a string, this is used to replace the goto string/callable before being passed into the goto handler.
goto (str) – The target node to go to next (may be replaced by runexec)..
raw_string (str) – The original user input.
runexec_kwargs (dict, optional) – Optional kwargs for runexec.
goto_kwargs (dict, optional) – Optional kwargs for goto.
-
print_debug_info
(arg)[source]¶ Messages the caller with the current menu state, for debug purposes.
- Parameters
arg (str) – Arg to debug instruction, either nothing, ‘full’ or the name of a property to inspect.
-
parse_input
(raw_string)[source]¶ Parses the incoming string from the menu user.
- Parameters
raw_string (str) – The incoming, unmodified string from the user.
Notes
This method is expected to parse input and use the result to relay execution to the relevant methods of the menu. It should also report errors directly to the user.
-
nodetext_formatter
(nodetext)[source]¶ Format the node text itself.
- Parameters
nodetext (str) – The full node text (the text describing the node).
- Returns
nodetext (str) – The formatted node text.
-
helptext_formatter
(helptext)[source]¶ Format the node’s help text
- Parameters
helptext (str) – The unformatted help text for the node.
- Returns
helptext (str) – The formatted help text.
-
options_formatter
(optionlist)[source]¶ Formats the option block.
- Parameters
optionlist (list) – List of (key, description) tuples for every option related to this node.
caller (Object, Account or None, optional) – The caller of the node.
- Returns
options (str) – The formatted option display.
-
node_formatter
(nodetext, optionstext)[source]¶ Formats the entirety of the node.
- Parameters
nodetext (str) – The node text as returned by self.nodetext_formatter.
optionstext (str) – The options display as returned by self.options_formatter.
caller (Object, Account or None, optional) – The caller of the node.
- Returns
node (str) – The formatted node to display.
-
-
evennia.utils.evmenu.
list_node
(option_generator, select=None, pagesize=10)[source]¶ Decorator for making an EvMenu node into a multi-page list node. Will add new options, prepending those options added in the node.
- Parameters
option_generator (callable or list) – A list of strings indicating the options, or a callable that is called as option_generator(caller) to produce such a list.
select (callable or str, optional) – Node to redirect a selection to. Its **kwargs will contain the available_choices list and selection will hold one of the elements in that list. If a callable, it will be called as select(caller, menuchoice, **kwargs) where menuchoice is the chosen option as a string and available_choices is the list of available options offered by the option_generator. The callable whould return the name of the target node to goto after this selection (or None to repeat the list-node). Note that if this is not given, the decorated node must itself provide a way to continue from the node!
pagesize (int) – How many options to show per page.
Example
def _selectfunc(caller, menuchoice, **kwargs): # menuchoice would be either 'foo' or 'bar' here # kwargs['available_choices'] would be the list ['foo', 'bar'] return "the_next_node_to_go_to" @list_node(['foo', 'bar'], _selectfunc) def node_index(caller): text = "describing the list" return text, []
Notes
All normal goto or exec callables returned from the decorated nodes will, if they accept **kwargs, get a new kwarg available_choices injected. This is the ordered list of named options (descs) visible on the current node page.
-
class
evennia.utils.evmenu.
CmdGetInput
(**kwargs)[source]¶ Bases:
evennia.commands.command.Command
Enter your data and press return.
-
key
= '__nomatch_command'¶
-
aliases
= ['__noinput_command']¶
-
help_category
= 'general'¶
-
lock_storage
= 'cmd:all();'¶
-
-
class
evennia.utils.evmenu.
InputCmdSet
(cmdsetobj=None, key=None)[source]¶ Bases:
evennia.commands.cmdset.CmdSet
This stores the input command
-
key
= 'input_cmdset'¶
-
priority
= 1¶
-
mergetype
= 'Replace'¶
-
no_objs
= True¶
-
no_exits
= True¶
-
no_channels
= False¶
-
path
= 'evennia.utils.evmenu.InputCmdSet'¶
-
-
evennia.utils.evmenu.
get_input
(caller, prompt, callback, session=None, *args, **kwargs)[source]¶ This is a helper function for easily request input from the caller.
- Parameters
caller (Account or Object) – The entity being asked the question. This should usually be an object controlled by a user.
prompt (str) – This text will be shown to the user, in order to let them know their input is needed.
callback (callable) – A function that will be called when the user enters a reply. It must take three arguments: the caller, the prompt text and the result of the input given by the user. If the callback doesn’t return anything or return False, the input prompt will be cleaned up and exited. If returning True, the prompt will remain and continue to accept input.
session (Session, optional) – This allows to specify the session to send the prompt to. It’s usually only needed if caller is an Account in multisession modes greater than 2. The session is then updated by the command and is available (for example in callbacks) through caller.ndb.getinput._session.
args (optional) – Extra arguments will be passed to the fall back function as a list ‘args’ and all keyword arguments as a dictionary ‘kwargs’. To utilise *args and **kwargs, a value for the session argument must be provided (None by default) and the callback function must take *args and **kwargs as arguments.
kwargs (optional) – Extra arguments will be passed to the fall back function as a list ‘args’ and all keyword arguments as a dictionary ‘kwargs’. To utilise *args and **kwargs, a value for the session argument must be provided (None by default) and the callback function must take *args and **kwargs as arguments.
- Raises
RuntimeError – If the given callback is not callable.
Notes
The result value sent to the callback is raw and not processed in any way. This means that you will get the ending line return character from most types of client inputs. So make sure to strip that before doing a comparison.
When the prompt is running, a temporary object caller.ndb._getinput is stored; this will be removed when the prompt finishes. If you need the specific Session of the caller (which may not be easy to get if caller is an account in higher multisession modes), then it is available in the callback through caller.ndb._getinput._session.
Chaining get_input functions will result in the caller stacking ever more instances of InputCmdSets. Whilst they will all be cleared on concluding the get_input chain, EvMenu should be considered for anything beyond a single question.
-
evennia.utils.evmenu.
parse_menu_template
(caller, menu_template, goto_callables=None)[source]¶ Parse menu-template string. The main function of the EvMenu templating system.
- Parameters
caller (Object or Account) – Entity using the menu.
menu_template (str) – Menu described using the templating format.
goto_callables (dict, optional) – Mapping between call-names and callables on the form callable(caller, raw_string, **kwargs). These are what is available to use in the menu_template string.
- Returns
dict – A {“node”: nodefunc} menutree suitable to pass into EvMenu.
-
evennia.utils.evmenu.
template2menu
(caller, menu_template, goto_callables=None, startnode='start', persistent=False, **kwargs)[source]¶ Helper function to generate and start an EvMenu based on a menu template string. This will internall call parse_menu_template and run a default EvMenu with its results.
- Parameters
caller (Object or Account) – The entity using the menu.
menu_template (str) – The menu-template string describing the content and structure of the menu. It can also be the python-path to, or a module containing a MENU_TEMPLATE global variable with the template.
goto_callables (dict, optional) – Mapping of callable-names to module-global objects to reference by name in the menu-template. Must be on the form callable(caller, raw_string, **kwargs).
startnode (str, optional) – The name of the startnode, if not ‘start’.
persistent (bool, optional) – If the generated menu should be persistent.
**kwargs – All kwargs will be passed into EvMenu.
- Returns
EvMenu – The generated EvMenu.