mirror of
https://github.com/evennia/evennia.git
synced 2026-03-23 16:26:30 +01:00
2196 lines
No EOL
253 KiB
HTML
2196 lines
No EOL
253 KiB
HTML
|
|
<!DOCTYPE html>
|
|
|
|
<html>
|
|
<head>
|
|
<meta charset="utf-8" />
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
<title>evennia.utils.evmenu — Evennia 1.0-dev documentation</title>
|
|
<link rel="stylesheet" href="../../../_static/nature.css" type="text/css" />
|
|
<link rel="stylesheet" href="../../../_static/pygments.css" type="text/css" />
|
|
<script id="documentation_options" data-url_root="../../../" src="../../../_static/documentation_options.js"></script>
|
|
<script src="../../../_static/jquery.js"></script>
|
|
<script src="../../../_static/underscore.js"></script>
|
|
<script src="../../../_static/doctools.js"></script>
|
|
<script src="../../../_static/language_data.js"></script>
|
|
<link rel="shortcut icon" href="../../../_static/favicon.ico"/>
|
|
<link rel="index" title="Index" href="../../../genindex.html" />
|
|
<link rel="search" title="Search" href="../../../search.html" />
|
|
</head><body>
|
|
<div class="related" role="navigation" aria-label="related navigation">
|
|
<h3>Navigation</h3>
|
|
<ul>
|
|
<li class="right" style="margin-right: 10px">
|
|
<a href="../../../genindex.html" title="General Index"
|
|
accesskey="I">index</a></li>
|
|
<li class="right" >
|
|
<a href="../../../py-modindex.html" title="Python Module Index"
|
|
>modules</a> |</li>
|
|
<li class="nav-item nav-item-0"><a href="../../../index.html">Evennia 1.0-dev</a> »</li>
|
|
<li class="nav-item nav-item-1"><a href="../../index.html" >Module code</a> »</li>
|
|
<li class="nav-item nav-item-2"><a href="../../evennia.html" accesskey="U">evennia</a> »</li>
|
|
<li class="nav-item nav-item-this"><a href="">evennia.utils.evmenu</a></li>
|
|
</ul>
|
|
<div class="develop">develop branch</div>
|
|
</div>
|
|
|
|
<div class="document">
|
|
<div class="documentwrapper">
|
|
<div class="bodywrapper">
|
|
<div class="body" role="main">
|
|
|
|
<h1>Source code for evennia.utils.evmenu</h1><div class="highlight"><pre>
|
|
<span></span><span class="sd">"""</span>
|
|
<span class="sd">EvMenu</span>
|
|
|
|
<span class="sd">This implements a full menu system for Evennia.</span>
|
|
|
|
<span class="sd">To start the menu, just import the EvMenu class from this module.</span>
|
|
<span class="sd">Example usage:</span>
|
|
|
|
<span class="sd">```python</span>
|
|
|
|
<span class="sd"> from evennia.utils.evmenu import EvMenu</span>
|
|
|
|
<span class="sd"> EvMenu(caller, menu_module_path,</span>
|
|
<span class="sd"> startnode="node1",</span>
|
|
<span class="sd"> cmdset_mergetype="Replace", cmdset_priority=1,</span>
|
|
<span class="sd"> auto_quit=True, cmd_on_exit="look", persistent=True)</span>
|
|
<span class="sd">```</span>
|
|
|
|
<span class="sd">Where `caller` is the Object to use the menu on - it will get a new</span>
|
|
<span class="sd">cmdset while using the Menu. The menu_module_path is the python path</span>
|
|
<span class="sd">to a python module containing function definitions. By adjusting the</span>
|
|
<span class="sd">keyword options of the Menu() initialization call you can start the</span>
|
|
<span class="sd">menu at different places in the menu definition file, adjust if the</span>
|
|
<span class="sd">menu command should overload the normal commands or not, etc.</span>
|
|
|
|
<span class="sd">The `persistent` keyword will make the menu survive a server reboot.</span>
|
|
<span class="sd">It is `False` by default. Note that if using persistent mode, every</span>
|
|
<span class="sd">node and callback in the menu must be possible to be *pickled*, this</span>
|
|
<span class="sd">excludes e.g. callables that are class methods or functions defined</span>
|
|
<span class="sd">dynamically or as part of another function. In non-persistent mode</span>
|
|
<span class="sd">no such restrictions exist.</span>
|
|
|
|
<span class="sd">The menu is defined in a module (this can be the same module as the</span>
|
|
<span class="sd">command definition too) with function definitions:</span>
|
|
|
|
<span class="sd">```python</span>
|
|
|
|
<span class="sd"> def node1(caller):</span>
|
|
<span class="sd"> # (this is the start node if called like above)</span>
|
|
<span class="sd"> # code</span>
|
|
<span class="sd"> return text, options</span>
|
|
|
|
<span class="sd"> def node_with_other_name(caller, input_string):</span>
|
|
<span class="sd"> # code</span>
|
|
<span class="sd"> return text, options</span>
|
|
|
|
<span class="sd"> def another_node(caller, input_string, **kwargs):</span>
|
|
<span class="sd"> # code</span>
|
|
<span class="sd"> return text, options</span>
|
|
<span class="sd">```</span>
|
|
|
|
<span class="sd">Where caller is the object using the menu and input_string is the</span>
|
|
<span class="sd">command entered by the user on the *previous* node (the command</span>
|
|
<span class="sd">entered to get to this node). The node function code will only be</span>
|
|
<span class="sd">executed once per node-visit and the system will accept nodes with</span>
|
|
<span class="sd">both one or two arguments interchangeably. It also accepts nodes</span>
|
|
<span class="sd">that takes `**kwargs`.</span>
|
|
|
|
<span class="sd">The menu tree itself is available on the caller as</span>
|
|
<span class="sd">`caller.ndb._evmenu`. This makes it a convenient place to store</span>
|
|
<span class="sd">temporary state variables between nodes, since this NAttribute is</span>
|
|
<span class="sd">deleted when the menu is exited.</span>
|
|
|
|
<span class="sd">The return values must be given in the above order, but each can be</span>
|
|
<span class="sd">returned as None as well. If the options are returned as None, the</span>
|
|
<span class="sd">menu is immediately exited and the default "look" command is called.</span>
|
|
|
|
<span class="sd">- `text` (str, tuple or None): Text shown at this node. If a tuple, the</span>
|
|
<span class="sd"> second element in the tuple is a help text to display at this</span>
|
|
<span class="sd"> node when the user enters the menu help command there.</span>
|
|
<span class="sd">- `options` (tuple, dict or None): If `None`, this exits the menu.</span>
|
|
<span class="sd"> If a single dict, this is a single-option node. If a tuple,</span>
|
|
<span class="sd"> it should be a tuple of option dictionaries. Option dicts have the following keys:</span>
|
|
|
|
<span class="sd"> - `key` (str or tuple, optional): What to enter to choose this option.</span>
|
|
<span class="sd"> If a tuple, it must be a tuple of strings, where the first string is the</span>
|
|
<span class="sd"> key which will be shown to the user and the others are aliases.</span>
|
|
<span class="sd"> If unset, the options' number will be used. The special key `_default`</span>
|
|
<span class="sd"> marks this option as the default fallback when no other option matches</span>
|
|
<span class="sd"> the user input. There can only be one `_default` option per node. It</span>
|
|
<span class="sd"> will not be displayed in the list.</span>
|
|
<span class="sd"> - `desc` (str, optional): This describes what choosing the option will do.</span>
|
|
<span class="sd"> - `goto` (str, tuple or callable): If string, should be the name of node to go to</span>
|
|
<span class="sd"> when this option is selected. If a callable, it has the signature</span>
|
|
<span class="sd"> `callable(caller[,raw_input][,**kwargs])`. If a tuple, the first element</span>
|
|
<span class="sd"> is the callable and the second is a dict with the `**kwargs` to pass to</span>
|
|
<span class="sd"> the callable. Those kwargs will also be passed into the next node if possible.</span>
|
|
<span class="sd"> Such a callable should return either a str or a (str, dict), where the</span>
|
|
<span class="sd"> string is the name of the next node to go to and the dict is the new,</span>
|
|
<span class="sd"> (possibly modified) kwarg to pass into the next node. If the callable returns</span>
|
|
<span class="sd"> None or the empty string, the current node will be revisited.</span>
|
|
<span class="sd"> - `exec` (str, callable or tuple, optional): This takes the same input as `goto` above</span>
|
|
<span class="sd"> and runs before it. If given a node name, the node will be executed but will not</span>
|
|
<span class="sd"> be considered the next node. If node/callback returns str or (str, dict), these will</span>
|
|
<span class="sd"> replace the `goto` step (`goto` callbacks will not fire), with the string being the</span>
|
|
<span class="sd"> next node name and the optional dict acting as the kwargs-input for the next node.</span>
|
|
<span class="sd"> If an exec callable returns the empty string (only), the current node is re-run.</span>
|
|
|
|
<span class="sd">If `key` is not given, the option will automatically be identified by</span>
|
|
<span class="sd">its number 1..N.</span>
|
|
|
|
<span class="sd">Example:</span>
|
|
|
|
<span class="sd">```python</span>
|
|
|
|
<span class="sd"> # in menu_module.py</span>
|
|
|
|
<span class="sd"> def node1(caller):</span>
|
|
<span class="sd"> text = ("This is a node text",</span>
|
|
<span class="sd"> "This is help text for this node")</span>
|
|
<span class="sd"> options = ({"key": "testing",</span>
|
|
<span class="sd"> "desc": "Select this to go to node 2",</span>
|
|
<span class="sd"> "goto": ("node2", {"foo": "bar"}),</span>
|
|
<span class="sd"> "exec": "callback1"},</span>
|
|
<span class="sd"> {"desc": "Go to node 3.",</span>
|
|
<span class="sd"> "goto": "node3"})</span>
|
|
<span class="sd"> return text, options</span>
|
|
|
|
<span class="sd"> def callback1(caller):</span>
|
|
<span class="sd"> # this is called when choosing the "testing" option in node1</span>
|
|
<span class="sd"> # (before going to node2). If it returned a string, say 'node3',</span>
|
|
<span class="sd"> # then the next node would be node3 instead of node2 as specified</span>
|
|
<span class="sd"> # by the normal 'goto' option key above.</span>
|
|
<span class="sd"> caller.msg("Callback called!")</span>
|
|
|
|
<span class="sd"> def node2(caller, **kwargs):</span>
|
|
<span class="sd"> text = '''</span>
|
|
<span class="sd"> This is node 2. It only allows you to go back</span>
|
|
<span class="sd"> to the original node1. This extra indent will</span>
|
|
<span class="sd"> be stripped. We don't include a help text but</span>
|
|
<span class="sd"> here are the variables passed to us: {}</span>
|
|
<span class="sd"> '''.format(kwargs)</span>
|
|
<span class="sd"> options = {"goto": "node1"}</span>
|
|
<span class="sd"> return text, options</span>
|
|
|
|
<span class="sd"> def node3(caller):</span>
|
|
<span class="sd"> text = "This ends the menu since there are no options."</span>
|
|
<span class="sd"> return text, None</span>
|
|
|
|
<span class="sd">```</span>
|
|
|
|
<span class="sd">When starting this menu with `Menu(caller, "path.to.menu_module")`,</span>
|
|
<span class="sd">the first node will look something like this:</span>
|
|
|
|
<span class="sd">::</span>
|
|
|
|
<span class="sd"> This is a node text</span>
|
|
<span class="sd"> ______________________________________</span>
|
|
|
|
<span class="sd"> testing: Select this to go to node 2</span>
|
|
<span class="sd"> 2: Go to node 3</span>
|
|
|
|
<span class="sd">Where you can both enter "testing" and "1" to select the first option.</span>
|
|
<span class="sd">If the client supports MXP, they may also mouse-click on "testing" to</span>
|
|
<span class="sd">do the same. When making this selection, a function "callback1" in the</span>
|
|
<span class="sd">same Using `help` will show the help text, otherwise a list of</span>
|
|
<span class="sd">available commands while in menu mode.</span>
|
|
|
|
<span class="sd">The menu tree is exited either by using the in-menu quit command or by</span>
|
|
<span class="sd">reaching a node without any options.</span>
|
|
|
|
|
|
<span class="sd">For a menu demo, import `CmdTestMenu` from this module and add it to</span>
|
|
<span class="sd">your default cmdset. Run it with this module, like `testmenu evennia.utils.evmenu`.</span>
|
|
|
|
|
|
<span class="sd">## Menu generation from template string</span>
|
|
|
|
<span class="sd">In evmenu.py is a helper function `parse_menu_template` that parses a</span>
|
|
<span class="sd">template-string and outputs a menu-tree dictionary suitable to pass into</span>
|
|
<span class="sd">EvMenu:</span>
|
|
<span class="sd">::</span>
|
|
|
|
<span class="sd"> menutree = evmenu.parse_menu_template(caller, menu_template, goto_callables)</span>
|
|
<span class="sd"> EvMenu(caller, menutree)</span>
|
|
|
|
<span class="sd">For maximum flexibility you can inject normally-created nodes in the menu tree</span>
|
|
<span class="sd">before passing it to EvMenu. If that's not needed, you can also create a menu</span>
|
|
<span class="sd">in one step with:</span>
|
|
|
|
<span class="sd">```python</span>
|
|
|
|
<span class="sd"> evmenu.template2menu(caller, menu_template, goto_callables)</span>
|
|
|
|
<span class="sd">```</span>
|
|
|
|
<span class="sd">The `goto_callables` is a mapping `{"funcname": callable, ...}`, where each</span>
|
|
<span class="sd">callable must be a module-global function on the form</span>
|
|
<span class="sd">`funcname(caller, raw_string, **kwargs)` (like any goto-callable). The</span>
|
|
<span class="sd">`menu_template` is a multi-line string on the following form:</span>
|
|
<span class="sd">::</span>
|
|
|
|
<span class="sd"> ## node start</span>
|
|
|
|
<span class="sd"> This is the text of the start node.</span>
|
|
<span class="sd"> The text area can have multiple lines, line breaks etc.</span>
|
|
|
|
<span class="sd"> Each option below is one of these forms</span>
|
|
<span class="sd"> key: desc -> gotostr_or_func</span>
|
|
<span class="sd"> key: gotostr_or_func</span>
|
|
<span class="sd"> >: gotostr_or_func</span>
|
|
<span class="sd"> > glob/regex: gotostr_or_func</span>
|
|
|
|
<span class="sd"> ## options</span>
|
|
|
|
<span class="sd"> # comments are only allowed from beginning of line.</span>
|
|
<span class="sd"> # Indenting is not necessary, but good for readability</span>
|
|
|
|
<span class="sd"> 1: Option number 1 -> node1</span>
|
|
<span class="sd"> 2: Option number 2 -> node2</span>
|
|
<span class="sd"> next: This steps next -> go_back()</span>
|
|
<span class="sd"> # the -> can be ignored if there is no desc</span>
|
|
<span class="sd"> back: go_back(from_node=start)</span>
|
|
<span class="sd"> abort: abort</span>
|
|
|
|
<span class="sd"> ## node node1</span>
|
|
|
|
<span class="sd"> Text for Node1. Enter a message!</span>
|
|
<span class="sd"> <return> to go back.</span>
|
|
|
|
<span class="sd"> ## options</span>
|
|
|
|
<span class="sd"> # Starting the option-line with ></span>
|
|
<span class="sd"> # allows to perform different actions depending on</span>
|
|
<span class="sd"> # what is inserted.</span>
|
|
|
|
<span class="sd"> # this catches everything starting with foo</span>
|
|
<span class="sd"> > foo*: handle_foo_message()</span>
|
|
|
|
<span class="sd"> # regex are also allowed (this catches number inputs)</span>
|
|
<span class="sd"> > [0-9]+?: handle_numbers()</span>
|
|
|
|
<span class="sd"> # this catches the empty return</span>
|
|
<span class="sd"> >: start</span>
|
|
|
|
<span class="sd"> # this catches everything else</span>
|
|
<span class="sd"> > *: handle_message(from_node=node1)</span>
|
|
|
|
<span class="sd"> ## node node2</span>
|
|
|
|
<span class="sd"> Text for Node2. Just go back.</span>
|
|
|
|
<span class="sd"> ## options</span>
|
|
|
|
<span class="sd"> >: start</span>
|
|
|
|
<span class="sd"> # node abort</span>
|
|
|
|
<span class="sd"> This exits the menu since there is no `## options` section.</span>
|
|
|
|
<span class="sd">Each menu node is defined by a `# node <name>` containing the text of the node,</span>
|
|
<span class="sd">followed by `## options` Also `## NODE` and `## OPTIONS` work. No python code</span>
|
|
<span class="sd">logics is allowed in the template, this code is not evaluated but parsed. More</span>
|
|
<span class="sd">advanced dynamic usage requires a full node-function (which can be added to the</span>
|
|
<span class="sd">generated dict, as said).</span>
|
|
|
|
<span class="sd">Adding `(..)` to a goto treats it as a callable and it must then be included in</span>
|
|
<span class="sd">the `goto_callable` mapping. Only named keywords (or no args at all) are</span>
|
|
<span class="sd">allowed, these will be added to the `**kwargs` going into the callable. Quoting</span>
|
|
<span class="sd">strings is only needed if wanting to pass strippable spaces, otherwise the</span>
|
|
<span class="sd">key:values will be converted to strings/numbers with literal_eval before passed</span>
|
|
<span class="sd">into the callable.</span>
|
|
|
|
<span class="sd">The \\> option takes a glob or regex to perform different actions depending</span>
|
|
<span class="sd">on user input. Make sure to sort these in increasing order of generality since</span>
|
|
<span class="sd">they will be tested in sequence.</span>
|
|
|
|
<span class="sd">----</span>
|
|
|
|
<span class="sd">"""</span>
|
|
|
|
<span class="kn">import</span> <span class="nn">re</span>
|
|
<span class="kn">import</span> <span class="nn">inspect</span>
|
|
|
|
<span class="kn">from</span> <span class="nn">ast</span> <span class="kn">import</span> <span class="n">literal_eval</span>
|
|
<span class="kn">from</span> <span class="nn">fnmatch</span> <span class="kn">import</span> <span class="n">fnmatch</span>
|
|
|
|
<span class="kn">from</span> <span class="nn">inspect</span> <span class="kn">import</span> <span class="n">isfunction</span><span class="p">,</span> <span class="n">getargspec</span>
|
|
<span class="kn">from</span> <span class="nn">django.conf</span> <span class="kn">import</span> <span class="n">settings</span>
|
|
<span class="kn">from</span> <span class="nn">evennia</span> <span class="kn">import</span> <span class="n">Command</span><span class="p">,</span> <span class="n">CmdSet</span>
|
|
<span class="kn">from</span> <span class="nn">evennia.utils</span> <span class="kn">import</span> <span class="n">logger</span>
|
|
<span class="kn">from</span> <span class="nn">evennia.utils.evtable</span> <span class="kn">import</span> <span class="n">EvTable</span>
|
|
<span class="kn">from</span> <span class="nn">evennia.utils.ansi</span> <span class="kn">import</span> <span class="n">strip_ansi</span>
|
|
<span class="kn">from</span> <span class="nn">evennia.utils.utils</span> <span class="kn">import</span> <span class="n">mod_import</span><span class="p">,</span> <span class="n">make_iter</span><span class="p">,</span> <span class="n">pad</span><span class="p">,</span> <span class="n">to_str</span><span class="p">,</span> <span class="n">m_len</span><span class="p">,</span> <span class="n">is_iter</span><span class="p">,</span> <span class="n">dedent</span><span class="p">,</span> <span class="n">crop</span>
|
|
<span class="kn">from</span> <span class="nn">evennia.commands</span> <span class="kn">import</span> <span class="n">cmdhandler</span>
|
|
|
|
<span class="c1"># i18n</span>
|
|
<span class="kn">from</span> <span class="nn">django.utils.translation</span> <span class="kn">import</span> <span class="n">gettext</span> <span class="k">as</span> <span class="n">_</span>
|
|
|
|
<span class="c1"># read from protocol NAWS later?</span>
|
|
<span class="n">_MAX_TEXT_WIDTH</span> <span class="o">=</span> <span class="n">settings</span><span class="o">.</span><span class="n">CLIENT_DEFAULT_WIDTH</span>
|
|
|
|
<span class="c1"># we use cmdhandler instead of evennia.syscmdkeys to</span>
|
|
<span class="c1"># avoid some cases of loading before evennia init'd</span>
|
|
<span class="n">_CMD_NOMATCH</span> <span class="o">=</span> <span class="n">cmdhandler</span><span class="o">.</span><span class="n">CMD_NOMATCH</span>
|
|
<span class="n">_CMD_NOINPUT</span> <span class="o">=</span> <span class="n">cmdhandler</span><span class="o">.</span><span class="n">CMD_NOINPUT</span>
|
|
|
|
<span class="c1"># Return messages</span>
|
|
|
|
|
|
<span class="n">_ERR_NOT_IMPLEMENTED</span> <span class="o">=</span> <span class="n">_</span><span class="p">(</span>
|
|
<span class="s2">"Menu node '</span><span class="si">{nodename}</span><span class="s2">' is either not implemented or caused an error. "</span>
|
|
<span class="s2">"Make another choice or try 'q' to abort."</span>
|
|
<span class="p">)</span>
|
|
<span class="n">_ERR_GENERAL</span> <span class="o">=</span> <span class="n">_</span><span class="p">(</span><span class="s2">"Error in menu node '</span><span class="si">{nodename}</span><span class="s2">'."</span><span class="p">)</span>
|
|
<span class="n">_ERR_NO_OPTION_DESC</span> <span class="o">=</span> <span class="n">_</span><span class="p">(</span><span class="s2">"No description."</span><span class="p">)</span>
|
|
<span class="n">_HELP_FULL</span> <span class="o">=</span> <span class="n">_</span><span class="p">(</span><span class="s2">"Commands: <menu option>, help, quit"</span><span class="p">)</span>
|
|
<span class="n">_HELP_NO_QUIT</span> <span class="o">=</span> <span class="n">_</span><span class="p">(</span><span class="s2">"Commands: <menu option>, help"</span><span class="p">)</span>
|
|
<span class="n">_HELP_NO_OPTIONS</span> <span class="o">=</span> <span class="n">_</span><span class="p">(</span><span class="s2">"Commands: help, quit"</span><span class="p">)</span>
|
|
<span class="n">_HELP_NO_OPTIONS_NO_QUIT</span> <span class="o">=</span> <span class="n">_</span><span class="p">(</span><span class="s2">"Commands: help"</span><span class="p">)</span>
|
|
<span class="n">_HELP_NO_OPTION_MATCH</span> <span class="o">=</span> <span class="n">_</span><span class="p">(</span><span class="s2">"Choose an option or try 'help'."</span><span class="p">)</span>
|
|
|
|
<span class="n">_ERROR_PERSISTENT_SAVING</span> <span class="o">=</span> <span class="s2">"""</span>
|
|
<span class="si">{error}</span><span class="s2"></span>
|
|
|
|
<span class="s2">|rThe menu state could not be saved for persistent mode. Switching</span>
|
|
<span class="s2">to non-persistent mode (which means the menu session won't survive</span>
|
|
<span class="s2">an eventual server reload).|n</span>
|
|
<span class="s2">"""</span>
|
|
|
|
<span class="n">_TRACE_PERSISTENT_SAVING</span> <span class="o">=</span> <span class="p">(</span>
|
|
<span class="s2">"EvMenu persistent-mode error. Commonly, this is because one or "</span>
|
|
<span class="s2">"more of the EvEditor callbacks could not be pickled, for example "</span>
|
|
<span class="s2">"because it's a class method or is defined inside another function."</span>
|
|
<span class="p">)</span>
|
|
|
|
|
|
<div class="viewcode-block" id="EvMenuError"><a class="viewcode-back" href="../../../api/evennia.utils.evmenu.html#evennia.utils.evmenu.EvMenuError">[docs]</a><span class="k">class</span> <span class="nc">EvMenuError</span><span class="p">(</span><span class="ne">RuntimeError</span><span class="p">):</span>
|
|
<span class="sd">"""</span>
|
|
<span class="sd"> Error raised by menu when facing internal errors.</span>
|
|
|
|
<span class="sd"> """</span>
|
|
|
|
<span class="k">pass</span></div>
|
|
|
|
|
|
<div class="viewcode-block" id="EvMenuGotoAbortMessage"><a class="viewcode-back" href="../../../api/evennia.utils.evmenu.html#evennia.utils.evmenu.EvMenuGotoAbortMessage">[docs]</a><span class="k">class</span> <span class="nc">EvMenuGotoAbortMessage</span><span class="p">(</span><span class="ne">RuntimeError</span><span class="p">):</span>
|
|
<span class="sd">"""</span>
|
|
<span class="sd"> This can be raised by a goto-callable to abort the goto flow. The message</span>
|
|
<span class="sd"> stored with the executable will be sent to the caller who will remain on</span>
|
|
<span class="sd"> the current node. This can be used to pass single-line returns without</span>
|
|
<span class="sd"> re-running the entire node with text and options.</span>
|
|
|
|
<span class="sd"> Example:</span>
|
|
<span class="sd"> raise EvMenuGotoMessage("That makes no sense.")</span>
|
|
|
|
<span class="sd"> """</span></div>
|
|
|
|
|
|
<span class="c1"># -------------------------------------------------------------</span>
|
|
<span class="c1">#</span>
|
|
<span class="c1"># Menu command and command set</span>
|
|
<span class="c1">#</span>
|
|
<span class="c1"># -------------------------------------------------------------</span>
|
|
|
|
|
|
<div class="viewcode-block" id="CmdEvMenuNode"><a class="viewcode-back" href="../../../api/evennia.utils.evmenu.html#evennia.utils.evmenu.CmdEvMenuNode">[docs]</a><span class="k">class</span> <span class="nc">CmdEvMenuNode</span><span class="p">(</span><span class="n">Command</span><span class="p">):</span>
|
|
<span class="sd">"""</span>
|
|
<span class="sd"> Menu options.</span>
|
|
<span class="sd"> """</span>
|
|
|
|
<span class="n">key</span> <span class="o">=</span> <span class="n">_CMD_NOINPUT</span>
|
|
<span class="n">aliases</span> <span class="o">=</span> <span class="p">[</span><span class="n">_CMD_NOMATCH</span><span class="p">]</span>
|
|
<span class="n">locks</span> <span class="o">=</span> <span class="s2">"cmd:all()"</span>
|
|
<span class="n">help_category</span> <span class="o">=</span> <span class="s2">"Menu"</span>
|
|
<span class="n">auto_help_display_key</span> <span class="o">=</span> <span class="s2">"<menu commands>"</span>
|
|
|
|
<div class="viewcode-block" id="CmdEvMenuNode.get_help"><a class="viewcode-back" href="../../../api/evennia.utils.evmenu.html#evennia.utils.evmenu.CmdEvMenuNode.get_help">[docs]</a> <span class="k">def</span> <span class="nf">get_help</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
|
<span class="k">return</span> <span class="s2">"Menu commands are explained within the menu."</span></div>
|
|
|
|
<div class="viewcode-block" id="CmdEvMenuNode.func"><a class="viewcode-back" href="../../../api/evennia.utils.evmenu.html#evennia.utils.evmenu.CmdEvMenuNode.func">[docs]</a> <span class="k">def</span> <span class="nf">func</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
|
<span class="sd">"""</span>
|
|
<span class="sd"> Implement all menu commands.</span>
|
|
<span class="sd"> """</span>
|
|
|
|
<span class="k">def</span> <span class="nf">_restore</span><span class="p">(</span><span class="n">caller</span><span class="p">):</span>
|
|
<span class="c1"># check if there is a saved menu available.</span>
|
|
<span class="c1"># this will re-start a completely new evmenu call.</span>
|
|
<span class="n">saved_options</span> <span class="o">=</span> <span class="n">caller</span><span class="o">.</span><span class="n">attributes</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">"_menutree_saved"</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="n">saved_options</span><span class="p">:</span>
|
|
<span class="n">startnode_tuple</span> <span class="o">=</span> <span class="n">caller</span><span class="o">.</span><span class="n">attributes</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">"_menutree_saved_startnode"</span><span class="p">)</span>
|
|
<span class="k">try</span><span class="p">:</span>
|
|
<span class="n">startnode</span><span class="p">,</span> <span class="n">startnode_input</span> <span class="o">=</span> <span class="n">startnode_tuple</span>
|
|
<span class="k">except</span> <span class="ne">ValueError</span><span class="p">:</span> <span class="c1"># old form of startnode store</span>
|
|
<span class="n">startnode</span><span class="p">,</span> <span class="n">startnode_input</span> <span class="o">=</span> <span class="n">startnode_tuple</span><span class="p">,</span> <span class="s2">""</span>
|
|
<span class="k">if</span> <span class="n">startnode</span><span class="p">:</span>
|
|
<span class="n">saved_options</span><span class="p">[</span><span class="mi">2</span><span class="p">][</span><span class="s2">"startnode"</span><span class="p">]</span> <span class="o">=</span> <span class="n">startnode</span>
|
|
<span class="n">saved_options</span><span class="p">[</span><span class="mi">2</span><span class="p">][</span><span class="s2">"startnode_input"</span><span class="p">]</span> <span class="o">=</span> <span class="n">startnode_input</span>
|
|
<span class="n">MenuClass</span> <span class="o">=</span> <span class="n">saved_options</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
|
|
<span class="c1"># this will create a completely new menu call</span>
|
|
<span class="n">MenuClass</span><span class="p">(</span><span class="n">caller</span><span class="p">,</span> <span class="o">*</span><span class="n">saved_options</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="o">**</span><span class="n">saved_options</span><span class="p">[</span><span class="mi">2</span><span class="p">])</span>
|
|
<span class="k">return</span> <span class="kc">True</span>
|
|
<span class="k">return</span> <span class="kc">None</span>
|
|
|
|
<span class="n">caller</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">caller</span>
|
|
<span class="c1"># we store Session on the menu since this can be hard to</span>
|
|
<span class="c1"># get in multisession environemtns if caller is an Account.</span>
|
|
<span class="n">menu</span> <span class="o">=</span> <span class="n">caller</span><span class="o">.</span><span class="n">ndb</span><span class="o">.</span><span class="n">_evmenu</span>
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="n">menu</span><span class="p">:</span>
|
|
<span class="k">if</span> <span class="n">_restore</span><span class="p">(</span><span class="n">caller</span><span class="p">):</span>
|
|
<span class="k">return</span>
|
|
<span class="n">orig_caller</span> <span class="o">=</span> <span class="n">caller</span>
|
|
<span class="n">caller</span> <span class="o">=</span> <span class="n">caller</span><span class="o">.</span><span class="n">account</span> <span class="k">if</span> <span class="nb">hasattr</span><span class="p">(</span><span class="n">caller</span><span class="p">,</span> <span class="s2">"account"</span><span class="p">)</span> <span class="k">else</span> <span class="kc">None</span>
|
|
<span class="n">menu</span> <span class="o">=</span> <span class="n">caller</span><span class="o">.</span><span class="n">ndb</span><span class="o">.</span><span class="n">_evmenu</span> <span class="k">if</span> <span class="n">caller</span> <span class="k">else</span> <span class="kc">None</span>
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="n">menu</span><span class="p">:</span>
|
|
<span class="k">if</span> <span class="n">caller</span> <span class="ow">and</span> <span class="n">_restore</span><span class="p">(</span><span class="n">caller</span><span class="p">):</span>
|
|
<span class="k">return</span>
|
|
<span class="n">caller</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">session</span>
|
|
<span class="n">menu</span> <span class="o">=</span> <span class="n">caller</span><span class="o">.</span><span class="n">ndb</span><span class="o">.</span><span class="n">_evmenu</span>
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="n">menu</span><span class="p">:</span>
|
|
<span class="c1"># can't restore from a session</span>
|
|
<span class="n">err</span> <span class="o">=</span> <span class="s2">"Menu object not found as </span><span class="si">%s</span><span class="s2">.ndb._evmenu!"</span> <span class="o">%</span> <span class="n">orig_caller</span>
|
|
<span class="n">orig_caller</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span>
|
|
<span class="n">err</span>
|
|
<span class="p">)</span> <span class="c1"># don't give the session as a kwarg here, direct to original</span>
|
|
<span class="k">raise</span> <span class="n">EvMenuError</span><span class="p">(</span><span class="n">err</span><span class="p">)</span>
|
|
<span class="c1"># we must do this after the caller with the menu has been correctly identified since it</span>
|
|
<span class="c1"># can be either Account, Object or Session (in the latter case this info will be superfluous).</span>
|
|
<span class="n">caller</span><span class="o">.</span><span class="n">ndb</span><span class="o">.</span><span class="n">_evmenu</span><span class="o">.</span><span class="n">_session</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">session</span>
|
|
<span class="c1"># we have a menu, use it.</span>
|
|
<span class="n">menu</span><span class="o">.</span><span class="n">parse_input</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">raw_string</span><span class="p">)</span></div></div>
|
|
|
|
|
|
<div class="viewcode-block" id="EvMenuCmdSet"><a class="viewcode-back" href="../../../api/evennia.utils.evmenu.html#evennia.utils.evmenu.EvMenuCmdSet">[docs]</a><span class="k">class</span> <span class="nc">EvMenuCmdSet</span><span class="p">(</span><span class="n">CmdSet</span><span class="p">):</span>
|
|
<span class="sd">"""</span>
|
|
<span class="sd"> The Menu cmdset replaces the current cmdset.</span>
|
|
|
|
<span class="sd"> """</span>
|
|
|
|
<span class="n">key</span> <span class="o">=</span> <span class="s2">"menu_cmdset"</span>
|
|
<span class="n">priority</span> <span class="o">=</span> <span class="mi">1</span>
|
|
<span class="n">mergetype</span> <span class="o">=</span> <span class="s2">"Replace"</span>
|
|
<span class="n">no_objs</span> <span class="o">=</span> <span class="kc">True</span>
|
|
<span class="n">no_exits</span> <span class="o">=</span> <span class="kc">True</span>
|
|
<span class="n">no_channels</span> <span class="o">=</span> <span class="kc">False</span>
|
|
|
|
<div class="viewcode-block" id="EvMenuCmdSet.at_cmdset_creation"><a class="viewcode-back" href="../../../api/evennia.utils.evmenu.html#evennia.utils.evmenu.EvMenuCmdSet.at_cmdset_creation">[docs]</a> <span class="k">def</span> <span class="nf">at_cmdset_creation</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
|
<span class="sd">"""</span>
|
|
<span class="sd"> Called when creating the set.</span>
|
|
<span class="sd"> """</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">CmdEvMenuNode</span><span class="p">())</span></div></div>
|
|
|
|
|
|
<span class="c1"># ------------------------------------------------------------</span>
|
|
<span class="c1">#</span>
|
|
<span class="c1"># Menu main class</span>
|
|
<span class="c1">#</span>
|
|
<span class="c1"># -------------------------------------------------------------</span>
|
|
|
|
|
|
<div class="viewcode-block" id="EvMenu"><a class="viewcode-back" href="../../../api/evennia.utils.evmenu.html#evennia.utils.evmenu.EvMenu">[docs]</a><span class="k">class</span> <span class="nc">EvMenu</span><span class="p">:</span>
|
|
<span class="sd">"""</span>
|
|
<span class="sd"> This object represents an operational menu. It is initialized from</span>
|
|
<span class="sd"> a menufile.py instruction.</span>
|
|
|
|
<span class="sd"> """</span>
|
|
|
|
<span class="c1"># convenient helpers for easy overloading</span>
|
|
<span class="n">node_border_char</span> <span class="o">=</span> <span class="s2">"_"</span>
|
|
|
|
<div class="viewcode-block" id="EvMenu.__init__"><a class="viewcode-back" href="../../../api/evennia.utils.evmenu.html#evennia.utils.evmenu.EvMenu.__init__">[docs]</a> <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span>
|
|
<span class="bp">self</span><span class="p">,</span>
|
|
<span class="n">caller</span><span class="p">,</span>
|
|
<span class="n">menudata</span><span class="p">,</span>
|
|
<span class="n">startnode</span><span class="o">=</span><span class="s2">"start"</span><span class="p">,</span>
|
|
<span class="n">cmdset_mergetype</span><span class="o">=</span><span class="s2">"Replace"</span><span class="p">,</span>
|
|
<span class="n">cmdset_priority</span><span class="o">=</span><span class="mi">1</span><span class="p">,</span>
|
|
<span class="n">auto_quit</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span>
|
|
<span class="n">auto_look</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span>
|
|
<span class="n">auto_help</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span>
|
|
<span class="n">cmd_on_exit</span><span class="o">=</span><span class="s2">"look"</span><span class="p">,</span>
|
|
<span class="n">persistent</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span>
|
|
<span class="n">startnode_input</span><span class="o">=</span><span class="s2">""</span><span class="p">,</span>
|
|
<span class="n">session</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
|
|
<span class="n">debug</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span>
|
|
<span class="o">**</span><span class="n">kwargs</span><span class="p">,</span>
|
|
<span class="p">):</span>
|
|
<span class="sd">"""</span>
|
|
<span class="sd"> Initialize the menu tree and start the caller onto the first node.</span>
|
|
|
|
<span class="sd"> Args:</span>
|
|
<span class="sd"> caller (Object, Account or Session): The user of the menu.</span>
|
|
<span class="sd"> menudata (str, module or dict): The full or relative path to the module</span>
|
|
<span class="sd"> holding the menu tree data. All global functions in this module</span>
|
|
<span class="sd"> whose name doesn't start with '_ ' will be parsed as menu nodes.</span>
|
|
<span class="sd"> Also the module itself is accepted as input. Finally, a dictionary</span>
|
|
<span class="sd"> menu tree can be given directly. This must then be a mapping</span>
|
|
<span class="sd"> `{"nodekey":callable,...}` where `callable` must be called as</span>
|
|
<span class="sd"> and return the data expected of a menu node. This allows for</span>
|
|
<span class="sd"> dynamic menu creation.</span>
|
|
<span class="sd"> startnode (str, optional): The starting node name in the menufile.</span>
|
|
<span class="sd"> cmdset_mergetype (str, optional): 'Replace' (default) means the menu</span>
|
|
<span class="sd"> commands will be exclusive - no other normal commands will</span>
|
|
<span class="sd"> be usable while the user is in the menu. 'Union' means the</span>
|
|
<span class="sd"> menu commands will be integrated with the existing commands</span>
|
|
<span class="sd"> (it will merge with `merge_priority`), if so, make sure that</span>
|
|
<span class="sd"> the menu's command names don't collide with existing commands</span>
|
|
<span class="sd"> in an unexpected way. Also the CMD_NOMATCH and CMD_NOINPUT will</span>
|
|
<span class="sd"> be overloaded by the menu cmdset. Other cmdser mergetypes</span>
|
|
<span class="sd"> has little purpose for the menu.</span>
|
|
<span class="sd"> cmdset_priority (int, optional): The merge priority for the</span>
|
|
<span class="sd"> menu command set. The default (1) is usually enough for most</span>
|
|
<span class="sd"> types of menus.</span>
|
|
<span class="sd"> auto_quit (bool, optional): Allow user to use "q", "quit" or</span>
|
|
<span class="sd"> "exit" to leave the menu at any point. Recommended during</span>
|
|
<span class="sd"> development!</span>
|
|
<span class="sd"> auto_look (bool, optional): Automatically make "looK" or "l" to</span>
|
|
<span class="sd"> re-show the last node. Turning this off means you have to handle</span>
|
|
<span class="sd"> re-showing nodes yourself, but may be useful if you need to</span>
|
|
<span class="sd"> use "l" for some other purpose.</span>
|
|
<span class="sd"> auto_help (bool, optional): Automatically make "help" or "h" show</span>
|
|
<span class="sd"> the current help entry for the node. If turned off, eventual</span>
|
|
<span class="sd"> help must be handled manually, but it may be useful if you</span>
|
|
<span class="sd"> need 'h' for some other purpose, for example.</span>
|
|
<span class="sd"> cmd_on_exit (callable, str or None, optional): When exiting the menu</span>
|
|
<span class="sd"> (either by reaching a node with no options or by using the</span>
|
|
<span class="sd"> in-built quit command (activated with `allow_quit`), this</span>
|
|
<span class="sd"> callback function or command string will be executed.</span>
|
|
<span class="sd"> The callback function takes two parameters, the caller then the</span>
|
|
<span class="sd"> EvMenu object. This is called after cleanup is complete.</span>
|
|
<span class="sd"> Set to None to not call any command.</span>
|
|
<span class="sd"> persistent (bool, optional): Make the Menu persistent (i.e. it will</span>
|
|
<span class="sd"> survive a reload. This will make the Menu cmdset persistent. Use</span>
|
|
<span class="sd"> with caution - if your menu is buggy you may end up in a state</span>
|
|
<span class="sd"> you can't get out of! Also note that persistent mode requires</span>
|
|
<span class="sd"> that all formatters, menu nodes and callables are possible to</span>
|
|
<span class="sd"> *pickle*. When the server is reloaded, the latest node shown will be completely</span>
|
|
<span class="sd"> re-run with the same input arguments - so be careful if you are counting</span>
|
|
<span class="sd"> up some persistent counter or similar - the counter may be run twice if</span>
|
|
<span class="sd"> reload happens on the node that does that. Note that if `debug` is True,</span>
|
|
<span class="sd"> this setting is ignored and assumed to be False.</span>
|
|
<span class="sd"> startnode_input (str or (str, dict), optional): Send an input text to `startnode` as if</span>
|
|
<span class="sd"> a user input text from a fictional previous node. If including the dict, this will</span>
|
|
<span class="sd"> be passed as **kwargs to that node. When the server reloads,</span>
|
|
<span class="sd"> the latest visited node will be re-run as `node(caller, raw_string, **kwargs)`.</span>
|
|
<span class="sd"> session (Session, optional): This is useful when calling EvMenu from an account</span>
|
|
<span class="sd"> in multisession mode > 2. Note that this session only really relevant</span>
|
|
<span class="sd"> for the very first display of the first node - after that, EvMenu itself</span>
|
|
<span class="sd"> will keep the session updated from the command input. So a persistent</span>
|
|
<span class="sd"> menu will *not* be using this same session anymore after a reload.</span>
|
|
<span class="sd"> debug (bool, optional): If set, the 'menudebug' command will be made available</span>
|
|
<span class="sd"> by default in all nodes of the menu. This will print out the current state of</span>
|
|
<span class="sd"> the menu. Deactivate for production use! When the debug flag is active, the</span>
|
|
<span class="sd"> `persistent` flag is deactivated.</span>
|
|
<span class="sd"> **kwargs: All kwargs will become initialization variables on `caller.ndb._menutree`,</span>
|
|
<span class="sd"> to be available at run.</span>
|
|
|
|
<span class="sd"> Raises:</span>
|
|
<span class="sd"> EvMenuError: If the start/end node is not found in menu tree.</span>
|
|
|
|
<span class="sd"> Notes:</span>
|
|
<span class="sd"> While running, the menu is stored on the caller as `caller.ndb._evmenu`. Also</span>
|
|
<span class="sd"> the current Session (from the Command, so this is still valid in multisession</span>
|
|
<span class="sd"> environments) is available through `caller.ndb._evmenu._session`. The `_evmenu`</span>
|
|
<span class="sd"> property is a good one for storing intermediary data on between nodes since it</span>
|
|
<span class="sd"> will be automatically deleted when the menu closes.</span>
|
|
|
|
<span class="sd"> In persistent mode, all nodes, formatters and callbacks in the menu must be</span>
|
|
<span class="sd"> possible to be *pickled*, this excludes e.g. callables that are class methods</span>
|
|
<span class="sd"> or functions defined dynamically or as part of another function. In</span>
|
|
<span class="sd"> non-persistent mode no such restrictions exist.</span>
|
|
|
|
<span class="sd"> """</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_startnode</span> <span class="o">=</span> <span class="n">startnode</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_menutree</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_parse_menudata</span><span class="p">(</span><span class="n">menudata</span><span class="p">)</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_persistent</span> <span class="o">=</span> <span class="n">persistent</span> <span class="k">if</span> <span class="ow">not</span> <span class="n">debug</span> <span class="k">else</span> <span class="kc">False</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_quitting</span> <span class="o">=</span> <span class="kc">False</span>
|
|
|
|
<span class="k">if</span> <span class="n">startnode</span> <span class="ow">not</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">_menutree</span><span class="p">:</span>
|
|
<span class="k">raise</span> <span class="n">EvMenuError</span><span class="p">(</span><span class="s2">"Start node '</span><span class="si">%s</span><span class="s2">' not in menu tree!"</span> <span class="o">%</span> <span class="n">startnode</span><span class="p">)</span>
|
|
|
|
<span class="c1"># public variables made available to the command</span>
|
|
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">caller</span> <span class="o">=</span> <span class="n">caller</span>
|
|
|
|
<span class="c1"># track EvMenu kwargs</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">auto_quit</span> <span class="o">=</span> <span class="n">auto_quit</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">auto_look</span> <span class="o">=</span> <span class="n">auto_look</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">auto_help</span> <span class="o">=</span> <span class="n">auto_help</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">debug_mode</span> <span class="o">=</span> <span class="n">debug</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_session</span> <span class="o">=</span> <span class="n">session</span>
|
|
<span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">cmd_on_exit</span><span class="p">,</span> <span class="nb">str</span><span class="p">):</span>
|
|
<span class="c1"># At this point menu._session will have been replaced by the</span>
|
|
<span class="c1"># menu command to the actual session calling.</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">cmd_on_exit</span> <span class="o">=</span> <span class="k">lambda</span> <span class="n">caller</span><span class="p">,</span> <span class="n">menu</span><span class="p">:</span> <span class="n">caller</span><span class="o">.</span><span class="n">execute_cmd</span><span class="p">(</span>
|
|
<span class="n">cmd_on_exit</span><span class="p">,</span> <span class="n">session</span><span class="o">=</span><span class="n">menu</span><span class="o">.</span><span class="n">_session</span>
|
|
<span class="p">)</span>
|
|
<span class="k">elif</span> <span class="n">callable</span><span class="p">(</span><span class="n">cmd_on_exit</span><span class="p">):</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">cmd_on_exit</span> <span class="o">=</span> <span class="n">cmd_on_exit</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">cmd_on_exit</span> <span class="o">=</span> <span class="kc">None</span>
|
|
<span class="c1"># current menu state</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">default</span> <span class="o">=</span> <span class="kc">None</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">nodetext</span> <span class="o">=</span> <span class="kc">None</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">helptext</span> <span class="o">=</span> <span class="kc">None</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">options</span> <span class="o">=</span> <span class="kc">None</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">nodename</span> <span class="o">=</span> <span class="kc">None</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">node_kwargs</span> <span class="o">=</span> <span class="p">{}</span>
|
|
|
|
<span class="c1"># used for testing</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">test_options</span> <span class="o">=</span> <span class="p">{}</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">test_nodetext</span> <span class="o">=</span> <span class="s2">""</span>
|
|
|
|
<span class="c1"># assign kwargs as initialization vars on ourselves.</span>
|
|
<span class="n">reserved_clash</span> <span class="o">=</span> <span class="nb">set</span><span class="p">(</span>
|
|
<span class="p">(</span>
|
|
<span class="s2">"_startnode"</span><span class="p">,</span>
|
|
<span class="s2">"_menutree"</span><span class="p">,</span>
|
|
<span class="s2">"_session"</span><span class="p">,</span>
|
|
<span class="s2">"_persistent"</span><span class="p">,</span>
|
|
<span class="s2">"cmd_on_exit"</span><span class="p">,</span>
|
|
<span class="s2">"default"</span><span class="p">,</span>
|
|
<span class="s2">"nodetext"</span><span class="p">,</span>
|
|
<span class="s2">"helptext"</span><span class="p">,</span>
|
|
<span class="s2">"options"</span><span class="p">,</span>
|
|
<span class="s2">"cmdset_mergetype"</span><span class="p">,</span>
|
|
<span class="s2">"auto_quit"</span><span class="p">,</span>
|
|
<span class="p">)</span>
|
|
<span class="p">)</span><span class="o">.</span><span class="n">intersection</span><span class="p">(</span><span class="nb">set</span><span class="p">(</span><span class="n">kwargs</span><span class="o">.</span><span class="n">keys</span><span class="p">()))</span>
|
|
<span class="k">if</span> <span class="n">reserved_clash</span><span class="p">:</span>
|
|
<span class="k">raise</span> <span class="ne">RuntimeError</span><span class="p">(</span>
|
|
<span class="sa">f</span><span class="s2">"One or more of the EvMenu `**kwargs` (</span><span class="si">{</span><span class="nb">list</span><span class="p">(</span><span class="n">reserved_clash</span><span class="p">)</span><span class="si">}</span><span class="s2">) is reserved by EvMenu for internal use."</span>
|
|
<span class="p">)</span>
|
|
<span class="k">for</span> <span class="n">key</span><span class="p">,</span> <span class="n">val</span> <span class="ow">in</span> <span class="n">kwargs</span><span class="o">.</span><span class="n">items</span><span class="p">():</span>
|
|
<span class="nb">setattr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">key</span><span class="p">,</span> <span class="n">val</span><span class="p">)</span>
|
|
|
|
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">caller</span><span class="o">.</span><span class="n">ndb</span><span class="o">.</span><span class="n">_evmenu</span><span class="p">:</span>
|
|
<span class="c1"># an evmenu already exists - we try to close it cleanly. Note that this will</span>
|
|
<span class="c1"># not fire the previous menu's end node.</span>
|
|
<span class="k">try</span><span class="p">:</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">caller</span><span class="o">.</span><span class="n">ndb</span><span class="o">.</span><span class="n">_evmenu</span><span class="o">.</span><span class="n">close_menu</span><span class="p">()</span>
|
|
<span class="k">except</span> <span class="ne">Exception</span><span class="p">:</span>
|
|
<span class="k">pass</span>
|
|
|
|
<span class="c1"># store ourself on the object</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">caller</span><span class="o">.</span><span class="n">ndb</span><span class="o">.</span><span class="n">_evmenu</span> <span class="o">=</span> <span class="bp">self</span>
|
|
|
|
<span class="c1"># DEPRECATED - for backwards-compatibility</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">caller</span><span class="o">.</span><span class="n">ndb</span><span class="o">.</span><span class="n">_menutree</span> <span class="o">=</span> <span class="bp">self</span>
|
|
|
|
<span class="k">if</span> <span class="n">persistent</span><span class="p">:</span>
|
|
<span class="c1"># save the menu to the database</span>
|
|
<span class="n">calldict</span> <span class="o">=</span> <span class="p">{</span>
|
|
<span class="s2">"startnode"</span><span class="p">:</span> <span class="n">startnode</span><span class="p">,</span>
|
|
<span class="s2">"cmdset_mergetype"</span><span class="p">:</span> <span class="n">cmdset_mergetype</span><span class="p">,</span>
|
|
<span class="s2">"cmdset_priority"</span><span class="p">:</span> <span class="n">cmdset_priority</span><span class="p">,</span>
|
|
<span class="s2">"auto_quit"</span><span class="p">:</span> <span class="n">auto_quit</span><span class="p">,</span>
|
|
<span class="s2">"auto_look"</span><span class="p">:</span> <span class="n">auto_look</span><span class="p">,</span>
|
|
<span class="s2">"auto_help"</span><span class="p">:</span> <span class="n">auto_help</span><span class="p">,</span>
|
|
<span class="s2">"cmd_on_exit"</span><span class="p">:</span> <span class="n">cmd_on_exit</span><span class="p">,</span>
|
|
<span class="s2">"persistent"</span><span class="p">:</span> <span class="n">persistent</span><span class="p">,</span>
|
|
<span class="p">}</span>
|
|
<span class="n">calldict</span><span class="o">.</span><span class="n">update</span><span class="p">(</span><span class="n">kwargs</span><span class="p">)</span>
|
|
<span class="k">try</span><span class="p">:</span>
|
|
<span class="n">caller</span><span class="o">.</span><span class="n">attributes</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="s2">"_menutree_saved"</span><span class="p">,</span> <span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="vm">__class__</span><span class="p">,</span> <span class="p">(</span><span class="n">menudata</span><span class="p">,),</span> <span class="n">calldict</span><span class="p">))</span>
|
|
<span class="n">caller</span><span class="o">.</span><span class="n">attributes</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="s2">"_menutree_saved_startnode"</span><span class="p">,</span> <span class="p">(</span><span class="n">startnode</span><span class="p">,</span> <span class="n">startnode_input</span><span class="p">))</span>
|
|
<span class="k">except</span> <span class="ne">Exception</span> <span class="k">as</span> <span class="n">err</span><span class="p">:</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="n">_ERROR_PERSISTENT_SAVING</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">error</span><span class="o">=</span><span class="n">err</span><span class="p">))</span>
|
|
<span class="n">logger</span><span class="o">.</span><span class="n">log_trace</span><span class="p">(</span><span class="n">_TRACE_PERSISTENT_SAVING</span><span class="p">)</span>
|
|
<span class="n">persistent</span> <span class="o">=</span> <span class="kc">False</span>
|
|
|
|
<span class="c1"># set up the menu command on the caller</span>
|
|
<span class="n">menu_cmdset</span> <span class="o">=</span> <span class="n">EvMenuCmdSet</span><span class="p">()</span>
|
|
<span class="n">menu_cmdset</span><span class="o">.</span><span class="n">mergetype</span> <span class="o">=</span> <span class="nb">str</span><span class="p">(</span><span class="n">cmdset_mergetype</span><span class="p">)</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span><span class="o">.</span><span class="n">capitalize</span><span class="p">()</span> <span class="ow">or</span> <span class="s2">"Replace"</span>
|
|
<span class="n">menu_cmdset</span><span class="o">.</span><span class="n">priority</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">cmdset_priority</span><span class="p">)</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">caller</span><span class="o">.</span><span class="n">cmdset</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">menu_cmdset</span><span class="p">,</span> <span class="n">permanent</span><span class="o">=</span><span class="n">persistent</span><span class="p">)</span>
|
|
|
|
<span class="n">reserved_startnode_kwargs</span> <span class="o">=</span> <span class="nb">set</span><span class="p">((</span><span class="s2">"nodename"</span><span class="p">,</span> <span class="s2">"raw_string"</span><span class="p">))</span>
|
|
<span class="n">startnode_kwargs</span> <span class="o">=</span> <span class="p">{}</span>
|
|
<span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">startnode_input</span><span class="p">,</span> <span class="p">(</span><span class="nb">tuple</span><span class="p">,</span> <span class="nb">list</span><span class="p">))</span> <span class="ow">and</span> <span class="nb">len</span><span class="p">(</span><span class="n">startnode_input</span><span class="p">)</span> <span class="o">></span> <span class="mi">1</span><span class="p">:</span>
|
|
<span class="n">startnode_input</span><span class="p">,</span> <span class="n">startnode_kwargs</span> <span class="o">=</span> <span class="n">startnode_input</span><span class="p">[:</span><span class="mi">2</span><span class="p">]</span>
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">startnode_kwargs</span><span class="p">,</span> <span class="nb">dict</span><span class="p">):</span>
|
|
<span class="k">raise</span> <span class="n">EvMenuError</span><span class="p">(</span><span class="s2">"startnode_input must be either a str or a tuple (str, dict)."</span><span class="p">)</span>
|
|
<span class="n">clashing_kwargs</span> <span class="o">=</span> <span class="n">reserved_startnode_kwargs</span><span class="o">.</span><span class="n">intersection</span><span class="p">(</span><span class="nb">set</span><span class="p">(</span><span class="n">startnode_kwargs</span><span class="o">.</span><span class="n">keys</span><span class="p">()))</span>
|
|
<span class="k">if</span> <span class="n">clashing_kwargs</span><span class="p">:</span>
|
|
<span class="k">raise</span> <span class="ne">RuntimeError</span><span class="p">(</span>
|
|
<span class="sa">f</span><span class="s2">"Evmenu startnode_inputs includes kwargs </span><span class="si">{</span><span class="nb">tuple</span><span class="p">(</span><span class="n">clashing_kwargs</span><span class="p">)</span><span class="si">}</span><span class="s2"> that "</span>
|
|
<span class="s2">"clashes with EvMenu's internal usage."</span>
|
|
<span class="p">)</span>
|
|
|
|
<span class="c1"># start the menu</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">goto</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_startnode</span><span class="p">,</span> <span class="n">startnode_input</span><span class="p">,</span> <span class="o">**</span><span class="n">startnode_kwargs</span><span class="p">)</span></div>
|
|
|
|
<span class="k">def</span> <span class="nf">_parse_menudata</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">menudata</span><span class="p">):</span>
|
|
<span class="sd">"""</span>
|
|
<span class="sd"> Parse a menufile for node functions and store in dictionary</span>
|
|
<span class="sd"> map. Alternatively, accept a pre-made mapping dictionary of</span>
|
|
<span class="sd"> node functions.</span>
|
|
|
|
<span class="sd"> Args:</span>
|
|
<span class="sd"> menudata (str, module or dict): The python.path to the menufile,</span>
|
|
<span class="sd"> or the python module itself. If a dict, this should be a</span>
|
|
<span class="sd"> mapping nodename:callable, where the callable must match</span>
|
|
<span class="sd"> the criteria for a menu node.</span>
|
|
|
|
<span class="sd"> Returns:</span>
|
|
<span class="sd"> menutree (dict): A {nodekey: func}</span>
|
|
|
|
<span class="sd"> """</span>
|
|
<span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">menudata</span><span class="p">,</span> <span class="nb">dict</span><span class="p">):</span>
|
|
<span class="c1"># This is assumed to be a pre-loaded menu tree.</span>
|
|
<span class="k">return</span> <span class="n">menudata</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="c1"># a python path of a module</span>
|
|
<span class="n">module</span> <span class="o">=</span> <span class="n">mod_import</span><span class="p">(</span><span class="n">menudata</span><span class="p">)</span>
|
|
<span class="k">return</span> <span class="nb">dict</span><span class="p">(</span>
|
|
<span class="p">(</span><span class="n">key</span><span class="p">,</span> <span class="n">func</span><span class="p">)</span>
|
|
<span class="k">for</span> <span class="n">key</span><span class="p">,</span> <span class="n">func</span> <span class="ow">in</span> <span class="n">module</span><span class="o">.</span><span class="vm">__dict__</span><span class="o">.</span><span class="n">items</span><span class="p">()</span>
|
|
<span class="k">if</span> <span class="n">isfunction</span><span class="p">(</span><span class="n">func</span><span class="p">)</span> <span class="ow">and</span> <span class="ow">not</span> <span class="n">key</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="s2">"_"</span><span class="p">)</span>
|
|
<span class="p">)</span>
|
|
|
|
<span class="k">def</span> <span class="nf">_format_node</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">nodetext</span><span class="p">,</span> <span class="n">optionlist</span><span class="p">):</span>
|
|
<span class="sd">"""</span>
|
|
<span class="sd"> Format the node text + option section</span>
|
|
|
|
<span class="sd"> Args:</span>
|
|
<span class="sd"> nodetext (str): The node text</span>
|
|
<span class="sd"> optionlist (list): List of (key, desc) pairs.</span>
|
|
|
|
<span class="sd"> Returns:</span>
|
|
<span class="sd"> string (str): The options section, including</span>
|
|
<span class="sd"> all needed spaces.</span>
|
|
|
|
<span class="sd"> Notes:</span>
|
|
<span class="sd"> This will adjust the columns of the options, first to use</span>
|
|
<span class="sd"> a maxiumum of 4 rows (expanding in columns), then gradually</span>
|
|
<span class="sd"> growing to make use of the screen space.</span>
|
|
|
|
<span class="sd"> """</span>
|
|
|
|
<span class="c1"># handle the node text</span>
|
|
<span class="n">nodetext</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">nodetext_formatter</span><span class="p">(</span><span class="n">nodetext</span><span class="p">)</span>
|
|
|
|
<span class="c1"># handle the options</span>
|
|
<span class="n">optionstext</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">options_formatter</span><span class="p">(</span><span class="n">optionlist</span><span class="p">)</span>
|
|
|
|
<span class="c1"># format the entire node</span>
|
|
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">node_formatter</span><span class="p">(</span><span class="n">nodetext</span><span class="p">,</span> <span class="n">optionstext</span><span class="p">)</span>
|
|
|
|
<span class="k">def</span> <span class="nf">_safe_call</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">callback</span><span class="p">,</span> <span class="n">raw_string</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
|
|
<span class="sd">"""</span>
|
|
<span class="sd"> Call a node-like callable, with a variable number of raw_string, *args, **kwargs, all of</span>
|
|
<span class="sd"> which should work also if not present (only `caller` is always required). Return its result.</span>
|
|
|
|
<span class="sd"> """</span>
|
|
<span class="k">try</span><span class="p">:</span>
|
|
<span class="k">try</span><span class="p">:</span>
|
|
<span class="n">nargs</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="n">getargspec</span><span class="p">(</span><span class="n">callback</span><span class="p">)</span><span class="o">.</span><span class="n">args</span><span class="p">)</span>
|
|
<span class="k">except</span> <span class="ne">TypeError</span><span class="p">:</span>
|
|
<span class="k">raise</span> <span class="n">EvMenuError</span><span class="p">(</span><span class="s2">"Callable </span><span class="si">{}</span><span class="s2"> doesn't accept any arguments!"</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">callback</span><span class="p">))</span>
|
|
<span class="n">supports_kwargs</span> <span class="o">=</span> <span class="nb">bool</span><span class="p">(</span><span class="n">getargspec</span><span class="p">(</span><span class="n">callback</span><span class="p">)</span><span class="o">.</span><span class="n">keywords</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="n">nargs</span> <span class="o"><=</span> <span class="mi">0</span><span class="p">:</span>
|
|
<span class="k">raise</span> <span class="n">EvMenuError</span><span class="p">(</span><span class="s2">"Callable </span><span class="si">{}</span><span class="s2"> doesn't accept any arguments!"</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">callback</span><span class="p">))</span>
|
|
|
|
<span class="k">if</span> <span class="n">supports_kwargs</span><span class="p">:</span>
|
|
<span class="k">if</span> <span class="n">nargs</span> <span class="o">></span> <span class="mi">1</span><span class="p">:</span>
|
|
<span class="n">ret</span> <span class="o">=</span> <span class="n">callback</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">caller</span><span class="p">,</span> <span class="n">raw_string</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">)</span>
|
|
<span class="c1"># callback accepting raw_string, **kwargs</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="c1"># callback accepting **kwargs</span>
|
|
<span class="n">ret</span> <span class="o">=</span> <span class="n">callback</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">caller</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">)</span>
|
|
<span class="k">elif</span> <span class="n">nargs</span> <span class="o">></span> <span class="mi">1</span><span class="p">:</span>
|
|
<span class="c1"># callback accepting raw_string</span>
|
|
<span class="n">ret</span> <span class="o">=</span> <span class="n">callback</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">caller</span><span class="p">,</span> <span class="n">raw_string</span><span class="p">)</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="c1"># normal callback, only the caller as arg</span>
|
|
<span class="n">ret</span> <span class="o">=</span> <span class="n">callback</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">caller</span><span class="p">)</span>
|
|
<span class="k">except</span> <span class="n">EvMenuError</span><span class="p">:</span>
|
|
<span class="n">errmsg</span> <span class="o">=</span> <span class="n">_ERR_GENERAL</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">nodename</span><span class="o">=</span><span class="n">callback</span><span class="p">)</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="n">errmsg</span><span class="p">)</span>
|
|
<span class="n">logger</span><span class="o">.</span><span class="n">log_trace</span><span class="p">()</span>
|
|
<span class="k">raise</span>
|
|
|
|
<span class="k">return</span> <span class="n">ret</span>
|
|
|
|
<span class="k">def</span> <span class="nf">_execute_node</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">nodename</span><span class="p">,</span> <span class="n">raw_string</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
|
|
<span class="sd">"""</span>
|
|
<span class="sd"> Execute a node.</span>
|
|
|
|
<span class="sd"> Args:</span>
|
|
<span class="sd"> nodename (str): Name of node.</span>
|
|
<span class="sd"> raw_string (str): The raw default string entered on the</span>
|
|
<span class="sd"> previous node (only used if the node accepts it as an</span>
|
|
<span class="sd"> argument)</span>
|
|
<span class="sd"> kwargs (any, optional): Optional kwargs for the node.</span>
|
|
|
|
<span class="sd"> Returns:</span>
|
|
<span class="sd"> nodetext, options (tuple): The node text (a string or a</span>
|
|
<span class="sd"> tuple and the options tuple, if any.</span>
|
|
|
|
<span class="sd"> """</span>
|
|
<span class="k">try</span><span class="p">:</span>
|
|
<span class="n">node</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_menutree</span><span class="p">[</span><span class="n">nodename</span><span class="p">]</span>
|
|
<span class="k">except</span> <span class="ne">KeyError</span><span class="p">:</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="n">_ERR_NOT_IMPLEMENTED</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">nodename</span><span class="o">=</span><span class="n">nodename</span><span class="p">))</span>
|
|
<span class="k">raise</span> <span class="n">EvMenuError</span>
|
|
<span class="k">try</span><span class="p">:</span>
|
|
<span class="n">kwargs</span><span class="p">[</span><span class="s2">"_current_nodename"</span><span class="p">]</span> <span class="o">=</span> <span class="n">nodename</span>
|
|
<span class="n">ret</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_safe_call</span><span class="p">(</span><span class="n">node</span><span class="p">,</span> <span class="n">raw_string</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">ret</span><span class="p">,</span> <span class="p">(</span><span class="nb">tuple</span><span class="p">,</span> <span class="nb">list</span><span class="p">))</span> <span class="ow">and</span> <span class="nb">len</span><span class="p">(</span><span class="n">ret</span><span class="p">)</span> <span class="o">></span> <span class="mi">1</span><span class="p">:</span>
|
|
<span class="n">nodetext</span><span class="p">,</span> <span class="n">options</span> <span class="o">=</span> <span class="n">ret</span><span class="p">[:</span><span class="mi">2</span><span class="p">]</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="n">nodetext</span><span class="p">,</span> <span class="n">options</span> <span class="o">=</span> <span class="n">ret</span><span class="p">,</span> <span class="kc">None</span>
|
|
<span class="k">except</span> <span class="ne">KeyError</span><span class="p">:</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="n">_ERR_NOT_IMPLEMENTED</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">nodename</span><span class="o">=</span><span class="n">nodename</span><span class="p">))</span>
|
|
<span class="n">logger</span><span class="o">.</span><span class="n">log_trace</span><span class="p">()</span>
|
|
<span class="k">raise</span> <span class="n">EvMenuError</span>
|
|
<span class="k">except</span> <span class="ne">Exception</span><span class="p">:</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="n">_ERR_GENERAL</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">nodename</span><span class="o">=</span><span class="n">nodename</span><span class="p">))</span>
|
|
<span class="n">logger</span><span class="o">.</span><span class="n">log_trace</span><span class="p">()</span>
|
|
<span class="k">raise</span>
|
|
|
|
<span class="c1"># store options to make them easier to test</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">test_options</span> <span class="o">=</span> <span class="n">options</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">test_nodetext</span> <span class="o">=</span> <span class="n">nodetext</span>
|
|
|
|
<span class="k">return</span> <span class="n">nodetext</span><span class="p">,</span> <span class="n">options</span>
|
|
|
|
<div class="viewcode-block" id="EvMenu.msg"><a class="viewcode-back" href="../../../api/evennia.utils.evmenu.html#evennia.utils.evmenu.EvMenu.msg">[docs]</a> <span class="k">def</span> <span class="nf">msg</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">txt</span><span class="p">):</span>
|
|
<span class="sd">"""</span>
|
|
<span class="sd"> This is a central point for sending return texts to the caller. It</span>
|
|
<span class="sd"> allows for a central point to add custom messaging when creating custom</span>
|
|
<span class="sd"> EvMenu overrides.</span>
|
|
|
|
<span class="sd"> Args:</span>
|
|
<span class="sd"> txt (str): The text to send.</span>
|
|
|
|
<span class="sd"> Notes:</span>
|
|
<span class="sd"> By default this will send to the same session provided to EvMenu</span>
|
|
<span class="sd"> (if `session` kwarg was provided to `EvMenu.__init__`). It will</span>
|
|
<span class="sd"> also send it with a `type=menu` for the benefit of OOB/webclient.</span>
|
|
|
|
<span class="sd"> """</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">caller</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="n">text</span><span class="o">=</span><span class="p">(</span><span class="n">txt</span><span class="p">,</span> <span class="p">{</span><span class="s2">"type"</span><span class="p">:</span> <span class="s2">"menu"</span><span class="p">}),</span> <span class="n">session</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">_session</span><span class="p">)</span></div>
|
|
|
|
<div class="viewcode-block" id="EvMenu.run_exec"><a class="viewcode-back" href="../../../api/evennia.utils.evmenu.html#evennia.utils.evmenu.EvMenu.run_exec">[docs]</a> <span class="k">def</span> <span class="nf">run_exec</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">nodename</span><span class="p">,</span> <span class="n">raw_string</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
|
|
<span class="sd">"""</span>
|
|
<span class="sd"> NOTE: This is deprecated. Use `goto` directly instead.</span>
|
|
|
|
<span class="sd"> Run a function or node as a callback (with the 'exec' option key).</span>
|
|
|
|
<span class="sd"> Args:</span>
|
|
<span class="sd"> nodename (callable or str): A callable to run as</span>
|
|
<span class="sd"> `callable(caller, raw_string)`, or the Name of an existing</span>
|
|
<span class="sd"> node to run as a callable. This may or may not return</span>
|
|
<span class="sd"> a string.</span>
|
|
<span class="sd"> raw_string (str): The raw default string entered on the</span>
|
|
<span class="sd"> previous node (only used if the node accepts it as an</span>
|
|
<span class="sd"> argument)</span>
|
|
<span class="sd"> kwargs (any): These are optional kwargs passed into goto</span>
|
|
|
|
<span class="sd"> Returns:</span>
|
|
<span class="sd"> new_goto (str or None): A replacement goto location string or</span>
|
|
<span class="sd"> None (no replacement).</span>
|
|
<span class="sd"> Notes:</span>
|
|
<span class="sd"> Relying on exec callbacks to set the goto location is</span>
|
|
<span class="sd"> very powerful but will easily lead to spaghetti structure and</span>
|
|
<span class="sd"> hard-to-trace paths through the menu logic. So be careful with</span>
|
|
<span class="sd"> relying on this.</span>
|
|
|
|
<span class="sd"> """</span>
|
|
<span class="k">try</span><span class="p">:</span>
|
|
<span class="k">if</span> <span class="n">callable</span><span class="p">(</span><span class="n">nodename</span><span class="p">):</span>
|
|
<span class="c1"># this is a direct callable - execute it directly</span>
|
|
<span class="n">ret</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_safe_call</span><span class="p">(</span><span class="n">nodename</span><span class="p">,</span> <span class="n">raw_string</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">ret</span><span class="p">,</span> <span class="p">(</span><span class="nb">tuple</span><span class="p">,</span> <span class="nb">list</span><span class="p">)):</span>
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="nb">len</span><span class="p">(</span><span class="n">ret</span><span class="p">)</span> <span class="o">></span> <span class="mi">1</span> <span class="ow">or</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">ret</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="nb">dict</span><span class="p">):</span>
|
|
<span class="k">raise</span> <span class="n">EvMenuError</span><span class="p">(</span>
|
|
<span class="s2">"exec callable must return either None, str or (str, dict)"</span>
|
|
<span class="p">)</span>
|
|
<span class="n">ret</span><span class="p">,</span> <span class="n">kwargs</span> <span class="o">=</span> <span class="n">ret</span><span class="p">[:</span><span class="mi">2</span><span class="p">]</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="c1"># nodename is a string; lookup as node and run as node in-place (don't goto it)</span>
|
|
<span class="c1"># execute the node</span>
|
|
<span class="n">ret</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_execute_node</span><span class="p">(</span><span class="n">nodename</span><span class="p">,</span> <span class="n">raw_string</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">ret</span><span class="p">,</span> <span class="p">(</span><span class="nb">tuple</span><span class="p">,</span> <span class="nb">list</span><span class="p">)):</span>
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="nb">len</span><span class="p">(</span><span class="n">ret</span><span class="p">)</span> <span class="o">></span> <span class="mi">1</span> <span class="ow">and</span> <span class="n">ret</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="ow">and</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">ret</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="nb">dict</span><span class="p">):</span>
|
|
<span class="k">raise</span> <span class="n">EvMenuError</span><span class="p">(</span><span class="s2">"exec node must return either None, str or (str, dict)"</span><span class="p">)</span>
|
|
<span class="n">ret</span><span class="p">,</span> <span class="n">kwargs</span> <span class="o">=</span> <span class="n">ret</span><span class="p">[:</span><span class="mi">2</span><span class="p">]</span>
|
|
<span class="k">except</span> <span class="n">EvMenuError</span> <span class="k">as</span> <span class="n">err</span><span class="p">:</span>
|
|
<span class="n">errmsg</span> <span class="o">=</span> <span class="s2">"Error in exec '</span><span class="si">%s</span><span class="s2">' (input: '</span><span class="si">%s</span><span class="s2">'): </span><span class="si">%s</span><span class="s2">"</span> <span class="o">%</span> <span class="p">(</span><span class="n">nodename</span><span class="p">,</span> <span class="n">raw_string</span><span class="o">.</span><span class="n">rstrip</span><span class="p">(),</span> <span class="n">err</span><span class="p">)</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="s2">"|r</span><span class="si">%s</span><span class="s2">|n"</span> <span class="o">%</span> <span class="n">errmsg</span><span class="p">)</span>
|
|
<span class="n">logger</span><span class="o">.</span><span class="n">log_trace</span><span class="p">(</span><span class="n">errmsg</span><span class="p">)</span>
|
|
<span class="k">return</span>
|
|
|
|
<span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">ret</span><span class="p">,</span> <span class="nb">str</span><span class="p">):</span>
|
|
<span class="c1"># only return a value if a string (a goto target), ignore all other returns</span>
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="n">ret</span><span class="p">:</span>
|
|
<span class="c1"># an empty string - rerun the same node</span>
|
|
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">nodename</span>
|
|
<span class="k">return</span> <span class="n">ret</span><span class="p">,</span> <span class="n">kwargs</span>
|
|
<span class="k">return</span> <span class="kc">None</span></div>
|
|
|
|
<div class="viewcode-block" id="EvMenu.extract_goto_exec"><a class="viewcode-back" href="../../../api/evennia.utils.evmenu.html#evennia.utils.evmenu.EvMenu.extract_goto_exec">[docs]</a> <span class="k">def</span> <span class="nf">extract_goto_exec</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">nodename</span><span class="p">,</span> <span class="n">option_dict</span><span class="p">):</span>
|
|
<span class="sd">"""</span>
|
|
<span class="sd"> Helper: Get callables and their eventual kwargs.</span>
|
|
|
|
<span class="sd"> Args:</span>
|
|
<span class="sd"> nodename (str): The current node name (used for error reporting).</span>
|
|
<span class="sd"> option_dict (dict): The seleted option's dict.</span>
|
|
|
|
<span class="sd"> Returns:</span>
|
|
<span class="sd"> goto (str, callable or None): The goto directive in the option.</span>
|
|
<span class="sd"> goto_kwargs (dict): Kwargs for `goto` if the former is callable, otherwise empty.</span>
|
|
<span class="sd"> execute (callable or None): Executable given by the `exec` directive.</span>
|
|
<span class="sd"> exec_kwargs (dict): Kwargs for `execute` if it's callable, otherwise empty.</span>
|
|
|
|
<span class="sd"> """</span>
|
|
<span class="n">goto_kwargs</span><span class="p">,</span> <span class="n">exec_kwargs</span> <span class="o">=</span> <span class="p">{},</span> <span class="p">{}</span>
|
|
<span class="n">goto</span><span class="p">,</span> <span class="n">execute</span> <span class="o">=</span> <span class="n">option_dict</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">"goto"</span><span class="p">,</span> <span class="kc">None</span><span class="p">),</span> <span class="n">option_dict</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">"exec"</span><span class="p">,</span> <span class="kc">None</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="n">goto</span> <span class="ow">and</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">goto</span><span class="p">,</span> <span class="p">(</span><span class="nb">tuple</span><span class="p">,</span> <span class="nb">list</span><span class="p">)):</span>
|
|
<span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">goto</span><span class="p">)</span> <span class="o">></span> <span class="mi">1</span><span class="p">:</span>
|
|
<span class="n">goto</span><span class="p">,</span> <span class="n">goto_kwargs</span> <span class="o">=</span> <span class="n">goto</span><span class="p">[:</span><span class="mi">2</span><span class="p">]</span> <span class="c1"># ignore any extra arguments</span>
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="nb">hasattr</span><span class="p">(</span><span class="n">goto_kwargs</span><span class="p">,</span> <span class="s2">"__getitem__"</span><span class="p">):</span>
|
|
<span class="c1"># not a dict-like structure</span>
|
|
<span class="k">raise</span> <span class="n">EvMenuError</span><span class="p">(</span>
|
|
<span class="s2">"EvMenu node </span><span class="si">{}</span><span class="s2">: goto kwargs is not a dict: </span><span class="si">{}</span><span class="s2">"</span><span class="o">.</span><span class="n">format</span><span class="p">(</span>
|
|
<span class="n">nodename</span><span class="p">,</span> <span class="n">goto_kwargs</span>
|
|
<span class="p">)</span>
|
|
<span class="p">)</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="n">goto</span> <span class="o">=</span> <span class="n">goto</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
|
|
<span class="k">if</span> <span class="n">execute</span> <span class="ow">and</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">execute</span><span class="p">,</span> <span class="p">(</span><span class="nb">tuple</span><span class="p">,</span> <span class="nb">list</span><span class="p">)):</span>
|
|
<span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">execute</span><span class="p">)</span> <span class="o">></span> <span class="mi">1</span><span class="p">:</span>
|
|
<span class="n">execute</span><span class="p">,</span> <span class="n">exec_kwargs</span> <span class="o">=</span> <span class="n">execute</span><span class="p">[:</span><span class="mi">2</span><span class="p">]</span> <span class="c1"># ignore any extra arguments</span>
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="nb">hasattr</span><span class="p">(</span><span class="n">exec_kwargs</span><span class="p">,</span> <span class="s2">"__getitem__"</span><span class="p">):</span>
|
|
<span class="c1"># not a dict-like structure</span>
|
|
<span class="k">raise</span> <span class="n">EvMenuError</span><span class="p">(</span>
|
|
<span class="s2">"EvMenu node </span><span class="si">{}</span><span class="s2">: exec kwargs is not a dict: </span><span class="si">{}</span><span class="s2">"</span><span class="o">.</span><span class="n">format</span><span class="p">(</span>
|
|
<span class="n">nodename</span><span class="p">,</span> <span class="n">goto_kwargs</span>
|
|
<span class="p">)</span>
|
|
<span class="p">)</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="n">execute</span> <span class="o">=</span> <span class="n">execute</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
|
|
<span class="k">return</span> <span class="n">goto</span><span class="p">,</span> <span class="n">goto_kwargs</span><span class="p">,</span> <span class="n">execute</span><span class="p">,</span> <span class="n">exec_kwargs</span></div>
|
|
|
|
<div class="viewcode-block" id="EvMenu.goto"><a class="viewcode-back" href="../../../api/evennia.utils.evmenu.html#evennia.utils.evmenu.EvMenu.goto">[docs]</a> <span class="k">def</span> <span class="nf">goto</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">nodename</span><span class="p">,</span> <span class="n">raw_string</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
|
|
<span class="sd">"""</span>
|
|
<span class="sd"> Run a node by name, optionally dynamically generating that name first.</span>
|
|
|
|
<span class="sd"> Args:</span>
|
|
<span class="sd"> nodename (str or callable): Name of node or a callable</span>
|
|
<span class="sd"> to be called as `function(caller, raw_string, **kwargs)` or</span>
|
|
<span class="sd"> `function(caller, **kwargs)` to return the actual goto string or</span>
|
|
<span class="sd"> a ("nodename", kwargs) tuple.</span>
|
|
<span class="sd"> raw_string (str): The raw default string entered on the</span>
|
|
<span class="sd"> previous node (only used if the node accepts it as an</span>
|
|
<span class="sd"> argument)</span>
|
|
<span class="sd"> **kwargs: Extra arguments to goto callables.</span>
|
|
|
|
<span class="sd"> """</span>
|
|
|
|
<span class="k">if</span> <span class="n">callable</span><span class="p">(</span><span class="n">nodename</span><span class="p">):</span>
|
|
<span class="c1"># run the "goto" callable, if possible</span>
|
|
<span class="n">inp_nodename</span> <span class="o">=</span> <span class="n">nodename</span>
|
|
<span class="n">nodename</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_safe_call</span><span class="p">(</span><span class="n">nodename</span><span class="p">,</span> <span class="n">raw_string</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">nodename</span><span class="p">,</span> <span class="p">(</span><span class="nb">tuple</span><span class="p">,</span> <span class="nb">list</span><span class="p">)):</span>
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="nb">len</span><span class="p">(</span><span class="n">nodename</span><span class="p">)</span> <span class="o">></span> <span class="mi">1</span> <span class="ow">or</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">nodename</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="nb">dict</span><span class="p">):</span>
|
|
<span class="k">raise</span> <span class="n">EvMenuError</span><span class="p">(</span>
|
|
<span class="s2">"</span><span class="si">{}</span><span class="s2">: goto callable must return str or (str, dict)"</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">inp_nodename</span><span class="p">)</span>
|
|
<span class="p">)</span>
|
|
<span class="n">nodename</span><span class="p">,</span> <span class="n">kwargs</span> <span class="o">=</span> <span class="n">nodename</span><span class="p">[:</span><span class="mi">2</span><span class="p">]</span>
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="n">nodename</span><span class="p">:</span>
|
|
<span class="c1"># no nodename return. Re-run current node</span>
|
|
<span class="n">nodename</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">nodename</span>
|
|
<span class="k">try</span><span class="p">:</span>
|
|
<span class="c1"># execute the found node, make use of the returns.</span>
|
|
<span class="n">nodetext</span><span class="p">,</span> <span class="n">options</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_execute_node</span><span class="p">(</span><span class="n">nodename</span><span class="p">,</span> <span class="n">raw_string</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">)</span>
|
|
<span class="k">except</span> <span class="n">EvMenuError</span><span class="p">:</span>
|
|
<span class="k">return</span>
|
|
|
|
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">_persistent</span><span class="p">:</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">caller</span><span class="o">.</span><span class="n">attributes</span><span class="o">.</span><span class="n">add</span><span class="p">(</span>
|
|
<span class="s2">"_menutree_saved_startnode"</span><span class="p">,</span> <span class="p">(</span><span class="n">nodename</span><span class="p">,</span> <span class="p">(</span><span class="n">raw_string</span><span class="p">,</span> <span class="n">kwargs</span><span class="p">))</span>
|
|
<span class="p">)</span>
|
|
|
|
<span class="c1"># validation of the node return values</span>
|
|
<span class="n">helptext</span> <span class="o">=</span> <span class="s2">""</span>
|
|
<span class="k">if</span> <span class="n">is_iter</span><span class="p">(</span><span class="n">nodetext</span><span class="p">):</span>
|
|
<span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">nodetext</span><span class="p">)</span> <span class="o">></span> <span class="mi">1</span><span class="p">:</span>
|
|
<span class="n">nodetext</span><span class="p">,</span> <span class="n">helptext</span> <span class="o">=</span> <span class="n">nodetext</span><span class="p">[:</span><span class="mi">2</span><span class="p">]</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="n">nodetext</span> <span class="o">=</span> <span class="n">nodetext</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
|
|
<span class="n">nodetext</span> <span class="o">=</span> <span class="s2">""</span> <span class="k">if</span> <span class="n">nodetext</span> <span class="ow">is</span> <span class="kc">None</span> <span class="k">else</span> <span class="nb">str</span><span class="p">(</span><span class="n">nodetext</span><span class="p">)</span>
|
|
<span class="n">options</span> <span class="o">=</span> <span class="p">[</span><span class="n">options</span><span class="p">]</span> <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">options</span><span class="p">,</span> <span class="nb">dict</span><span class="p">)</span> <span class="k">else</span> <span class="n">options</span>
|
|
|
|
<span class="c1"># this will be displayed in the given order</span>
|
|
<span class="n">display_options</span> <span class="o">=</span> <span class="p">[]</span>
|
|
<span class="c1"># this is used for lookup</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">options</span> <span class="o">=</span> <span class="p">{}</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">default</span> <span class="o">=</span> <span class="kc">None</span>
|
|
<span class="k">if</span> <span class="n">options</span><span class="p">:</span>
|
|
<span class="k">for</span> <span class="n">inum</span><span class="p">,</span> <span class="n">dic</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">(</span><span class="n">options</span><span class="p">):</span>
|
|
<span class="c1"># fix up the option dicts</span>
|
|
<span class="n">keys</span> <span class="o">=</span> <span class="n">make_iter</span><span class="p">(</span><span class="n">dic</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">"key"</span><span class="p">))</span>
|
|
<span class="n">desc</span> <span class="o">=</span> <span class="n">dic</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">"desc"</span><span class="p">,</span> <span class="n">dic</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">"text"</span><span class="p">,</span> <span class="kc">None</span><span class="p">))</span>
|
|
<span class="k">if</span> <span class="s2">"_default"</span> <span class="ow">in</span> <span class="n">keys</span><span class="p">:</span>
|
|
<span class="n">keys</span> <span class="o">=</span> <span class="p">[</span><span class="n">key</span> <span class="k">for</span> <span class="n">key</span> <span class="ow">in</span> <span class="n">keys</span> <span class="k">if</span> <span class="n">key</span> <span class="o">!=</span> <span class="s2">"_default"</span><span class="p">]</span>
|
|
<span class="n">goto</span><span class="p">,</span> <span class="n">goto_kwargs</span><span class="p">,</span> <span class="n">execute</span><span class="p">,</span> <span class="n">exec_kwargs</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">extract_goto_exec</span><span class="p">(</span><span class="n">nodename</span><span class="p">,</span> <span class="n">dic</span><span class="p">)</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">default</span> <span class="o">=</span> <span class="p">(</span><span class="n">goto</span><span class="p">,</span> <span class="n">goto_kwargs</span><span class="p">,</span> <span class="n">execute</span><span class="p">,</span> <span class="n">exec_kwargs</span><span class="p">)</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="c1"># use the key (only) if set, otherwise use the running number</span>
|
|
<span class="n">keys</span> <span class="o">=</span> <span class="nb">list</span><span class="p">(</span><span class="n">make_iter</span><span class="p">(</span><span class="n">dic</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">"key"</span><span class="p">,</span> <span class="nb">str</span><span class="p">(</span><span class="n">inum</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span><span class="o">.</span><span class="n">strip</span><span class="p">())))</span>
|
|
<span class="n">goto</span><span class="p">,</span> <span class="n">goto_kwargs</span><span class="p">,</span> <span class="n">execute</span><span class="p">,</span> <span class="n">exec_kwargs</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">extract_goto_exec</span><span class="p">(</span><span class="n">nodename</span><span class="p">,</span> <span class="n">dic</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="n">keys</span><span class="p">:</span>
|
|
<span class="n">display_options</span><span class="o">.</span><span class="n">append</span><span class="p">((</span><span class="n">keys</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">desc</span><span class="p">))</span>
|
|
<span class="k">for</span> <span class="n">key</span> <span class="ow">in</span> <span class="n">keys</span><span class="p">:</span>
|
|
<span class="k">if</span> <span class="n">goto</span> <span class="ow">or</span> <span class="n">execute</span><span class="p">:</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">options</span><span class="p">[</span><span class="n">strip_ansi</span><span class="p">(</span><span class="n">key</span><span class="p">)</span><span class="o">.</span><span class="n">strip</span><span class="p">()</span><span class="o">.</span><span class="n">lower</span><span class="p">()]</span> <span class="o">=</span> <span class="p">(</span>
|
|
<span class="n">goto</span><span class="p">,</span>
|
|
<span class="n">goto_kwargs</span><span class="p">,</span>
|
|
<span class="n">execute</span><span class="p">,</span>
|
|
<span class="n">exec_kwargs</span><span class="p">,</span>
|
|
<span class="p">)</span>
|
|
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">nodetext</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_format_node</span><span class="p">(</span><span class="n">nodetext</span><span class="p">,</span> <span class="n">display_options</span><span class="p">)</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">node_kwargs</span> <span class="o">=</span> <span class="n">kwargs</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">nodename</span> <span class="o">=</span> <span class="n">nodename</span>
|
|
|
|
<span class="c1"># handle the helptext</span>
|
|
<span class="k">if</span> <span class="n">helptext</span><span class="p">:</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">helptext</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">helptext_formatter</span><span class="p">(</span><span class="n">helptext</span><span class="p">)</span>
|
|
<span class="k">elif</span> <span class="n">options</span><span class="p">:</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">helptext</span> <span class="o">=</span> <span class="n">_HELP_FULL</span> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">auto_quit</span> <span class="k">else</span> <span class="n">_HELP_NO_QUIT</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">helptext</span> <span class="o">=</span> <span class="n">_HELP_NO_OPTIONS</span> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">auto_quit</span> <span class="k">else</span> <span class="n">_HELP_NO_OPTIONS_NO_QUIT</span>
|
|
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">display_nodetext</span><span class="p">()</span>
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="n">options</span><span class="p">:</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">close_menu</span><span class="p">()</span></div>
|
|
|
|
<div class="viewcode-block" id="EvMenu.run_exec_then_goto"><a class="viewcode-back" href="../../../api/evennia.utils.evmenu.html#evennia.utils.evmenu.EvMenu.run_exec_then_goto">[docs]</a> <span class="k">def</span> <span class="nf">run_exec_then_goto</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">runexec</span><span class="p">,</span> <span class="n">goto</span><span class="p">,</span> <span class="n">raw_string</span><span class="p">,</span> <span class="n">runexec_kwargs</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">goto_kwargs</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
|
|
<span class="sd">"""</span>
|
|
<span class="sd"> Call 'exec' callback and goto (which may also be a callable) in sequence.</span>
|
|
|
|
<span class="sd"> Args:</span>
|
|
<span class="sd"> runexec (callable or str): Callback to run before goto. If</span>
|
|
<span class="sd"> the callback returns a string, this is used to replace</span>
|
|
<span class="sd"> the `goto` string/callable before being passed into the goto handler.</span>
|
|
<span class="sd"> goto (str): The target node to go to next (may be replaced</span>
|
|
<span class="sd"> by `runexec`)..</span>
|
|
<span class="sd"> raw_string (str): The original user input.</span>
|
|
<span class="sd"> runexec_kwargs (dict, optional): Optional kwargs for runexec.</span>
|
|
<span class="sd"> goto_kwargs (dict, optional): Optional kwargs for goto.</span>
|
|
|
|
<span class="sd"> """</span>
|
|
<span class="k">if</span> <span class="n">runexec</span><span class="p">:</span>
|
|
<span class="c1"># replace goto only if callback returns</span>
|
|
<span class="n">goto</span><span class="p">,</span> <span class="n">goto_kwargs</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">run_exec</span><span class="p">(</span>
|
|
<span class="n">runexec</span><span class="p">,</span> <span class="n">raw_string</span><span class="p">,</span> <span class="o">**</span><span class="p">(</span><span class="n">runexec_kwargs</span> <span class="k">if</span> <span class="n">runexec_kwargs</span> <span class="k">else</span> <span class="p">{})</span>
|
|
<span class="p">)</span> <span class="ow">or</span> <span class="p">(</span><span class="n">goto</span><span class="p">,</span> <span class="n">goto_kwargs</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="n">goto</span><span class="p">:</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">goto</span><span class="p">(</span><span class="n">goto</span><span class="p">,</span> <span class="n">raw_string</span><span class="p">,</span> <span class="o">**</span><span class="p">(</span><span class="n">goto_kwargs</span> <span class="k">if</span> <span class="n">goto_kwargs</span> <span class="k">else</span> <span class="p">{}))</span></div>
|
|
|
|
<div class="viewcode-block" id="EvMenu.close_menu"><a class="viewcode-back" href="../../../api/evennia.utils.evmenu.html#evennia.utils.evmenu.EvMenu.close_menu">[docs]</a> <span class="k">def</span> <span class="nf">close_menu</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
|
<span class="sd">"""</span>
|
|
<span class="sd"> Shutdown menu; occurs when reaching the end node or using the quit command.</span>
|
|
<span class="sd"> """</span>
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">_quitting</span><span class="p">:</span>
|
|
<span class="c1"># avoid multiple calls from different sources</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_quitting</span> <span class="o">=</span> <span class="kc">True</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">caller</span><span class="o">.</span><span class="n">cmdset</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="n">EvMenuCmdSet</span><span class="p">)</span>
|
|
<span class="k">del</span> <span class="bp">self</span><span class="o">.</span><span class="n">caller</span><span class="o">.</span><span class="n">ndb</span><span class="o">.</span><span class="n">_evmenu</span>
|
|
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">_persistent</span><span class="p">:</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">caller</span><span class="o">.</span><span class="n">attributes</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="s2">"_menutree_saved"</span><span class="p">)</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">caller</span><span class="o">.</span><span class="n">attributes</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="s2">"_menutree_saved_startnode"</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">cmd_on_exit</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">cmd_on_exit</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">caller</span><span class="p">,</span> <span class="bp">self</span><span class="p">)</span>
|
|
<span class="c1"># special for template-generated menues</span>
|
|
<span class="k">del</span> <span class="bp">self</span><span class="o">.</span><span class="n">caller</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">_evmenu_template_contents</span></div>
|
|
|
|
<div class="viewcode-block" id="EvMenu.print_debug_info"><a class="viewcode-back" href="../../../api/evennia.utils.evmenu.html#evennia.utils.evmenu.EvMenu.print_debug_info">[docs]</a> <span class="k">def</span> <span class="nf">print_debug_info</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">arg</span><span class="p">):</span>
|
|
<span class="sd">"""</span>
|
|
<span class="sd"> Messages the caller with the current menu state, for debug purposes.</span>
|
|
|
|
<span class="sd"> Args:</span>
|
|
<span class="sd"> arg (str): Arg to debug instruction, either nothing, 'full' or the name</span>
|
|
<span class="sd"> of a property to inspect.</span>
|
|
|
|
<span class="sd"> """</span>
|
|
<span class="n">all_props</span> <span class="o">=</span> <span class="n">inspect</span><span class="o">.</span><span class="n">getmembers</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span>
|
|
<span class="n">all_methods</span> <span class="o">=</span> <span class="p">[</span><span class="n">name</span> <span class="k">for</span> <span class="n">name</span><span class="p">,</span> <span class="n">_</span> <span class="ow">in</span> <span class="n">inspect</span><span class="o">.</span><span class="n">getmembers</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">predicate</span><span class="o">=</span><span class="n">inspect</span><span class="o">.</span><span class="n">ismethod</span><span class="p">)]</span>
|
|
<span class="n">all_builtins</span> <span class="o">=</span> <span class="p">[</span><span class="n">name</span> <span class="k">for</span> <span class="n">name</span><span class="p">,</span> <span class="n">_</span> <span class="ow">in</span> <span class="n">inspect</span><span class="o">.</span><span class="n">getmembers</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">predicate</span><span class="o">=</span><span class="n">inspect</span><span class="o">.</span><span class="n">isbuiltin</span><span class="p">)]</span>
|
|
<span class="n">props</span> <span class="o">=</span> <span class="p">{</span>
|
|
<span class="n">prop</span><span class="p">:</span> <span class="n">value</span>
|
|
<span class="k">for</span> <span class="n">prop</span><span class="p">,</span> <span class="n">value</span> <span class="ow">in</span> <span class="n">all_props</span>
|
|
<span class="k">if</span> <span class="n">prop</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">all_methods</span> <span class="ow">and</span> <span class="n">prop</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">all_builtins</span> <span class="ow">and</span> <span class="ow">not</span> <span class="n">prop</span><span class="o">.</span><span class="n">endswith</span><span class="p">(</span><span class="s2">"__"</span><span class="p">)</span>
|
|
<span class="p">}</span>
|
|
|
|
<span class="n">local</span> <span class="o">=</span> <span class="p">{</span>
|
|
<span class="n">key</span><span class="p">:</span> <span class="n">var</span>
|
|
<span class="k">for</span> <span class="n">key</span><span class="p">,</span> <span class="n">var</span> <span class="ow">in</span> <span class="nb">locals</span><span class="p">()</span><span class="o">.</span><span class="n">items</span><span class="p">()</span>
|
|
<span class="k">if</span> <span class="n">key</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">all_props</span> <span class="ow">and</span> <span class="ow">not</span> <span class="n">key</span><span class="o">.</span><span class="n">endswith</span><span class="p">(</span><span class="s2">"__"</span><span class="p">)</span>
|
|
<span class="p">}</span>
|
|
|
|
<span class="k">if</span> <span class="n">arg</span><span class="p">:</span>
|
|
<span class="k">if</span> <span class="n">arg</span> <span class="ow">in</span> <span class="n">props</span><span class="p">:</span>
|
|
<span class="n">debugtxt</span> <span class="o">=</span> <span class="s2">" |y* </span><span class="si">{}</span><span class="s2">:|n</span><span class="se">\n</span><span class="si">{}</span><span class="s2">"</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">arg</span><span class="p">,</span> <span class="n">props</span><span class="p">[</span><span class="n">arg</span><span class="p">])</span>
|
|
<span class="k">elif</span> <span class="n">arg</span> <span class="ow">in</span> <span class="n">local</span><span class="p">:</span>
|
|
<span class="n">debugtxt</span> <span class="o">=</span> <span class="s2">" |y* </span><span class="si">{}</span><span class="s2">:|n</span><span class="se">\n</span><span class="si">{}</span><span class="s2">"</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">arg</span><span class="p">,</span> <span class="n">local</span><span class="p">[</span><span class="n">arg</span><span class="p">])</span>
|
|
<span class="k">elif</span> <span class="n">arg</span> <span class="o">==</span> <span class="s2">"full"</span><span class="p">:</span>
|
|
<span class="n">debugtxt</span> <span class="o">=</span> <span class="p">(</span>
|
|
<span class="s2">"|yMENU DEBUG full ... |n</span><span class="se">\n</span><span class="s2">"</span>
|
|
<span class="o">+</span> <span class="s2">"</span><span class="se">\n</span><span class="s2">"</span><span class="o">.</span><span class="n">join</span><span class="p">(</span>
|
|
<span class="s2">"|y *|n </span><span class="si">{}</span><span class="s2">: </span><span class="si">{}</span><span class="s2">"</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">key</span><span class="p">,</span> <span class="n">val</span><span class="p">)</span> <span class="k">for</span> <span class="n">key</span><span class="p">,</span> <span class="n">val</span> <span class="ow">in</span> <span class="nb">sorted</span><span class="p">(</span><span class="n">props</span><span class="o">.</span><span class="n">items</span><span class="p">())</span>
|
|
<span class="p">)</span>
|
|
<span class="o">+</span> <span class="s2">"</span><span class="se">\n</span><span class="s2"> |yLOCAL VARS:|n</span><span class="se">\n</span><span class="s2">"</span>
|
|
<span class="o">+</span> <span class="s2">"</span><span class="se">\n</span><span class="s2">"</span><span class="o">.</span><span class="n">join</span><span class="p">(</span>
|
|
<span class="s2">"|y *|n </span><span class="si">{}</span><span class="s2">: </span><span class="si">{}</span><span class="s2">"</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">key</span><span class="p">,</span> <span class="n">val</span><span class="p">)</span> <span class="k">for</span> <span class="n">key</span><span class="p">,</span> <span class="n">val</span> <span class="ow">in</span> <span class="nb">sorted</span><span class="p">(</span><span class="n">local</span><span class="o">.</span><span class="n">items</span><span class="p">())</span>
|
|
<span class="p">)</span>
|
|
<span class="o">+</span> <span class="s2">"</span><span class="se">\n</span><span class="s2"> |y... END MENU DEBUG|n"</span>
|
|
<span class="p">)</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="n">debugtxt</span> <span class="o">=</span> <span class="s2">"|yUsage: menudebug full|<name of property>|n"</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="n">debugtxt</span> <span class="o">=</span> <span class="p">(</span>
|
|
<span class="s2">"|yMENU DEBUG properties ... |n</span><span class="se">\n</span><span class="s2">"</span>
|
|
<span class="o">+</span> <span class="s2">"</span><span class="se">\n</span><span class="s2">"</span><span class="o">.</span><span class="n">join</span><span class="p">(</span>
|
|
<span class="s2">"|y *|n </span><span class="si">{}</span><span class="s2">: </span><span class="si">{}</span><span class="s2">"</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">key</span><span class="p">,</span> <span class="n">crop</span><span class="p">(</span><span class="n">to_str</span><span class="p">(</span><span class="n">val</span><span class="p">,</span> <span class="n">force_string</span><span class="o">=</span><span class="kc">True</span><span class="p">),</span> <span class="n">width</span><span class="o">=</span><span class="mi">50</span><span class="p">))</span>
|
|
<span class="k">for</span> <span class="n">key</span><span class="p">,</span> <span class="n">val</span> <span class="ow">in</span> <span class="nb">sorted</span><span class="p">(</span><span class="n">props</span><span class="o">.</span><span class="n">items</span><span class="p">())</span>
|
|
<span class="p">)</span>
|
|
<span class="o">+</span> <span class="s2">"</span><span class="se">\n</span><span class="s2"> |yLOCAL VARS:|n</span><span class="se">\n</span><span class="s2">"</span>
|
|
<span class="o">+</span> <span class="s2">"</span><span class="se">\n</span><span class="s2">"</span><span class="o">.</span><span class="n">join</span><span class="p">(</span>
|
|
<span class="s2">"|y *|n </span><span class="si">{}</span><span class="s2">: </span><span class="si">{}</span><span class="s2">"</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">key</span><span class="p">,</span> <span class="n">crop</span><span class="p">(</span><span class="n">to_str</span><span class="p">(</span><span class="n">val</span><span class="p">,</span> <span class="n">force_string</span><span class="o">=</span><span class="kc">True</span><span class="p">),</span> <span class="n">width</span><span class="o">=</span><span class="mi">50</span><span class="p">))</span>
|
|
<span class="k">for</span> <span class="n">key</span><span class="p">,</span> <span class="n">val</span> <span class="ow">in</span> <span class="nb">sorted</span><span class="p">(</span><span class="n">local</span><span class="o">.</span><span class="n">items</span><span class="p">())</span>
|
|
<span class="p">)</span>
|
|
<span class="o">+</span> <span class="s2">"</span><span class="se">\n</span><span class="s2"> |y... END MENU DEBUG|n"</span>
|
|
<span class="p">)</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="n">debugtxt</span><span class="p">)</span></div>
|
|
|
|
<div class="viewcode-block" id="EvMenu.parse_input"><a class="viewcode-back" href="../../../api/evennia.utils.evmenu.html#evennia.utils.evmenu.EvMenu.parse_input">[docs]</a> <span class="k">def</span> <span class="nf">parse_input</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">raw_string</span><span class="p">):</span>
|
|
<span class="sd">"""</span>
|
|
<span class="sd"> Parses the incoming string from the menu user.</span>
|
|
|
|
<span class="sd"> Args:</span>
|
|
<span class="sd"> raw_string (str): The incoming, unmodified string</span>
|
|
<span class="sd"> from the user.</span>
|
|
<span class="sd"> Notes:</span>
|
|
<span class="sd"> This method is expected to parse input and use the result</span>
|
|
<span class="sd"> to relay execution to the relevant methods of the menu. It</span>
|
|
<span class="sd"> should also report errors directly to the user.</span>
|
|
|
|
<span class="sd"> """</span>
|
|
<span class="n">cmd</span> <span class="o">=</span> <span class="n">strip_ansi</span><span class="p">(</span><span class="n">raw_string</span><span class="o">.</span><span class="n">strip</span><span class="p">()</span><span class="o">.</span><span class="n">lower</span><span class="p">())</span>
|
|
|
|
<span class="k">try</span><span class="p">:</span>
|
|
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">options</span> <span class="ow">and</span> <span class="n">cmd</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">options</span><span class="p">:</span>
|
|
<span class="c1"># this will take precedence over the default commands</span>
|
|
<span class="c1"># below</span>
|
|
<span class="n">goto</span><span class="p">,</span> <span class="n">goto_kwargs</span><span class="p">,</span> <span class="n">execfunc</span><span class="p">,</span> <span class="n">exec_kwargs</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">options</span><span class="p">[</span><span class="n">cmd</span><span class="p">]</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">run_exec_then_goto</span><span class="p">(</span><span class="n">execfunc</span><span class="p">,</span> <span class="n">goto</span><span class="p">,</span> <span class="n">raw_string</span><span class="p">,</span> <span class="n">exec_kwargs</span><span class="p">,</span> <span class="n">goto_kwargs</span><span class="p">)</span>
|
|
<span class="k">elif</span> <span class="bp">self</span><span class="o">.</span><span class="n">auto_look</span> <span class="ow">and</span> <span class="n">cmd</span> <span class="ow">in</span> <span class="p">(</span><span class="s2">"look"</span><span class="p">,</span> <span class="s2">"l"</span><span class="p">):</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">display_nodetext</span><span class="p">()</span>
|
|
<span class="k">elif</span> <span class="bp">self</span><span class="o">.</span><span class="n">auto_help</span> <span class="ow">and</span> <span class="n">cmd</span> <span class="ow">in</span> <span class="p">(</span><span class="s2">"help"</span><span class="p">,</span> <span class="s2">"h"</span><span class="p">):</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">display_helptext</span><span class="p">()</span>
|
|
<span class="k">elif</span> <span class="bp">self</span><span class="o">.</span><span class="n">auto_quit</span> <span class="ow">and</span> <span class="n">cmd</span> <span class="ow">in</span> <span class="p">(</span><span class="s2">"quit"</span><span class="p">,</span> <span class="s2">"q"</span><span class="p">,</span> <span class="s2">"exit"</span><span class="p">):</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">close_menu</span><span class="p">()</span>
|
|
<span class="k">elif</span> <span class="bp">self</span><span class="o">.</span><span class="n">debug_mode</span> <span class="ow">and</span> <span class="n">cmd</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="s2">"menudebug"</span><span class="p">):</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">print_debug_info</span><span class="p">(</span><span class="n">cmd</span><span class="p">[</span><span class="mi">9</span><span class="p">:]</span><span class="o">.</span><span class="n">strip</span><span class="p">())</span>
|
|
<span class="k">elif</span> <span class="bp">self</span><span class="o">.</span><span class="n">default</span><span class="p">:</span>
|
|
<span class="n">goto</span><span class="p">,</span> <span class="n">goto_kwargs</span><span class="p">,</span> <span class="n">execfunc</span><span class="p">,</span> <span class="n">exec_kwargs</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">default</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">run_exec_then_goto</span><span class="p">(</span><span class="n">execfunc</span><span class="p">,</span> <span class="n">goto</span><span class="p">,</span> <span class="n">raw_string</span><span class="p">,</span> <span class="n">exec_kwargs</span><span class="p">,</span> <span class="n">goto_kwargs</span><span class="p">)</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="n">_HELP_NO_OPTION_MATCH</span><span class="p">)</span>
|
|
<span class="k">except</span> <span class="n">EvMenuGotoAbortMessage</span> <span class="k">as</span> <span class="n">err</span><span class="p">:</span>
|
|
<span class="c1"># custom interrupt from inside a goto callable - print the message and</span>
|
|
<span class="c1"># stay on the current node.</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">err</span><span class="p">))</span></div>
|
|
|
|
<div class="viewcode-block" id="EvMenu.display_nodetext"><a class="viewcode-back" href="../../../api/evennia.utils.evmenu.html#evennia.utils.evmenu.EvMenu.display_nodetext">[docs]</a> <span class="k">def</span> <span class="nf">display_nodetext</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">nodetext</span><span class="p">)</span></div>
|
|
|
|
<div class="viewcode-block" id="EvMenu.display_helptext"><a class="viewcode-back" href="../../../api/evennia.utils.evmenu.html#evennia.utils.evmenu.EvMenu.display_helptext">[docs]</a> <span class="k">def</span> <span class="nf">display_helptext</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">helptext</span><span class="p">)</span></div>
|
|
|
|
<span class="c1"># formatters - override in a child class</span>
|
|
|
|
<div class="viewcode-block" id="EvMenu.nodetext_formatter"><a class="viewcode-back" href="../../../api/evennia.utils.evmenu.html#evennia.utils.evmenu.EvMenu.nodetext_formatter">[docs]</a> <span class="k">def</span> <span class="nf">nodetext_formatter</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">nodetext</span><span class="p">):</span>
|
|
<span class="sd">"""</span>
|
|
<span class="sd"> Format the node text itself.</span>
|
|
|
|
<span class="sd"> Args:</span>
|
|
<span class="sd"> nodetext (str): The full node text (the text describing the node).</span>
|
|
|
|
<span class="sd"> Returns:</span>
|
|
<span class="sd"> nodetext (str): The formatted node text.</span>
|
|
|
|
<span class="sd"> """</span>
|
|
<span class="k">return</span> <span class="n">dedent</span><span class="p">(</span><span class="n">nodetext</span><span class="o">.</span><span class="n">strip</span><span class="p">(</span><span class="s2">"</span><span class="se">\n</span><span class="s2">"</span><span class="p">),</span> <span class="n">baseline_index</span><span class="o">=</span><span class="mi">0</span><span class="p">)</span><span class="o">.</span><span class="n">rstrip</span><span class="p">()</span></div>
|
|
|
|
<div class="viewcode-block" id="EvMenu.helptext_formatter"><a class="viewcode-back" href="../../../api/evennia.utils.evmenu.html#evennia.utils.evmenu.EvMenu.helptext_formatter">[docs]</a> <span class="k">def</span> <span class="nf">helptext_formatter</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">helptext</span><span class="p">):</span>
|
|
<span class="sd">"""</span>
|
|
<span class="sd"> Format the node's help text</span>
|
|
|
|
<span class="sd"> Args:</span>
|
|
<span class="sd"> helptext (str): The unformatted help text for the node.</span>
|
|
|
|
<span class="sd"> Returns:</span>
|
|
<span class="sd"> helptext (str): The formatted help text.</span>
|
|
|
|
<span class="sd"> """</span>
|
|
<span class="k">return</span> <span class="n">dedent</span><span class="p">(</span><span class="n">helptext</span><span class="o">.</span><span class="n">strip</span><span class="p">(</span><span class="s2">"</span><span class="se">\n</span><span class="s2">"</span><span class="p">),</span> <span class="n">baseline_index</span><span class="o">=</span><span class="mi">0</span><span class="p">)</span><span class="o">.</span><span class="n">rstrip</span><span class="p">()</span></div>
|
|
|
|
<div class="viewcode-block" id="EvMenu.options_formatter"><a class="viewcode-back" href="../../../api/evennia.utils.evmenu.html#evennia.utils.evmenu.EvMenu.options_formatter">[docs]</a> <span class="k">def</span> <span class="nf">options_formatter</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">optionlist</span><span class="p">):</span>
|
|
<span class="sd">"""</span>
|
|
<span class="sd"> Formats the option block.</span>
|
|
|
|
<span class="sd"> Args:</span>
|
|
<span class="sd"> optionlist (list): List of (key, description) tuples for every</span>
|
|
<span class="sd"> option related to this node.</span>
|
|
<span class="sd"> caller (Object, Account or None, optional): The caller of the node.</span>
|
|
|
|
<span class="sd"> Returns:</span>
|
|
<span class="sd"> options (str): The formatted option display.</span>
|
|
|
|
<span class="sd"> """</span>
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="n">optionlist</span><span class="p">:</span>
|
|
<span class="k">return</span> <span class="s2">""</span>
|
|
|
|
<span class="c1"># column separation distance</span>
|
|
<span class="n">colsep</span> <span class="o">=</span> <span class="mi">4</span>
|
|
|
|
<span class="n">nlist</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="n">optionlist</span><span class="p">)</span>
|
|
|
|
<span class="c1"># get the widest option line in the table.</span>
|
|
<span class="n">table_width_max</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span>
|
|
<span class="n">table</span> <span class="o">=</span> <span class="p">[]</span>
|
|
<span class="k">for</span> <span class="n">key</span><span class="p">,</span> <span class="n">desc</span> <span class="ow">in</span> <span class="n">optionlist</span><span class="p">:</span>
|
|
<span class="k">if</span> <span class="n">key</span> <span class="ow">or</span> <span class="n">desc</span><span class="p">:</span>
|
|
<span class="n">desc_string</span> <span class="o">=</span> <span class="s2">": </span><span class="si">%s</span><span class="s2">"</span> <span class="o">%</span> <span class="n">desc</span> <span class="k">if</span> <span class="n">desc</span> <span class="k">else</span> <span class="s2">""</span>
|
|
<span class="n">table_width_max</span> <span class="o">=</span> <span class="nb">max</span><span class="p">(</span>
|
|
<span class="n">table_width_max</span><span class="p">,</span>
|
|
<span class="nb">max</span><span class="p">(</span><span class="n">m_len</span><span class="p">(</span><span class="n">p</span><span class="p">)</span> <span class="k">for</span> <span class="n">p</span> <span class="ow">in</span> <span class="n">key</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s2">"</span><span class="se">\n</span><span class="s2">"</span><span class="p">))</span>
|
|
<span class="o">+</span> <span class="nb">max</span><span class="p">(</span><span class="n">m_len</span><span class="p">(</span><span class="n">p</span><span class="p">)</span> <span class="k">for</span> <span class="n">p</span> <span class="ow">in</span> <span class="n">desc_string</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s2">"</span><span class="se">\n</span><span class="s2">"</span><span class="p">))</span>
|
|
<span class="o">+</span> <span class="n">colsep</span><span class="p">,</span>
|
|
<span class="p">)</span>
|
|
<span class="n">raw_key</span> <span class="o">=</span> <span class="n">strip_ansi</span><span class="p">(</span><span class="n">key</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="n">raw_key</span> <span class="o">!=</span> <span class="n">key</span><span class="p">:</span>
|
|
<span class="c1"># already decorations in key definition</span>
|
|
<span class="n">table</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="s2">" |lc</span><span class="si">%s</span><span class="s2">|lt</span><span class="si">%s</span><span class="s2">|le</span><span class="si">%s</span><span class="s2">"</span> <span class="o">%</span> <span class="p">(</span><span class="n">raw_key</span><span class="p">,</span> <span class="n">key</span><span class="p">,</span> <span class="n">desc_string</span><span class="p">))</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="c1"># add a default white color to key</span>
|
|
<span class="n">table</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="s2">" |lc</span><span class="si">%s</span><span class="s2">|lt|w</span><span class="si">%s</span><span class="s2">|n|le</span><span class="si">%s</span><span class="s2">"</span> <span class="o">%</span> <span class="p">(</span><span class="n">raw_key</span><span class="p">,</span> <span class="n">raw_key</span><span class="p">,</span> <span class="n">desc_string</span><span class="p">))</span>
|
|
<span class="n">ncols</span> <span class="o">=</span> <span class="n">_MAX_TEXT_WIDTH</span> <span class="o">//</span> <span class="n">table_width_max</span> <span class="c1"># number of ncols</span>
|
|
|
|
<span class="k">if</span> <span class="n">ncols</span> <span class="o"><</span> <span class="mi">0</span><span class="p">:</span>
|
|
<span class="c1"># no visible option at all</span>
|
|
<span class="k">return</span> <span class="s2">""</span>
|
|
|
|
<span class="n">ncols</span> <span class="o">=</span> <span class="n">ncols</span> <span class="o">+</span> <span class="mi">1</span> <span class="k">if</span> <span class="n">ncols</span> <span class="o">==</span> <span class="mi">0</span> <span class="k">else</span> <span class="n">ncols</span>
|
|
<span class="c1"># get the amount of rows needed (start with 4 rows)</span>
|
|
<span class="n">nrows</span> <span class="o">=</span> <span class="mi">4</span>
|
|
<span class="k">while</span> <span class="n">nrows</span> <span class="o">*</span> <span class="n">ncols</span> <span class="o"><</span> <span class="n">nlist</span><span class="p">:</span>
|
|
<span class="n">nrows</span> <span class="o">+=</span> <span class="mi">1</span>
|
|
<span class="n">ncols</span> <span class="o">=</span> <span class="n">nlist</span> <span class="o">//</span> <span class="n">nrows</span> <span class="c1"># number of full columns</span>
|
|
<span class="n">nlastcol</span> <span class="o">=</span> <span class="n">nlist</span> <span class="o">%</span> <span class="n">nrows</span> <span class="c1"># number of elements in last column</span>
|
|
|
|
<span class="c1"># get the final column count</span>
|
|
<span class="n">ncols</span> <span class="o">=</span> <span class="n">ncols</span> <span class="o">+</span> <span class="mi">1</span> <span class="k">if</span> <span class="n">nlastcol</span> <span class="o">></span> <span class="mi">0</span> <span class="k">else</span> <span class="n">ncols</span>
|
|
<span class="k">if</span> <span class="n">ncols</span> <span class="o">></span> <span class="mi">1</span><span class="p">:</span>
|
|
<span class="c1"># only extend if longer than one column</span>
|
|
<span class="n">table</span><span class="o">.</span><span class="n">extend</span><span class="p">([</span><span class="s2">" "</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">nrows</span> <span class="o">-</span> <span class="n">nlastcol</span><span class="p">)])</span>
|
|
|
|
<span class="c1"># build the actual table grid</span>
|
|
<span class="n">table</span> <span class="o">=</span> <span class="p">[</span><span class="n">table</span><span class="p">[</span><span class="n">icol</span> <span class="o">*</span> <span class="n">nrows</span> <span class="p">:</span> <span class="p">(</span><span class="n">icol</span> <span class="o">*</span> <span class="n">nrows</span><span class="p">)</span> <span class="o">+</span> <span class="n">nrows</span><span class="p">]</span> <span class="k">for</span> <span class="n">icol</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="n">ncols</span><span class="p">)]</span>
|
|
|
|
<span class="c1"># adjust the width of each column</span>
|
|
<span class="k">for</span> <span class="n">icol</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">table</span><span class="p">)):</span>
|
|
<span class="n">col_width</span> <span class="o">=</span> <span class="p">(</span>
|
|
<span class="nb">max</span><span class="p">(</span><span class="nb">max</span><span class="p">(</span><span class="n">m_len</span><span class="p">(</span><span class="n">p</span><span class="p">)</span> <span class="k">for</span> <span class="n">p</span> <span class="ow">in</span> <span class="n">part</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s2">"</span><span class="se">\n</span><span class="s2">"</span><span class="p">))</span> <span class="k">for</span> <span class="n">part</span> <span class="ow">in</span> <span class="n">table</span><span class="p">[</span><span class="n">icol</span><span class="p">])</span> <span class="o">+</span> <span class="n">colsep</span>
|
|
<span class="p">)</span>
|
|
<span class="n">table</span><span class="p">[</span><span class="n">icol</span><span class="p">]</span> <span class="o">=</span> <span class="p">[</span><span class="n">pad</span><span class="p">(</span><span class="n">part</span><span class="p">,</span> <span class="n">width</span><span class="o">=</span><span class="n">col_width</span> <span class="o">+</span> <span class="n">colsep</span><span class="p">,</span> <span class="n">align</span><span class="o">=</span><span class="s2">"l"</span><span class="p">)</span> <span class="k">for</span> <span class="n">part</span> <span class="ow">in</span> <span class="n">table</span><span class="p">[</span><span class="n">icol</span><span class="p">]]</span>
|
|
|
|
<span class="c1"># format the table into columns</span>
|
|
<span class="k">return</span> <span class="nb">str</span><span class="p">(</span><span class="n">EvTable</span><span class="p">(</span><span class="n">table</span><span class="o">=</span><span class="n">table</span><span class="p">,</span> <span class="n">border</span><span class="o">=</span><span class="s2">"none"</span><span class="p">))</span></div>
|
|
|
|
<div class="viewcode-block" id="EvMenu.node_formatter"><a class="viewcode-back" href="../../../api/evennia.utils.evmenu.html#evennia.utils.evmenu.EvMenu.node_formatter">[docs]</a> <span class="k">def</span> <span class="nf">node_formatter</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">nodetext</span><span class="p">,</span> <span class="n">optionstext</span><span class="p">):</span>
|
|
<span class="sd">"""</span>
|
|
<span class="sd"> Formats the entirety of the node.</span>
|
|
|
|
<span class="sd"> Args:</span>
|
|
<span class="sd"> nodetext (str): The node text as returned by `self.nodetext_formatter`.</span>
|
|
<span class="sd"> optionstext (str): The options display as returned by `self.options_formatter`.</span>
|
|
<span class="sd"> caller (Object, Account or None, optional): The caller of the node.</span>
|
|
|
|
<span class="sd"> Returns:</span>
|
|
<span class="sd"> node (str): The formatted node to display.</span>
|
|
|
|
<span class="sd"> """</span>
|
|
<span class="n">sep</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">node_border_char</span>
|
|
|
|
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">_session</span><span class="p">:</span>
|
|
<span class="n">screen_width</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_session</span><span class="o">.</span><span class="n">protocol_flags</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">"SCREENWIDTH"</span><span class="p">,</span> <span class="p">{</span><span class="mi">0</span><span class="p">:</span> <span class="n">_MAX_TEXT_WIDTH</span><span class="p">})[</span><span class="mi">0</span><span class="p">]</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="n">screen_width</span> <span class="o">=</span> <span class="n">_MAX_TEXT_WIDTH</span>
|
|
|
|
<span class="n">nodetext_width_max</span> <span class="o">=</span> <span class="nb">max</span><span class="p">(</span><span class="n">m_len</span><span class="p">(</span><span class="n">line</span><span class="p">)</span> <span class="k">for</span> <span class="n">line</span> <span class="ow">in</span> <span class="n">nodetext</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s2">"</span><span class="se">\n</span><span class="s2">"</span><span class="p">))</span>
|
|
<span class="n">options_width_max</span> <span class="o">=</span> <span class="nb">max</span><span class="p">(</span><span class="n">m_len</span><span class="p">(</span><span class="n">line</span><span class="p">)</span> <span class="k">for</span> <span class="n">line</span> <span class="ow">in</span> <span class="n">optionstext</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s2">"</span><span class="se">\n</span><span class="s2">"</span><span class="p">))</span>
|
|
<span class="n">total_width</span> <span class="o">=</span> <span class="nb">min</span><span class="p">(</span><span class="n">screen_width</span><span class="p">,</span> <span class="nb">max</span><span class="p">(</span><span class="n">options_width_max</span><span class="p">,</span> <span class="n">nodetext_width_max</span><span class="p">))</span>
|
|
<span class="n">separator1</span> <span class="o">=</span> <span class="n">sep</span> <span class="o">*</span> <span class="n">total_width</span> <span class="o">+</span> <span class="s2">"</span><span class="se">\n\n</span><span class="s2">"</span> <span class="k">if</span> <span class="n">nodetext_width_max</span> <span class="k">else</span> <span class="s2">""</span>
|
|
<span class="n">separator2</span> <span class="o">=</span> <span class="s2">"</span><span class="se">\n</span><span class="s2">"</span> <span class="o">+</span> <span class="n">sep</span> <span class="o">*</span> <span class="n">total_width</span> <span class="o">+</span> <span class="s2">"</span><span class="se">\n\n</span><span class="s2">"</span> <span class="k">if</span> <span class="n">total_width</span> <span class="k">else</span> <span class="s2">""</span>
|
|
<span class="k">return</span> <span class="n">separator1</span> <span class="o">+</span> <span class="s2">"|n"</span> <span class="o">+</span> <span class="n">nodetext</span> <span class="o">+</span> <span class="s2">"|n"</span> <span class="o">+</span> <span class="n">separator2</span> <span class="o">+</span> <span class="s2">"|n"</span> <span class="o">+</span> <span class="n">optionstext</span></div></div>
|
|
|
|
|
|
<span class="c1"># -----------------------------------------------------------</span>
|
|
<span class="c1">#</span>
|
|
<span class="c1"># List node (decorator turning a node into a list with</span>
|
|
<span class="c1"># look/edit/add functionality for the elements)</span>
|
|
<span class="c1">#</span>
|
|
<span class="c1"># -----------------------------------------------------------</span>
|
|
|
|
|
|
<div class="viewcode-block" id="list_node"><a class="viewcode-back" href="../../../api/evennia.utils.evmenu.html#evennia.utils.evmenu.list_node">[docs]</a><span class="k">def</span> <span class="nf">list_node</span><span class="p">(</span><span class="n">option_generator</span><span class="p">,</span> <span class="n">select</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">pagesize</span><span class="o">=</span><span class="mi">10</span><span class="p">):</span>
|
|
<span class="sd">"""</span>
|
|
<span class="sd"> Decorator for making an EvMenu node into a multi-page list node. Will add new options,</span>
|
|
<span class="sd"> prepending those options added in the node.</span>
|
|
|
|
<span class="sd"> Args:</span>
|
|
<span class="sd"> option_generator (callable or list): A list of strings indicating the options, or a callable</span>
|
|
<span class="sd"> that is called as option_generator(caller) to produce such a list.</span>
|
|
<span class="sd"> select (callable or str, optional): Node to redirect a selection to. Its `**kwargs` will</span>
|
|
<span class="sd"> contain the `available_choices` list and `selection` will hold one of the elements in</span>
|
|
<span class="sd"> that list. If a callable, it will be called as</span>
|
|
<span class="sd"> `select(caller, menuchoice, **kwargs)` where menuchoice is the chosen option as a</span>
|
|
<span class="sd"> string and `available_choices` is a kwarg mapping the option keys to the choices</span>
|
|
<span class="sd"> offered by the option_generator. The callable whould return the name of the target node</span>
|
|
<span class="sd"> to goto after this selection (or None to repeat the list-node). Note that if this is not</span>
|
|
<span class="sd"> given, the decorated node must itself provide a way to continue from the node!</span>
|
|
<span class="sd"> pagesize (int): How many options to show per page.</span>
|
|
|
|
<span class="sd"> Example:</span>
|
|
|
|
<span class="sd"> ```python</span>
|
|
<span class="sd"> list_node(['foo', 'bar'], select)</span>
|
|
<span class="sd"> def node_index(caller):</span>
|
|
<span class="sd"> text = "describing the list"</span>
|
|
<span class="sd"> return text, []</span>
|
|
<span class="sd"> ```</span>
|
|
|
|
<span class="sd"> Notes:</span>
|
|
<span class="sd"> All normal `goto` or `exec` callables returned from the decorated nodes</span>
|
|
<span class="sd"> will, if they accept `**kwargs`, get a new kwarg 'available_choices'</span>
|
|
<span class="sd"> injected. These are the ordered list of named options (descs) visible</span>
|
|
<span class="sd"> on the current node page.</span>
|
|
|
|
<span class="sd"> """</span>
|
|
|
|
<span class="k">def</span> <span class="nf">decorator</span><span class="p">(</span><span class="n">func</span><span class="p">):</span>
|
|
<span class="k">def</span> <span class="nf">_select_parser</span><span class="p">(</span><span class="n">caller</span><span class="p">,</span> <span class="n">raw_string</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
|
|
<span class="sd">"""</span>
|
|
<span class="sd"> Parse the select action</span>
|
|
<span class="sd"> """</span>
|
|
<span class="n">available_choices</span> <span class="o">=</span> <span class="n">kwargs</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">"available_choices"</span><span class="p">,</span> <span class="p">[])</span>
|
|
|
|
<span class="k">try</span><span class="p">:</span>
|
|
<span class="n">index</span> <span class="o">=</span> <span class="nb">int</span><span class="p">(</span><span class="n">raw_string</span><span class="o">.</span><span class="n">strip</span><span class="p">())</span> <span class="o">-</span> <span class="mi">1</span>
|
|
<span class="n">selection</span> <span class="o">=</span> <span class="n">available_choices</span><span class="p">[</span><span class="n">index</span><span class="p">]</span>
|
|
<span class="k">except</span> <span class="ne">Exception</span><span class="p">:</span>
|
|
<span class="n">caller</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="s2">"|rInvalid choice.|n"</span><span class="p">)</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="k">if</span> <span class="n">callable</span><span class="p">(</span><span class="n">select</span><span class="p">):</span>
|
|
<span class="k">try</span><span class="p">:</span>
|
|
<span class="k">if</span> <span class="nb">bool</span><span class="p">(</span><span class="n">getargspec</span><span class="p">(</span><span class="n">select</span><span class="p">)</span><span class="o">.</span><span class="n">keywords</span><span class="p">):</span>
|
|
<span class="k">return</span> <span class="n">select</span><span class="p">(</span><span class="n">caller</span><span class="p">,</span> <span class="n">selection</span><span class="p">,</span> <span class="n">available_choices</span><span class="o">=</span><span class="n">available_choices</span><span class="p">)</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="k">return</span> <span class="n">select</span><span class="p">(</span><span class="n">caller</span><span class="p">,</span> <span class="n">selection</span><span class="p">)</span>
|
|
<span class="k">except</span> <span class="ne">Exception</span><span class="p">:</span>
|
|
<span class="n">logger</span><span class="o">.</span><span class="n">log_trace</span><span class="p">()</span>
|
|
<span class="k">elif</span> <span class="n">select</span><span class="p">:</span>
|
|
<span class="c1"># we assume a string was given, we inject the result into the kwargs</span>
|
|
<span class="c1"># to pass on to the next node</span>
|
|
<span class="n">kwargs</span><span class="p">[</span><span class="s2">"selection"</span><span class="p">]</span> <span class="o">=</span> <span class="n">selection</span>
|
|
<span class="k">return</span> <span class="nb">str</span><span class="p">(</span><span class="n">select</span><span class="p">)</span>
|
|
<span class="c1"># this means the previous node will be re-run with these same kwargs</span>
|
|
<span class="k">return</span> <span class="kc">None</span>
|
|
|
|
<span class="k">def</span> <span class="nf">_list_node</span><span class="p">(</span><span class="n">caller</span><span class="p">,</span> <span class="n">raw_string</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
|
|
|
|
<span class="n">option_list</span> <span class="o">=</span> <span class="p">(</span>
|
|
<span class="n">option_generator</span><span class="p">(</span><span class="n">caller</span><span class="p">)</span> <span class="k">if</span> <span class="n">callable</span><span class="p">(</span><span class="n">option_generator</span><span class="p">)</span> <span class="k">else</span> <span class="n">option_generator</span>
|
|
<span class="p">)</span>
|
|
|
|
<span class="n">npages</span> <span class="o">=</span> <span class="mi">0</span>
|
|
<span class="n">page_index</span> <span class="o">=</span> <span class="mi">0</span>
|
|
<span class="n">page</span> <span class="o">=</span> <span class="p">[]</span>
|
|
<span class="n">options</span> <span class="o">=</span> <span class="p">[]</span>
|
|
|
|
<span class="k">if</span> <span class="n">option_list</span><span class="p">:</span>
|
|
<span class="n">nall_options</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="n">option_list</span><span class="p">)</span>
|
|
<span class="n">pages</span> <span class="o">=</span> <span class="p">[</span>
|
|
<span class="n">option_list</span><span class="p">[</span><span class="n">ind</span> <span class="p">:</span> <span class="n">ind</span> <span class="o">+</span> <span class="n">pagesize</span><span class="p">]</span> <span class="k">for</span> <span class="n">ind</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="n">nall_options</span><span class="p">,</span> <span class="n">pagesize</span><span class="p">)</span>
|
|
<span class="p">]</span>
|
|
<span class="n">npages</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="n">pages</span><span class="p">)</span>
|
|
|
|
<span class="n">page_index</span> <span class="o">=</span> <span class="nb">max</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="nb">min</span><span class="p">(</span><span class="n">npages</span> <span class="o">-</span> <span class="mi">1</span><span class="p">,</span> <span class="n">kwargs</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">"optionpage_index"</span><span class="p">,</span> <span class="mi">0</span><span class="p">)))</span>
|
|
<span class="n">page</span> <span class="o">=</span> <span class="n">pages</span><span class="p">[</span><span class="n">page_index</span><span class="p">]</span>
|
|
|
|
<span class="n">text</span> <span class="o">=</span> <span class="s2">""</span>
|
|
<span class="n">extra_text</span> <span class="o">=</span> <span class="kc">None</span>
|
|
|
|
<span class="c1"># dynamic, multi-page option list. Each selection leads to the `select`</span>
|
|
<span class="c1"># callback being called with a result from the available choices</span>
|
|
<span class="n">options</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span>
|
|
<span class="p">[</span>
|
|
<span class="p">{</span><span class="s2">"desc"</span><span class="p">:</span> <span class="n">opt</span><span class="p">,</span> <span class="s2">"goto"</span><span class="p">:</span> <span class="p">(</span><span class="n">_select_parser</span><span class="p">,</span> <span class="p">{</span><span class="s2">"available_choices"</span><span class="p">:</span> <span class="n">page</span><span class="p">})}</span>
|
|
<span class="k">for</span> <span class="n">opt</span> <span class="ow">in</span> <span class="n">page</span>
|
|
<span class="p">]</span>
|
|
<span class="p">)</span>
|
|
|
|
<span class="k">if</span> <span class="n">npages</span> <span class="o">></span> <span class="mi">1</span><span class="p">:</span>
|
|
<span class="c1"># if the goto callable returns None, the same node is rerun, and</span>
|
|
<span class="c1"># kwargs not used by the callable are passed on to the node. This</span>
|
|
<span class="c1"># allows us to call ourselves over and over, using different kwargs.</span>
|
|
<span class="n">options</span><span class="o">.</span><span class="n">append</span><span class="p">(</span>
|
|
<span class="p">{</span>
|
|
<span class="s2">"key"</span><span class="p">:</span> <span class="p">(</span><span class="s2">"|Wcurrent|n"</span><span class="p">,</span> <span class="s2">"c"</span><span class="p">),</span>
|
|
<span class="s2">"desc"</span><span class="p">:</span> <span class="s2">"|W(</span><span class="si">{}</span><span class="s2">/</span><span class="si">{}</span><span class="s2">)|n"</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">page_index</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="n">npages</span><span class="p">),</span>
|
|
<span class="s2">"goto"</span><span class="p">:</span> <span class="p">(</span><span class="k">lambda</span> <span class="n">caller</span><span class="p">:</span> <span class="kc">None</span><span class="p">,</span> <span class="p">{</span><span class="s2">"optionpage_index"</span><span class="p">:</span> <span class="n">page_index</span><span class="p">}),</span>
|
|
<span class="p">}</span>
|
|
<span class="p">)</span>
|
|
<span class="k">if</span> <span class="n">page_index</span> <span class="o">></span> <span class="mi">0</span><span class="p">:</span>
|
|
<span class="n">options</span><span class="o">.</span><span class="n">append</span><span class="p">(</span>
|
|
<span class="p">{</span>
|
|
<span class="s2">"key"</span><span class="p">:</span> <span class="p">(</span><span class="s2">"|wp|Wrevious page|n"</span><span class="p">,</span> <span class="s2">"p"</span><span class="p">),</span>
|
|
<span class="s2">"goto"</span><span class="p">:</span> <span class="p">(</span><span class="k">lambda</span> <span class="n">caller</span><span class="p">:</span> <span class="kc">None</span><span class="p">,</span> <span class="p">{</span><span class="s2">"optionpage_index"</span><span class="p">:</span> <span class="n">page_index</span> <span class="o">-</span> <span class="mi">1</span><span class="p">}),</span>
|
|
<span class="p">}</span>
|
|
<span class="p">)</span>
|
|
<span class="k">if</span> <span class="n">page_index</span> <span class="o"><</span> <span class="n">npages</span> <span class="o">-</span> <span class="mi">1</span><span class="p">:</span>
|
|
<span class="n">options</span><span class="o">.</span><span class="n">append</span><span class="p">(</span>
|
|
<span class="p">{</span>
|
|
<span class="s2">"key"</span><span class="p">:</span> <span class="p">(</span><span class="s2">"|wn|Wext page|n"</span><span class="p">,</span> <span class="s2">"n"</span><span class="p">),</span>
|
|
<span class="s2">"goto"</span><span class="p">:</span> <span class="p">(</span><span class="k">lambda</span> <span class="n">caller</span><span class="p">:</span> <span class="kc">None</span><span class="p">,</span> <span class="p">{</span><span class="s2">"optionpage_index"</span><span class="p">:</span> <span class="n">page_index</span> <span class="o">+</span> <span class="mi">1</span><span class="p">}),</span>
|
|
<span class="p">}</span>
|
|
<span class="p">)</span>
|
|
|
|
<span class="c1"># add data from the decorated node</span>
|
|
|
|
<span class="n">decorated_options</span> <span class="o">=</span> <span class="p">[]</span>
|
|
<span class="n">supports_kwargs</span> <span class="o">=</span> <span class="nb">bool</span><span class="p">(</span><span class="n">getargspec</span><span class="p">(</span><span class="n">func</span><span class="p">)</span><span class="o">.</span><span class="n">keywords</span><span class="p">)</span>
|
|
<span class="k">try</span><span class="p">:</span>
|
|
<span class="k">if</span> <span class="n">supports_kwargs</span><span class="p">:</span>
|
|
<span class="n">text</span><span class="p">,</span> <span class="n">decorated_options</span> <span class="o">=</span> <span class="n">func</span><span class="p">(</span><span class="n">caller</span><span class="p">,</span> <span class="n">raw_string</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">)</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="n">text</span><span class="p">,</span> <span class="n">decorated_options</span> <span class="o">=</span> <span class="n">func</span><span class="p">(</span><span class="n">caller</span><span class="p">,</span> <span class="n">raw_string</span><span class="p">)</span>
|
|
<span class="k">except</span> <span class="ne">TypeError</span><span class="p">:</span>
|
|
<span class="k">try</span><span class="p">:</span>
|
|
<span class="k">if</span> <span class="n">supports_kwargs</span><span class="p">:</span>
|
|
<span class="n">text</span><span class="p">,</span> <span class="n">decorated_options</span> <span class="o">=</span> <span class="n">func</span><span class="p">(</span><span class="n">caller</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">)</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="n">text</span><span class="p">,</span> <span class="n">decorated_options</span> <span class="o">=</span> <span class="n">func</span><span class="p">(</span><span class="n">caller</span><span class="p">)</span>
|
|
<span class="k">except</span> <span class="ne">Exception</span><span class="p">:</span>
|
|
<span class="k">raise</span>
|
|
<span class="k">except</span> <span class="ne">Exception</span><span class="p">:</span>
|
|
<span class="n">logger</span><span class="o">.</span><span class="n">log_trace</span><span class="p">()</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">decorated_options</span><span class="p">,</span> <span class="nb">dict</span><span class="p">):</span>
|
|
<span class="n">decorated_options</span> <span class="o">=</span> <span class="p">[</span><span class="n">decorated_options</span><span class="p">]</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="n">decorated_options</span> <span class="o">=</span> <span class="n">make_iter</span><span class="p">(</span><span class="n">decorated_options</span><span class="p">)</span>
|
|
|
|
<span class="n">extra_options</span> <span class="o">=</span> <span class="p">[]</span>
|
|
<span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">decorated_options</span><span class="p">,</span> <span class="nb">dict</span><span class="p">):</span>
|
|
<span class="n">decorated_options</span> <span class="o">=</span> <span class="p">[</span><span class="n">decorated_options</span><span class="p">]</span>
|
|
<span class="k">for</span> <span class="n">eopt</span> <span class="ow">in</span> <span class="n">decorated_options</span><span class="p">:</span>
|
|
<span class="n">cback</span> <span class="o">=</span> <span class="p">(</span><span class="s2">"goto"</span> <span class="ow">in</span> <span class="n">eopt</span> <span class="ow">and</span> <span class="s2">"goto"</span><span class="p">)</span> <span class="ow">or</span> <span class="p">(</span><span class="s2">"exec"</span> <span class="ow">in</span> <span class="n">eopt</span> <span class="ow">and</span> <span class="s2">"exec"</span><span class="p">)</span> <span class="ow">or</span> <span class="kc">None</span>
|
|
<span class="k">if</span> <span class="n">cback</span><span class="p">:</span>
|
|
<span class="n">signature</span> <span class="o">=</span> <span class="n">eopt</span><span class="p">[</span><span class="n">cback</span><span class="p">]</span>
|
|
<span class="k">if</span> <span class="n">callable</span><span class="p">(</span><span class="n">signature</span><span class="p">):</span>
|
|
<span class="c1"># callable with no kwargs defined</span>
|
|
<span class="n">eopt</span><span class="p">[</span><span class="n">cback</span><span class="p">]</span> <span class="o">=</span> <span class="p">(</span><span class="n">signature</span><span class="p">,</span> <span class="p">{</span><span class="s2">"available_choices"</span><span class="p">:</span> <span class="n">page</span><span class="p">})</span>
|
|
<span class="k">elif</span> <span class="n">is_iter</span><span class="p">(</span><span class="n">signature</span><span class="p">):</span>
|
|
<span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">signature</span><span class="p">)</span> <span class="o">></span> <span class="mi">1</span> <span class="ow">and</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">signature</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="nb">dict</span><span class="p">):</span>
|
|
<span class="n">signature</span><span class="p">[</span><span class="mi">1</span><span class="p">][</span><span class="s2">"available_choices"</span><span class="p">]</span> <span class="o">=</span> <span class="n">page</span>
|
|
<span class="n">eopt</span><span class="p">[</span><span class="n">cback</span><span class="p">]</span> <span class="o">=</span> <span class="n">signature</span>
|
|
<span class="k">elif</span> <span class="n">signature</span><span class="p">:</span>
|
|
<span class="c1"># a callable alone in a tuple (i.e. no previous kwargs)</span>
|
|
<span class="n">eopt</span><span class="p">[</span><span class="n">cback</span><span class="p">]</span> <span class="o">=</span> <span class="p">(</span><span class="n">signature</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="p">{</span><span class="s2">"available_choices"</span><span class="p">:</span> <span class="n">page</span><span class="p">})</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="c1"># malformed input.</span>
|
|
<span class="n">logger</span><span class="o">.</span><span class="n">log_err</span><span class="p">(</span>
|
|
<span class="s2">"EvMenu @list_node decorator found "</span>
|
|
<span class="s2">"malformed option to decorate: </span><span class="si">{}</span><span class="s2">"</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">eopt</span><span class="p">)</span>
|
|
<span class="p">)</span>
|
|
<span class="n">extra_options</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">eopt</span><span class="p">)</span>
|
|
|
|
<span class="n">options</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">extra_options</span><span class="p">)</span>
|
|
<span class="n">text</span> <span class="o">=</span> <span class="n">text</span> <span class="o">+</span> <span class="s2">"</span><span class="se">\n\n</span><span class="s2">"</span> <span class="o">+</span> <span class="n">extra_text</span> <span class="k">if</span> <span class="n">extra_text</span> <span class="k">else</span> <span class="n">text</span>
|
|
|
|
<span class="k">return</span> <span class="n">text</span><span class="p">,</span> <span class="n">options</span>
|
|
|
|
<span class="k">return</span> <span class="n">_list_node</span>
|
|
|
|
<span class="k">return</span> <span class="n">decorator</span></div>
|
|
|
|
|
|
<span class="c1"># -------------------------------------------------------------------------------------------------</span>
|
|
<span class="c1">#</span>
|
|
<span class="c1"># Simple input shortcuts</span>
|
|
<span class="c1">#</span>
|
|
<span class="c1"># -------------------------------------------------------------------------------------------------</span>
|
|
|
|
|
|
<div class="viewcode-block" id="CmdGetInput"><a class="viewcode-back" href="../../../api/evennia.utils.evmenu.html#evennia.utils.evmenu.CmdGetInput">[docs]</a><span class="k">class</span> <span class="nc">CmdGetInput</span><span class="p">(</span><span class="n">Command</span><span class="p">):</span>
|
|
<span class="sd">"""</span>
|
|
<span class="sd"> Enter your data and press return.</span>
|
|
<span class="sd"> """</span>
|
|
|
|
<span class="n">key</span> <span class="o">=</span> <span class="n">_CMD_NOMATCH</span>
|
|
<span class="n">aliases</span> <span class="o">=</span> <span class="n">_CMD_NOINPUT</span>
|
|
|
|
<div class="viewcode-block" id="CmdGetInput.func"><a class="viewcode-back" href="../../../api/evennia.utils.evmenu.html#evennia.utils.evmenu.CmdGetInput.func">[docs]</a> <span class="k">def</span> <span class="nf">func</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
|
<span class="sd">"""This is called when user enters anything."""</span>
|
|
<span class="n">caller</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">caller</span>
|
|
<span class="k">try</span><span class="p">:</span>
|
|
<span class="n">getinput</span> <span class="o">=</span> <span class="n">caller</span><span class="o">.</span><span class="n">ndb</span><span class="o">.</span><span class="n">_getinput</span>
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="n">getinput</span> <span class="ow">and</span> <span class="nb">hasattr</span><span class="p">(</span><span class="n">caller</span><span class="p">,</span> <span class="s2">"account"</span><span class="p">):</span>
|
|
<span class="n">getinput</span> <span class="o">=</span> <span class="n">caller</span><span class="o">.</span><span class="n">account</span><span class="o">.</span><span class="n">ndb</span><span class="o">.</span><span class="n">_getinput</span>
|
|
<span class="n">caller</span> <span class="o">=</span> <span class="n">caller</span><span class="o">.</span><span class="n">account</span>
|
|
<span class="n">callback</span> <span class="o">=</span> <span class="n">getinput</span><span class="o">.</span><span class="n">_callback</span>
|
|
|
|
<span class="n">caller</span><span class="o">.</span><span class="n">ndb</span><span class="o">.</span><span class="n">_getinput</span><span class="o">.</span><span class="n">_session</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">session</span>
|
|
<span class="n">prompt</span> <span class="o">=</span> <span class="n">caller</span><span class="o">.</span><span class="n">ndb</span><span class="o">.</span><span class="n">_getinput</span><span class="o">.</span><span class="n">_prompt</span>
|
|
<span class="n">args</span> <span class="o">=</span> <span class="n">caller</span><span class="o">.</span><span class="n">ndb</span><span class="o">.</span><span class="n">_getinput</span><span class="o">.</span><span class="n">_args</span>
|
|
<span class="n">kwargs</span> <span class="o">=</span> <span class="n">caller</span><span class="o">.</span><span class="n">ndb</span><span class="o">.</span><span class="n">_getinput</span><span class="o">.</span><span class="n">_kwargs</span>
|
|
<span class="n">result</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">raw_string</span><span class="o">.</span><span class="n">rstrip</span><span class="p">()</span> <span class="c1"># we strip the ending line break caused by sending</span>
|
|
|
|
<span class="n">ok</span> <span class="o">=</span> <span class="ow">not</span> <span class="n">callback</span><span class="p">(</span><span class="n">caller</span><span class="p">,</span> <span class="n">prompt</span><span class="p">,</span> <span class="n">result</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="n">ok</span><span class="p">:</span>
|
|
<span class="c1"># only clear the state if the callback does not return</span>
|
|
<span class="c1"># anything</span>
|
|
<span class="k">del</span> <span class="n">caller</span><span class="o">.</span><span class="n">ndb</span><span class="o">.</span><span class="n">_getinput</span>
|
|
<span class="n">caller</span><span class="o">.</span><span class="n">cmdset</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="n">InputCmdSet</span><span class="p">)</span>
|
|
<span class="k">except</span> <span class="ne">Exception</span><span class="p">:</span>
|
|
<span class="c1"># make sure to clean up cmdset if something goes wrong</span>
|
|
<span class="n">caller</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="s2">"|rError in get_input. Choice not confirmed (report to admin)|n"</span><span class="p">)</span>
|
|
<span class="n">logger</span><span class="o">.</span><span class="n">log_trace</span><span class="p">(</span><span class="s2">"Error in get_input"</span><span class="p">)</span>
|
|
<span class="n">caller</span><span class="o">.</span><span class="n">cmdset</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="n">InputCmdSet</span><span class="p">)</span></div></div>
|
|
|
|
|
|
<div class="viewcode-block" id="InputCmdSet"><a class="viewcode-back" href="../../../api/evennia.utils.evmenu.html#evennia.utils.evmenu.InputCmdSet">[docs]</a><span class="k">class</span> <span class="nc">InputCmdSet</span><span class="p">(</span><span class="n">CmdSet</span><span class="p">):</span>
|
|
<span class="sd">"""</span>
|
|
<span class="sd"> This stores the input command</span>
|
|
<span class="sd"> """</span>
|
|
|
|
<span class="n">key</span> <span class="o">=</span> <span class="s2">"input_cmdset"</span>
|
|
<span class="n">priority</span> <span class="o">=</span> <span class="mi">1</span>
|
|
<span class="n">mergetype</span> <span class="o">=</span> <span class="s2">"Replace"</span>
|
|
<span class="n">no_objs</span> <span class="o">=</span> <span class="kc">True</span>
|
|
<span class="n">no_exits</span> <span class="o">=</span> <span class="kc">True</span>
|
|
<span class="n">no_channels</span> <span class="o">=</span> <span class="kc">False</span>
|
|
|
|
<div class="viewcode-block" id="InputCmdSet.at_cmdset_creation"><a class="viewcode-back" href="../../../api/evennia.utils.evmenu.html#evennia.utils.evmenu.InputCmdSet.at_cmdset_creation">[docs]</a> <span class="k">def</span> <span class="nf">at_cmdset_creation</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
|
<span class="sd">"""called once at creation"""</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">CmdGetInput</span><span class="p">())</span></div></div>
|
|
|
|
|
|
<span class="k">class</span> <span class="nc">_Prompt</span><span class="p">:</span>
|
|
<span class="sd">"""Dummy holder"""</span>
|
|
|
|
<span class="k">pass</span>
|
|
|
|
|
|
<div class="viewcode-block" id="get_input"><a class="viewcode-back" href="../../../api/evennia.utils.evmenu.html#evennia.utils.evmenu.get_input">[docs]</a><span class="k">def</span> <span class="nf">get_input</span><span class="p">(</span><span class="n">caller</span><span class="p">,</span> <span class="n">prompt</span><span class="p">,</span> <span class="n">callback</span><span class="p">,</span> <span class="n">session</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
|
|
<span class="sd">"""</span>
|
|
<span class="sd"> This is a helper function for easily request input from the caller.</span>
|
|
|
|
<span class="sd"> Args:</span>
|
|
<span class="sd"> caller (Account or Object): The entity being asked the question. This</span>
|
|
<span class="sd"> should usually be an object controlled by a user.</span>
|
|
<span class="sd"> prompt (str): This text will be shown to the user, in order to let them</span>
|
|
<span class="sd"> know their input is needed.</span>
|
|
<span class="sd"> callback (callable): A function that will be called</span>
|
|
<span class="sd"> when the user enters a reply. It must take three arguments: the</span>
|
|
<span class="sd"> `caller`, the `prompt` text and the `result` of the input given by</span>
|
|
<span class="sd"> the user. If the callback doesn't return anything or return False,</span>
|
|
<span class="sd"> the input prompt will be cleaned up and exited. If returning True,</span>
|
|
<span class="sd"> the prompt will remain and continue to accept input.</span>
|
|
<span class="sd"> session (Session, optional): This allows to specify the</span>
|
|
<span class="sd"> session to send the prompt to. It's usually only needed if `caller`</span>
|
|
<span class="sd"> is an Account in multisession modes greater than 2. The session is</span>
|
|
<span class="sd"> then updated by the command and is available (for example in</span>
|
|
<span class="sd"> callbacks) through `caller.ndb.getinput._session`.</span>
|
|
<span class="sd"> *args (any): Extra arguments to pass to `callback`. To utilise `*args`</span>
|
|
<span class="sd"> (and `**kwargs`), a value for the `session` argument must also be</span>
|
|
<span class="sd"> provided.</span>
|
|
<span class="sd"> **kwargs (any): Extra kwargs to pass to `callback`.</span>
|
|
|
|
<span class="sd"> Raises:</span>
|
|
<span class="sd"> RuntimeError: If the given callback is not callable.</span>
|
|
|
|
<span class="sd"> Notes:</span>
|
|
<span class="sd"> The result value sent to the callback is raw and not processed in any</span>
|
|
<span class="sd"> way. This means that you will get the ending line return character from</span>
|
|
<span class="sd"> most types of client inputs. So make sure to strip that before doing a</span>
|
|
<span class="sd"> comparison.</span>
|
|
|
|
<span class="sd"> When the prompt is running, a temporary object `caller.ndb._getinput`</span>
|
|
<span class="sd"> is stored; this will be removed when the prompt finishes.</span>
|
|
|
|
<span class="sd"> If you need the specific Session of the caller (which may not be easy</span>
|
|
<span class="sd"> to get if caller is an account in higher multisession modes), then it</span>
|
|
<span class="sd"> is available in the callback through `caller.ndb._getinput._session`.</span>
|
|
<span class="sd"> This is why the `session` is required as input.</span>
|
|
|
|
<span class="sd"> It's not recommended to 'chain' `get_input` into a sequence of</span>
|
|
<span class="sd"> questions. This will result in the caller stacking ever more instances</span>
|
|
<span class="sd"> of InputCmdSets. While they will all be cleared on concluding the</span>
|
|
<span class="sd"> get_input chain, EvMenu should be considered for anything beyond a</span>
|
|
<span class="sd"> single question.</span>
|
|
|
|
<span class="sd"> """</span>
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="n">callable</span><span class="p">(</span><span class="n">callback</span><span class="p">):</span>
|
|
<span class="k">raise</span> <span class="ne">RuntimeError</span><span class="p">(</span><span class="s2">"get_input: input callback is not callable."</span><span class="p">)</span>
|
|
<span class="n">caller</span><span class="o">.</span><span class="n">ndb</span><span class="o">.</span><span class="n">_getinput</span> <span class="o">=</span> <span class="n">_Prompt</span><span class="p">()</span>
|
|
<span class="n">caller</span><span class="o">.</span><span class="n">ndb</span><span class="o">.</span><span class="n">_getinput</span><span class="o">.</span><span class="n">_callback</span> <span class="o">=</span> <span class="n">callback</span>
|
|
<span class="n">caller</span><span class="o">.</span><span class="n">ndb</span><span class="o">.</span><span class="n">_getinput</span><span class="o">.</span><span class="n">_prompt</span> <span class="o">=</span> <span class="n">prompt</span>
|
|
<span class="n">caller</span><span class="o">.</span><span class="n">ndb</span><span class="o">.</span><span class="n">_getinput</span><span class="o">.</span><span class="n">_session</span> <span class="o">=</span> <span class="n">session</span>
|
|
<span class="n">caller</span><span class="o">.</span><span class="n">ndb</span><span class="o">.</span><span class="n">_getinput</span><span class="o">.</span><span class="n">_args</span> <span class="o">=</span> <span class="n">args</span>
|
|
<span class="n">caller</span><span class="o">.</span><span class="n">ndb</span><span class="o">.</span><span class="n">_getinput</span><span class="o">.</span><span class="n">_kwargs</span> <span class="o">=</span> <span class="n">kwargs</span>
|
|
<span class="n">caller</span><span class="o">.</span><span class="n">cmdset</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">InputCmdSet</span><span class="p">)</span>
|
|
<span class="n">caller</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="n">prompt</span><span class="p">,</span> <span class="n">session</span><span class="o">=</span><span class="n">session</span><span class="p">)</span></div>
|
|
|
|
|
|
<div class="viewcode-block" id="CmdYesNoQuestion"><a class="viewcode-back" href="../../../api/evennia.utils.evmenu.html#evennia.utils.evmenu.CmdYesNoQuestion">[docs]</a><span class="k">class</span> <span class="nc">CmdYesNoQuestion</span><span class="p">(</span><span class="n">Command</span><span class="p">):</span>
|
|
<span class="sd">"""</span>
|
|
<span class="sd"> Handle a prompt for yes or no. Press [return] for the default choice.</span>
|
|
|
|
<span class="sd"> """</span>
|
|
|
|
<span class="n">key</span> <span class="o">=</span> <span class="n">_CMD_NOINPUT</span>
|
|
<span class="n">aliases</span> <span class="o">=</span> <span class="p">[</span><span class="n">_CMD_NOMATCH</span><span class="p">,</span> <span class="s2">"yes"</span><span class="p">,</span> <span class="s2">"no"</span><span class="p">,</span> <span class="s1">'y'</span><span class="p">,</span> <span class="s1">'n'</span><span class="p">,</span> <span class="s1">'a'</span><span class="p">,</span> <span class="s1">'abort'</span><span class="p">]</span>
|
|
<span class="n">arg_regex</span> <span class="o">=</span> <span class="sa">r</span><span class="s2">"^$"</span>
|
|
|
|
<span class="k">def</span> <span class="nf">_clean</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">caller</span><span class="p">):</span>
|
|
<span class="k">del</span> <span class="n">caller</span><span class="o">.</span><span class="n">ndb</span><span class="o">.</span><span class="n">_yes_no_question</span>
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="n">caller</span><span class="o">.</span><span class="n">cmdset</span><span class="o">.</span><span class="n">has</span><span class="p">(</span><span class="n">YesNoQuestionCmdSet</span><span class="p">)</span> <span class="ow">and</span> <span class="nb">hasattr</span><span class="p">(</span><span class="n">caller</span><span class="p">,</span> <span class="s2">"account"</span><span class="p">):</span>
|
|
<span class="n">caller</span><span class="o">.</span><span class="n">account</span><span class="o">.</span><span class="n">cmdset</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="n">YesNoQuestionCmdSet</span><span class="p">)</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="n">caller</span><span class="o">.</span><span class="n">cmdset</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="n">YesNoQuestionCmdSet</span><span class="p">)</span>
|
|
|
|
<div class="viewcode-block" id="CmdYesNoQuestion.func"><a class="viewcode-back" href="../../../api/evennia.utils.evmenu.html#evennia.utils.evmenu.CmdYesNoQuestion.func">[docs]</a> <span class="k">def</span> <span class="nf">func</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
|
<span class="sd">"""This is called when user enters anything."""</span>
|
|
<span class="n">caller</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">caller</span>
|
|
<span class="k">try</span><span class="p">:</span>
|
|
<span class="n">yes_no_question</span> <span class="o">=</span> <span class="n">caller</span><span class="o">.</span><span class="n">ndb</span><span class="o">.</span><span class="n">_yes_no_question</span>
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="n">yes_no_question</span> <span class="ow">and</span> <span class="nb">hasattr</span><span class="p">(</span><span class="n">caller</span><span class="p">,</span> <span class="s2">"account"</span><span class="p">):</span>
|
|
<span class="n">yes_no_question</span> <span class="o">=</span> <span class="n">caller</span><span class="o">.</span><span class="n">account</span><span class="o">.</span><span class="n">ndb</span><span class="o">.</span><span class="n">_yes_no_question</span>
|
|
<span class="n">caller</span> <span class="o">=</span> <span class="n">caller</span><span class="o">.</span><span class="n">account</span>
|
|
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="n">yes_no_question</span><span class="p">:</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_clean</span><span class="p">(</span><span class="n">caller</span><span class="p">)</span>
|
|
<span class="k">return</span>
|
|
|
|
<span class="n">inp</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">cmdname</span>
|
|
|
|
<span class="k">if</span> <span class="n">inp</span> <span class="o">==</span> <span class="n">_CMD_NOINPUT</span><span class="p">:</span>
|
|
<span class="n">raw</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">raw_cmdname</span><span class="o">.</span><span class="n">strip</span><span class="p">()</span>
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="n">raw</span><span class="p">:</span>
|
|
<span class="c1"># use default</span>
|
|
<span class="n">inp</span> <span class="o">=</span> <span class="n">yes_no_question</span><span class="o">.</span><span class="n">default</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="n">inp</span> <span class="o">=</span> <span class="n">raw</span>
|
|
|
|
<span class="k">if</span> <span class="n">inp</span> <span class="ow">in</span> <span class="p">(</span><span class="s1">'a'</span><span class="p">,</span> <span class="s1">'abort'</span><span class="p">)</span> <span class="ow">and</span> <span class="n">yes_no_question</span><span class="o">.</span><span class="n">allow_abort</span><span class="p">:</span>
|
|
<span class="n">caller</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="s2">"Aborted."</span><span class="p">)</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_clean</span><span class="p">(</span><span class="n">caller</span><span class="p">)</span>
|
|
<span class="k">return</span>
|
|
|
|
<span class="n">caller</span><span class="o">.</span><span class="n">ndb</span><span class="o">.</span><span class="n">_yes_no_question</span><span class="o">.</span><span class="n">session</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">session</span>
|
|
|
|
<span class="n">args</span> <span class="o">=</span> <span class="n">yes_no_question</span><span class="o">.</span><span class="n">args</span>
|
|
<span class="n">kwargs</span> <span class="o">=</span> <span class="n">yes_no_question</span><span class="o">.</span><span class="n">kwargs</span>
|
|
<span class="n">kwargs</span><span class="p">[</span><span class="s1">'caller_session'</span><span class="p">]</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">session</span>
|
|
|
|
<span class="n">ok</span> <span class="o">=</span> <span class="kc">False</span>
|
|
<span class="k">if</span> <span class="n">inp</span> <span class="ow">in</span> <span class="p">(</span><span class="s1">'yes'</span><span class="p">,</span> <span class="s1">'y'</span><span class="p">):</span>
|
|
<span class="n">yes_no_question</span><span class="o">.</span><span class="n">yes_callable</span><span class="p">(</span><span class="n">caller</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">)</span>
|
|
<span class="k">elif</span> <span class="n">inp</span> <span class="ow">in</span> <span class="p">(</span><span class="s1">'no'</span><span class="p">,</span> <span class="s1">'n'</span><span class="p">):</span>
|
|
<span class="n">yes_no_question</span><span class="o">.</span><span class="n">no_callable</span><span class="p">(</span><span class="n">caller</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">)</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="c1"># invalid input. Resend prompt without cleaning</span>
|
|
<span class="n">caller</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="n">yes_no_question</span><span class="o">.</span><span class="n">prompt</span><span class="p">,</span> <span class="n">session</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">session</span><span class="p">)</span>
|
|
<span class="k">return</span>
|
|
|
|
<span class="c1"># cleanup</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_clean</span><span class="p">(</span><span class="n">caller</span><span class="p">)</span>
|
|
<span class="k">except</span> <span class="ne">Exception</span> <span class="k">as</span> <span class="n">err</span><span class="p">:</span>
|
|
<span class="c1"># make sure to clean up cmdset if something goes wrong</span>
|
|
<span class="n">caller</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="s2">"|rError in ask_yes_no. Choice not confirmed (report to admin)|n"</span><span class="p">)</span>
|
|
<span class="n">logger</span><span class="o">.</span><span class="n">log_trace</span><span class="p">(</span><span class="s2">"Error in ask_yes_no"</span><span class="p">)</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">_clean</span><span class="p">(</span><span class="n">caller</span><span class="p">)</span>
|
|
<span class="k">raise</span></div></div>
|
|
|
|
|
|
<div class="viewcode-block" id="YesNoQuestionCmdSet"><a class="viewcode-back" href="../../../api/evennia.utils.evmenu.html#evennia.utils.evmenu.YesNoQuestionCmdSet">[docs]</a><span class="k">class</span> <span class="nc">YesNoQuestionCmdSet</span><span class="p">(</span><span class="n">CmdSet</span><span class="p">):</span>
|
|
<span class="sd">"""</span>
|
|
<span class="sd"> This stores the input command</span>
|
|
<span class="sd"> """</span>
|
|
|
|
<span class="n">key</span> <span class="o">=</span> <span class="s2">"yes_no_question_cmdset"</span>
|
|
<span class="n">priority</span> <span class="o">=</span> <span class="mi">1</span>
|
|
<span class="n">mergetype</span> <span class="o">=</span> <span class="s2">"Replace"</span>
|
|
<span class="n">no_objs</span> <span class="o">=</span> <span class="kc">True</span>
|
|
<span class="n">no_exits</span> <span class="o">=</span> <span class="kc">True</span>
|
|
<span class="n">no_channels</span> <span class="o">=</span> <span class="kc">False</span>
|
|
|
|
<div class="viewcode-block" id="YesNoQuestionCmdSet.at_cmdset_creation"><a class="viewcode-back" href="../../../api/evennia.utils.evmenu.html#evennia.utils.evmenu.YesNoQuestionCmdSet.at_cmdset_creation">[docs]</a> <span class="k">def</span> <span class="nf">at_cmdset_creation</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
|
|
<span class="sd">"""called once at creation"""</span>
|
|
<span class="bp">self</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">CmdYesNoQuestion</span><span class="p">())</span></div></div>
|
|
|
|
|
|
<div class="viewcode-block" id="ask_yes_no"><a class="viewcode-back" href="../../../api/evennia.utils.evmenu.html#evennia.utils.evmenu.ask_yes_no">[docs]</a><span class="k">def</span> <span class="nf">ask_yes_no</span><span class="p">(</span><span class="n">caller</span><span class="p">,</span> <span class="n">prompt</span><span class="o">=</span><span class="s2">"Yes or No </span><span class="si">{options}</span><span class="s2">?"</span><span class="p">,</span> <span class="n">yes_action</span><span class="o">=</span><span class="s2">"Yes"</span><span class="p">,</span> <span class="n">no_action</span><span class="o">=</span><span class="s2">"No"</span><span class="p">,</span>
|
|
<span class="n">default</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">allow_abort</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="n">session</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
|
|
<span class="sd">"""</span>
|
|
<span class="sd"> A helper question for asking a simple yes/no question. This will cause</span>
|
|
<span class="sd"> the system to pause and wait for input from the player.</span>
|
|
|
|
<span class="sd"> Args:</span>
|
|
<span class="sd"> prompt (str): The yes/no question to ask. This takes an optional formatting</span>
|
|
<span class="sd"> marker `{options}` which will be filled with 'Y/N', '[Y]/N' or</span>
|
|
<span class="sd"> 'Y/[N]' depending on the setting of `default`. If `allow_abort` is set,</span>
|
|
<span class="sd"> then the 'A(bort)' option will also be available.</span>
|
|
<span class="sd"> yes_action (callable or str): If a callable, this will be called</span>
|
|
<span class="sd"> with `(caller, *args, **kwargs)` when the Yes-choice is made.</span>
|
|
<span class="sd"> If a string, this string will be echoed back to the caller.</span>
|
|
<span class="sd"> no_action (callable or str): If a callable, this will be called</span>
|
|
<span class="sd"> with `(caller, *args, **kwargs)` when the No-choice is made.</span>
|
|
<span class="sd"> If a string, this string will be echoed back to the caller.</span>
|
|
<span class="sd"> default (str optional): This is what the user will get if they just press the</span>
|
|
<span class="sd"> return key without giving any input. One of 'N', 'Y', 'A' or `None`</span>
|
|
<span class="sd"> for no default (an explicit choice must be given). If 'A' (abort)</span>
|
|
<span class="sd"> is given, `allow_abort` kwarg is ignored and assumed set.</span>
|
|
<span class="sd"> allow_abort (bool, optional): If set, the 'A(bort)' option is available</span>
|
|
<span class="sd"> (a third option meaning neither yes or no but just exits the prompt).</span>
|
|
<span class="sd"> session (Session, optional): This allows to specify the</span>
|
|
<span class="sd"> session to send the prompt to. It's usually only needed if `caller`</span>
|
|
<span class="sd"> is an Account in multisession modes greater than 2. The session is</span>
|
|
<span class="sd"> then updated by the command and is available (for example in</span>
|
|
<span class="sd"> callbacks) through `caller.ndb._yes_no_question.session`.</span>
|
|
<span class="sd"> *args: Additional arguments passed on into callables.</span>
|
|
<span class="sd"> **kwargs: Additional keyword args passed on into callables.</span>
|
|
|
|
<span class="sd"> Raises:</span>
|
|
<span class="sd"> RuntimeError, FooError: If default and `allow_abort` clashes.</span>
|
|
|
|
<span class="sd"> Example:</span>
|
|
<span class="sd"> ::</span>
|
|
|
|
<span class="sd"> # just returning strings</span>
|
|
<span class="sd"> ask_yes_no(caller, "Are you happy {options}?",</span>
|
|
<span class="sd"> "you answered yes", "you answered no")</span>
|
|
<span class="sd"> # trigger callables</span>
|
|
<span class="sd"> ask_yes_no(caller, "Are you sad {options}?",</span>
|
|
<span class="sd"> _callable_yes, _callable_no, allow_abort=True)</span>
|
|
|
|
<span class="sd"> """</span>
|
|
<span class="k">def</span> <span class="nf">_callable_yes_txt</span><span class="p">(</span><span class="n">caller</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
|
|
<span class="n">yes_txt</span> <span class="o">=</span> <span class="n">kwargs</span><span class="p">[</span><span class="s1">'yes_txt'</span><span class="p">]</span>
|
|
<span class="n">session</span> <span class="o">=</span> <span class="n">kwargs</span><span class="p">[</span><span class="s1">'caller_session'</span><span class="p">]</span>
|
|
<span class="n">caller</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="n">yes_txt</span><span class="p">,</span> <span class="n">session</span><span class="o">=</span><span class="n">session</span><span class="p">)</span>
|
|
|
|
<span class="k">def</span> <span class="nf">_callable_no_txt</span><span class="p">(</span><span class="n">caller</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
|
|
<span class="n">no_txt</span> <span class="o">=</span> <span class="n">kwargs</span><span class="p">[</span><span class="s1">'no_txt'</span><span class="p">]</span>
|
|
<span class="n">session</span> <span class="o">=</span> <span class="n">kwargs</span><span class="p">[</span><span class="s1">'caller_session'</span><span class="p">]</span>
|
|
<span class="n">caller</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="n">no_txt</span><span class="p">,</span> <span class="n">session</span><span class="o">=</span><span class="n">session</span><span class="p">)</span>
|
|
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="n">callable</span><span class="p">(</span><span class="n">yes_action</span><span class="p">):</span>
|
|
<span class="n">kwargs</span><span class="p">[</span><span class="s1">'yes_txt'</span><span class="p">]</span> <span class="o">=</span> <span class="nb">str</span><span class="p">(</span><span class="n">yes_action</span><span class="p">)</span>
|
|
<span class="n">yes_action</span> <span class="o">=</span> <span class="n">_callable_yes_txt</span>
|
|
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="n">callable</span><span class="p">(</span><span class="n">no_action</span><span class="p">):</span>
|
|
<span class="n">kwargs</span><span class="p">[</span><span class="s1">'no_txt'</span><span class="p">]</span> <span class="o">=</span> <span class="nb">str</span><span class="p">(</span><span class="n">no_action</span><span class="p">)</span>
|
|
<span class="n">no_action</span> <span class="o">=</span> <span class="n">_callable_no_txt</span>
|
|
|
|
<span class="c1"># prepare the prompt with options</span>
|
|
<span class="n">options</span> <span class="o">=</span> <span class="s2">"Y/N"</span>
|
|
<span class="n">abort_txt</span> <span class="o">=</span> <span class="s2">"/Abort"</span> <span class="k">if</span> <span class="n">allow_abort</span> <span class="k">else</span> <span class="s2">""</span>
|
|
<span class="k">if</span> <span class="n">default</span><span class="p">:</span>
|
|
<span class="n">default</span> <span class="o">=</span> <span class="n">default</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span>
|
|
<span class="k">if</span> <span class="n">default</span> <span class="o">==</span> <span class="s2">"y"</span><span class="p">:</span>
|
|
<span class="n">options</span> <span class="o">=</span> <span class="s2">"[Y]/N"</span>
|
|
<span class="k">elif</span> <span class="n">default</span> <span class="o">==</span> <span class="s2">"n"</span><span class="p">:</span>
|
|
<span class="n">options</span> <span class="o">=</span> <span class="s2">"Y/[N]"</span>
|
|
<span class="k">elif</span> <span class="n">default</span> <span class="o">==</span> <span class="s2">"a"</span><span class="p">:</span>
|
|
<span class="n">allow_abort</span> <span class="o">=</span> <span class="kc">True</span>
|
|
<span class="n">abort_txt</span> <span class="o">=</span> <span class="s2">"/[A]bort"</span>
|
|
<span class="n">options</span> <span class="o">+=</span> <span class="n">abort_txt</span>
|
|
<span class="n">prompt</span> <span class="o">=</span> <span class="n">prompt</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">options</span><span class="o">=</span><span class="n">options</span><span class="p">)</span>
|
|
|
|
<span class="n">caller</span><span class="o">.</span><span class="n">ndb</span><span class="o">.</span><span class="n">_yes_no_question</span> <span class="o">=</span> <span class="n">_Prompt</span><span class="p">()</span>
|
|
<span class="n">caller</span><span class="o">.</span><span class="n">ndb</span><span class="o">.</span><span class="n">_yes_no_question</span><span class="o">.</span><span class="n">prompt</span> <span class="o">=</span> <span class="n">prompt</span>
|
|
<span class="n">caller</span><span class="o">.</span><span class="n">ndb</span><span class="o">.</span><span class="n">_yes_no_question</span><span class="o">.</span><span class="n">session</span> <span class="o">=</span> <span class="n">session</span>
|
|
<span class="n">caller</span><span class="o">.</span><span class="n">ndb</span><span class="o">.</span><span class="n">_yes_no_question</span><span class="o">.</span><span class="n">prompt</span> <span class="o">=</span> <span class="n">prompt</span>
|
|
<span class="n">caller</span><span class="o">.</span><span class="n">ndb</span><span class="o">.</span><span class="n">_yes_no_question</span><span class="o">.</span><span class="n">default</span> <span class="o">=</span> <span class="n">default</span>
|
|
<span class="n">caller</span><span class="o">.</span><span class="n">ndb</span><span class="o">.</span><span class="n">_yes_no_question</span><span class="o">.</span><span class="n">allow_abort</span> <span class="o">=</span> <span class="n">allow_abort</span>
|
|
<span class="n">caller</span><span class="o">.</span><span class="n">ndb</span><span class="o">.</span><span class="n">_yes_no_question</span><span class="o">.</span><span class="n">yes_callable</span> <span class="o">=</span> <span class="n">yes_action</span>
|
|
<span class="n">caller</span><span class="o">.</span><span class="n">ndb</span><span class="o">.</span><span class="n">_yes_no_question</span><span class="o">.</span><span class="n">no_callable</span> <span class="o">=</span> <span class="n">no_action</span>
|
|
<span class="n">caller</span><span class="o">.</span><span class="n">ndb</span><span class="o">.</span><span class="n">_yes_no_question</span><span class="o">.</span><span class="n">args</span> <span class="o">=</span> <span class="n">args</span>
|
|
<span class="n">caller</span><span class="o">.</span><span class="n">ndb</span><span class="o">.</span><span class="n">_yes_no_question</span><span class="o">.</span><span class="n">kwargs</span> <span class="o">=</span> <span class="n">kwargs</span>
|
|
|
|
<span class="n">caller</span><span class="o">.</span><span class="n">cmdset</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">YesNoQuestionCmdSet</span><span class="p">)</span>
|
|
<span class="n">caller</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="n">prompt</span><span class="p">,</span> <span class="n">session</span><span class="o">=</span><span class="n">session</span><span class="p">)</span></div>
|
|
|
|
|
|
<span class="c1"># -------------------------------------------------------------</span>
|
|
<span class="c1">#</span>
|
|
<span class="c1"># Menu generation from menu template string</span>
|
|
<span class="c1">#</span>
|
|
<span class="c1"># -------------------------------------------------------------</span>
|
|
|
|
<span class="n">_RE_NODE</span> <span class="o">=</span> <span class="n">re</span><span class="o">.</span><span class="n">compile</span><span class="p">(</span><span class="sa">r</span><span class="s2">"##\s*?NODE\s+?(?P<nodename>\S[\S\s]*?)$"</span><span class="p">,</span> <span class="n">re</span><span class="o">.</span><span class="n">I</span> <span class="o">+</span> <span class="n">re</span><span class="o">.</span><span class="n">M</span><span class="p">)</span>
|
|
<span class="n">_RE_OPTIONS_SEP</span> <span class="o">=</span> <span class="n">re</span><span class="o">.</span><span class="n">compile</span><span class="p">(</span><span class="sa">r</span><span class="s2">"##\s*?OPTIONS\s*?$"</span><span class="p">,</span> <span class="n">re</span><span class="o">.</span><span class="n">I</span> <span class="o">+</span> <span class="n">re</span><span class="o">.</span><span class="n">M</span><span class="p">)</span>
|
|
<span class="n">_RE_CALLABLE</span> <span class="o">=</span> <span class="n">re</span><span class="o">.</span><span class="n">compile</span><span class="p">(</span><span class="sa">r</span><span class="s2">"\S+?\(\)"</span><span class="p">,</span> <span class="n">re</span><span class="o">.</span><span class="n">I</span> <span class="o">+</span> <span class="n">re</span><span class="o">.</span><span class="n">M</span><span class="p">)</span>
|
|
<span class="n">_RE_CALLABLE</span> <span class="o">=</span> <span class="n">re</span><span class="o">.</span><span class="n">compile</span><span class="p">(</span>
|
|
<span class="sa">r</span><span class="s2">"(?P<funcname>\S+?)(?:\((?P<kwargs>[\S\s]+?)\)|\(\))"</span><span class="p">,</span> <span class="n">re</span><span class="o">.</span><span class="n">I</span> <span class="o">+</span> <span class="n">re</span><span class="o">.</span><span class="n">M</span>
|
|
<span class="p">)</span>
|
|
|
|
<span class="n">_HELP_NO_OPTION_MATCH</span> <span class="o">=</span> <span class="n">_</span><span class="p">(</span><span class="s2">"Choose an option or try 'help'."</span><span class="p">)</span>
|
|
|
|
<span class="n">_OPTION_INPUT_MARKER</span> <span class="o">=</span> <span class="s2">">"</span>
|
|
<span class="n">_OPTION_ALIAS_MARKER</span> <span class="o">=</span> <span class="s2">";"</span>
|
|
<span class="n">_OPTION_SEP_MARKER</span> <span class="o">=</span> <span class="s2">":"</span>
|
|
<span class="n">_OPTION_CALL_MARKER</span> <span class="o">=</span> <span class="s2">"->"</span>
|
|
<span class="n">_OPTION_COMMENT_START</span> <span class="o">=</span> <span class="s2">"#"</span>
|
|
|
|
|
|
<span class="c1"># Input/option/goto handler functions that allows for dynamically generated</span>
|
|
<span class="c1"># nodes read from the menu template.</span>
|
|
|
|
<span class="k">def</span> <span class="nf">_process_callable</span><span class="p">(</span><span class="n">caller</span><span class="p">,</span> <span class="n">goto</span><span class="p">,</span> <span class="n">goto_callables</span><span class="p">,</span> <span class="n">raw_string</span><span class="p">,</span>
|
|
<span class="n">current_nodename</span><span class="p">,</span> <span class="n">kwargs</span><span class="p">):</span>
|
|
<span class="sd">"""</span>
|
|
<span class="sd"> Central helper for parsing a goto-callable (`funcname(**kwargs)`) out of</span>
|
|
<span class="sd"> the right-hand-side of the template options and map this to an actual</span>
|
|
<span class="sd"> callable registered with the template generator. This involves parsing the</span>
|
|
<span class="sd"> func-name and running literal-eval on its kwargs.</span>
|
|
|
|
<span class="sd"> """</span>
|
|
<span class="n">match</span> <span class="o">=</span> <span class="n">_RE_CALLABLE</span><span class="o">.</span><span class="n">match</span><span class="p">(</span><span class="n">goto</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="n">match</span><span class="p">:</span>
|
|
<span class="n">gotofunc</span> <span class="o">=</span> <span class="n">match</span><span class="o">.</span><span class="n">group</span><span class="p">(</span><span class="s2">"funcname"</span><span class="p">)</span>
|
|
<span class="n">gotokwargs</span> <span class="o">=</span> <span class="n">match</span><span class="o">.</span><span class="n">group</span><span class="p">(</span><span class="s2">"kwargs"</span><span class="p">)</span> <span class="ow">or</span> <span class="s2">""</span>
|
|
<span class="k">if</span> <span class="n">gotofunc</span> <span class="ow">in</span> <span class="n">goto_callables</span><span class="p">:</span>
|
|
<span class="k">for</span> <span class="n">kwarg</span> <span class="ow">in</span> <span class="n">gotokwargs</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s2">","</span><span class="p">):</span>
|
|
<span class="k">if</span> <span class="n">kwarg</span> <span class="ow">and</span> <span class="s2">"="</span> <span class="ow">in</span> <span class="n">kwarg</span><span class="p">:</span>
|
|
<span class="n">key</span><span class="p">,</span> <span class="n">value</span> <span class="o">=</span> <span class="p">[</span><span class="n">part</span><span class="o">.</span><span class="n">strip</span><span class="p">()</span> <span class="k">for</span> <span class="n">part</span> <span class="ow">in</span> <span class="n">kwarg</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s2">"="</span><span class="p">,</span> <span class="mi">1</span><span class="p">)]</span>
|
|
<span class="k">if</span> <span class="n">key</span> <span class="ow">in</span> <span class="p">(</span><span class="s2">"evmenu_goto"</span><span class="p">,</span> <span class="s2">"evmenu_gotomap"</span><span class="p">,</span> <span class="s2">"_current_nodename"</span><span class="p">,</span>
|
|
<span class="s2">"evmenu_current_nodename"</span><span class="p">,</span> <span class="s2">"evmenu_goto_callables"</span><span class="p">):</span>
|
|
<span class="k">raise</span> <span class="ne">RuntimeError</span><span class="p">(</span>
|
|
<span class="sa">f</span><span class="s2">"EvMenu template error: goto-callable '</span><span class="si">{</span><span class="n">goto</span><span class="si">}</span><span class="s2">' uses a "</span>
|
|
<span class="sa">f</span><span class="s2">"kwarg (</span><span class="si">{</span><span class="n">kwarg</span><span class="si">}</span><span class="s2">) that is reserved for the EvMenu templating "</span>
|
|
<span class="s2">"system. Rename the kwarg."</span><span class="p">)</span>
|
|
<span class="k">try</span><span class="p">:</span>
|
|
<span class="n">key</span> <span class="o">=</span> <span class="n">literal_eval</span><span class="p">(</span><span class="n">key</span><span class="p">)</span>
|
|
<span class="k">except</span> <span class="ne">ValueError</span><span class="p">:</span>
|
|
<span class="k">pass</span>
|
|
<span class="k">try</span><span class="p">:</span>
|
|
<span class="n">value</span> <span class="o">=</span> <span class="n">literal_eval</span><span class="p">(</span><span class="n">value</span><span class="p">)</span>
|
|
<span class="k">except</span> <span class="ne">ValueError</span><span class="p">:</span>
|
|
<span class="k">pass</span>
|
|
<span class="n">kwargs</span><span class="p">[</span><span class="n">key</span><span class="p">]</span> <span class="o">=</span> <span class="n">value</span>
|
|
|
|
<span class="n">goto</span> <span class="o">=</span> <span class="n">goto_callables</span><span class="p">[</span><span class="n">gotofunc</span><span class="p">](</span><span class="n">caller</span><span class="p">,</span> <span class="n">raw_string</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="n">goto</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
|
|
<span class="k">return</span> <span class="n">goto</span><span class="p">,</span> <span class="p">{</span><span class="s2">"generated_nodename"</span><span class="p">:</span> <span class="n">current_nodename</span><span class="p">}</span>
|
|
<span class="k">return</span> <span class="n">goto</span><span class="p">,</span> <span class="p">{</span><span class="s2">"generated_nodename"</span><span class="p">:</span> <span class="n">goto</span><span class="p">}</span>
|
|
|
|
|
|
<span class="k">def</span> <span class="nf">_generated_goto_func</span><span class="p">(</span><span class="n">caller</span><span class="p">,</span> <span class="n">raw_string</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
|
|
<span class="sd">"""</span>
|
|
<span class="sd"> This rerouter handles normal direct goto func call matches.</span>
|
|
|
|
<span class="sd"> key : ... -> goto_callable(**kwargs)</span>
|
|
|
|
<span class="sd"> """</span>
|
|
<span class="n">goto</span> <span class="o">=</span> <span class="n">kwargs</span><span class="p">[</span><span class="s2">"evmenu_goto"</span><span class="p">]</span>
|
|
<span class="n">goto_callables</span> <span class="o">=</span> <span class="n">kwargs</span><span class="p">[</span><span class="s2">"evmenu_goto_callables"</span><span class="p">]</span>
|
|
<span class="n">current_nodename</span> <span class="o">=</span> <span class="n">kwargs</span><span class="p">[</span><span class="s2">"evmenu_current_nodename"</span><span class="p">]</span>
|
|
<span class="k">return</span> <span class="n">_process_callable</span><span class="p">(</span><span class="n">caller</span><span class="p">,</span> <span class="n">goto</span><span class="p">,</span> <span class="n">goto_callables</span><span class="p">,</span> <span class="n">raw_string</span><span class="p">,</span>
|
|
<span class="n">current_nodename</span><span class="p">,</span> <span class="n">kwargs</span><span class="p">)</span>
|
|
|
|
|
|
<span class="k">def</span> <span class="nf">_generated_input_goto_func</span><span class="p">(</span><span class="n">caller</span><span class="p">,</span> <span class="n">raw_string</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
|
|
<span class="sd">"""</span>
|
|
<span class="sd"> This goto-func acts as a rerouter for >-type line parsing (by acting as the</span>
|
|
<span class="sd"> _default option). The patterns discovered in the menu maps to different</span>
|
|
<span class="sd"> *actual* goto-funcs. We map to those here.</span>
|
|
|
|
<span class="sd"> >pattern: ... -> goto_callable</span>
|
|
|
|
<span class="sd"> """</span>
|
|
<span class="n">gotomap</span> <span class="o">=</span> <span class="n">kwargs</span><span class="p">[</span><span class="s2">"evmenu_gotomap"</span><span class="p">]</span>
|
|
<span class="n">goto_callables</span> <span class="o">=</span> <span class="n">kwargs</span><span class="p">[</span><span class="s2">"evmenu_goto_callables"</span><span class="p">]</span>
|
|
<span class="n">current_nodename</span> <span class="o">=</span> <span class="n">kwargs</span><span class="p">[</span><span class="s2">"evmenu_current_nodename"</span><span class="p">]</span>
|
|
<span class="n">raw_string</span> <span class="o">=</span> <span class="n">raw_string</span><span class="o">.</span><span class="n">strip</span><span class="p">(</span><span class="s2">"</span><span class="se">\n</span><span class="s2">"</span><span class="p">)</span> <span class="c1"># strip is necessary to catch empty return</span>
|
|
|
|
<span class="c1"># start with glob patterns</span>
|
|
<span class="k">for</span> <span class="n">pattern</span><span class="p">,</span> <span class="n">goto</span> <span class="ow">in</span> <span class="n">gotomap</span><span class="o">.</span><span class="n">items</span><span class="p">():</span>
|
|
<span class="k">if</span> <span class="n">fnmatch</span><span class="p">(</span><span class="n">raw_string</span><span class="o">.</span><span class="n">lower</span><span class="p">(),</span> <span class="n">pattern</span><span class="p">):</span>
|
|
<span class="k">return</span> <span class="n">_process_callable</span><span class="p">(</span><span class="n">caller</span><span class="p">,</span> <span class="n">goto</span><span class="p">,</span> <span class="n">goto_callables</span><span class="p">,</span> <span class="n">raw_string</span><span class="p">,</span>
|
|
<span class="n">current_nodename</span><span class="p">,</span> <span class="n">kwargs</span><span class="p">)</span>
|
|
<span class="c1"># no glob pattern match; try regex</span>
|
|
<span class="k">for</span> <span class="n">pattern</span><span class="p">,</span> <span class="n">goto</span> <span class="ow">in</span> <span class="n">gotomap</span><span class="o">.</span><span class="n">items</span><span class="p">():</span>
|
|
<span class="k">if</span> <span class="n">pattern</span> <span class="ow">and</span> <span class="n">re</span><span class="o">.</span><span class="n">match</span><span class="p">(</span><span class="n">pattern</span><span class="p">,</span> <span class="n">raw_string</span><span class="o">.</span><span class="n">lower</span><span class="p">(),</span> <span class="n">flags</span><span class="o">=</span><span class="n">re</span><span class="o">.</span><span class="n">I</span> <span class="o">+</span> <span class="n">re</span><span class="o">.</span><span class="n">M</span><span class="p">):</span>
|
|
<span class="k">return</span> <span class="n">_process_callable</span><span class="p">(</span><span class="n">caller</span><span class="p">,</span> <span class="n">goto</span><span class="p">,</span> <span class="n">goto_callables</span><span class="p">,</span> <span class="n">raw_string</span><span class="p">,</span>
|
|
<span class="n">current_nodename</span><span class="p">,</span> <span class="n">kwargs</span><span class="p">)</span>
|
|
<span class="c1"># no match, show error</span>
|
|
<span class="k">raise</span> <span class="n">EvMenuGotoAbortMessage</span><span class="p">(</span><span class="n">_HELP_NO_OPTION_MATCH</span><span class="p">)</span>
|
|
|
|
|
|
<span class="k">def</span> <span class="nf">_generated_node</span><span class="p">(</span><span class="n">caller</span><span class="p">,</span> <span class="n">raw_string</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
|
|
<span class="sd">"""</span>
|
|
<span class="sd"> Every node in the templated menu will be this node, but with dynamically</span>
|
|
<span class="sd"> changing text/options. It must be a global function like this because</span>
|
|
<span class="sd"> otherwise we could not make the templated-menu persistent.</span>
|
|
|
|
<span class="sd"> """</span>
|
|
<span class="n">text</span><span class="p">,</span> <span class="n">options</span> <span class="o">=</span> <span class="n">caller</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">_evmenu_template_contents</span><span class="p">[</span><span class="n">kwargs</span><span class="p">[</span><span class="s2">"_current_nodename"</span><span class="p">]]</span>
|
|
<span class="k">return</span> <span class="n">text</span><span class="p">,</span> <span class="n">options</span>
|
|
|
|
|
|
<div class="viewcode-block" id="parse_menu_template"><a class="viewcode-back" href="../../../api/evennia.utils.evmenu.html#evennia.utils.evmenu.parse_menu_template">[docs]</a><span class="k">def</span> <span class="nf">parse_menu_template</span><span class="p">(</span><span class="n">caller</span><span class="p">,</span> <span class="n">menu_template</span><span class="p">,</span> <span class="n">goto_callables</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
|
|
<span class="sd">"""</span>
|
|
<span class="sd"> Parse menu-template string. The main function of the EvMenu templating system.</span>
|
|
|
|
<span class="sd"> Args:</span>
|
|
<span class="sd"> caller (Object or Account): Entity using the menu.</span>
|
|
<span class="sd"> menu_template (str): Menu described using the templating format.</span>
|
|
<span class="sd"> goto_callables (dict, optional): Mapping between call-names and callables</span>
|
|
<span class="sd"> on the form `callable(caller, raw_string, **kwargs)`. These are what is</span>
|
|
<span class="sd"> available to use in the `menu_template` string.</span>
|
|
|
|
<span class="sd"> Returns:</span>
|
|
<span class="sd"> dict: A `{"node": nodefunc}` menutree suitable to pass into EvMenu.</span>
|
|
|
|
<span class="sd"> """</span>
|
|
<span class="k">def</span> <span class="nf">_validate_kwarg</span><span class="p">(</span><span class="n">goto</span><span class="p">,</span> <span class="n">kwarg</span><span class="p">):</span>
|
|
<span class="sd">"""</span>
|
|
<span class="sd"> Validate goto-callable kwarg is on correct form.</span>
|
|
<span class="sd"> """</span>
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="s2">"="</span> <span class="ow">in</span> <span class="n">kwarg</span><span class="p">:</span>
|
|
<span class="k">raise</span> <span class="ne">RuntimeError</span><span class="p">(</span>
|
|
<span class="sa">f</span><span class="s2">"EvMenu template error: goto-callable '</span><span class="si">{</span><span class="n">goto</span><span class="si">}</span><span class="s2">' has a "</span>
|
|
<span class="sa">f</span><span class="s2">"non-kwarg argument (</span><span class="si">{</span><span class="n">kwarg</span><span class="si">}</span><span class="s2">). All callables in the "</span>
|
|
<span class="s2">"template must have only keyword-arguments, or no "</span>
|
|
<span class="s2">"args at all."</span><span class="p">)</span>
|
|
<span class="n">key</span><span class="p">,</span> <span class="n">_</span> <span class="o">=</span> <span class="p">[</span><span class="n">part</span><span class="o">.</span><span class="n">strip</span><span class="p">()</span> <span class="k">for</span> <span class="n">part</span> <span class="ow">in</span> <span class="n">kwarg</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s2">"="</span><span class="p">,</span> <span class="mi">1</span><span class="p">)]</span>
|
|
<span class="k">if</span> <span class="n">key</span> <span class="ow">in</span> <span class="p">(</span><span class="s2">"evmenu_goto"</span><span class="p">,</span> <span class="s2">"evmenu_gotomap"</span><span class="p">,</span> <span class="s2">"_current_nodename"</span><span class="p">,</span>
|
|
<span class="s2">"evmenu_current_nodename"</span><span class="p">,</span> <span class="s2">"evmenu_goto_callables"</span><span class="p">):</span>
|
|
<span class="k">raise</span> <span class="ne">RuntimeError</span><span class="p">(</span>
|
|
<span class="sa">f</span><span class="s2">"EvMenu template error: goto-callable '</span><span class="si">{</span><span class="n">goto</span><span class="si">}</span><span class="s2">' uses a "</span>
|
|
<span class="sa">f</span><span class="s2">"kwarg (</span><span class="si">{</span><span class="n">kwarg</span><span class="si">}</span><span class="s2">) that is reserved for the EvMenu templating "</span>
|
|
<span class="s2">"system. Rename the kwarg."</span><span class="p">)</span>
|
|
|
|
<span class="k">def</span> <span class="nf">_parse_options</span><span class="p">(</span><span class="n">nodename</span><span class="p">,</span> <span class="n">optiontxt</span><span class="p">,</span> <span class="n">goto_callables</span><span class="p">):</span>
|
|
<span class="sd">"""</span>
|
|
<span class="sd"> Parse option section into option dict.</span>
|
|
<span class="sd"> """</span>
|
|
<span class="n">options</span> <span class="o">=</span> <span class="p">[]</span>
|
|
<span class="n">optiontxt</span> <span class="o">=</span> <span class="n">optiontxt</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">strip</span><span class="p">()</span> <span class="k">if</span> <span class="n">optiontxt</span> <span class="k">else</span> <span class="s2">""</span>
|
|
<span class="n">optionlist</span> <span class="o">=</span> <span class="p">[</span><span class="n">optline</span><span class="o">.</span><span class="n">strip</span><span class="p">()</span> <span class="k">for</span> <span class="n">optline</span> <span class="ow">in</span> <span class="n">optiontxt</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s2">"</span><span class="se">\n</span><span class="s2">"</span><span class="p">)]</span>
|
|
<span class="n">inputparsemap</span> <span class="o">=</span> <span class="p">{}</span>
|
|
|
|
<span class="k">for</span> <span class="n">inum</span><span class="p">,</span> <span class="n">optline</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">(</span><span class="n">optionlist</span><span class="p">):</span>
|
|
<span class="k">if</span> <span class="n">optline</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="n">_OPTION_COMMENT_START</span><span class="p">)</span> <span class="ow">or</span> <span class="n">_OPTION_SEP_MARKER</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">optline</span><span class="p">:</span>
|
|
<span class="c1"># skip comments or invalid syntax</span>
|
|
<span class="k">continue</span>
|
|
<span class="n">key</span> <span class="o">=</span> <span class="s2">""</span>
|
|
<span class="n">desc</span> <span class="o">=</span> <span class="s2">""</span>
|
|
<span class="n">pattern</span> <span class="o">=</span> <span class="kc">None</span>
|
|
|
|
<span class="n">key</span><span class="p">,</span> <span class="n">goto</span> <span class="o">=</span> <span class="p">[</span><span class="n">part</span><span class="o">.</span><span class="n">strip</span><span class="p">()</span> <span class="k">for</span> <span class="n">part</span> <span class="ow">in</span> <span class="n">optline</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="n">_OPTION_SEP_MARKER</span><span class="p">,</span> <span class="mi">1</span><span class="p">)]</span>
|
|
|
|
<span class="c1"># desc -> goto</span>
|
|
<span class="k">if</span> <span class="n">_OPTION_CALL_MARKER</span> <span class="ow">in</span> <span class="n">goto</span><span class="p">:</span>
|
|
<span class="n">desc</span><span class="p">,</span> <span class="n">goto</span> <span class="o">=</span> <span class="p">[</span><span class="n">part</span><span class="o">.</span><span class="n">strip</span><span class="p">()</span> <span class="k">for</span> <span class="n">part</span> <span class="ow">in</span> <span class="n">goto</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="n">_OPTION_CALL_MARKER</span><span class="p">,</span> <span class="mi">1</span><span class="p">)]</span>
|
|
|
|
<span class="c1"># validate callable</span>
|
|
<span class="n">match</span> <span class="o">=</span> <span class="n">_RE_CALLABLE</span><span class="o">.</span><span class="n">match</span><span class="p">(</span><span class="n">goto</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="n">match</span><span class="p">:</span>
|
|
<span class="n">kwargs</span> <span class="o">=</span> <span class="n">match</span><span class="o">.</span><span class="n">group</span><span class="p">(</span><span class="s2">"kwargs"</span><span class="p">)</span>
|
|
<span class="k">if</span> <span class="n">kwargs</span><span class="p">:</span>
|
|
<span class="k">for</span> <span class="n">kwarg</span> <span class="ow">in</span> <span class="n">kwargs</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s1">','</span><span class="p">):</span>
|
|
<span class="n">_validate_kwarg</span><span class="p">(</span><span class="n">goto</span><span class="p">,</span> <span class="n">kwarg</span><span class="p">)</span>
|
|
|
|
<span class="c1"># parse key [;aliases|pattern]</span>
|
|
<span class="n">key</span> <span class="o">=</span> <span class="p">[</span><span class="n">part</span><span class="o">.</span><span class="n">strip</span><span class="p">()</span> <span class="k">for</span> <span class="n">part</span> <span class="ow">in</span> <span class="n">key</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="n">_OPTION_ALIAS_MARKER</span><span class="p">)]</span>
|
|
<span class="k">if</span> <span class="ow">not</span> <span class="n">key</span><span class="p">:</span>
|
|
<span class="c1"># fall back to this being the Nth option</span>
|
|
<span class="n">key</span> <span class="o">=</span> <span class="p">[</span><span class="sa">f</span><span class="s2">"</span><span class="si">{</span><span class="n">inum</span> <span class="o">+</span> <span class="mi">1</span><span class="si">}</span><span class="s2">"</span><span class="p">]</span>
|
|
<span class="n">main_key</span> <span class="o">=</span> <span class="n">key</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
|
|
|
|
<span class="k">if</span> <span class="n">main_key</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="n">_OPTION_INPUT_MARKER</span><span class="p">):</span>
|
|
<span class="c1"># if we have a pattern, build the arguments for _default later</span>
|
|
<span class="n">pattern</span> <span class="o">=</span> <span class="n">main_key</span><span class="p">[</span><span class="nb">len</span><span class="p">(</span><span class="n">_OPTION_INPUT_MARKER</span><span class="p">):]</span><span class="o">.</span><span class="n">strip</span><span class="p">()</span>
|
|
<span class="n">inputparsemap</span><span class="p">[</span><span class="n">pattern</span><span class="p">]</span> <span class="o">=</span> <span class="n">goto</span>
|
|
<span class="k">else</span><span class="p">:</span>
|
|
<span class="c1"># a regular goto string/callable target</span>
|
|
<span class="n">option</span> <span class="o">=</span> <span class="p">{</span>
|
|
<span class="s2">"key"</span><span class="p">:</span> <span class="n">key</span><span class="p">,</span>
|
|
<span class="s2">"goto"</span><span class="p">:</span> <span class="p">(</span>
|
|
<span class="n">_generated_goto_func</span><span class="p">,</span>
|
|
<span class="p">{</span>
|
|
<span class="s2">"evmenu_goto"</span><span class="p">:</span> <span class="n">goto</span><span class="p">,</span>
|
|
<span class="s2">"evmenu_current_nodename"</span><span class="p">:</span> <span class="n">nodename</span><span class="p">,</span>
|
|
<span class="s2">"evmenu_goto_callables"</span><span class="p">:</span> <span class="n">goto_callables</span><span class="p">,</span>
|
|
<span class="p">},</span>
|
|
<span class="p">),</span>
|
|
<span class="p">}</span>
|
|
<span class="k">if</span> <span class="n">desc</span><span class="p">:</span>
|
|
<span class="n">option</span><span class="p">[</span><span class="s2">"desc"</span><span class="p">]</span> <span class="o">=</span> <span class="n">desc</span>
|
|
<span class="n">options</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">option</span><span class="p">)</span>
|
|
|
|
<span class="k">if</span> <span class="n">inputparsemap</span><span class="p">:</span>
|
|
<span class="c1"># if this exists we must create a _default entry too</span>
|
|
<span class="n">options</span><span class="o">.</span><span class="n">append</span><span class="p">(</span>
|
|
<span class="p">{</span>
|
|
<span class="s2">"key"</span><span class="p">:</span> <span class="s2">"_default"</span><span class="p">,</span>
|
|
<span class="s2">"goto"</span><span class="p">:</span> <span class="p">(</span>
|
|
<span class="n">_generated_input_goto_func</span><span class="p">,</span>
|
|
<span class="p">{</span>
|
|
<span class="s2">"evmenu_gotomap"</span><span class="p">:</span> <span class="n">inputparsemap</span><span class="p">,</span>
|
|
<span class="s2">"evmenu_current_nodename"</span><span class="p">:</span> <span class="n">nodename</span><span class="p">,</span>
|
|
<span class="s2">"evmenu_goto_callables"</span><span class="p">:</span> <span class="n">goto_callables</span><span class="p">,</span>
|
|
<span class="p">},</span>
|
|
<span class="p">),</span>
|
|
<span class="p">}</span>
|
|
<span class="p">)</span>
|
|
|
|
<span class="k">return</span> <span class="n">options</span>
|
|
|
|
<span class="k">def</span> <span class="nf">_parse</span><span class="p">(</span><span class="n">caller</span><span class="p">,</span> <span class="n">menu_template</span><span class="p">,</span> <span class="n">goto_callables</span><span class="p">):</span>
|
|
<span class="sd">"""</span>
|
|
<span class="sd"> Parse the menu string format into a node tree.</span>
|
|
<span class="sd"> """</span>
|
|
<span class="n">nodetree</span> <span class="o">=</span> <span class="p">{}</span>
|
|
<span class="n">splits</span> <span class="o">=</span> <span class="n">_RE_NODE</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="n">menu_template</span><span class="p">)</span>
|
|
<span class="n">splits</span> <span class="o">=</span> <span class="n">splits</span><span class="p">[</span><span class="mi">1</span><span class="p">:]</span> <span class="k">if</span> <span class="n">splits</span> <span class="k">else</span> <span class="p">[]</span>
|
|
|
|
<span class="c1"># from evennia import set_trace;set_trace(term_size=(140,120))</span>
|
|
<span class="n">content_map</span> <span class="o">=</span> <span class="p">{}</span>
|
|
<span class="k">for</span> <span class="n">node_ind</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="nb">len</span><span class="p">(</span><span class="n">splits</span><span class="p">),</span> <span class="mi">2</span><span class="p">):</span>
|
|
<span class="n">nodename</span><span class="p">,</span> <span class="n">nodetxt</span> <span class="o">=</span> <span class="n">splits</span><span class="p">[</span><span class="n">node_ind</span><span class="p">],</span> <span class="n">splits</span><span class="p">[</span><span class="n">node_ind</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]</span>
|
|
<span class="n">text</span><span class="p">,</span> <span class="o">*</span><span class="n">optiontxt</span> <span class="o">=</span> <span class="n">_RE_OPTIONS_SEP</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="n">nodetxt</span><span class="p">,</span> <span class="n">maxsplit</span><span class="o">=</span><span class="mi">2</span><span class="p">)</span>
|
|
<span class="n">options</span> <span class="o">=</span> <span class="n">_parse_options</span><span class="p">(</span><span class="n">nodename</span><span class="p">,</span> <span class="n">optiontxt</span><span class="p">,</span> <span class="n">goto_callables</span><span class="p">)</span>
|
|
<span class="n">content_map</span><span class="p">[</span><span class="n">nodename</span><span class="p">]</span> <span class="o">=</span> <span class="p">(</span><span class="n">text</span><span class="p">,</span> <span class="n">options</span><span class="p">)</span>
|
|
<span class="n">nodetree</span><span class="p">[</span><span class="n">nodename</span><span class="p">]</span> <span class="o">=</span> <span class="n">_generated_node</span>
|
|
<span class="n">caller</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">_evmenu_template_contents</span> <span class="o">=</span> <span class="n">content_map</span>
|
|
|
|
<span class="k">return</span> <span class="n">nodetree</span>
|
|
|
|
<span class="k">return</span> <span class="n">_parse</span><span class="p">(</span><span class="n">caller</span><span class="p">,</span> <span class="n">menu_template</span><span class="p">,</span> <span class="n">goto_callables</span><span class="p">)</span></div>
|
|
|
|
|
|
<div class="viewcode-block" id="template2menu"><a class="viewcode-back" href="../../../api/evennia.utils.evmenu.html#evennia.utils.evmenu.template2menu">[docs]</a><span class="k">def</span> <span class="nf">template2menu</span><span class="p">(</span>
|
|
<span class="n">caller</span><span class="p">,</span>
|
|
<span class="n">menu_template</span><span class="p">,</span>
|
|
<span class="n">goto_callables</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
|
|
<span class="n">startnode</span><span class="o">=</span><span class="s2">"start"</span><span class="p">,</span>
|
|
<span class="n">persistent</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span>
|
|
<span class="o">**</span><span class="n">kwargs</span><span class="p">,</span>
|
|
<span class="p">):</span>
|
|
<span class="sd">"""</span>
|
|
<span class="sd"> Helper function to generate and start an EvMenu based on a menu template</span>
|
|
<span class="sd"> string. This will internall call `parse_menu_template` and run a default</span>
|
|
<span class="sd"> EvMenu with its results.</span>
|
|
|
|
<span class="sd"> Args:</span>
|
|
<span class="sd"> caller (Object or Account): The entity using the menu.</span>
|
|
<span class="sd"> menu_template (str): The menu-template string describing the content</span>
|
|
<span class="sd"> and structure of the menu. It can also be the python-path to, or a module</span>
|
|
<span class="sd"> containing a `MENU_TEMPLATE` global variable with the template.</span>
|
|
<span class="sd"> goto_callables (dict, optional): Mapping of callable-names to</span>
|
|
<span class="sd"> module-global objects to reference by name in the menu-template.</span>
|
|
<span class="sd"> Must be on the form `callable(caller, raw_string, **kwargs)`.</span>
|
|
<span class="sd"> startnode (str, optional): The name of the startnode, if not 'start'.</span>
|
|
<span class="sd"> persistent (bool, optional): If the generated menu should be persistent.</span>
|
|
<span class="sd"> **kwargs: All kwargs will be passed into EvMenu.</span>
|
|
|
|
<span class="sd"> Returns:</span>
|
|
<span class="sd"> EvMenu: The generated EvMenu.</span>
|
|
|
|
<span class="sd"> """</span>
|
|
<span class="n">goto_callables</span> <span class="o">=</span> <span class="n">goto_callables</span> <span class="ow">or</span> <span class="p">{}</span>
|
|
<span class="n">menu_tree</span> <span class="o">=</span> <span class="n">parse_menu_template</span><span class="p">(</span><span class="n">caller</span><span class="p">,</span> <span class="n">menu_template</span><span class="p">,</span> <span class="n">goto_callables</span><span class="p">)</span>
|
|
<span class="k">return</span> <span class="n">EvMenu</span><span class="p">(</span>
|
|
<span class="n">caller</span><span class="p">,</span>
|
|
<span class="n">menu_tree</span><span class="p">,</span>
|
|
<span class="n">persistent</span><span class="o">=</span><span class="n">persistent</span><span class="p">,</span>
|
|
<span class="o">**</span><span class="n">kwargs</span><span class="p">,</span>
|
|
<span class="p">)</span></div>
|
|
</pre></div>
|
|
|
|
<div class="clearer"></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="sphinxsidebar" role="navigation" aria-label="main navigation">
|
|
<div class="sphinxsidebarwrapper">
|
|
<p class="logo"><a href="../../../index.html">
|
|
<img class="logo" src="../../../_static/evennia_logo.png" alt="Logo"/>
|
|
</a></p>
|
|
<div id="searchbox" style="display: none" role="search">
|
|
<h3 id="searchlabel">Quick search</h3>
|
|
<div class="searchformwrapper">
|
|
<form class="search" action="../../../search.html" method="get">
|
|
<input type="text" name="q" aria-labelledby="searchlabel" />
|
|
<input type="submit" value="Go" />
|
|
</form>
|
|
</div>
|
|
</div>
|
|
<script>$('#searchbox').show(0);</script><h3>Links</h3>
|
|
<ul>
|
|
<li><a href="https://www.evennia.com">Home page</a> </li>
|
|
<li><a href="https://github.com/evennia/evennia">Evennia Github</a> </li>
|
|
<li><a href="http://games.evennia.com">Game Index</a> </li>
|
|
<li><a href="http://webchat.freenode.net/?channels=evennia&uio=MT1mYWxzZSY5PXRydWUmMTE9MTk1JjEyPXRydWUbb">IRC</a> -
|
|
<a href="https://discord.gg/NecFePw">Discord</a> -
|
|
<a href="https://groups.google.com/forum/#%21forum/evennia">Forums</a>
|
|
</li>
|
|
<li><a href="http://evennia.blogspot.com/">Evennia Dev blog</a> </li>
|
|
</ul>
|
|
<h3>Versions</h3>
|
|
<ul>
|
|
<li><a href="evmenu.html">1.0-dev (develop branch)</a></li>
|
|
<li><a href="../../../../0.9.5/index.html">0.9.5 (v0.9.5 branch)</a></li>
|
|
</ul>
|
|
|
|
</div>
|
|
</div>
|
|
<div class="clearer"></div>
|
|
</div>
|
|
<div class="related" role="navigation" aria-label="related navigation">
|
|
<h3>Navigation</h3>
|
|
<ul>
|
|
<li class="right" style="margin-right: 10px">
|
|
<a href="../../../genindex.html" title="General Index"
|
|
>index</a></li>
|
|
<li class="right" >
|
|
<a href="../../../py-modindex.html" title="Python Module Index"
|
|
>modules</a> |</li>
|
|
<li class="nav-item nav-item-0"><a href="../../../index.html">Evennia 1.0-dev</a> »</li>
|
|
<li class="nav-item nav-item-1"><a href="../../index.html" >Module code</a> »</li>
|
|
<li class="nav-item nav-item-2"><a href="../../evennia.html" >evennia</a> »</li>
|
|
<li class="nav-item nav-item-this"><a href="">evennia.utils.evmenu</a></li>
|
|
</ul>
|
|
<div class="develop">develop branch</div>
|
|
</div>
|
|
<div class="footer" role="contentinfo">
|
|
© Copyright 2020, The Evennia developer community.
|
|
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 3.2.1.
|
|
</div>
|
|
</body>
|
|
</html> |