<pclass="last">You are reading an old version of the Evennia documentation. <ahref="https://www.evennia.com/docs/latest/index.html">The latest version is here</a></p>.
<p><em>EvMenu</em> is used for generate branching multi-choice menus. Each menu ‘node’ can
accepts specific options as input or free-form input. Depending what the player
chooses, they are forwarded to different nodes in the menu.</p>
<p>The <codeclass="docutils literal notranslate"><spanclass="pre">EvMenu</span></code> utility class is located in <aclass="reference internal"href="../api/evennia.utils.evmenu.html#evennia-utils-evmenu"><spanclass="std std-ref">evennia/utils/evmenu.py</span></a>.
It allows for easily adding interactive menus to the game; for example to implement Character creation, building commands or similar. Below is an example of offering NPC conversation choices:</p>
<p>This is how the example menu at the top of this page will look in code:</p>
<p>Note the call to <codeclass="docutils literal notranslate"><spanclass="pre">EvMenu</span></code> at the end; this immediately creates the menu for the
<codeclass="docutils literal notranslate"><spanclass="pre">caller</span></code>. It also assigns the two node-functions to menu node-names <codeclass="docutils literal notranslate"><spanclass="pre">start</span></code> and
<codeclass="docutils literal notranslate"><spanclass="pre">end</span></code>, which is what the menu then uses to reference the nodes.</p>
<p>Each node of the menu is a function that returns the text and a list of dicts
describing the choices you can make on that node.</p>
<p>Each option details what it should show (key/desc) as well as which node to go
to (goto) next. The “goto” should be the name of the next node to go (if <codeclass="docutils literal notranslate"><spanclass="pre">None</span></code>,
the same node will be rerun again).</p>
<p>Above, the <codeclass="docutils literal notranslate"><spanclass="pre">Abort</span></code> option gives the “end” node name just as a string whereas the
yes/no options instead uses the callable <codeclass="docutils literal notranslate"><spanclass="pre">_handle_answer</span></code> but pass different
arguments to it. <codeclass="docutils literal notranslate"><spanclass="pre">_handle_answer</span></code> then returns the name of the next node (this
allows you to perform actions when making a choice before you move on to the
next node the menu). Note that <codeclass="docutils literal notranslate"><spanclass="pre">_handle_answer</span></code> is <em>not</em> a node in the menu,
it’s just a helper function.</p>
<p>When choosing ‘yes’ (or ‘no’) what happens here is that <codeclass="docutils literal notranslate"><spanclass="pre">_handle_answer</span></code> gets
called and echoes your choice before directing to the “end” node, which exits
the menu (since it doesn’t return any options).</p>
<p>You can also write menus using the <aclass="reference internal"href="#evmenu-templating-language"><spanclass="std std-doc">EvMenu templating language</span></a>. This
allows you to use a text string to generate simpler menus with less boiler
plate. Let’s create exactly the same menu using the templating language:</p>
<p>As seen, the <codeclass="docutils literal notranslate"><spanclass="pre">_handle_answer</span></code> is the same, but the menu structure is
described in the <codeclass="docutils literal notranslate"><spanclass="pre">menu_template</span></code> string. The <codeclass="docutils literal notranslate"><spanclass="pre">template2menu</span></code> helper
uses the template-string and a mapping of callables (we must add
<codeclass="docutils literal notranslate"><spanclass="pre">_handle_answer</span></code> here) to build a full EvMenu for us.</p>
<p>Here’s another menu example, where we can choose how to interact with an NPC:</p>
<spanclass="p">{</span><spanclass="s2">"desc"</span><spanclass="p">:</span><spanclass="s2">"Try to bribe on [Cha + 10 gold]"</span><spanclass="p">,</span>
<spanclass="p">{</span><spanclass="s2">"desc"</span><spanclass="p">:</span><spanclass="s2">"Convince him you work here [Int]."</span><spanclass="p">,</span>
<spanclass="p">{</span><spanclass="s2">"desc"</span><spanclass="p">:</span><spanclass="s2">"Appeal to his vanity [Cha]"</span><spanclass="p">,</span>
<spanclass="p">{</span><spanclass="s2">"desc"</span><spanclass="p">:</span><spanclass="s2">"Try to knock him out [Luck + Dex]"</span><spanclass="p">,</span>
<spanclass="p">{</span><spanclass="s2">"desc"</span><spanclass="p">:</span><spanclass="s2">"Try to run away [Dex]"</span><spanclass="p">,</span>
<spanclass="c1"># EvMenu called below, with all the nodes ...</span>
</pre></div>
</div>
<p>Note that by skipping the <codeclass="docutils literal notranslate"><spanclass="pre">key</span></code> of the options, we instead get an
(auto-generated) list of numbered options to choose from.</p>
<p>Here the <codeclass="docutils literal notranslate"><spanclass="pre">_skill_check</span></code> helper will check (roll your stats, exactly what this
means depends on your game) to decide if your approach succeeded. It may then
choose to point you to nodes that continue the conversation or maybe dump you
into combat!</p>
<sectionid="launching-the-menu">
<h2>Launching the menu<aclass="headerlink"href="#launching-the-menu"title="Permalink to this headline">¶</a></h2>
<p>Initializing the menu is done using a call to the <codeclass="docutils literal notranslate"><spanclass="pre">evennia.utils.evmenu.EvMenu</span></code> class. This is the most common way to do so - from inside a <aclass="reference internal"href="Commands.html"><spanclass="doc std std-doc">Command</span></a>:</p>
<divclass="highlight-python notranslate"><divclass="highlight"><pre><span></span><spanclass="c1"># in, for example gamedir/commands/command.py</span>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">caller</span></code> (Object or Account): is a reference to the object using the menu. This object will get a new <aclass="reference internal"href="Command-Sets.html"><spanclass="doc std std-doc">CmdSet</span></a> assigned to it, for handling the menu.</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">menu_data</span></code> (str, module or dict): is a module or python path to a module where the global-level functions will each be considered to be a menu node. Their names in the module will be the names by which they are referred to in the module. Importantly, function names starting with an underscore <codeclass="docutils literal notranslate"><spanclass="pre">_</span></code> will be ignored by the loader. Alternatively, this can be a direct mapping
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">startnode</span></code> (str): is the name of the menu-node to start the menu at. Changing this means that you can jump into a menu tree at different positions depending on circumstance and thus possibly re-use menu entries.</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">cmdset_mergetype</span></code> (str): This is usually one of “Replace” or “Union” (see [CmdSets](Command- Sets). The first means that the menu is exclusive - the user has no access to any other commands while in the menu. The Union mergetype means the menu co-exists with previous commands (and may overload them, so be careful as to what to name your menu entries in this case).</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">cmdset_priority</span></code> (int): The priority with which to merge in the menu cmdset. This allows for advanced usage.</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">auto_quit</span></code>, <codeclass="docutils literal notranslate"><spanclass="pre">auto_look</span></code>, <codeclass="docutils literal notranslate"><spanclass="pre">auto_help</span></code> (bool): If either of these are <codeclass="docutils literal notranslate"><spanclass="pre">True</span></code>, the menu automatically makes a <codeclass="docutils literal notranslate"><spanclass="pre">quit</span></code>, <codeclass="docutils literal notranslate"><spanclass="pre">look</span></code> or <codeclass="docutils literal notranslate"><spanclass="pre">help</span></code> command available to the user. The main reason why you’d want to turn this off is if you want to use the aliases “q”, “l” or “h” for something in your menu. The <codeclass="docutils literal notranslate"><spanclass="pre">auto_help</span></code> also activates the ability to have arbitrary “tool tips” in your menu node (see below), At least <codeclass="docutils literal notranslate"><spanclass="pre">quit</span></code> is highly recommend - if <codeclass="docutils literal notranslate"><spanclass="pre">False</span></code>, the menu <em>must</em> itself supply an “exit node” (a node without any options), or the user will be stuck in the menu until the server reloads (or eternally if the menu is <codeclass="docutils literal notranslate"><spanclass="pre">persistent</span></code>)!</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">cmd_on_exit</span></code> (str): This command string will be executed right <em>after</em> the menu has closed down. From experience, it’s useful to trigger a “look” command to make sure the user is aware of the change of state; but any command can be used. If set to <codeclass="docutils literal notranslate"><spanclass="pre">None</span></code>, no command will be triggered after exiting the menu.</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">persistent</span></code> (bool) - if <codeclass="docutils literal notranslate"><spanclass="pre">True</span></code>, the menu will survive a reload (so the user will not be kicked
out by the reload - make sure they can exit on their own!)</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">startnode_input</span></code> (str or (str, dict) tuple): Pass an input text or a input text + kwargs to the
start node as if it was entered on a fictional previous node. This can be very useful in order to
start a menu differently depending on the Command’s arguments in which it was initialized.</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">session</span></code> (Session): Useful when calling the menu from an <aclass="reference internal"href="Accounts.html"><spanclass="doc std std-doc">Account</span></a> in
<codeclass="docutils literal notranslate"><spanclass="pre">MULTISESSION_MODE</span></code> higher than 2, to make sure only the right Session sees the menu output.</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">debug</span></code> (bool): If set, the <codeclass="docutils literal notranslate"><spanclass="pre">menudebug</span></code> command will be made available in the menu. Use it to
list the current state of the menu and use <codeclass="docutils literal notranslate"><spanclass="pre">menudebug</span><spanclass="pre"><variable></span></code> to inspect a specific state
variable from the list.</p></li>
<li><p>All other keyword arguments will be available as initial data for the nodes. They will be available in all nodes as properties on <codeclass="docutils literal notranslate"><spanclass="pre">caller.ndb._evmenu</span></code> (see below). These will also survive a <codeclass="docutils literal notranslate"><spanclass="pre">reload</span></code> if the menu is <codeclass="docutils literal notranslate"><spanclass="pre">persistent</span></code>.</p></li>
</ul>
<p>You don’t need to store the EvMenu instance anywhere - the very act of initializing it will store it
as <codeclass="docutils literal notranslate"><spanclass="pre">caller.ndb._evmenu</span></code> on the <codeclass="docutils literal notranslate"><spanclass="pre">caller</span></code>. This object will be deleted automatically when the menu
is exited and you can also use it to store your own temporary variables for access throughout the
menu. Temporary variables you store on a persistent <codeclass="docutils literal notranslate"><spanclass="pre">_evmenu</span></code> as it runs will
<em>not</em> survive a <codeclass="docutils literal notranslate"><spanclass="pre">@reload</span></code>, only those you set as part of the original <codeclass="docutils literal notranslate"><spanclass="pre">EvMenu</span></code> call.</p>
</section>
<sectionid="the-menu-nodes">
<h2>The Menu nodes<aclass="headerlink"href="#the-menu-nodes"title="Permalink to this headline">¶</a></h2>
<p>The EvMenu nodes consist of functions on one of these forms.</p>
<div><p>While all of the above forms are okay, it’s recommended to stick to the third and last form since it gives the most flexibility. The previous forms are mainly there for backwards compatibility with existing menus from a time when EvMenu was less able and may become deprecated at some time in the future.</p>
</div></blockquote>
<sectionid="input-arguments-to-the-node">
<h3>Input arguments to the node<aclass="headerlink"href="#input-arguments-to-the-node"title="Permalink to this headline">¶</a></h3>
<ulclass="simple">
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">caller</span></code> (Object or Account): The object using the menu - usually a Character but could also be a Session or Account depending on where the menu is used.</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">raw_string</span></code> (str): If this is given, it will be set to the exact text the user entered on the
<em>previous</em> node (that is, the command entered to get to this node). On the starting-node of the menu, this will be an empty string, unless <codeclass="docutils literal notranslate"><spanclass="pre">startnode_input</span></code> was set.</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">kwargs</span></code> (dict): These extra keyword arguments are extra optional arguments passed to the node when the user makes a choice on the <em>previous</em> node. This may include things like status flags and details about which exact option was chosen (which can be impossible to determine from
<codeclass="docutils literal notranslate"><spanclass="pre">raw_string</span></code> alone). Just what is passed in <codeclass="docutils literal notranslate"><spanclass="pre">kwargs</span></code> is up to you when you create the previous node.</p></li>
</ul>
</section>
<sectionid="return-values-from-the-node">
<h3>Return values from the node<aclass="headerlink"href="#return-values-from-the-node"title="Permalink to this headline">¶</a></h3>
<p>Each node function must return two variables, <codeclass="docutils literal notranslate"><spanclass="pre">text</span></code> and <codeclass="docutils literal notranslate"><spanclass="pre">options</span></code>.</p>
<sectionid="text">
<h4>text<aclass="headerlink"href="#text"title="Permalink to this headline">¶</a></h4>
<p>The <codeclass="docutils literal notranslate"><spanclass="pre">text</span></code> variable is either a string or a tuple. This is the simplest form:</p>
<p>This is what will be displayed as text in the menu node when entering it. You can modify this dynamically in the node if you want. Returning a <codeclass="docutils literal notranslate"><spanclass="pre">None</span></code> node text text is allowed - this leads to a node with no text and only options.</p>
<divclass="highlight-python notranslate"><divclass="highlight"><pre><span></span><spanclass="n">text</span><spanclass="o">=</span><spanclass="p">(</span><spanclass="s2">"Node text"</span><spanclass="p">,</span><spanclass="s2">"help text to show with h|elp"</span><spanclass="p">)</span>
</pre></div>
</div>
<p>In this form, we also add an optional help text. If <codeclass="docutils literal notranslate"><spanclass="pre">auto_help=True</span></code> when initializing the EvMenu, the user will be able to use <codeclass="docutils literal notranslate"><spanclass="pre">h</span></code> or <codeclass="docutils literal notranslate"><spanclass="pre">help</span></code> to see this text when viewing this node. If the user were to provide a custom option overriding <codeclass="docutils literal notranslate"><spanclass="pre">h</span></code> or <codeclass="docutils literal notranslate"><spanclass="pre">help</span></code>, that will be shown instead.</p>
<p>If <codeclass="docutils literal notranslate"><spanclass="pre">auto_help=True</span></code> and no help text is provided, using <codeclass="docutils literal notranslate"><spanclass="pre">h|elp</span></code> will give a generic error message.</p>
<p>This is ‘tooltip’ or ‘multi-help category’ mode. This also requires <codeclass="docutils literal notranslate"><spanclass="pre">auto_help=True</span></code> when initializing the EvMenu. By providing a <codeclass="docutils literal notranslate"><spanclass="pre">dict</span></code> as the second element of the <codeclass="docutils literal notranslate"><spanclass="pre">text</span></code> tuple, the user will be able to help about any of these topics. Use a tuple as key to add multiple aliases to the same help entry. This allows the user to get more detailed help text without leaving the given node.</p>
<p>Note that in ‘tooltip’ mode, the normal <codeclass="docutils literal notranslate"><spanclass="pre">h|elp</span></code> command won’t work. The <codeclass="docutils literal notranslate"><spanclass="pre">h|elp</span></code> entry must be added manually in the dict. As an example, this would reproduce the normal help functionality:</p>
<h4>options<aclass="headerlink"href="#options"title="Permalink to this headline">¶</a></h4>
<p>The <codeclass="docutils literal notranslate"><spanclass="pre">options</span></code> list describe all the choices available to the user when viewing this node. If <codeclass="docutils literal notranslate"><spanclass="pre">options</span></code> is returned as <codeclass="docutils literal notranslate"><spanclass="pre">None</span></code>, it means that this node is an <em>Exit node</em> - any text is displayed and then the menu immediately exits, running the <codeclass="docutils literal notranslate"><spanclass="pre">exit_cmd</span></code> if given.</p>
<p>Otherwise, <codeclass="docutils literal notranslate"><spanclass="pre">options</span></code> should be a list (or tuple) of dictionaries, one for each option. If only one option is available, a single dictionary can also be returned. This is how it could look:</p>
<spanclass="s2">"desc"</span><spanclass="p">:</span><spanclass="s2">"Strike the enemy with all your might"</span><spanclass="p">,</span>
<h5>option-key ‘key’<aclass="headerlink"href="#option-key-key"title="Permalink to this headline">¶</a></h5>
<p>The option’s <codeclass="docutils literal notranslate"><spanclass="pre">key</span></code> is what the user should enter in order to choose that option. If given as a tuple, the first string of that tuple will be what is shown on-screen while the rest are aliases for picking that option. In the above example, the user could enter “Attack” (or “attack”, it’s not case-sensitive), “a” or “att” in order to attack the goblin. Aliasing is useful for adding custom coloring to the choice. The first element of the aliasing tuple should then be the colored version, followed by a version without color - since otherwise the user would have to enter the color codes to select that choice.</p>
<p>Note that the <codeclass="docutils literal notranslate"><spanclass="pre">key</span></code> is <em>optional</em>. If no key is given, it will instead automatically be replaced
with a running number starting from <codeclass="docutils literal notranslate"><spanclass="pre">1</span></code>. If removing the <codeclass="docutils literal notranslate"><spanclass="pre">key</span></code> part of each option, the resulting
<p>Whether you want to use a key or rely on numbers is mostly a matter of style and the type of menu.</p>
<p>EvMenu accepts one important special <codeclass="docutils literal notranslate"><spanclass="pre">key</span></code> given only as <codeclass="docutils literal notranslate"><spanclass="pre">"_default"</span></code>. This key is used when a user enters something that does not match any other fixed keys. It is particularly useful for getting user input:</p>
<p>A <codeclass="docutils literal notranslate"><spanclass="pre">"_default"</span></code> option does not show up in the menu, so the above will just be a node saying
<codeclass="docutils literal notranslate"><spanclass="pre">"Please</span><spanclass="pre">enter</span><spanclass="pre">your</span><spanclass="pre">name"</span></code>. The name they entered will appear as <codeclass="docutils literal notranslate"><spanclass="pre">raw_string</span></code> in the next node.</p>
</section>
</section>
<sectionid="option-key-desc">
<h4>option-key ‘desc’<aclass="headerlink"href="#option-key-desc"title="Permalink to this headline">¶</a></h4>
<p>This simply contains the description as to what happens when selecting the menu option. For <codeclass="docutils literal notranslate"><spanclass="pre">"_default"</span></code> options or if the <codeclass="docutils literal notranslate"><spanclass="pre">key</span></code> is already long or descriptive, it is not strictly needed. But usually it’s better to keep the <codeclass="docutils literal notranslate"><spanclass="pre">key</span></code> short and put more detail in <codeclass="docutils literal notranslate"><spanclass="pre">desc</span></code>.</p>
</section>
<sectionid="option-key-goto">
<h4>option-key ‘goto’<aclass="headerlink"href="#option-key-goto"title="Permalink to this headline">¶</a></h4>
<p>This is the operational part of the option and fires only when the user chooses said option. Here are three ways to write it</p>
<p>As seen above, <codeclass="docutils literal notranslate"><spanclass="pre">goto</span></code> could just be pointing to a single <codeclass="docutils literal notranslate"><spanclass="pre">nodename</span></code> string - the name of the node to go to. When given like this, EvMenu will look for a node named like this and call its associated function as</p>
<p>Here, <codeclass="docutils literal notranslate"><spanclass="pre">raw_string</span></code> is always the input the user entered to make that choice and <codeclass="docutils literal notranslate"><spanclass="pre">kwargs</span></code> are the same as those <codeclass="docutils literal notranslate"><spanclass="pre">kwargs</span></code> that already entered the <em>current</em> node (they are passed on).</p>
<p>Alternatively the <codeclass="docutils literal notranslate"><spanclass="pre">goto</span></code> could point to a “goto-callable”. Such callables are usually defined in the same module as the menu nodes and given names starting with <codeclass="docutils literal notranslate"><spanclass="pre">_</span></code> (to avoid being parsed as nodes themselves). These callables will be called the same as a node function - <codeclass="docutils literal notranslate"><spanclass="pre">callable(caller,</span><spanclass="pre">raw_string,</span><spanclass="pre">**kwargs)</span></code>, where <codeclass="docutils literal notranslate"><spanclass="pre">raw_string</span></code> is what the user entered on this node and <codeclass="docutils literal notranslate"><spanclass="pre">**kwargs</span></code> is forwarded from the node’s own input.</p>
<p>The <codeclass="docutils literal notranslate"><spanclass="pre">goto</span></code> option key could also point to a tuple <codeclass="docutils literal notranslate"><spanclass="pre">(callable,</span><spanclass="pre">kwargs)</span></code> - this allows for customizing the kwargs passed into the goto-callable, for example you could use the same callable but change the kwargs passed into it depending on which option was actually chosen.</p>
<p>The “goto callable” must either return a string <codeclass="docutils literal notranslate"><spanclass="pre">"nodename"</span></code> or a tuple <codeclass="docutils literal notranslate"><spanclass="pre">("nodename",</span><spanclass="pre">mykwargs)</span></code>. This will lead to the next node being called as either <codeclass="docutils literal notranslate"><spanclass="pre">nodename(caller,</span><spanclass="pre">raw_string,</span><spanclass="pre">**kwargs)</span></code> or <codeclass="docutils literal notranslate"><spanclass="pre">nodename(caller,</span><spanclass="pre">raw_string,</span><spanclass="pre">**mykwargs)</span></code> - so this allows changing (or replacing) the options going into the next node depending on what option was chosen.</p>
<p>There is one important case - if the goto-callable returns <codeclass="docutils literal notranslate"><spanclass="pre">None</span></code> for a <codeclass="docutils literal notranslate"><spanclass="pre">nodename</span></code>, <em>the current node will run again</em>, possibly with different kwargs. This makes it very easy to re-use a node over and over, for example allowing different options to update some text form being passed and manipulated for every iteration.</p>
</section>
</section>
<sectionid="temporary-storage">
<h3>Temporary storage<aclass="headerlink"href="#temporary-storage"title="Permalink to this headline">¶</a></h3>
<p>When the menu starts, the EvMenu instance is stored on the caller as <codeclass="docutils literal notranslate"><spanclass="pre">caller.ndb._evmenu</span></code>. Through this object you can in principle reach the menu’s internal state if you know what you are doing. This is also a good place to store temporary, more global variables that may be cumbersome to keep passing from node to node via the <codeclass="docutils literal notranslate"><spanclass="pre">**kwargs</span></code>. The <codeclass="docutils literal notranslate"><spanclass="pre">_evmnenu</span></code> will be deleted automatically when the menu closes, meaning you don’t need to worry about cleaning anything up.</p>
<p>If you want <em>permanent</em> state storage, it’s instead better to use an Attribute on <codeclass="docutils literal notranslate"><spanclass="pre">caller</span></code>. Remember that this will remain after the menu closes though, so you need to handle any needed cleanup yourself.</p>
</section>
<sectionid="customizing-menu-formatting">
<h3>Customizing Menu formatting<aclass="headerlink"href="#customizing-menu-formatting"title="Permalink to this headline">¶</a></h3>
<p>The <codeclass="docutils literal notranslate"><spanclass="pre">EvMenu</span></code> display of nodes, options etc are controlled by a series of formatting methods on the <codeclass="docutils literal notranslate"><spanclass="pre">EvMenu</span></code> class. To customize these, simply create a new child class of <codeclass="docutils literal notranslate"><spanclass="pre">EvMenu</span></code> and override as needed. Here is an example:</p>
<spanclass="sd"> Formats the entirety of the node.</span>
<spanclass="sd"> Args:</span>
<spanclass="sd"> nodetext (str): The node text as returned by `self.nodetext_formatter`.</span>
<spanclass="sd"> optionstext (str): The options display as returned by `self.options_formatter`.</span>
<spanclass="sd"> caller (Object, Account or None, optional): The caller of the node.</span>
<spanclass="sd"> Returns:</span>
<spanclass="sd"> node (str): The formatted node to display.</span>
<spanclass="sd">"""</span>
</pre></div>
</div>
<p>See <codeclass="docutils literal notranslate"><spanclass="pre">evennia/utils/evmenu.py</span></code> for the details of their default implementations.</p>
</section>
</section>
<sectionid="evmenu-templating-language">
<h2>EvMenu templating language<aclass="headerlink"href="#evmenu-templating-language"title="Permalink to this headline">¶</a></h2>
<p>In <aclass="reference external"href="http://evmenu.py">evmenu.py</a> are two helper functions <codeclass="docutils literal notranslate"><spanclass="pre">parse_menu_template</span></code> and <codeclass="docutils literal notranslate"><spanclass="pre">template2menu</span></code> that is used to parse a <em>menu template</em> string into an EvMenu:</p>
<p>With this latter solution, one could mix and match normally created menu nodes
with those generated by the template engine.</p>
<p>The <codeclass="docutils literal notranslate"><spanclass="pre">goto_callables</span></code> is a mapping <codeclass="docutils literal notranslate"><spanclass="pre">{"funcname":</span><spanclass="pre">callable,</span><spanclass="pre">...}</span></code>, where each
callable must be a module-global function on the form
<codeclass="docutils literal notranslate"><spanclass="pre">funcname(caller,</span><spanclass="pre">raw_string,</span><spanclass="pre">**kwargs)</span></code> (like any goto-callable). The
<codeclass="docutils literal notranslate"><spanclass="pre">menu_template</span></code> is a multi-line string on the following form:</p>
<p>Each menu node is defined by a <codeclass="docutils literal notranslate"><spanclass="pre">##</span><spanclass="pre">node</span><spanclass="pre"><name></span></code> containing the text of the node,
followed by <codeclass="docutils literal notranslate"><spanclass="pre">##</span><spanclass="pre">options</span></code> Also <codeclass="docutils literal notranslate"><spanclass="pre">##</span><spanclass="pre">NODE</span></code> and <codeclass="docutils literal notranslate"><spanclass="pre">##</span><spanclass="pre">OPTIONS</span></code> work. No python code
logics is allowed in the template, this code is not evaluated but parsed. More
advanced dynamic usage requires a full node-function.</p>
<p>Except for defining the node/options, <codeclass="docutils literal notranslate"><spanclass="pre">#</span></code> act as comments - everything following
will be ignored by the template parser.</p>
<sectionid="template-options">
<h3>Template Options<aclass="headerlink"href="#template-options"title="Permalink to this headline">¶</a></h3>
<p>The option syntax is</p>
<divclass="highlight-none notranslate"><divclass="highlight"><pre><span></span><key>: [desc ->] nodename or function-call
</pre></div>
</div>
<p>The ‘desc’ part is optional, and if that is not given, the <codeclass="docutils literal notranslate"><spanclass="pre">-></span></code> can be skipped
<p>Starting the key with the special letter <codeclass="docutils literal notranslate"><spanclass="pre">></span></code> indicates that what follows is a
<p>For this to work <codeclass="docutils literal notranslate"><spanclass="pre">template2menu</span></code> or <codeclass="docutils literal notranslate"><spanclass="pre">parse_menu_template</span></code> must be given a dict
that includes <codeclass="docutils literal notranslate"><spanclass="pre">{"myfunc":</span><spanclass="pre">_actual_myfunc_callable}</span></code>. All callables to be
available in the template must be mapped this way. Goto callables act like
normal EvMenu goto-callables and should have a callsign of
<codeclass="docutils literal notranslate"><spanclass="pre">_actual_myfunc_callable(caller,</span><spanclass="pre">raw_string,</span><spanclass="pre">**kwargs)</span></code> and return the next node
(passing dynamic kwargs into the next node does not work with the template</p>
<ulclass="simple">
<li><p>use the full EvMenu if you want advanced dynamic data passing).</p></li>
</ul>
<p>Only no or named keywords are allowed in these callables. So</p>
<divclass="highlight-none notranslate"><divclass="highlight"><pre><span></span>myfunc() # OK
myfunc(foo=bar) # OK
myfunc(foo) # error!
</pre></div>
</div>
<p>This is because these properties are passed as <codeclass="docutils literal notranslate"><spanclass="pre">**kwargs</span></code> into the goto callable.</p>
</section>
<sectionid="templating-example">
<h3>Templating example<aclass="headerlink"href="#templating-example"title="Permalink to this headline">¶</a></h3>
<spanclass="n">caller</span><spanclass="o">.</span><spanclass="n">msg</span><spanclass="p">(</span><spanclass="s2">"You roll the dice ..."</span><spanclass="p">)</span>
<h2>Asking for one-line input<aclass="headerlink"href="#asking-for-one-line-input"title="Permalink to this headline">¶</a></h2>
<p>This describes two ways for asking for simple questions from the user. Using Python’s <codeclass="docutils literal notranslate"><spanclass="pre">input</span></code>
will <em>not</em> work in Evennia. <codeclass="docutils literal notranslate"><spanclass="pre">input</span></code> will <em>block</em> the entire server for <em>everyone</em> until that one
player has entered their text, which is not what you want.</p>
<sectionid="the-yield-way">
<h3>The <codeclass="docutils literal notranslate"><spanclass="pre">yield</span></code> way<aclass="headerlink"href="#the-yield-way"title="Permalink to this headline">¶</a></h3>
<p>In the <codeclass="docutils literal notranslate"><spanclass="pre">func</span></code> method of your Commands (only) you can use Python’s built-in <codeclass="docutils literal notranslate"><spanclass="pre">yield</span></code> command to
request input in a similar way to <codeclass="docutils literal notranslate"><spanclass="pre">input</span></code>. It looks like this:</p>
<divclass="highlight-python notranslate"><divclass="highlight"><pre><span></span><spanclass="n">result</span><spanclass="o">=</span><spanclass="k">yield</span><spanclass="p">(</span><spanclass="s2">"Please enter your answer:"</span><spanclass="p">)</span>
</pre></div>
</div>
<p>This will send “Please enter your answer” to the Command’s <codeclass="docutils literal notranslate"><spanclass="pre">self.caller</span></code> and then pause at that
point. All other players at the server will be unaffected. Once caller enteres a reply, the code
execution will continue and you can do stuff with the <codeclass="docutils literal notranslate"><spanclass="pre">result</span></code>. Here is an example:</p>
<spanclass="n">result</span><spanclass="o">=</span><spanclass="k">yield</span><spanclass="p">(</span><spanclass="s2">"Please enter something:"</span><spanclass="p">)</span>
<spanclass="n">result2</span><spanclass="o">=</span><spanclass="k">yield</span><spanclass="p">(</span><spanclass="s2">"Now enter something else:"</span><spanclass="p">)</span>
<spanclass="bp">self</span><spanclass="o">.</span><spanclass="n">caller</span><spanclass="o">.</span><spanclass="n">msg</span><spanclass="p">(</span><spanclass="sa">f</span><spanclass="s2">"You now entered </span><spanclass="si">{</span><spanclass="n">result2</span><spanclass="si">}</span><spanclass="s2">."</span><spanclass="p">)</span>
</pre></div>
</div>
<p>Using <codeclass="docutils literal notranslate"><spanclass="pre">yield</span></code> is simple and intuitive, but it will only access input from <codeclass="docutils literal notranslate"><spanclass="pre">self.caller</span></code> and you
cannot abort or time out the pause until the player has responded. Under the hood, it is actually
just a wrapper calling <codeclass="docutils literal notranslate"><spanclass="pre">get_input</span></code> described in the following section.</p>
<blockquote>
<div><p>Important Note: In Python you <em>cannot mix <codeclass="docutils literal notranslate"><spanclass="pre">yield</span></code> and <codeclass="docutils literal notranslate"><spanclass="pre">return</span><spanclass="pre"><value></span></code> in the same method</em>. It has
to do with <codeclass="docutils literal notranslate"><spanclass="pre">yield</span></code> turning the method into a
<aclass="reference external"href="https://www.learnpython.org/en/Generators">generator</a>. A <codeclass="docutils literal notranslate"><spanclass="pre">return</span></code> without an argument works, you
can just not do <codeclass="docutils literal notranslate"><spanclass="pre">return</span><spanclass="pre"><value></span></code>. This is usually not something you need to do in <codeclass="docutils literal notranslate"><spanclass="pre">func()</span></code> anyway,
but worth keeping in mind.</p>
</div></blockquote>
</section>
<sectionid="the-get-input-way">
<h3>The <codeclass="docutils literal notranslate"><spanclass="pre">get_input</span></code> way<aclass="headerlink"href="#the-get-input-way"title="Permalink to this headline">¶</a></h3>
<p>The evmenu module offers a helper function named <codeclass="docutils literal notranslate"><spanclass="pre">get_input</span></code>. This is wrapped by the <codeclass="docutils literal notranslate"><spanclass="pre">yield</span></code>
statement which is often easier and more intuitive to use. But <codeclass="docutils literal notranslate"><spanclass="pre">get_input</span></code> offers more flexibility
and power if you need it. While in the same module as <codeclass="docutils literal notranslate"><spanclass="pre">EvMenu</span></code>, <codeclass="docutils literal notranslate"><spanclass="pre">get_input</span></code> is technically unrelated
to it. The <codeclass="docutils literal notranslate"><spanclass="pre">get_input</span></code> allows you to ask and receive simple one-line input from the user without
launching the full power of a menu to do so. To use, call <codeclass="docutils literal notranslate"><spanclass="pre">get_input</span></code> like this:</p>
<p>Here <codeclass="docutils literal notranslate"><spanclass="pre">caller</span></code> is the entity that should receive the prompt for input given as <codeclass="docutils literal notranslate"><spanclass="pre">prompt</span></code>. The
<codeclass="docutils literal notranslate"><spanclass="pre">callback</span></code> is a callable <codeclass="docutils literal notranslate"><spanclass="pre">function(caller,</span><spanclass="pre">prompt,</span><spanclass="pre">user_input)</span></code> that you define to handle the answer
from the user. When run, the caller will see <codeclass="docutils literal notranslate"><spanclass="pre">prompt</span></code> appear on their screens and <em>any</em> text they
enter will be sent into the callback for whatever processing you want.</p>
<p>Below is a fully explained callback and example call:</p>
When asked 'Write something!', you answered 'Hello'.
</pre></div>
</div>
<p>Normally, the <codeclass="docutils literal notranslate"><spanclass="pre">get_input</span></code> function quits after any input, but as seen in the example docs, you could
return True from the callback to repeat the prompt until you pass whatever check you want.</p>
<blockquote>
<div><p>Note: You <em>cannot</em> link consecutive questions by putting a new <codeclass="docutils literal notranslate"><spanclass="pre">get_input</span></code> call inside the
callback If you want that you should use an EvMenu instead (see the <aclass="reference internal"href="#example-repeating-the-same-node"><spanclass="std std-doc">Repeating the same
node</span></a> example above). Otherwise you can either peek at the
implementation of <codeclass="docutils literal notranslate"><spanclass="pre">get_input</span></code> and implement your own mechanism (it’s just using cmdset nesting) or
you can look at <aclass="reference external"href="https://groups.google.com/forum/#%21category-topic/evennia/evennia-questions/16pi0SfMO5U">this extension suggested on the mailing
list</a>.</p>
</div></blockquote>
<sectionid="example-yes-no-prompt">
<h4>Example: Yes/No prompt<aclass="headerlink"href="#example-yes-no-prompt"title="Permalink to this headline">¶</a></h4>
<p>Below is an example of a Yes/No prompt using the <codeclass="docutils literal notranslate"><spanclass="pre">get_input</span></code> function:</p>
<spanclass="n">get_input</span><spanclass="p">(</span><spanclass="n">caller</span><spanclass="p">,</span><spanclass="s2">"Is Evennia great (Yes/No)?"</span><spanclass="p">,</span><spanclass="n">yesno</span><spanclass="p">)</span>
</pre></div>
</div>
</section>
</section>
</section>
<sectionid="the-list-node-decorator">
<h2>The <codeclass="docutils literal notranslate"><spanclass="pre">@list_node</span></code> decorator<aclass="headerlink"href="#the-list-node-decorator"title="Permalink to this headline">¶</a></h2>
<p>The <codeclass="docutils literal notranslate"><spanclass="pre">evennia.utils.evmenu.list_node</span></code> is an advanced decorator for use with <codeclass="docutils literal notranslate"><spanclass="pre">EvMenu</span></code> node functions.
It is used to quickly create menus for manipulating large numbers of items.</p>
<p>The <codeclass="docutils literal notranslate"><spanclass="pre">options</span></code> argument to <codeclass="docutils literal notranslate"><spanclass="pre">list_node</span></code> is either a list, a generator or a callable returning a list
of strings for each option that should be displayed in the node.</p>
<p>The <codeclass="docutils literal notranslate"><spanclass="pre">select</span></code> is a callable in the example above but could also be the name of a menu node. If a
callable, the <codeclass="docutils literal notranslate"><spanclass="pre">menuchoice</span></code> argument holds the selection done and <codeclass="docutils literal notranslate"><spanclass="pre">available_choices</span></code> holds all the
options available. The callable should return the menu to go to depending on the selection (or
<codeclass="docutils literal notranslate"><spanclass="pre">None</span></code> to rerun the same node). If the name of a menu node, the selection will be passed as
<codeclass="docutils literal notranslate"><spanclass="pre">selection</span></code> kwarg to that node.</p>
<p>The decorated node itself should return <codeclass="docutils literal notranslate"><spanclass="pre">text</span></code> to display in the node. It must return at least an
empty dictionary for its options. It returning options, those will supplement the options
auto-created by the <codeclass="docutils literal notranslate"><spanclass="pre">list_node</span></code> decorator.</p>
</section>
<sectionid="example-menus">
<h2>Example Menus<aclass="headerlink"href="#example-menus"title="Permalink to this headline">¶</a></h2>
<p>Here is a diagram to help visualize the flow of data from node to node, including goto-callables in-between:</p>
Node B│ text = "Result of operation: " + kwargs["c"]
│ return text, {}
└─
┌─
Menu │ EvMenu(caller, {"node_A": nodeA, "node_B": nodeB}, startnode="node_A")
Start│
└─
</pre></div>
</div>
<p>Above we create a very simple/stupid menu (in the <codeclass="docutils literal notranslate"><spanclass="pre">EvMenu</span></code> call at the end) where we map the node identifier <codeclass="docutils literal notranslate"><spanclass="pre">"node_A"</span></code> to the Python function <codeclass="docutils literal notranslate"><spanclass="pre">nodeA</span></code> and <codeclass="docutils literal notranslate"><spanclass="pre">"node_B"</span></code> to the function <codeclass="docutils literal notranslate"><spanclass="pre">nodeB</span></code>.</p>
<p>We start the menu in <codeclass="docutils literal notranslate"><spanclass="pre">"node_A"</span></code> where we get three options A, B and C. Options A and B will route via a a goto-callable <codeclass="docutils literal notranslate"><spanclass="pre">_callback</span></code> that either multiples or adds the numbers 2 and 3 together before continuing to <codeclass="docutils literal notranslate"><spanclass="pre">"node_B"</span></code>. Option C routes directly to <codeclass="docutils literal notranslate"><spanclass="pre">"node_B"</span></code>, passing the number 5.</p>
<p>In every step, we pass a dict which becomes the ingoing <codeclass="docutils literal notranslate"><spanclass="pre">**kwargs</span></code> in the next step. If we didn’t pass anything (it’s optional), the next step’s <codeclass="docutils literal notranslate"><spanclass="pre">**kwargs</span></code> would just be empty.</p>
<p>More examples:</p>
<ulclass="simple">
<li><p><strong><aclass="reference internal"href="#example-simple-branching-menu"><spanclass="std std-doc">Simple branching menu</span></a></strong> - choose from options</p></li>
<li><p><strong><aclass="reference internal"href="#example-dynamic-goto"><spanclass="std std-doc">Dynamic goto</span></a></strong> - jumping to different nodes based on response</p></li>
<li><p><strong><aclass="reference internal"href="#example-set-caller-properties"><spanclass="std std-doc">Set caller properties</span></a></strong> - a menu that changes things</p></li>
<li><p><strong><aclass="reference internal"href="#example-storing-data-between-nodes"><spanclass="std std-doc">Storing data between nodes</span></a></strong> - keeping states and
information while in the menu</p></li>
<li><p><strong><aclass="reference internal"href="#example-repeating-the-same-node"><spanclass="std std-doc">Repeating the same node</span></a></strong> - validating within the node
before moving to the next</p></li>
<li><p><strong><aclass="reference internal"href="#example-yes-no-prompt"><spanclass="std std-doc">Yes/No prompt</span></a></strong> - entering text with limited possible responses
(this is <em>not</em> using EvMenu but the conceptually similar yet technically unrelated <codeclass="docutils literal notranslate"><spanclass="pre">get_input</span></code>
helper function accessed as <codeclass="docutils literal notranslate"><spanclass="pre">evennia.utils.evmenu.get_input</span></code>).</p></li>
</ul>
<sectionid="example-simple-branching-menu">
<h3>Example: Simple branching menu<aclass="headerlink"href="#example-simple-branching-menu"title="Permalink to this headline">¶</a></h3>
<p>Below is an example of a simple branching menu node leading to different other nodes depending on choice:</p>
<divclass="highlight-python notranslate"><divclass="highlight"><pre><span></span><spanclass="c1"># in mygame/world/mychargen.py</span>
<spanclass="sd"> What aspect of your character do you want</span>
<spanclass="sd"> to change next?</span>
<spanclass="sd">"""</span>
<spanclass="n">options</span><spanclass="o">=</span><spanclass="p">({</span><spanclass="s2">"desc"</span><spanclass="p">:</span><spanclass="s2">"Change the name"</span><spanclass="p">,</span>
<spanclass="p">{</span><spanclass="s2">"desc"</span><spanclass="p">:</span><spanclass="s2">"Change the description"</span><spanclass="p">,</span>
<p>This will result in the following node display:</p>
<divclass="highlight-default notranslate"><divclass="highlight"><pre><span></span>What aspect of your character do you want
to change next?
_________________________
1: Change the name
2: Change the description
</pre></div>
</div>
<p>Note that since we didn’t specify the “name” key, EvMenu will let the user enter numbers instead. In
the following examples we will not include the <codeclass="docutils literal notranslate"><spanclass="pre">EvMenu</span></code> call but just show nodes running inside the
menu. Also, since <codeclass="docutils literal notranslate"><spanclass="pre">EvMenu</span></code> also takes a dictionary to describe the menu, we could have called it
<spanclass="n">text</span><spanclass="o">=</span><spanclass="s1">'You say to the mage guard:'</span>
<spanclass="n">options</span><spanclass="p">({</span><spanclass="s1">'desc'</span><spanclass="p">:</span><spanclass="s1">'I need to get in there.'</span><spanclass="p">,</span>
<p>This simple callable goto will analyse what happens depending on who the <codeclass="docutils literal notranslate"><spanclass="pre">caller</span></code> is. The
<codeclass="docutils literal notranslate"><spanclass="pre">enter_guild</span></code> node will give you a choice of what to say to the guard. If you try to enter, you will
end up in different nodes depending on (in this example) if you have the right <aclass="reference internal"href="Tags.html"><spanclass="doc std std-doc">Tag</span></a> set on
yourself or not. Note that since we don’t include any ‘key’s in the option dictionary, you will just
get to pick between numbers.</p>
</section>
<sectionid="example-set-caller-properties">
<h3>Example: Set caller properties<aclass="headerlink"href="#example-set-caller-properties"title="Permalink to this headline">¶</a></h3>
<p>Here is an example of passing arguments into the <codeclass="docutils literal notranslate"><spanclass="pre">goto</span></code> callable and use that to influence
<spanclass="s2"></span><spanclass="si">{</span><spanclass="n">caller</span><spanclass="o">.</span><spanclass="n">key</span><spanclass="si">}</span><spanclass="s2"> experienced a traumatic event</span>
<spanclass="s2"> in their childhood. What was it?</span>
<spanclass="s2">"desc"</span><spanclass="p">:</span><spanclass="s2">"The betrayal of a trusted grown-up"</span><spanclass="p">,</span>
<p>Note above how we use the <codeclass="docutils literal notranslate"><spanclass="pre">_set_attribute</span></code> helper function to set the attribute depending on the
User’s choice. In thie case the helper function doesn’t know anything about what node called it - we
even tell it which nodename it should return, so the choices leads to different paths in the menu.
We could also imagine the helper function analyzing what other choices</p>
</section>
<sectionid="example-get-arbitrary-input">
<h3>Example: Get arbitrary input<aclass="headerlink"href="#example-get-arbitrary-input"title="Permalink to this headline">¶</a></h3>
<p>An example of the menu asking the user for input - any input.</p>
<spanclass="n">caller</span><spanclass="o">.</span><spanclass="n">msg</span><spanclass="p">(</span><spanclass="sa">f</span><spanclass="s2">"Set name to </span><spanclass="si">{</span><spanclass="n">prev_entry</span><spanclass="si">}</span><spanclass="s2">."</span><spanclass="p">)</span>
<spanclass="n">text</span><spanclass="o">=</span><spanclass="s2">"Current name: </span><spanclass="si">{}</span><spanclass="s2">.</span><spanclass="se">\n</span><spanclass="s2">Enter another name or <return> to accept."</span>
<spanclass="k">else</span><spanclass="p">:</span>
<spanclass="n">text</span><spanclass="o">=</span><spanclass="s2">"Enter your character's name or <return> to abort."</span>
<divclass="highlight-default notranslate"><divclass="highlight"><pre><span></span><spanclass="n">Enter</span><spanclass="n">your</span><spanclass="n">character</span><spanclass="s1">'s name or <return> to abort.</span>
<p>Here we re-use the same node twice for reading the input data from the user. Whatever we enter will
be caught by the <codeclass="docutils literal notranslate"><spanclass="pre">_default</span></code> option and passed into the helper function. We also pass along whatever
name we have entered before. This allows us to react correctly on an “empty” input - continue to the
node named <codeclass="docutils literal notranslate"><spanclass="pre">"node_background"</span></code> if we accept the input or go to an exit node if we presses Return
without entering anything. By returning <codeclass="docutils literal notranslate"><spanclass="pre">None</span></code> from the helper function we automatically re-run the
previous node, but updating its ingoing kwargs to tell it to display a different text.</p>
</section>
<sectionid="example-storing-data-between-nodes">
<h3>Example: Storing data between nodes<aclass="headerlink"href="#example-storing-data-between-nodes"title="Permalink to this headline">¶</a></h3>
<p>A convenient way to store data is to store it on the <codeclass="docutils literal notranslate"><spanclass="pre">caller.ndb._evmenu</span></code> which you can reach from
every node. The advantage of doing this is that the <codeclass="docutils literal notranslate"><spanclass="pre">_evmenu</span></code> NAttribute will be deleted
<spanclass="n">caller</span><spanclass="o">.</span><spanclass="n">msg</span><spanclass="p">(</span><spanclass="sa">f</span><spanclass="s2">"You set your name to </span><spanclass="si">{</span><spanclass="n">raw_string</span><spanclass="si">}</span><spanclass="s2">"</span><spanclass="p">)</span>
<p>Instead of passing the character sheet along from node to node through the <codeclass="docutils literal notranslate"><spanclass="pre">kwargs</span></code> we instead
set it up temporarily on <codeclass="docutils literal notranslate"><spanclass="pre">caller.ndb._evmenu.charactersheet</span></code>. This makes it easy to reach from
all nodes. At the end we look at it and, if we accept the character the menu will likely save the
result to permanent storage and exit.</p>
<blockquote>
<div><p>One point to remember though is that storage on <codeclass="docutils literal notranslate"><spanclass="pre">caller.ndb._evmenu</span></code> is not persistent across
<codeclass="docutils literal notranslate"><spanclass="pre">@reloads</span></code>. If you are using a persistent menu (using <codeclass="docutils literal notranslate"><spanclass="pre">EvMenu(...,</span><spanclass="pre">persistent=True)</span></code> you should
use
<codeclass="docutils literal notranslate"><spanclass="pre">caller.db</span></code> to store in-menu data like this as well. You must then yourself make sure to clean it
when the user exits the menu.</p>
</div></blockquote>
</section>
<sectionid="example-repeating-the-same-node">
<h3>Example: Repeating the same node<aclass="headerlink"href="#example-repeating-the-same-node"title="Permalink to this headline">¶</a></h3>
<p>Sometimes you want to make a chain of menu nodes one after another, but you don’t want the user to be able to continue to the next node until you have verified that what they input in the previous node is ok. A common example is a login menu:</p>
<spanclass="c1"># re-run current node by returning `None`</span>
<spanclass="n">caller</span><spanclass="o">.</span><spanclass="n">msg</span><spanclass="p">(</span><spanclass="s2">"|rUsername not found. Try again."</span><spanclass="p">)</span>
<p>Here the goto-callables will return to the previous node if there is an error. In the case of
password attempts, this will tick up the <codeclass="docutils literal notranslate"><spanclass="pre">nattempts</span></code> argument that will get passed on from iteration
to iteration until too many attempts have been made.</p>
</section>
<sectionid="defining-nodes-in-a-dictionary">
<h3>Defining nodes in a dictionary<aclass="headerlink"href="#defining-nodes-in-a-dictionary"title="Permalink to this headline">¶</a></h3>
<p>You can also define your nodes directly in a dictionary to feed into the <codeclass="docutils literal notranslate"><spanclass="pre">EvMenu</span></code> creator.</p>
<p>The keys of the dictionary become the node identifiers. You can use any callable on the right form
to describe each node. If you use Python <codeclass="docutils literal notranslate"><spanclass="pre">lambda</span></code> expressions you can make nodes really on the fly.
If you do, the lambda expression must accept one or two arguments and always return a tuple with two
elements (the text of the node and its options), same as any menu node function.</p>
<p>Creating menus like this is one way to present a menu that changes with the circumstances - you
could for example remove or add nodes before launching the menu depending on some criteria. The
drawback is that a <codeclass="docutils literal notranslate"><spanclass="pre">lambda</span></code> expression <aclass="reference external"href="https://docs.python.org/2/tutorial/controlflow.html#lambda-expressions">is much more
limited</a> than a full
function - for example you can’t use other Python keywords like <codeclass="docutils literal notranslate"><spanclass="pre">if</span></code> inside the body of the
<p>Unless you are dealing with a relatively simple dynamic menu, defining menus with lambda’s is
probably more work than it’s worth: You can create dynamic menus by instead making each node
function more clever. See the <aclass="reference internal"href="../Howtos/Tutorial-NPC-Merchants.html"><spanclass="doc std std-doc">NPC shop tutorial</span></a> for an example of this.</p>
<pclass="last">You are reading an old version of the Evennia documentation. <ahref="https://www.evennia.com/docs/latest/index.html">The latest version is here</a></p>.