evennia/docs/1.0-dev/_modules/evennia/contrib/building_menu.html
2020-11-14 13:44:49 +01:00

1362 lines
No EOL
142 KiB
HTML

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>evennia.contrib.building_menu &#8212; 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> &#187;</li>
<li class="nav-item nav-item-1"><a href="../../index.html" >Module code</a> &#187;</li>
<li class="nav-item nav-item-2"><a href="../../evennia.html" accesskey="U">evennia</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">evennia.contrib.building_menu</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.contrib.building_menu</h1><div class="highlight"><pre>
<span></span><span class="sd">&quot;&quot;&quot;</span>
<span class="sd">Module containing the building menu system.</span>
<span class="sd">Evennia contributor: vincent-lg 2018</span>
<span class="sd">Building menus are in-game menus, not unlike `EvMenu` though using a</span>
<span class="sd">different approach. Building menus have been specifically designed to edit</span>
<span class="sd">information as a builder. Creating a building menu in a command allows</span>
<span class="sd">builders quick-editing of a given object, like a room. If you follow the</span>
<span class="sd">steps below to add the contrib, you will have access to an `@edit` command</span>
<span class="sd">that will edit any default object offering to change its key and description.</span>
<span class="sd">1. Import the `GenericBuildingCmd` class from this contrib in your `mygame/commands/default_cmdset.py` file:</span>
<span class="sd"> ```python</span>
<span class="sd"> from evennia.contrib.building_menu import GenericBuildingCmd</span>
<span class="sd"> ```</span>
<span class="sd">2. Below, add the command in the `CharacterCmdSet`:</span>
<span class="sd"> ```python</span>
<span class="sd"> # ... These lines should exist in the file</span>
<span class="sd"> class CharacterCmdSet(default_cmds.CharacterCmdSet):</span>
<span class="sd"> key = &quot;DefaultCharacter&quot;</span>
<span class="sd"> def at_cmdset_creation(self):</span>
<span class="sd"> super(CharacterCmdSet, self).at_cmdset_creation()</span>
<span class="sd"> # ... add the line below</span>
<span class="sd"> self.add(GenericBuildingCmd())</span>
<span class="sd"> ```</span>
<span class="sd">The `@edit` command will allow you to edit any object. You will need to</span>
<span class="sd">specify the object name or ID as an argument. For instance: `@edit here`</span>
<span class="sd">will edit the current room. However, building menus can perform much more</span>
<span class="sd">than this very simple example, read on for more details.</span>
<span class="sd">Building menus can be set to edit about anything. Here is an example of</span>
<span class="sd">output you could obtain when editing the room:</span>
<span class="sd">```</span>
<span class="sd"> Editing the room: Limbo(#2)</span>
<span class="sd"> [T]itle: the limbo room</span>
<span class="sd"> [D]escription</span>
<span class="sd"> This is the limbo room. You can easily change this default description,</span>
<span class="sd"> either by using the |y@desc/edit|n command, or simply by entering this</span>
<span class="sd"> menu (enter |yd|n).</span>
<span class="sd"> [E]xits:</span>
<span class="sd"> north to A parking(#4)</span>
<span class="sd"> [Q]uit this menu</span>
<span class="sd">```</span>
<span class="sd">From there, you can open the title choice by pressing t. You can then</span>
<span class="sd">change the room title by simply entering text, and go back to the</span>
<span class="sd">main menu entering @ (all this is customizable). Press q to quit this menu.</span>
<span class="sd">The first thing to do is to create a new module and place a class</span>
<span class="sd">inheriting from `BuildingMenu` in it.</span>
<span class="sd">```python</span>
<span class="sd">from evennia.contrib.building_menu import BuildingMenu</span>
<span class="sd">class RoomBuildingMenu(BuildingMenu):</span>
<span class="sd"> # ...</span>
<span class="sd">```</span>
<span class="sd">Next, override the `init` method. You can add choices (like the title,</span>
<span class="sd">description, and exits choices as seen above) by using the `add_choice`</span>
<span class="sd">method.</span>
<span class="sd">```</span>
<span class="sd">class RoomBuildingMenu(BuildingMenu):</span>
<span class="sd"> def init(self, room):</span>
<span class="sd"> self.add_choice(&quot;title&quot;, &quot;t&quot;, attr=&quot;key&quot;)</span>
<span class="sd">```</span>
<span class="sd">That will create the first choice, the title choice. If one opens your menu</span>
<span class="sd">and enter t, she will be in the title choice. She can change the title</span>
<span class="sd">(it will write in the room&#39;s `key` attribute) and then go back to the</span>
<span class="sd">main menu using `@`.</span>
<span class="sd">`add_choice` has a lot of arguments and offers a great deal of</span>
<span class="sd">flexibility. The most useful ones is probably the usage of callbacks,</span>
<span class="sd">as you can set almost any argument in `add_choice` to be a callback, a</span>
<span class="sd">function that you have defined above in your module. This function will be</span>
<span class="sd">called when the menu element is triggered.</span>
<span class="sd">Notice that in order to edit a description, the best method to call isn&#39;t</span>
<span class="sd">`add_choice`, but `add_choice_edit`. This is a convenient shortcut</span>
<span class="sd">which is available to quickly open an `EvEditor` when entering this choice</span>
<span class="sd">and going back to the menu when the editor closes.</span>
<span class="sd">```</span>
<span class="sd">class RoomBuildingMenu(BuildingMenu):</span>
<span class="sd"> def init(self, room):</span>
<span class="sd"> self.add_choice(&quot;title&quot;, &quot;t&quot;, attr=&quot;key&quot;)</span>
<span class="sd"> self.add_choice_edit(&quot;description&quot;, key=&quot;d&quot;, attr=&quot;db.desc&quot;)</span>
<span class="sd">```</span>
<span class="sd">When you wish to create a building menu, you just need to import your</span>
<span class="sd">class, create it specifying your intended caller and object to edit,</span>
<span class="sd">then call `open`:</span>
<span class="sd">```python</span>
<span class="sd">from &lt;wherever&gt; import RoomBuildingMenu</span>
<span class="sd">class CmdEdit(Command):</span>
<span class="sd"> key = &quot;redit&quot;</span>
<span class="sd"> def func(self):</span>
<span class="sd"> menu = RoomBuildingMenu(self.caller, self.caller.location)</span>
<span class="sd"> menu.open()</span>
<span class="sd">```</span>
<span class="sd">This is a very short introduction. For more details, see the online tutorial</span>
<span class="sd">(https://github.com/evennia/evennia/wiki/Building-menus) or read the</span>
<span class="sd">heavily-documented code below.</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="kn">from</span> <span class="nn">inspect</span> <span class="k">import</span> <span class="n">getargspec</span>
<span class="kn">from</span> <span class="nn">textwrap</span> <span class="k">import</span> <span class="n">dedent</span>
<span class="kn">from</span> <span class="nn">django.conf</span> <span class="k">import</span> <span class="n">settings</span>
<span class="kn">from</span> <span class="nn">evennia</span> <span class="k">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.commands</span> <span class="k">import</span> <span class="n">cmdhandler</span>
<span class="kn">from</span> <span class="nn">evennia.utils.ansi</span> <span class="k">import</span> <span class="n">strip_ansi</span>
<span class="kn">from</span> <span class="nn">evennia.utils.eveditor</span> <span class="k">import</span> <span class="n">EvEditor</span>
<span class="kn">from</span> <span class="nn">evennia.utils.logger</span> <span class="k">import</span> <span class="n">log_err</span><span class="p">,</span> <span class="n">log_trace</span>
<span class="kn">from</span> <span class="nn">evennia.utils.utils</span> <span class="k">import</span> <span class="n">class_from_module</span>
<span class="c1"># Constants</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="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"># Private functions</span>
<span class="k">def</span> <span class="nf">_menu_loadfunc</span><span class="p">(</span><span class="n">caller</span><span class="p">):</span>
<span class="n">obj</span><span class="p">,</span> <span class="n">attr</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">&quot;_building_menu_to_edit&quot;</span><span class="p">,</span> <span class="p">[</span><span class="kc">None</span><span class="p">,</span> <span class="kc">None</span><span class="p">])</span>
<span class="k">if</span> <span class="n">obj</span> <span class="ow">and</span> <span class="n">attr</span><span class="p">:</span>
<span class="k">for</span> <span class="n">part</span> <span class="ow">in</span> <span class="n">attr</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s2">&quot;.&quot;</span><span class="p">)[:</span><span class="o">-</span><span class="mi">1</span><span class="p">]:</span>
<span class="n">obj</span> <span class="o">=</span> <span class="nb">getattr</span><span class="p">(</span><span class="n">obj</span><span class="p">,</span> <span class="n">part</span><span class="p">)</span>
<span class="k">return</span> <span class="nb">getattr</span><span class="p">(</span><span class="n">obj</span><span class="p">,</span> <span class="n">attr</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s2">&quot;.&quot;</span><span class="p">)[</span><span class="o">-</span><span class="mi">1</span><span class="p">])</span> <span class="k">if</span> <span class="n">obj</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span> <span class="k">else</span> <span class="s2">&quot;&quot;</span>
<span class="k">def</span> <span class="nf">_menu_savefunc</span><span class="p">(</span><span class="n">caller</span><span class="p">,</span> <span class="n">buf</span><span class="p">):</span>
<span class="n">obj</span><span class="p">,</span> <span class="n">attr</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">&quot;_building_menu_to_edit&quot;</span><span class="p">,</span> <span class="p">[</span><span class="kc">None</span><span class="p">,</span> <span class="kc">None</span><span class="p">])</span>
<span class="k">if</span> <span class="n">obj</span> <span class="ow">and</span> <span class="n">attr</span><span class="p">:</span>
<span class="k">for</span> <span class="n">part</span> <span class="ow">in</span> <span class="n">attr</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s2">&quot;.&quot;</span><span class="p">)[:</span><span class="o">-</span><span class="mi">1</span><span class="p">]:</span>
<span class="n">obj</span> <span class="o">=</span> <span class="nb">getattr</span><span class="p">(</span><span class="n">obj</span><span class="p">,</span> <span class="n">part</span><span class="p">)</span>
<span class="nb">setattr</span><span class="p">(</span><span class="n">obj</span><span class="p">,</span> <span class="n">attr</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s2">&quot;.&quot;</span><span class="p">)[</span><span class="o">-</span><span class="mi">1</span><span class="p">],</span> <span class="n">buf</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">remove</span><span class="p">(</span><span class="s2">&quot;_building_menu_to_edit&quot;</span><span class="p">)</span>
<span class="k">return</span> <span class="kc">True</span>
<span class="k">def</span> <span class="nf">_menu_quitfunc</span><span class="p">(</span><span class="n">caller</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">add</span><span class="p">(</span>
<span class="n">BuildingMenuCmdSet</span><span class="p">,</span>
<span class="n">permanent</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">_building_menu</span> <span class="ow">and</span> <span class="n">caller</span><span class="o">.</span><span class="n">ndb</span><span class="o">.</span><span class="n">_building_menu</span><span class="o">.</span><span class="n">persistent</span> <span class="ow">or</span> <span class="kc">False</span><span class="p">,</span>
<span class="p">)</span>
<span class="k">if</span> <span class="n">caller</span><span class="o">.</span><span class="n">ndb</span><span class="o">.</span><span class="n">_building_menu</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">_building_menu</span><span class="o">.</span><span class="n">move</span><span class="p">(</span><span class="n">back</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">_call_or_get</span><span class="p">(</span><span class="n">value</span><span class="p">,</span> <span class="n">menu</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">choice</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">string</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">obj</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">caller</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Call the value, if appropriate, or just return it.</span>
<span class="sd"> Args:</span>
<span class="sd"> value (any): the value to obtain. It might be a callable (see note).</span>
<span class="sd"> Keyword Args:</span>
<span class="sd"> menu (BuildingMenu, optional): the building menu to pass to value</span>
<span class="sd"> if it is a callable.</span>
<span class="sd"> choice (Choice, optional): the choice to pass to value if a callable.</span>
<span class="sd"> string (str, optional): the raw string to pass to value if a callback.</span>
<span class="sd"> obj (Object): the object to pass to value if a callable.</span>
<span class="sd"> caller (Account or Object, optional): the caller to pass to value</span>
<span class="sd"> if a callable.</span>
<span class="sd"> Returns:</span>
<span class="sd"> The value itself. If the argument is a function, call it with</span>
<span class="sd"> specific arguments (see note).</span>
<span class="sd"> Note:</span>
<span class="sd"> If `value` is a function, call it with varying arguments. The</span>
<span class="sd"> list of arguments will depend on the argument names in your callable.</span>
<span class="sd"> - An argument named `menu` will contain the building menu or None.</span>
<span class="sd"> - The `choice` argument will contain the choice or None.</span>
<span class="sd"> - The `string` argument will contain the raw string or None.</span>
<span class="sd"> - The `obj` argument will contain the object or None.</span>
<span class="sd"> - The `caller` argument will contain the caller or None.</span>
<span class="sd"> - Any other argument will contain the object (`obj`).</span>
<span class="sd"> Thus, you could define callbacks like this:</span>
<span class="sd"> def on_enter(menu, caller, obj):</span>
<span class="sd"> def on_nomatch(string, choice, menu):</span>
<span class="sd"> def on_leave(caller, room): # note that room will contain `obj`</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">if</span> <span class="n">callable</span><span class="p">(</span><span class="n">value</span><span class="p">):</span>
<span class="c1"># Check the function arguments</span>
<span class="n">kwargs</span> <span class="o">=</span> <span class="p">{}</span>
<span class="n">spec</span> <span class="o">=</span> <span class="n">getargspec</span><span class="p">(</span><span class="n">value</span><span class="p">)</span>
<span class="n">args</span> <span class="o">=</span> <span class="n">spec</span><span class="o">.</span><span class="n">args</span>
<span class="k">if</span> <span class="n">spec</span><span class="o">.</span><span class="n">keywords</span><span class="p">:</span>
<span class="n">kwargs</span><span class="o">.</span><span class="n">update</span><span class="p">(</span><span class="nb">dict</span><span class="p">(</span><span class="n">menu</span><span class="o">=</span><span class="n">menu</span><span class="p">,</span> <span class="n">choice</span><span class="o">=</span><span class="n">choice</span><span class="p">,</span> <span class="n">string</span><span class="o">=</span><span class="n">string</span><span class="p">,</span> <span class="n">obj</span><span class="o">=</span><span class="n">obj</span><span class="p">,</span> <span class="n">caller</span><span class="o">=</span><span class="n">caller</span><span class="p">))</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">if</span> <span class="s2">&quot;menu&quot;</span> <span class="ow">in</span> <span class="n">args</span><span class="p">:</span>
<span class="n">kwargs</span><span class="p">[</span><span class="s2">&quot;menu&quot;</span><span class="p">]</span> <span class="o">=</span> <span class="n">menu</span>
<span class="k">if</span> <span class="s2">&quot;choice&quot;</span> <span class="ow">in</span> <span class="n">args</span><span class="p">:</span>
<span class="n">kwargs</span><span class="p">[</span><span class="s2">&quot;choice&quot;</span><span class="p">]</span> <span class="o">=</span> <span class="n">choice</span>
<span class="k">if</span> <span class="s2">&quot;string&quot;</span> <span class="ow">in</span> <span class="n">args</span><span class="p">:</span>
<span class="n">kwargs</span><span class="p">[</span><span class="s2">&quot;string&quot;</span><span class="p">]</span> <span class="o">=</span> <span class="n">string</span>
<span class="k">if</span> <span class="s2">&quot;obj&quot;</span> <span class="ow">in</span> <span class="n">args</span><span class="p">:</span>
<span class="n">kwargs</span><span class="p">[</span><span class="s2">&quot;obj&quot;</span><span class="p">]</span> <span class="o">=</span> <span class="n">obj</span>
<span class="k">if</span> <span class="s2">&quot;caller&quot;</span> <span class="ow">in</span> <span class="n">args</span><span class="p">:</span>
<span class="n">kwargs</span><span class="p">[</span><span class="s2">&quot;caller&quot;</span><span class="p">]</span> <span class="o">=</span> <span class="n">caller</span>
<span class="c1"># Fill missing arguments</span>
<span class="k">for</span> <span class="n">arg</span> <span class="ow">in</span> <span class="n">args</span><span class="p">:</span>
<span class="k">if</span> <span class="n">arg</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">kwargs</span><span class="p">:</span>
<span class="n">kwargs</span><span class="p">[</span><span class="n">arg</span><span class="p">]</span> <span class="o">=</span> <span class="n">obj</span>
<span class="c1"># Call the function and return its return value</span>
<span class="k">return</span> <span class="n">value</span><span class="p">(</span><span class="o">**</span><span class="n">kwargs</span><span class="p">)</span>
<span class="k">return</span> <span class="n">value</span>
<span class="c1"># Helper functions, to be used in menu choices</span>
<div class="viewcode-block" id="menu_setattr"><a class="viewcode-back" href="../../../api/evennia.contrib.building_menu.html#evennia.contrib.building_menu.menu_setattr">[docs]</a><span class="k">def</span> <span class="nf">menu_setattr</span><span class="p">(</span><span class="n">menu</span><span class="p">,</span> <span class="n">choice</span><span class="p">,</span> <span class="n">obj</span><span class="p">,</span> <span class="n">string</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Set the value at the specified attribute.</span>
<span class="sd"> Args:</span>
<span class="sd"> menu (BuildingMenu): the menu object.</span>
<span class="sd"> choice (Chocie): the specific choice.</span>
<span class="sd"> obj (Object): the object to modify.</span>
<span class="sd"> string (str): the string with the new value.</span>
<span class="sd"> Note:</span>
<span class="sd"> This function is supposed to be used as a default to</span>
<span class="sd"> `BuildingMenu.add_choice`, when an attribute name is specified</span>
<span class="sd"> (in the `attr` argument) but no function `on_nomatch` is defined.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="n">attr</span> <span class="o">=</span> <span class="nb">getattr</span><span class="p">(</span><span class="n">choice</span><span class="p">,</span> <span class="s2">&quot;attr&quot;</span><span class="p">,</span> <span class="kc">None</span><span class="p">)</span> <span class="k">if</span> <span class="n">choice</span> <span class="k">else</span> <span class="kc">None</span>
<span class="k">if</span> <span class="n">choice</span> <span class="ow">is</span> <span class="kc">None</span> <span class="ow">or</span> <span class="n">string</span> <span class="ow">is</span> <span class="kc">None</span> <span class="ow">or</span> <span class="n">attr</span> <span class="ow">is</span> <span class="kc">None</span> <span class="ow">or</span> <span class="n">menu</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
<span class="n">log_err</span><span class="p">(</span>
<span class="n">dedent</span><span class="p">(</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> The `menu_setattr` function was called to set the attribute {} of object {} to {},</span>
<span class="sd"> but the choice {} of menu {} or another information is missing.</span>
<span class="sd"> &quot;&quot;&quot;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span>
<span class="n">attr</span><span class="p">,</span> <span class="n">obj</span><span class="p">,</span> <span class="nb">repr</span><span class="p">(</span><span class="n">string</span><span class="p">),</span> <span class="n">choice</span><span class="p">,</span> <span class="n">menu</span>
<span class="p">)</span>
<span class="p">)</span><span class="o">.</span><span class="n">strip</span><span class="p">(</span><span class="s2">&quot;</span><span class="se">\n</span><span class="s2">&quot;</span><span class="p">)</span>
<span class="p">)</span><span class="o">.</span><span class="n">strip</span><span class="p">()</span>
<span class="k">return</span>
<span class="k">for</span> <span class="n">part</span> <span class="ow">in</span> <span class="n">attr</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s2">&quot;.&quot;</span><span class="p">)[:</span><span class="o">-</span><span class="mi">1</span><span class="p">]:</span>
<span class="n">obj</span> <span class="o">=</span> <span class="nb">getattr</span><span class="p">(</span><span class="n">obj</span><span class="p">,</span> <span class="n">part</span><span class="p">)</span>
<span class="nb">setattr</span><span class="p">(</span><span class="n">obj</span><span class="p">,</span> <span class="n">attr</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s2">&quot;.&quot;</span><span class="p">)[</span><span class="o">-</span><span class="mi">1</span><span class="p">],</span> <span class="n">string</span><span class="p">)</span>
<span class="k">return</span> <span class="kc">True</span></div>
<div class="viewcode-block" id="menu_quit"><a class="viewcode-back" href="../../../api/evennia.contrib.building_menu.html#evennia.contrib.building_menu.menu_quit">[docs]</a><span class="k">def</span> <span class="nf">menu_quit</span><span class="p">(</span><span class="n">caller</span><span class="p">,</span> <span class="n">menu</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Quit the menu, closing the CmdSet.</span>
<span class="sd"> Args:</span>
<span class="sd"> caller (Account or Object): the caller.</span>
<span class="sd"> menu (BuildingMenu): the building menu to close.</span>
<span class="sd"> Note:</span>
<span class="sd"> This callback is used by default when using the</span>
<span class="sd"> `BuildingMenu.add_choice_quit` method. This method is called</span>
<span class="sd"> automatically if the menu has no parent.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">if</span> <span class="n">caller</span> <span class="ow">is</span> <span class="kc">None</span> <span class="ow">or</span> <span class="n">menu</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
<span class="n">log_err</span><span class="p">(</span>
<span class="s2">&quot;The function `menu_quit` was called with missing &quot;</span>
<span class="s2">&quot;arguments: caller=</span><span class="si">{}</span><span class="s2">, menu=</span><span class="si">{}</span><span class="s2">&quot;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">caller</span><span class="p">,</span> <span class="n">menu</span><span class="p">)</span>
<span class="p">)</span>
<span class="k">if</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">BuildingMenuCmdSet</span><span class="p">):</span>
<span class="n">menu</span><span class="o">.</span><span class="n">close</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">&quot;Closing the building menu.&quot;</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">msg</span><span class="p">(</span><span class="s2">&quot;It looks like the building menu has already been closed.&quot;</span><span class="p">)</span></div>
<div class="viewcode-block" id="menu_edit"><a class="viewcode-back" href="../../../api/evennia.contrib.building_menu.html#evennia.contrib.building_menu.menu_edit">[docs]</a><span class="k">def</span> <span class="nf">menu_edit</span><span class="p">(</span><span class="n">caller</span><span class="p">,</span> <span class="n">choice</span><span class="p">,</span> <span class="n">obj</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Open the EvEditor to edit a specified attribute.</span>
<span class="sd"> Args:</span>
<span class="sd"> caller (Account or Object): the caller.</span>
<span class="sd"> choice (Choice): the choice object.</span>
<span class="sd"> obj (Object): the object to edit.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="n">attr</span> <span class="o">=</span> <span class="n">choice</span><span class="o">.</span><span class="n">attr</span>
<span class="n">caller</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">_building_menu_to_edit</span> <span class="o">=</span> <span class="p">(</span><span class="n">obj</span><span class="p">,</span> <span class="n">attr</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">BuildingMenuCmdSet</span><span class="p">)</span>
<span class="n">EvEditor</span><span class="p">(</span>
<span class="n">caller</span><span class="p">,</span>
<span class="n">loadfunc</span><span class="o">=</span><span class="n">_menu_loadfunc</span><span class="p">,</span>
<span class="n">savefunc</span><span class="o">=</span><span class="n">_menu_savefunc</span><span class="p">,</span>
<span class="n">quitfunc</span><span class="o">=</span><span class="n">_menu_quitfunc</span><span class="p">,</span>
<span class="n">key</span><span class="o">=</span><span class="s2">&quot;editor&quot;</span><span class="p">,</span>
<span class="n">persistent</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span>
<span class="p">)</span></div>
<span class="c1"># Building menu commands and CmdSet</span>
<div class="viewcode-block" id="CmdNoInput"><a class="viewcode-back" href="../../../api/evennia.contrib.building_menu.html#evennia.contrib.building_menu.CmdNoInput">[docs]</a><span class="k">class</span> <span class="nc">CmdNoInput</span><span class="p">(</span><span class="n">Command</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;No input has been found.&quot;&quot;&quot;</span>
<span class="n">key</span> <span class="o">=</span> <span class="n">_CMD_NOINPUT</span>
<span class="n">locks</span> <span class="o">=</span> <span class="s2">&quot;cmd:all()&quot;</span>
<div class="viewcode-block" id="CmdNoInput.__init__"><a class="viewcode-back" href="../../../api/evennia.contrib.building_menu.html#evennia.contrib.building_menu.CmdNoInput.__init__">[docs]</a> <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">menu</span> <span class="o">=</span> <span class="n">kwargs</span><span class="o">.</span><span class="n">pop</span><span class="p">(</span><span class="s2">&quot;building_menu&quot;</span><span class="p">,</span> <span class="kc">None</span><span class="p">)</span>
<span class="nb">super</span><span class="p">(</span><span class="n">Command</span><span class="p">,</span> <span class="bp">self</span><span class="p">)</span><span class="o">.</span><span class="fm">__init__</span><span class="p">(</span><span class="o">**</span><span class="n">kwargs</span><span class="p">)</span></div>
<div class="viewcode-block" id="CmdNoInput.func"><a class="viewcode-back" href="../../../api/evennia.contrib.building_menu.html#evennia.contrib.building_menu.CmdNoInput.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">&quot;&quot;&quot;Display the menu or choice text.&quot;&quot;&quot;</span>
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">menu</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">menu</span><span class="o">.</span><span class="n">display</span><span class="p">()</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">log_err</span><span class="p">(</span><span class="s2">&quot;When CMDNOINPUT was called, the building menu couldn&#39;t be found&quot;</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">msg</span><span class="p">(</span><span class="s2">&quot;|rThe building menu couldn&#39;t be found, remove the CmdSet.|n&quot;</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">delete</span><span class="p">(</span><span class="n">BuildingMenuCmdSet</span><span class="p">)</span></div></div>
<div class="viewcode-block" id="CmdNoMatch"><a class="viewcode-back" href="../../../api/evennia.contrib.building_menu.html#evennia.contrib.building_menu.CmdNoMatch">[docs]</a><span class="k">class</span> <span class="nc">CmdNoMatch</span><span class="p">(</span><span class="n">Command</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;No input has been found.&quot;&quot;&quot;</span>
<span class="n">key</span> <span class="o">=</span> <span class="n">_CMD_NOMATCH</span>
<span class="n">locks</span> <span class="o">=</span> <span class="s2">&quot;cmd:all()&quot;</span>
<div class="viewcode-block" id="CmdNoMatch.__init__"><a class="viewcode-back" href="../../../api/evennia.contrib.building_menu.html#evennia.contrib.building_menu.CmdNoMatch.__init__">[docs]</a> <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">menu</span> <span class="o">=</span> <span class="n">kwargs</span><span class="o">.</span><span class="n">pop</span><span class="p">(</span><span class="s2">&quot;building_menu&quot;</span><span class="p">,</span> <span class="kc">None</span><span class="p">)</span>
<span class="nb">super</span><span class="p">(</span><span class="n">Command</span><span class="p">,</span> <span class="bp">self</span><span class="p">)</span><span class="o">.</span><span class="fm">__init__</span><span class="p">(</span><span class="o">**</span><span class="n">kwargs</span><span class="p">)</span></div>
<div class="viewcode-block" id="CmdNoMatch.func"><a class="viewcode-back" href="../../../api/evennia.contrib.building_menu.html#evennia.contrib.building_menu.CmdNoMatch.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">&quot;&quot;&quot;Call the proper menu or redirect to nomatch.&quot;&quot;&quot;</span>
<span class="n">raw_string</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">args</span><span class="o">.</span><span class="n">rstrip</span><span class="p">()</span>
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">menu</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
<span class="n">log_err</span><span class="p">(</span><span class="s2">&quot;When CMDNOMATCH was called, the building menu couldn&#39;t be found&quot;</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">msg</span><span class="p">(</span><span class="s2">&quot;|rThe building menu couldn&#39;t be found, remove the CmdSet.|n&quot;</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">delete</span><span class="p">(</span><span class="n">BuildingMenuCmdSet</span><span class="p">)</span>
<span class="k">return</span>
<span class="n">choice</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">menu</span><span class="o">.</span><span class="n">current_choice</span>
<span class="k">if</span> <span class="n">raw_string</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">menu</span><span class="o">.</span><span class="n">keys_go_back</span><span class="p">:</span>
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">menu</span><span class="o">.</span><span class="n">keys</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">menu</span><span class="o">.</span><span class="n">move</span><span class="p">(</span><span class="n">back</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
<span class="k">elif</span> <span class="bp">self</span><span class="o">.</span><span class="n">menu</span><span class="o">.</span><span class="n">parents</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">menu</span><span class="o">.</span><span class="n">open_parent_menu</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">menu</span><span class="o">.</span><span class="n">display</span><span class="p">()</span>
<span class="k">elif</span> <span class="n">choice</span><span class="p">:</span>
<span class="k">if</span> <span class="n">choice</span><span class="o">.</span><span class="n">nomatch</span><span class="p">(</span><span class="n">raw_string</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">msg</span><span class="p">(</span><span class="n">choice</span><span class="o">.</span><span class="n">format_text</span><span class="p">())</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">for</span> <span class="n">choice</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">menu</span><span class="o">.</span><span class="n">relevant_choices</span><span class="p">:</span>
<span class="k">if</span> <span class="n">choice</span><span class="o">.</span><span class="n">key</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span> <span class="o">==</span> <span class="n">raw_string</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span> <span class="ow">or</span> <span class="nb">any</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="o">==</span> <span class="n">alias</span> <span class="k">for</span> <span class="n">alias</span> <span class="ow">in</span> <span class="n">choice</span><span class="o">.</span><span class="n">aliases</span>
<span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">menu</span><span class="o">.</span><span class="n">move</span><span class="p">(</span><span class="n">choice</span><span class="o">.</span><span class="n">key</span><span class="p">)</span>
<span class="k">return</span>
<span class="bp">self</span><span class="o">.</span><span class="n">msg</span><span class="p">(</span><span class="s2">&quot;|rUnknown command: </span><span class="si">{}</span><span class="s2">|n.&quot;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">raw_string</span><span class="p">))</span></div></div>
<div class="viewcode-block" id="BuildingMenuCmdSet"><a class="viewcode-back" href="../../../api/evennia.contrib.building_menu.html#evennia.contrib.building_menu.BuildingMenuCmdSet">[docs]</a><span class="k">class</span> <span class="nc">BuildingMenuCmdSet</span><span class="p">(</span><span class="n">CmdSet</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;Building menu CmdSet.&quot;&quot;&quot;</span>
<span class="n">key</span> <span class="o">=</span> <span class="s2">&quot;building_menu&quot;</span>
<span class="n">priority</span> <span class="o">=</span> <span class="mi">5</span>
<div class="viewcode-block" id="BuildingMenuCmdSet.at_cmdset_creation"><a class="viewcode-back" href="../../../api/evennia.contrib.building_menu.html#evennia.contrib.building_menu.BuildingMenuCmdSet.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">&quot;&quot;&quot;Populates the cmdset with commands.&quot;&quot;&quot;</span>
<span class="n">caller</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">cmdsetobj</span>
<span class="c1"># The caller could recall the menu</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">_building_menu</span>
<span class="k">if</span> <span class="n">menu</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
<span class="n">menu</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">_building_menu</span>
<span class="k">if</span> <span class="n">menu</span><span class="p">:</span>
<span class="n">menu</span> <span class="o">=</span> <span class="n">BuildingMenu</span><span class="o">.</span><span class="n">restore</span><span class="p">(</span><span class="n">caller</span><span class="p">)</span>
<span class="n">cmds</span> <span class="o">=</span> <span class="p">[</span><span class="n">CmdNoInput</span><span class="p">,</span> <span class="n">CmdNoMatch</span><span class="p">]</span>
<span class="k">for</span> <span class="n">cmd</span> <span class="ow">in</span> <span class="n">cmds</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="n">cmd</span><span class="p">(</span><span class="n">building_menu</span><span class="o">=</span><span class="n">menu</span><span class="p">))</span></div></div>
<span class="c1"># Menu classes</span>
<div class="viewcode-block" id="Choice"><a class="viewcode-back" href="../../../api/evennia.contrib.building_menu.html#evennia.contrib.building_menu.Choice">[docs]</a><span class="k">class</span> <span class="nc">Choice</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;A choice object, created by `add_choice`.&quot;&quot;&quot;</span>
<div class="viewcode-block" id="Choice.__init__"><a class="viewcode-back" href="../../../api/evennia.contrib.building_menu.html#evennia.contrib.building_menu.Choice.__init__">[docs]</a> <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span>
<span class="bp">self</span><span class="p">,</span>
<span class="n">title</span><span class="p">,</span>
<span class="n">key</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
<span class="n">aliases</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
<span class="n">attr</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
<span class="n">text</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
<span class="n">glance</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
<span class="n">on_enter</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
<span class="n">on_nomatch</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
<span class="n">on_leave</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
<span class="n">menu</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
<span class="n">caller</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
<span class="n">obj</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
<span class="p">):</span>
<span class="sd">&quot;&quot;&quot;Constructor.</span>
<span class="sd"> Args:</span>
<span class="sd"> title (str): the choice&#39;s title.</span>
<span class="sd"> key (str, optional): the key of the letters to type to access</span>
<span class="sd"> the choice. If not set, try to guess it based on the title.</span>
<span class="sd"> aliases (list of str, optional): the allowed aliases for this choice.</span>
<span class="sd"> attr (str, optional): the name of the attribute of &#39;obj&#39; to set.</span>
<span class="sd"> text (str or callable, optional): a text to be displayed for this</span>
<span class="sd"> choice. It can be a callable.</span>
<span class="sd"> glance (str or callable, optional): an at-a-glance summary of the</span>
<span class="sd"> sub-menu shown in the main menu. It can be set to</span>
<span class="sd"> display the current value of the attribute in the</span>
<span class="sd"> main menu itself.</span>
<span class="sd"> menu (BuildingMenu, optional): the parent building menu.</span>
<span class="sd"> on_enter (callable, optional): a callable to call when the</span>
<span class="sd"> caller enters into the choice.</span>
<span class="sd"> on_nomatch (callable, optional): a callable to call when no</span>
<span class="sd"> match is entered in the choice.</span>
<span class="sd"> on_leave (callable, optional): a callable to call when the caller</span>
<span class="sd"> leaves the choice.</span>
<span class="sd"> caller (Account or Object, optional): the caller.</span>
<span class="sd"> obj (Object, optional): the object to edit.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="bp">self</span><span class="o">.</span><span class="n">title</span> <span class="o">=</span> <span class="n">title</span>
<span class="bp">self</span><span class="o">.</span><span class="n">key</span> <span class="o">=</span> <span class="n">key</span>
<span class="bp">self</span><span class="o">.</span><span class="n">aliases</span> <span class="o">=</span> <span class="n">aliases</span>
<span class="bp">self</span><span class="o">.</span><span class="n">attr</span> <span class="o">=</span> <span class="n">attr</span>
<span class="bp">self</span><span class="o">.</span><span class="n">text</span> <span class="o">=</span> <span class="n">text</span>
<span class="bp">self</span><span class="o">.</span><span class="n">glance</span> <span class="o">=</span> <span class="n">glance</span>
<span class="bp">self</span><span class="o">.</span><span class="n">on_enter</span> <span class="o">=</span> <span class="n">on_enter</span>
<span class="bp">self</span><span class="o">.</span><span class="n">on_nomatch</span> <span class="o">=</span> <span class="n">on_nomatch</span>
<span class="bp">self</span><span class="o">.</span><span class="n">on_leave</span> <span class="o">=</span> <span class="n">on_leave</span>
<span class="bp">self</span><span class="o">.</span><span class="n">menu</span> <span class="o">=</span> <span class="n">menu</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="bp">self</span><span class="o">.</span><span class="n">obj</span> <span class="o">=</span> <span class="n">obj</span></div>
<span class="k">def</span> <span class="nf">__repr__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">return</span> <span class="s2">&quot;&lt;Choice (title=</span><span class="si">{}</span><span class="s2">, key=</span><span class="si">{}</span><span class="s2">)&gt;&quot;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">title</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">key</span><span class="p">)</span>
<span class="nd">@property</span>
<span class="k">def</span> <span class="nf">keys</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;Return a tuple of keys separated by `sep_keys`.&quot;&quot;&quot;</span>
<span class="k">return</span> <span class="nb">tuple</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">key</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">menu</span><span class="o">.</span><span class="n">sep_keys</span><span class="p">))</span>
<div class="viewcode-block" id="Choice.format_text"><a class="viewcode-back" href="../../../api/evennia.contrib.building_menu.html#evennia.contrib.building_menu.Choice.format_text">[docs]</a> <span class="k">def</span> <span class="nf">format_text</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;Format the choice text and return it, or an empty string.&quot;&quot;&quot;</span>
<span class="n">text</span> <span class="o">=</span> <span class="s2">&quot;&quot;</span>
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">text</span><span class="p">:</span>
<span class="n">text</span> <span class="o">=</span> <span class="n">_call_or_get</span><span class="p">(</span>
<span class="bp">self</span><span class="o">.</span><span class="n">text</span><span class="p">,</span> <span class="n">menu</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">menu</span><span class="p">,</span> <span class="n">choice</span><span class="o">=</span><span class="bp">self</span><span class="p">,</span> <span class="n">string</span><span class="o">=</span><span class="s2">&quot;&quot;</span><span class="p">,</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="p">,</span> <span class="n">obj</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">obj</span>
<span class="p">)</span>
<span class="n">text</span> <span class="o">=</span> <span class="n">dedent</span><span class="p">(</span><span class="n">text</span><span class="o">.</span><span class="n">strip</span><span class="p">(</span><span class="s2">&quot;</span><span class="se">\n</span><span class="s2">&quot;</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="n">format</span><span class="p">(</span><span class="n">obj</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">obj</span><span class="p">,</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="p">)</span>
<span class="k">return</span> <span class="n">text</span></div>
<div class="viewcode-block" id="Choice.enter"><a class="viewcode-back" href="../../../api/evennia.contrib.building_menu.html#evennia.contrib.building_menu.Choice.enter">[docs]</a> <span class="k">def</span> <span class="nf">enter</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">string</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;Called when the user opens the choice.</span>
<span class="sd"> Args:</span>
<span class="sd"> string (str): the entered string.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">on_enter</span><span class="p">:</span>
<span class="n">_call_or_get</span><span class="p">(</span>
<span class="bp">self</span><span class="o">.</span><span class="n">on_enter</span><span class="p">,</span>
<span class="n">menu</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">menu</span><span class="p">,</span>
<span class="n">choice</span><span class="o">=</span><span class="bp">self</span><span class="p">,</span>
<span class="n">string</span><span class="o">=</span><span class="n">string</span><span class="p">,</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="p">,</span>
<span class="n">obj</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">obj</span><span class="p">,</span>
<span class="p">)</span></div>
<div class="viewcode-block" id="Choice.nomatch"><a class="viewcode-back" href="../../../api/evennia.contrib.building_menu.html#evennia.contrib.building_menu.Choice.nomatch">[docs]</a> <span class="k">def</span> <span class="nf">nomatch</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">string</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;Called when the user entered something in the choice.</span>
<span class="sd"> Args:</span>
<span class="sd"> string (str): the entered string.</span>
<span class="sd"> Returns:</span>
<span class="sd"> to_display (bool): The return value of `nomatch` if set or</span>
<span class="sd"> `True`. The rule is that if `no_match` returns `True`,</span>
<span class="sd"> then the choice or menu is displayed.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">on_nomatch</span><span class="p">:</span>
<span class="k">return</span> <span class="n">_call_or_get</span><span class="p">(</span>
<span class="bp">self</span><span class="o">.</span><span class="n">on_nomatch</span><span class="p">,</span>
<span class="n">menu</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">menu</span><span class="p">,</span>
<span class="n">choice</span><span class="o">=</span><span class="bp">self</span><span class="p">,</span>
<span class="n">string</span><span class="o">=</span><span class="n">string</span><span class="p">,</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="p">,</span>
<span class="n">obj</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">obj</span><span class="p">,</span>
<span class="p">)</span>
<span class="k">return</span> <span class="kc">True</span></div>
<div class="viewcode-block" id="Choice.leave"><a class="viewcode-back" href="../../../api/evennia.contrib.building_menu.html#evennia.contrib.building_menu.Choice.leave">[docs]</a> <span class="k">def</span> <span class="nf">leave</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">string</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;Called when the user closes the choice.</span>
<span class="sd"> Args:</span>
<span class="sd"> string (str): the entered string.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">on_leave</span><span class="p">:</span>
<span class="n">_call_or_get</span><span class="p">(</span>
<span class="bp">self</span><span class="o">.</span><span class="n">on_leave</span><span class="p">,</span>
<span class="n">menu</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">menu</span><span class="p">,</span>
<span class="n">choice</span><span class="o">=</span><span class="bp">self</span><span class="p">,</span>
<span class="n">string</span><span class="o">=</span><span class="n">string</span><span class="p">,</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="p">,</span>
<span class="n">obj</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">obj</span><span class="p">,</span>
<span class="p">)</span></div></div>
<div class="viewcode-block" id="BuildingMenu"><a class="viewcode-back" href="../../../api/evennia.contrib.building_menu.html#evennia.contrib.building_menu.BuildingMenu">[docs]</a><span class="k">class</span> <span class="nc">BuildingMenu</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Class allowing to create and set building menus to edit specific objects.</span>
<span class="sd"> A building menu is somewhat similar to `EvMenu`, but designed to edit</span>
<span class="sd"> objects by builders, although it can be used for players in some contexts.</span>
<span class="sd"> You could, for instance, create a building menu to edit a room with a</span>
<span class="sd"> sub-menu for the room&#39;s key, another for the room&#39;s description,</span>
<span class="sd"> another for the room&#39;s exits, and so on.</span>
<span class="sd"> To add choices (simple sub-menus), you should call `add_choice` (see the</span>
<span class="sd"> full documentation of this method). With most arguments, you can</span>
<span class="sd"> specify either a plain string or a callback. This callback will be</span>
<span class="sd"> called when the operation is to be performed.</span>
<span class="sd"> Some methods are provided for frequent needs (see the `add_choice_*`</span>
<span class="sd"> methods). Some helper functions are defined at the top of this</span>
<span class="sd"> module in order to be used as arguments to `add_choice`</span>
<span class="sd"> in frequent cases.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="n">keys_go_back</span> <span class="o">=</span> <span class="p">[</span><span class="s2">&quot;@&quot;</span><span class="p">]</span> <span class="c1"># The keys allowing to go back in the menu tree</span>
<span class="n">sep_keys</span> <span class="o">=</span> <span class="s2">&quot;.&quot;</span> <span class="c1"># The key separator for menus with more than 2 levels</span>
<span class="n">joker_key</span> <span class="o">=</span> <span class="s2">&quot;*&quot;</span> <span class="c1"># The special key meaning &quot;anything&quot; in a choice key</span>
<span class="n">min_shortcut</span> <span class="o">=</span> <span class="mi">1</span> <span class="c1"># The minimum length of shorcuts when `key` is not set</span>
<div class="viewcode-block" id="BuildingMenu.__init__"><a class="viewcode-back" href="../../../api/evennia.contrib.building_menu.html#evennia.contrib.building_menu.BuildingMenu.__init__">[docs]</a> <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span>
<span class="bp">self</span><span class="p">,</span>
<span class="n">caller</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
<span class="n">obj</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
<span class="n">title</span><span class="o">=</span><span class="s2">&quot;Building menu: </span><span class="si">{obj}</span><span class="s2">&quot;</span><span class="p">,</span>
<span class="n">keys</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
<span class="n">parents</span><span class="o">=</span><span class="kc">None</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="p">):</span>
<span class="sd">&quot;&quot;&quot;Constructor, you shouldn&#39;t override. See `init` instead.</span>
<span class="sd"> Args:</span>
<span class="sd"> caller (Account or Object): the caller.</span>
<span class="sd"> obj (Object): the object to be edited, like a room.</span>
<span class="sd"> title (str, optional): the menu title.</span>
<span class="sd"> keys (list of str, optional): the starting menu keys (None</span>
<span class="sd"> to start from the first level).</span>
<span class="sd"> parents (tuple, optional): information for parent menus,</span>
<span class="sd"> automatically supplied.</span>
<span class="sd"> persistent (bool, optional): should this building menu</span>
<span class="sd"> survive a reload/restart?</span>
<span class="sd"> Note:</span>
<span class="sd"> If some of these options have to be changed, it is</span>
<span class="sd"> preferable to do so in the `init` method and not to</span>
<span class="sd"> override `__init__`. For instance:</span>
<span class="sd"> class RoomBuildingMenu(BuildingMenu):</span>
<span class="sd"> def init(self, room):</span>
<span class="sd"> self.title = &quot;Menu for room: {obj.key}(#{obj.id})&quot;</span>
<span class="sd"> # ...</span>
<span class="sd"> &quot;&quot;&quot;</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="bp">self</span><span class="o">.</span><span class="n">obj</span> <span class="o">=</span> <span class="n">obj</span>
<span class="bp">self</span><span class="o">.</span><span class="n">title</span> <span class="o">=</span> <span class="n">title</span>
<span class="bp">self</span><span class="o">.</span><span class="n">keys</span> <span class="o">=</span> <span class="n">keys</span> <span class="ow">or</span> <span class="p">[]</span>
<span class="bp">self</span><span class="o">.</span><span class="n">parents</span> <span class="o">=</span> <span class="n">parents</span> <span class="ow">or</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="bp">self</span><span class="o">.</span><span class="n">choices</span> <span class="o">=</span> <span class="p">[]</span>
<span class="bp">self</span><span class="o">.</span><span class="n">cmds</span> <span class="o">=</span> <span class="p">{}</span>
<span class="bp">self</span><span class="o">.</span><span class="n">can_quit</span> <span class="o">=</span> <span class="kc">False</span>
<span class="k">if</span> <span class="n">obj</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">init</span><span class="p">(</span><span class="n">obj</span><span class="p">)</span>
<span class="k">if</span> <span class="ow">not</span> <span class="n">parents</span> <span class="ow">and</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">can_quit</span><span class="p">:</span>
<span class="c1"># Automatically add the menu to quit</span>
<span class="bp">self</span><span class="o">.</span><span class="n">add_choice_quit</span><span class="p">(</span><span class="n">key</span><span class="o">=</span><span class="kc">None</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">_add_keys_choice</span><span class="p">()</span></div>
<span class="nd">@property</span>
<span class="k">def</span> <span class="nf">current_choice</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;Return the current choice or None.</span>
<span class="sd"> Returns:</span>
<span class="sd"> choice (Choice): the current choice or None.</span>
<span class="sd"> Note:</span>
<span class="sd"> We use the menu keys to identify the current position of</span>
<span class="sd"> the caller in the menu. The menu `keys` hold a list of</span>
<span class="sd"> keys that should match a choice to be usable.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="n">menu_keys</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">keys</span>
<span class="k">if</span> <span class="ow">not</span> <span class="n">menu_keys</span><span class="p">:</span>
<span class="k">return</span> <span class="kc">None</span>
<span class="k">for</span> <span class="n">choice</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">choices</span><span class="p">:</span>
<span class="n">choice_keys</span> <span class="o">=</span> <span class="n">choice</span><span class="o">.</span><span class="n">keys</span>
<span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">menu_keys</span><span class="p">)</span> <span class="o">==</span> <span class="nb">len</span><span class="p">(</span><span class="n">choice_keys</span><span class="p">):</span>
<span class="c1"># Check all the intermediate keys</span>
<span class="n">common</span> <span class="o">=</span> <span class="kc">True</span>
<span class="k">for</span> <span class="n">menu_key</span><span class="p">,</span> <span class="n">choice_key</span> <span class="ow">in</span> <span class="nb">zip</span><span class="p">(</span><span class="n">menu_keys</span><span class="p">,</span> <span class="n">choice_keys</span><span class="p">):</span>
<span class="k">if</span> <span class="n">choice_key</span> <span class="o">==</span> <span class="bp">self</span><span class="o">.</span><span class="n">joker_key</span><span class="p">:</span>
<span class="k">continue</span>
<span class="k">if</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">menu_key</span><span class="p">,</span> <span class="nb">str</span><span class="p">)</span> <span class="ow">or</span> <span class="n">menu_key</span> <span class="o">!=</span> <span class="n">choice_key</span><span class="p">:</span>
<span class="n">common</span> <span class="o">=</span> <span class="kc">False</span>
<span class="k">break</span>
<span class="k">if</span> <span class="n">common</span><span class="p">:</span>
<span class="k">return</span> <span class="n">choice</span>
<span class="k">return</span> <span class="kc">None</span>
<span class="nd">@property</span>
<span class="k">def</span> <span class="nf">relevant_choices</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;Only return the relevant choices according to the current meny key.</span>
<span class="sd"> Returns:</span>
<span class="sd"> relevant (list of Choice object): the relevant choices.</span>
<span class="sd"> Note:</span>
<span class="sd"> We use the menu keys to identify the current position of</span>
<span class="sd"> the caller in the menu. The menu `keys` hold a list of</span>
<span class="sd"> keys that should match a choice to be usable.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="n">menu_keys</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">keys</span>
<span class="n">relevant</span> <span class="o">=</span> <span class="p">[]</span>
<span class="k">for</span> <span class="n">choice</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">choices</span><span class="p">:</span>
<span class="n">choice_keys</span> <span class="o">=</span> <span class="n">choice</span><span class="o">.</span><span class="n">keys</span>
<span class="k">if</span> <span class="ow">not</span> <span class="n">menu_keys</span> <span class="ow">and</span> <span class="nb">len</span><span class="p">(</span><span class="n">choice_keys</span><span class="p">)</span> <span class="o">==</span> <span class="mi">1</span><span class="p">:</span>
<span class="c1"># First level choice with the menu key empty, that&#39;s relevant</span>
<span class="n">relevant</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">choice</span><span class="p">)</span>
<span class="k">elif</span> <span class="nb">len</span><span class="p">(</span><span class="n">menu_keys</span><span class="p">)</span> <span class="o">==</span> <span class="nb">len</span><span class="p">(</span><span class="n">choice_keys</span><span class="p">)</span> <span class="o">-</span> <span class="mi">1</span><span class="p">:</span>
<span class="c1"># Check all the intermediate keys</span>
<span class="n">common</span> <span class="o">=</span> <span class="kc">True</span>
<span class="k">for</span> <span class="n">menu_key</span><span class="p">,</span> <span class="n">choice_key</span> <span class="ow">in</span> <span class="nb">zip</span><span class="p">(</span><span class="n">menu_keys</span><span class="p">,</span> <span class="n">choice_keys</span><span class="p">):</span>
<span class="k">if</span> <span class="n">choice_key</span> <span class="o">==</span> <span class="bp">self</span><span class="o">.</span><span class="n">joker_key</span><span class="p">:</span>
<span class="k">continue</span>
<span class="k">if</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">menu_key</span><span class="p">,</span> <span class="nb">str</span><span class="p">)</span> <span class="ow">or</span> <span class="n">menu_key</span> <span class="o">!=</span> <span class="n">choice_key</span><span class="p">:</span>
<span class="n">common</span> <span class="o">=</span> <span class="kc">False</span>
<span class="k">break</span>
<span class="k">if</span> <span class="n">common</span><span class="p">:</span>
<span class="n">relevant</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">choice</span><span class="p">)</span>
<span class="k">return</span> <span class="n">relevant</span>
<span class="k">def</span> <span class="nf">_save</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;Save the menu in a attributes on the caller.</span>
<span class="sd"> If `persistent` is set to `True`, also save in a persistent attribute.</span>
<span class="sd"> &quot;&quot;&quot;</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">_building_menu</span> <span class="o">=</span> <span class="bp">self</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">db</span><span class="o">.</span><span class="n">_building_menu</span> <span class="o">=</span> <span class="p">{</span>
<span class="s2">&quot;class&quot;</span><span class="p">:</span> <span class="nb">type</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span><span class="o">.</span><span class="vm">__module__</span> <span class="o">+</span> <span class="s2">&quot;.&quot;</span> <span class="o">+</span> <span class="nb">type</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span><span class="o">.</span><span class="vm">__name__</span><span class="p">,</span>
<span class="s2">&quot;obj&quot;</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">obj</span><span class="p">,</span>
<span class="s2">&quot;title&quot;</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">title</span><span class="p">,</span>
<span class="s2">&quot;keys&quot;</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">keys</span><span class="p">,</span>
<span class="s2">&quot;parents&quot;</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">parents</span><span class="p">,</span>
<span class="s2">&quot;persistent&quot;</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">persistent</span><span class="p">,</span>
<span class="p">}</span>
<span class="k">def</span> <span class="nf">_add_keys_choice</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;Add the choices&#39; keys if some choices don&#39;t have valid keys.&quot;&quot;&quot;</span>
<span class="c1"># If choices have been added without keys, try to guess them</span>
<span class="k">for</span> <span class="n">choice</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">choices</span><span class="p">:</span>
<span class="k">if</span> <span class="ow">not</span> <span class="n">choice</span><span class="o">.</span><span class="n">key</span><span class="p">:</span>
<span class="n">title</span> <span class="o">=</span> <span class="n">strip_ansi</span><span class="p">(</span><span class="n">choice</span><span class="o">.</span><span class="n">title</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="n">length</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">min_shortcut</span>
<span class="k">while</span> <span class="n">length</span> <span class="o">&lt;=</span> <span class="nb">len</span><span class="p">(</span><span class="n">title</span><span class="p">):</span>
<span class="n">i</span> <span class="o">=</span> <span class="mi">0</span>
<span class="k">while</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="nb">len</span><span class="p">(</span><span class="n">title</span><span class="p">)</span> <span class="o">-</span> <span class="n">length</span> <span class="o">+</span> <span class="mi">1</span><span class="p">:</span>
<span class="n">guess</span> <span class="o">=</span> <span class="n">title</span><span class="p">[</span><span class="n">i</span> <span class="p">:</span> <span class="n">i</span> <span class="o">+</span> <span class="n">length</span><span class="p">]</span>
<span class="k">if</span> <span class="n">guess</span> <span class="ow">not</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">cmds</span><span class="p">:</span>
<span class="n">choice</span><span class="o">.</span><span class="n">key</span> <span class="o">=</span> <span class="n">guess</span>
<span class="k">break</span>
<span class="n">i</span> <span class="o">+=</span> <span class="mi">1</span>
<span class="k">if</span> <span class="n">choice</span><span class="o">.</span><span class="n">key</span><span class="p">:</span>
<span class="k">break</span>
<span class="n">length</span> <span class="o">+=</span> <span class="mi">1</span>
<span class="k">if</span> <span class="n">choice</span><span class="o">.</span><span class="n">key</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">cmds</span><span class="p">[</span><span class="n">choice</span><span class="o">.</span><span class="n">key</span><span class="p">]</span> <span class="o">=</span> <span class="n">choice</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s2">&quot;Cannot guess the key for </span><span class="si">{}</span><span class="s2">&quot;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">choice</span><span class="p">))</span>
<div class="viewcode-block" id="BuildingMenu.init"><a class="viewcode-back" href="../../../api/evennia.contrib.building_menu.html#evennia.contrib.building_menu.BuildingMenu.init">[docs]</a> <span class="k">def</span> <span class="nf">init</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">obj</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;Create the sub-menu to edit the specified object.</span>
<span class="sd"> Args:</span>
<span class="sd"> obj (Object): the object to edit.</span>
<span class="sd"> Note:</span>
<span class="sd"> This method is probably to be overridden in your subclasses.</span>
<span class="sd"> Use `add_choice` and its variants to create menu choices.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="k">pass</span></div>
<div class="viewcode-block" id="BuildingMenu.add_choice"><a class="viewcode-back" href="../../../api/evennia.contrib.building_menu.html#evennia.contrib.building_menu.BuildingMenu.add_choice">[docs]</a> <span class="k">def</span> <span class="nf">add_choice</span><span class="p">(</span>
<span class="bp">self</span><span class="p">,</span>
<span class="n">title</span><span class="p">,</span>
<span class="n">key</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
<span class="n">aliases</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
<span class="n">attr</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
<span class="n">text</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
<span class="n">glance</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
<span class="n">on_enter</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
<span class="n">on_nomatch</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
<span class="n">on_leave</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
<span class="p">):</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Add a choice, a valid sub-menu, in the current builder menu.</span>
<span class="sd"> Args:</span>
<span class="sd"> title (str): the choice&#39;s title.</span>
<span class="sd"> key (str, optional): the key of the letters to type to access</span>
<span class="sd"> the sub-neu. If not set, try to guess it based on the</span>
<span class="sd"> choice title.</span>
<span class="sd"> aliases (list of str, optional): the aliases for this choice.</span>
<span class="sd"> attr (str, optional): the name of the attribute of &#39;obj&#39; to set.</span>
<span class="sd"> This is really useful if you want to edit an</span>
<span class="sd"> attribute of the object (that&#39;s a frequent need). If</span>
<span class="sd"> you don&#39;t want to do so, just use the `on_*` arguments.</span>
<span class="sd"> text (str or callable, optional): a text to be displayed when</span>
<span class="sd"> the menu is opened It can be a callable.</span>
<span class="sd"> glance (str or callable, optional): an at-a-glance summary of the</span>
<span class="sd"> sub-menu shown in the main menu. It can be set to</span>
<span class="sd"> display the current value of the attribute in the</span>
<span class="sd"> main menu itself.</span>
<span class="sd"> on_enter (callable, optional): a callable to call when the</span>
<span class="sd"> caller enters into this choice.</span>
<span class="sd"> on_nomatch (callable, optional): a callable to call when</span>
<span class="sd"> the caller enters something in this choice. If you</span>
<span class="sd"> don&#39;t set this argument but you have specified</span>
<span class="sd"> `attr`, then `obj`.`attr` will be set with the value</span>
<span class="sd"> entered by the user.</span>
<span class="sd"> on_leave (callable, optional): a callable to call when the</span>
<span class="sd"> caller leaves the choice.</span>
<span class="sd"> Returns:</span>
<span class="sd"> choice (Choice): the newly-created choice.</span>
<span class="sd"> Raises:</span>
<span class="sd"> ValueError if the choice cannot be added.</span>
<span class="sd"> Note:</span>
<span class="sd"> Most arguments can be callables, like functions. This has the</span>
<span class="sd"> advantage of allowing great flexibility. If you specify</span>
<span class="sd"> a callable in most of the arguments, the callable should return</span>
<span class="sd"> the value expected by the argument (a str more often than</span>
<span class="sd"> not). For instance, you could set a function to be called</span>
<span class="sd"> to get the menu text, which allows for some filtering:</span>
<span class="sd"> def text_exits(menu):</span>
<span class="sd"> return &quot;Some text to display&quot;</span>
<span class="sd"> class RoomBuildingMenu(BuildingMenu):</span>
<span class="sd"> def init(self):</span>
<span class="sd"> self.add_choice(&quot;exits&quot;, key=&quot;x&quot;, text=text_exits)</span>
<span class="sd"> The allowed arguments in a callable are specific to the</span>
<span class="sd"> argument names (they are not sensitive to orders, not all</span>
<span class="sd"> arguments have to be present). For more information, see</span>
<span class="sd"> `_call_or_get`.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="n">key</span> <span class="o">=</span> <span class="n">key</span> <span class="ow">or</span> <span class="s2">&quot;&quot;</span>
<span class="n">key</span> <span class="o">=</span> <span class="n">key</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span>
<span class="n">aliases</span> <span class="o">=</span> <span class="n">aliases</span> <span class="ow">or</span> <span class="p">[]</span>
<span class="n">aliases</span> <span class="o">=</span> <span class="p">[</span><span class="n">a</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span> <span class="k">for</span> <span class="n">a</span> <span class="ow">in</span> <span class="n">aliases</span><span class="p">]</span>
<span class="k">if</span> <span class="n">attr</span> <span class="ow">and</span> <span class="n">on_nomatch</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
<span class="n">on_nomatch</span> <span class="o">=</span> <span class="n">menu_setattr</span>
<span class="k">if</span> <span class="n">key</span> <span class="ow">and</span> <span class="n">key</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">cmds</span><span class="p">:</span>
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span>
<span class="s2">&quot;A conflict exists between </span><span class="si">{}</span><span class="s2"> and </span><span class="si">{}</span><span class="s2">, both use &quot;</span>
<span class="s2">&quot;key or alias </span><span class="si">{}</span><span class="s2">&quot;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">cmds</span><span class="p">[</span><span class="n">key</span><span class="p">],</span> <span class="n">title</span><span class="p">,</span> <span class="nb">repr</span><span class="p">(</span><span class="n">key</span><span class="p">))</span>
<span class="p">)</span>
<span class="k">if</span> <span class="n">attr</span><span class="p">:</span>
<span class="k">if</span> <span class="n">glance</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
<span class="n">glance</span> <span class="o">=</span> <span class="s2">&quot;{obj.&quot;</span> <span class="o">+</span> <span class="n">attr</span> <span class="o">+</span> <span class="s2">&quot;}&quot;</span>
<span class="k">if</span> <span class="n">text</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
<span class="n">text</span> <span class="o">=</span> <span class="s2">&quot;&quot;&quot;</span>
<span class="s2"> -------------------------------------------------------------------------------</span>
<span class="s2"> </span><span class="si">{attr}</span><span class="s2"> for {{obj}}(#{{obj.id}})</span>
<span class="s2"> You can change this value simply by entering it.</span>
<span class="s2"> Use |y</span><span class="si">{back}</span><span class="s2">|n to go back to the main menu.</span>
<span class="s2"> Current value: |c{{</span><span class="si">{obj_attr}</span><span class="s2">}}|n</span>
<span class="s2"> &quot;&quot;&quot;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span>
<span class="n">attr</span><span class="o">=</span><span class="n">attr</span><span class="p">,</span> <span class="n">obj_attr</span><span class="o">=</span><span class="s2">&quot;obj.&quot;</span> <span class="o">+</span> <span class="n">attr</span><span class="p">,</span> <span class="n">back</span><span class="o">=</span><span class="s2">&quot;|n or |y&quot;</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">keys_go_back</span><span class="p">)</span>
<span class="p">)</span>
<span class="n">choice</span> <span class="o">=</span> <span class="n">Choice</span><span class="p">(</span>
<span class="n">title</span><span class="p">,</span>
<span class="n">key</span><span class="o">=</span><span class="n">key</span><span class="p">,</span>
<span class="n">aliases</span><span class="o">=</span><span class="n">aliases</span><span class="p">,</span>
<span class="n">attr</span><span class="o">=</span><span class="n">attr</span><span class="p">,</span>
<span class="n">text</span><span class="o">=</span><span class="n">text</span><span class="p">,</span>
<span class="n">glance</span><span class="o">=</span><span class="n">glance</span><span class="p">,</span>
<span class="n">on_enter</span><span class="o">=</span><span class="n">on_enter</span><span class="p">,</span>
<span class="n">on_nomatch</span><span class="o">=</span><span class="n">on_nomatch</span><span class="p">,</span>
<span class="n">on_leave</span><span class="o">=</span><span class="n">on_leave</span><span class="p">,</span>
<span class="n">menu</span><span class="o">=</span><span class="bp">self</span><span class="p">,</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="p">,</span>
<span class="n">obj</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">obj</span><span class="p">,</span>
<span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">choices</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">choice</span><span class="p">)</span>
<span class="k">if</span> <span class="n">key</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">cmds</span><span class="p">[</span><span class="n">key</span><span class="p">]</span> <span class="o">=</span> <span class="n">choice</span>
<span class="k">for</span> <span class="n">alias</span> <span class="ow">in</span> <span class="n">aliases</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">cmds</span><span class="p">[</span><span class="n">alias</span><span class="p">]</span> <span class="o">=</span> <span class="n">choice</span>
<span class="k">return</span> <span class="n">choice</span></div>
<div class="viewcode-block" id="BuildingMenu.add_choice_edit"><a class="viewcode-back" href="../../../api/evennia.contrib.building_menu.html#evennia.contrib.building_menu.BuildingMenu.add_choice_edit">[docs]</a> <span class="k">def</span> <span class="nf">add_choice_edit</span><span class="p">(</span>
<span class="bp">self</span><span class="p">,</span>
<span class="n">title</span><span class="o">=</span><span class="s2">&quot;description&quot;</span><span class="p">,</span>
<span class="n">key</span><span class="o">=</span><span class="s2">&quot;d&quot;</span><span class="p">,</span>
<span class="n">aliases</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
<span class="n">attr</span><span class="o">=</span><span class="s2">&quot;db.desc&quot;</span><span class="p">,</span>
<span class="n">glance</span><span class="o">=</span><span class="s2">&quot;</span><span class="se">\n</span><span class="s2"> </span><span class="si">{obj.db.desc}</span><span class="s2">&quot;</span><span class="p">,</span>
<span class="n">on_enter</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
<span class="p">):</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Add a simple choice to edit a given attribute in the EvEditor.</span>
<span class="sd"> Args:</span>
<span class="sd"> title (str, optional): the choice&#39;s title.</span>
<span class="sd"> key (str, optional): the choice&#39;s key.</span>
<span class="sd"> aliases (list of str, optional): the choice&#39;s aliases.</span>
<span class="sd"> glance (str or callable, optional): the at-a-glance description.</span>
<span class="sd"> on_enter (callable, optional): a different callable to edit</span>
<span class="sd"> the attribute.</span>
<span class="sd"> Returns:</span>
<span class="sd"> choice (Choice): the newly-created choice.</span>
<span class="sd"> Note:</span>
<span class="sd"> This is just a shortcut method, calling `add_choice`.</span>
<span class="sd"> If `on_enter` is not set, use `menu_edit` which opens</span>
<span class="sd"> an EvEditor to edit the specified attribute.</span>
<span class="sd"> When the caller closes the editor (with :q), the menu</span>
<span class="sd"> will be re-opened.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="n">on_enter</span> <span class="o">=</span> <span class="n">on_enter</span> <span class="ow">or</span> <span class="n">menu_edit</span>
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">add_choice</span><span class="p">(</span>
<span class="n">title</span><span class="p">,</span> <span class="n">key</span><span class="o">=</span><span class="n">key</span><span class="p">,</span> <span class="n">aliases</span><span class="o">=</span><span class="n">aliases</span><span class="p">,</span> <span class="n">attr</span><span class="o">=</span><span class="n">attr</span><span class="p">,</span> <span class="n">glance</span><span class="o">=</span><span class="n">glance</span><span class="p">,</span> <span class="n">on_enter</span><span class="o">=</span><span class="n">on_enter</span><span class="p">,</span> <span class="n">text</span><span class="o">=</span><span class="s2">&quot;&quot;</span>
<span class="p">)</span></div>
<div class="viewcode-block" id="BuildingMenu.add_choice_quit"><a class="viewcode-back" href="../../../api/evennia.contrib.building_menu.html#evennia.contrib.building_menu.BuildingMenu.add_choice_quit">[docs]</a> <span class="k">def</span> <span class="nf">add_choice_quit</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">title</span><span class="o">=</span><span class="s2">&quot;quit the menu&quot;</span><span class="p">,</span> <span class="n">key</span><span class="o">=</span><span class="s2">&quot;q&quot;</span><span class="p">,</span> <span class="n">aliases</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">on_enter</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Add a simple choice just to quit the building menu.</span>
<span class="sd"> Args:</span>
<span class="sd"> title (str, optional): the choice&#39;s title.</span>
<span class="sd"> key (str, optional): the choice&#39;s key.</span>
<span class="sd"> aliases (list of str, optional): the choice&#39;s aliases.</span>
<span class="sd"> on_enter (callable, optional): a different callable</span>
<span class="sd"> to quit the building menu.</span>
<span class="sd"> Note:</span>
<span class="sd"> This is just a shortcut method, calling `add_choice`.</span>
<span class="sd"> If `on_enter` is not set, use `menu_quit` which simply</span>
<span class="sd"> closes the menu and displays a message. It also</span>
<span class="sd"> removes the CmdSet from the caller. If you supply</span>
<span class="sd"> another callable instead, make sure to do the same.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="n">on_enter</span> <span class="o">=</span> <span class="n">on_enter</span> <span class="ow">or</span> <span class="n">menu_quit</span>
<span class="bp">self</span><span class="o">.</span><span class="n">can_quit</span> <span class="o">=</span> <span class="kc">True</span>
<span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">add_choice</span><span class="p">(</span><span class="n">title</span><span class="p">,</span> <span class="n">key</span><span class="o">=</span><span class="n">key</span><span class="p">,</span> <span class="n">aliases</span><span class="o">=</span><span class="n">aliases</span><span class="p">,</span> <span class="n">on_enter</span><span class="o">=</span><span class="n">on_enter</span><span class="p">)</span></div>
<div class="viewcode-block" id="BuildingMenu.open"><a class="viewcode-back" href="../../../api/evennia.contrib.building_menu.html#evennia.contrib.building_menu.BuildingMenu.open">[docs]</a> <span class="k">def</span> <span class="nf">open</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;Open the building menu for the caller.</span>
<span class="sd"> Note:</span>
<span class="sd"> This method should be called once when the building menu</span>
<span class="sd"> has been instanciated. From there, the building menu will</span>
<span class="sd"> be re-created automatically when the server</span>
<span class="sd"> reloads/restarts, assuming `persistent` is set to `True`.</span>
<span class="sd"> &quot;&quot;&quot;</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="bp">self</span><span class="o">.</span><span class="n">_save</span><span class="p">()</span>
<span class="c1"># Remove the same-key cmdset if exists</span>
<span class="k">if</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">BuildingMenuCmdSet</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">BuildingMenuCmdSet</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">BuildingMenuCmdSet</span><span class="p">,</span> <span class="n">permanent</span><span class="o">=</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">display</span><span class="p">()</span></div>
<div class="viewcode-block" id="BuildingMenu.open_parent_menu"><a class="viewcode-back" href="../../../api/evennia.contrib.building_menu.html#evennia.contrib.building_menu.BuildingMenu.open_parent_menu">[docs]</a> <span class="k">def</span> <span class="nf">open_parent_menu</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;Open the parent menu, using `self.parents`.</span>
<span class="sd"> Note:</span>
<span class="sd"> You probably don&#39;t need to call this method directly,</span>
<span class="sd"> since the caller can go back to the parent menu using the</span>
<span class="sd"> `keys_go_back` automatically.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="n">parents</span> <span class="o">=</span> <span class="nb">list</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">parents</span><span class="p">)</span>
<span class="k">if</span> <span class="n">parents</span><span class="p">:</span>
<span class="n">parent_class</span><span class="p">,</span> <span class="n">parent_obj</span><span class="p">,</span> <span class="n">parent_keys</span> <span class="o">=</span> <span class="n">parents</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span>
<span class="k">del</span> <span class="n">parents</span><span class="p">[</span><span class="o">-</span><span class="mi">1</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">cmdset</span><span class="o">.</span><span class="n">has</span><span class="p">(</span><span class="n">BuildingMenuCmdSet</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">remove</span><span class="p">(</span><span class="n">BuildingMenuCmdSet</span><span class="p">)</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">menu_class</span> <span class="o">=</span> <span class="n">class_from_module</span><span class="p">(</span><span class="n">parent_class</span><span class="p">)</span>
<span class="k">except</span> <span class="ne">Exception</span><span class="p">:</span>
<span class="n">log_trace</span><span class="p">(</span>
<span class="s2">&quot;BuildingMenu: attempting to load class </span><span class="si">{}</span><span class="s2"> failed&quot;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="nb">repr</span><span class="p">(</span><span class="n">parent_class</span><span class="p">))</span>
<span class="p">)</span>
<span class="k">return</span>
<span class="c1"># Create the parent menu</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">building_menu</span> <span class="o">=</span> <span class="n">menu_class</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">parent_obj</span><span class="p">,</span> <span class="n">keys</span><span class="o">=</span><span class="n">parent_keys</span><span class="p">,</span> <span class="n">parents</span><span class="o">=</span><span class="nb">tuple</span><span class="p">(</span><span class="n">parents</span><span class="p">)</span>
<span class="p">)</span>
<span class="k">except</span> <span class="ne">Exception</span><span class="p">:</span>
<span class="n">log_trace</span><span class="p">(</span>
<span class="s2">&quot;An error occurred while creating building menu </span><span class="si">{}</span><span class="s2">&quot;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="nb">repr</span><span class="p">(</span><span class="n">parent_class</span><span class="p">))</span>
<span class="p">)</span>
<span class="k">return</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">return</span> <span class="n">building_menu</span><span class="o">.</span><span class="n">open</span><span class="p">()</span></div>
<div class="viewcode-block" id="BuildingMenu.open_submenu"><a class="viewcode-back" href="../../../api/evennia.contrib.building_menu.html#evennia.contrib.building_menu.BuildingMenu.open_submenu">[docs]</a> <span class="k">def</span> <span class="nf">open_submenu</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">submenu_class</span><span class="p">,</span> <span class="n">submenu_obj</span><span class="p">,</span> <span class="n">parent_keys</span><span class="o">=</span><span class="kc">None</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Open a sub-menu, closing the current menu and opening the new one.</span>
<span class="sd"> Args:</span>
<span class="sd"> submenu_class (str): the submenu class as a Python path.</span>
<span class="sd"> submenu_obj (Object): the object to give to the submenu.</span>
<span class="sd"> parent_keys (list of str, optional): the parent keys when</span>
<span class="sd"> the submenu is closed.</span>
<span class="sd"> Note:</span>
<span class="sd"> When the user enters `@` in the submenu, she will go back to</span>
<span class="sd"> the current menu, with the `parent_keys` set as its keys.</span>
<span class="sd"> Therefore, you should set it on the keys of the choice that</span>
<span class="sd"> should be opened when the user leaves the submenu.</span>
<span class="sd"> Returns:</span>
<span class="sd"> new_menu (BuildingMenu): the new building menu or None.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="n">parent_keys</span> <span class="o">=</span> <span class="n">parent_keys</span> <span class="ow">or</span> <span class="p">[]</span>
<span class="n">parents</span> <span class="o">=</span> <span class="nb">list</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">parents</span><span class="p">)</span>
<span class="n">parents</span><span class="o">.</span><span class="n">append</span><span class="p">((</span><span class="nb">type</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span><span class="o">.</span><span class="vm">__module__</span> <span class="o">+</span> <span class="s2">&quot;.&quot;</span> <span class="o">+</span> <span class="nb">type</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span><span class="o">.</span><span class="vm">__name__</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">obj</span><span class="p">,</span> <span class="n">parent_keys</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">cmdset</span><span class="o">.</span><span class="n">has</span><span class="p">(</span><span class="n">BuildingMenuCmdSet</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">remove</span><span class="p">(</span><span class="n">BuildingMenuCmdSet</span><span class="p">)</span>
<span class="c1"># Shift to the new menu</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">menu_class</span> <span class="o">=</span> <span class="n">class_from_module</span><span class="p">(</span><span class="n">submenu_class</span><span class="p">)</span>
<span class="k">except</span> <span class="ne">Exception</span><span class="p">:</span>
<span class="n">log_trace</span><span class="p">(</span>
<span class="s2">&quot;BuildingMenu: attempting to load class </span><span class="si">{}</span><span class="s2"> failed&quot;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="nb">repr</span><span class="p">(</span><span class="n">submenu_class</span><span class="p">))</span>
<span class="p">)</span>
<span class="k">return</span>
<span class="c1"># Create the submenu</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">building_menu</span> <span class="o">=</span> <span class="n">menu_class</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">submenu_obj</span><span class="p">,</span> <span class="n">parents</span><span class="o">=</span><span class="n">parents</span><span class="p">)</span>
<span class="k">except</span> <span class="ne">Exception</span><span class="p">:</span>
<span class="n">log_trace</span><span class="p">(</span>
<span class="s2">&quot;An error occurred while creating building menu </span><span class="si">{}</span><span class="s2">&quot;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="nb">repr</span><span class="p">(</span><span class="n">submenu_class</span><span class="p">))</span>
<span class="p">)</span>
<span class="k">return</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">return</span> <span class="n">building_menu</span><span class="o">.</span><span class="n">open</span><span class="p">()</span></div>
<div class="viewcode-block" id="BuildingMenu.move"><a class="viewcode-back" href="../../../api/evennia.contrib.building_menu.html#evennia.contrib.building_menu.BuildingMenu.move">[docs]</a> <span class="k">def</span> <span class="nf">move</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">key</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">back</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="n">quiet</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span> <span class="n">string</span><span class="o">=</span><span class="s2">&quot;&quot;</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Move inside the menu.</span>
<span class="sd"> Args:</span>
<span class="sd"> key (any): the portion of the key to add to the current</span>
<span class="sd"> menu keys. If you wish to go back in the menu</span>
<span class="sd"> tree, don&#39;t provide a `key`, just set `back` to `True`.</span>
<span class="sd"> back (bool, optional): go back in the menu (`False` by default).</span>
<span class="sd"> quiet (bool, optional): should the menu or choice be</span>
<span class="sd"> displayed afterward?</span>
<span class="sd"> string (str, optional): the string sent by the caller to move.</span>
<span class="sd"> Note:</span>
<span class="sd"> This method will need to be called directly should you</span>
<span class="sd"> use more than two levels in your menu. For instance,</span>
<span class="sd"> in your room menu, if you want to have an &quot;exits&quot;</span>
<span class="sd"> option, and then be able to enter &quot;north&quot; in this</span>
<span class="sd"> choice to edit an exit. The specific exit choice</span>
<span class="sd"> could be a different menu (with a different class), but</span>
<span class="sd"> it could also be an additional level in your original menu.</span>
<span class="sd"> If that&#39;s the case, you will need to use this method.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="n">choice</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">current_choice</span>
<span class="k">if</span> <span class="n">choice</span><span class="p">:</span>
<span class="n">choice</span><span class="o">.</span><span class="n">leave</span><span class="p">(</span><span class="s2">&quot;&quot;</span><span class="p">)</span>
<span class="k">if</span> <span class="ow">not</span> <span class="n">back</span><span class="p">:</span> <span class="c1"># Move forward</span>
<span class="k">if</span> <span class="ow">not</span> <span class="n">key</span><span class="p">:</span>
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s2">&quot;you are asking to move forward, you should specify a key.&quot;</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">keys</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">key</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span> <span class="c1"># Move backward</span>
<span class="k">if</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">keys</span><span class="p">:</span>
<span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span>
<span class="s2">&quot;you already are at the top of the tree, you cannot move backward.&quot;</span>
<span class="p">)</span>
<span class="k">del</span> <span class="bp">self</span><span class="o">.</span><span class="n">keys</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span>
<span class="bp">self</span><span class="o">.</span><span class="n">_save</span><span class="p">()</span>
<span class="n">choice</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">current_choice</span>
<span class="k">if</span> <span class="n">choice</span><span class="p">:</span>
<span class="n">choice</span><span class="o">.</span><span class="n">enter</span><span class="p">(</span><span class="n">string</span><span class="p">)</span>
<span class="k">if</span> <span class="ow">not</span> <span class="n">quiet</span><span class="p">:</span>
<span class="bp">self</span><span class="o">.</span><span class="n">display</span><span class="p">()</span></div>
<div class="viewcode-block" id="BuildingMenu.close"><a class="viewcode-back" href="../../../api/evennia.contrib.building_menu.html#evennia.contrib.building_menu.BuildingMenu.close">[docs]</a> <span class="k">def</span> <span class="nf">close</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;Close the building menu, removing the CmdSet.&quot;&quot;&quot;</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">cmdset</span><span class="o">.</span><span class="n">has</span><span class="p">(</span><span class="n">BuildingMenuCmdSet</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">delete</span><span class="p">(</span><span class="n">BuildingMenuCmdSet</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">attributes</span><span class="o">.</span><span class="n">has</span><span class="p">(</span><span class="s2">&quot;_building_menu&quot;</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">&quot;_building_menu&quot;</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">nattributes</span><span class="o">.</span><span class="n">has</span><span class="p">(</span><span class="s2">&quot;_building_menu&quot;</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">nattributes</span><span class="o">.</span><span class="n">remove</span><span class="p">(</span><span class="s2">&quot;_building_menu&quot;</span><span class="p">)</span></div>
<span class="c1"># Display methods. Override for customization</span>
<div class="viewcode-block" id="BuildingMenu.display_title"><a class="viewcode-back" href="../../../api/evennia.contrib.building_menu.html#evennia.contrib.building_menu.BuildingMenu.display_title">[docs]</a> <span class="k">def</span> <span class="nf">display_title</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;Return the menu title to be displayed.&quot;&quot;&quot;</span>
<span class="k">return</span> <span class="n">_call_or_get</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">title</span><span class="p">,</span> <span class="n">menu</span><span class="o">=</span><span class="bp">self</span><span class="p">,</span> <span class="n">obj</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">obj</span><span class="p">,</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="p">)</span><span class="o">.</span><span class="n">format</span><span class="p">(</span>
<span class="n">obj</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">obj</span>
<span class="p">)</span></div>
<div class="viewcode-block" id="BuildingMenu.display_choice"><a class="viewcode-back" href="../../../api/evennia.contrib.building_menu.html#evennia.contrib.building_menu.BuildingMenu.display_choice">[docs]</a> <span class="k">def</span> <span class="nf">display_choice</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">choice</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;Display the specified choice.</span>
<span class="sd"> Args:</span>
<span class="sd"> choice (Choice): the menu choice.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="n">title</span> <span class="o">=</span> <span class="n">_call_or_get</span><span class="p">(</span>
<span class="n">choice</span><span class="o">.</span><span class="n">title</span><span class="p">,</span> <span class="n">menu</span><span class="o">=</span><span class="bp">self</span><span class="p">,</span> <span class="n">choice</span><span class="o">=</span><span class="n">choice</span><span class="p">,</span> <span class="n">obj</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">obj</span><span class="p">,</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="p">)</span>
<span class="n">clear_title</span> <span class="o">=</span> <span class="n">title</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span>
<span class="n">pos</span> <span class="o">=</span> <span class="n">clear_title</span><span class="o">.</span><span class="n">find</span><span class="p">(</span><span class="n">choice</span><span class="o">.</span><span class="n">key</span><span class="o">.</span><span class="n">lower</span><span class="p">())</span>
<span class="n">ret</span> <span class="o">=</span> <span class="s2">&quot; &quot;</span>
<span class="k">if</span> <span class="n">pos</span> <span class="o">&gt;=</span> <span class="mi">0</span><span class="p">:</span>
<span class="n">ret</span> <span class="o">+=</span> <span class="n">title</span><span class="p">[:</span><span class="n">pos</span><span class="p">]</span> <span class="o">+</span> <span class="s2">&quot;[|y&quot;</span> <span class="o">+</span> <span class="n">choice</span><span class="o">.</span><span class="n">key</span><span class="o">.</span><span class="n">title</span><span class="p">()</span> <span class="o">+</span> <span class="s2">&quot;|n]&quot;</span> <span class="o">+</span> <span class="n">title</span><span class="p">[</span><span class="n">pos</span> <span class="o">+</span> <span class="nb">len</span><span class="p">(</span><span class="n">choice</span><span class="o">.</span><span class="n">key</span><span class="p">)</span> <span class="p">:]</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">ret</span> <span class="o">+=</span> <span class="s2">&quot;[|y&quot;</span> <span class="o">+</span> <span class="n">choice</span><span class="o">.</span><span class="n">key</span><span class="o">.</span><span class="n">title</span><span class="p">()</span> <span class="o">+</span> <span class="s2">&quot;|n] &quot;</span> <span class="o">+</span> <span class="n">title</span>
<span class="k">if</span> <span class="n">choice</span><span class="o">.</span><span class="n">glance</span><span class="p">:</span>
<span class="n">glance</span> <span class="o">=</span> <span class="n">_call_or_get</span><span class="p">(</span>
<span class="n">choice</span><span class="o">.</span><span class="n">glance</span><span class="p">,</span> <span class="n">menu</span><span class="o">=</span><span class="bp">self</span><span class="p">,</span> <span class="n">choice</span><span class="o">=</span><span class="n">choice</span><span class="p">,</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="p">,</span> <span class="n">string</span><span class="o">=</span><span class="s2">&quot;&quot;</span><span class="p">,</span> <span class="n">obj</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">obj</span>
<span class="p">)</span>
<span class="n">glance</span> <span class="o">=</span> <span class="n">glance</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">obj</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">obj</span><span class="p">,</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="p">)</span>
<span class="n">ret</span> <span class="o">+=</span> <span class="s2">&quot;: &quot;</span> <span class="o">+</span> <span class="n">glance</span>
<span class="k">return</span> <span class="n">ret</span></div>
<div class="viewcode-block" id="BuildingMenu.display"><a class="viewcode-back" href="../../../api/evennia.contrib.building_menu.html#evennia.contrib.building_menu.BuildingMenu.display">[docs]</a> <span class="k">def</span> <span class="nf">display</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;Display the entire menu or a single choice, depending on the keys.&quot;&quot;&quot;</span>
<span class="n">choice</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">current_choice</span>
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">keys</span> <span class="ow">and</span> <span class="n">choice</span><span class="p">:</span>
<span class="n">text</span> <span class="o">=</span> <span class="n">choice</span><span class="o">.</span><span class="n">format_text</span><span class="p">()</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">text</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">display_title</span><span class="p">()</span> <span class="o">+</span> <span class="s2">&quot;</span><span class="se">\n</span><span class="s2">&quot;</span>
<span class="k">for</span> <span class="n">choice</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">relevant_choices</span><span class="p">:</span>
<span class="n">text</span> <span class="o">+=</span> <span class="s2">&quot;</span><span class="se">\n</span><span class="s2">&quot;</span> <span class="o">+</span> <span class="bp">self</span><span class="o">.</span><span class="n">display_choice</span><span class="p">(</span><span class="n">choice</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">msg</span><span class="p">(</span><span class="n">text</span><span class="p">)</span></div>
<div class="viewcode-block" id="BuildingMenu.restore"><a class="viewcode-back" href="../../../api/evennia.contrib.building_menu.html#evennia.contrib.building_menu.BuildingMenu.restore">[docs]</a> <span class="nd">@staticmethod</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="sd">&quot;&quot;&quot;Restore the building menu for the caller.</span>
<span class="sd"> Args:</span>
<span class="sd"> caller (Account or Object): the caller.</span>
<span class="sd"> Note:</span>
<span class="sd"> This method should be automatically called if a menu is</span>
<span class="sd"> saved in the caller, but the object itself cannot be found.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="n">menu</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">_building_menu</span>
<span class="k">if</span> <span class="n">menu</span><span class="p">:</span>
<span class="n">class_name</span> <span class="o">=</span> <span class="n">menu</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;class&quot;</span><span class="p">)</span>
<span class="k">if</span> <span class="ow">not</span> <span class="n">class_name</span><span class="p">:</span>
<span class="n">log_err</span><span class="p">(</span>
<span class="s2">&quot;BuildingMenu: on caller </span><span class="si">{}</span><span class="s2">, a persistent attribute holds building menu &quot;</span>
<span class="s2">&quot;data, but no class could be found to restore the menu&quot;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="n">caller</span><span class="p">)</span>
<span class="p">)</span>
<span class="k">return</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">menu_class</span> <span class="o">=</span> <span class="n">class_from_module</span><span class="p">(</span><span class="n">class_name</span><span class="p">)</span>
<span class="k">except</span> <span class="ne">Exception</span><span class="p">:</span>
<span class="n">log_trace</span><span class="p">(</span>
<span class="s2">&quot;BuildingMenu: attempting to load class </span><span class="si">{}</span><span class="s2"> failed&quot;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="nb">repr</span><span class="p">(</span><span class="n">class_name</span><span class="p">))</span>
<span class="p">)</span>
<span class="k">return</span>
<span class="c1"># Create the menu</span>
<span class="n">obj</span> <span class="o">=</span> <span class="n">menu</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;obj&quot;</span><span class="p">)</span>
<span class="n">keys</span> <span class="o">=</span> <span class="n">menu</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;keys&quot;</span><span class="p">)</span>
<span class="n">title</span> <span class="o">=</span> <span class="n">menu</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;title&quot;</span><span class="p">,</span> <span class="s2">&quot;&quot;</span><span class="p">)</span>
<span class="n">parents</span> <span class="o">=</span> <span class="n">menu</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;parents&quot;</span><span class="p">)</span>
<span class="n">persistent</span> <span class="o">=</span> <span class="n">menu</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;persistent&quot;</span><span class="p">,</span> <span class="kc">False</span><span class="p">)</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">building_menu</span> <span class="o">=</span> <span class="n">menu_class</span><span class="p">(</span>
<span class="n">caller</span><span class="p">,</span> <span class="n">obj</span><span class="p">,</span> <span class="n">title</span><span class="o">=</span><span class="n">title</span><span class="p">,</span> <span class="n">keys</span><span class="o">=</span><span class="n">keys</span><span class="p">,</span> <span class="n">parents</span><span class="o">=</span><span class="n">parents</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="k">except</span> <span class="ne">Exception</span><span class="p">:</span>
<span class="n">log_trace</span><span class="p">(</span>
<span class="s2">&quot;An error occurred while creating building menu </span><span class="si">{}</span><span class="s2">&quot;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span><span class="nb">repr</span><span class="p">(</span><span class="n">class_name</span><span class="p">))</span>
<span class="p">)</span>
<span class="k">return</span>
<span class="k">return</span> <span class="n">building_menu</span></div></div>
<span class="c1"># Generic building menu and command</span>
<div class="viewcode-block" id="GenericBuildingMenu"><a class="viewcode-back" href="../../../api/evennia.contrib.building_menu.html#evennia.contrib.building_menu.GenericBuildingMenu">[docs]</a><span class="k">class</span> <span class="nc">GenericBuildingMenu</span><span class="p">(</span><span class="n">BuildingMenu</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;A generic building menu, allowing to edit any object.</span>
<span class="sd"> This is more a demonstration menu. By default, it allows to edit the</span>
<span class="sd"> object key and description. Nevertheless, it will be useful to demonstrate</span>
<span class="sd"> how building menus are meant to be used.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<div class="viewcode-block" id="GenericBuildingMenu.init"><a class="viewcode-back" href="../../../api/evennia.contrib.building_menu.html#evennia.contrib.building_menu.GenericBuildingMenu.init">[docs]</a> <span class="k">def</span> <span class="nf">init</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">obj</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;Build the meny, adding the &#39;key&#39; and &#39;description&#39; choices.</span>
<span class="sd"> Args:</span>
<span class="sd"> obj (Object): any object to be edited, like a character or room.</span>
<span class="sd"> Note:</span>
<span class="sd"> The &#39;quit&#39; choice will be automatically added, though you can</span>
<span class="sd"> call `add_choice_quit` to add this choice with different options.</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="bp">self</span><span class="o">.</span><span class="n">add_choice</span><span class="p">(</span>
<span class="s2">&quot;key&quot;</span><span class="p">,</span>
<span class="n">key</span><span class="o">=</span><span class="s2">&quot;k&quot;</span><span class="p">,</span>
<span class="n">attr</span><span class="o">=</span><span class="s2">&quot;key&quot;</span><span class="p">,</span>
<span class="n">glance</span><span class="o">=</span><span class="s2">&quot;</span><span class="si">{obj.key}</span><span class="s2">&quot;</span><span class="p">,</span>
<span class="n">text</span><span class="o">=</span><span class="s2">&quot;&quot;&quot;</span>
<span class="s2"> -------------------------------------------------------------------------------</span>
<span class="s2"> Editing the key of {{obj.key}}(#{{obj.id}})</span>
<span class="s2"> You can change the simply by entering it.</span>
<span class="s2"> Use |y</span><span class="si">{back}</span><span class="s2">|n to go back to the main menu.</span>
<span class="s2"> Current key: |c{{obj.key}}|n</span>
<span class="s2"> &quot;&quot;&quot;</span><span class="o">.</span><span class="n">format</span><span class="p">(</span>
<span class="n">back</span><span class="o">=</span><span class="s2">&quot;|n or |y&quot;</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">keys_go_back</span><span class="p">)</span>
<span class="p">),</span>
<span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">add_choice_edit</span><span class="p">(</span><span class="s2">&quot;description&quot;</span><span class="p">,</span> <span class="n">key</span><span class="o">=</span><span class="s2">&quot;d&quot;</span><span class="p">,</span> <span class="n">attr</span><span class="o">=</span><span class="s2">&quot;db.desc&quot;</span><span class="p">)</span></div></div>
<div class="viewcode-block" id="GenericBuildingCmd"><a class="viewcode-back" href="../../../api/evennia.contrib.building_menu.html#evennia.contrib.building_menu.GenericBuildingCmd">[docs]</a><span class="k">class</span> <span class="nc">GenericBuildingCmd</span><span class="p">(</span><span class="n">Command</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;</span>
<span class="sd"> Generic building command.</span>
<span class="sd"> Syntax:</span>
<span class="sd"> @edit [object]</span>
<span class="sd"> Open a building menu to edit the specified object. This menu allows to</span>
<span class="sd"> change the object&#39;s key and description.</span>
<span class="sd"> Examples:</span>
<span class="sd"> @edit here</span>
<span class="sd"> @edit self</span>
<span class="sd"> @edit #142</span>
<span class="sd"> &quot;&quot;&quot;</span>
<span class="n">key</span> <span class="o">=</span> <span class="s2">&quot;@edit&quot;</span>
<div class="viewcode-block" id="GenericBuildingCmd.func"><a class="viewcode-back" href="../../../api/evennia.contrib.building_menu.html#evennia.contrib.building_menu.GenericBuildingCmd.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="k">if</span> <span class="ow">not</span> <span class="bp">self</span><span class="o">.</span><span class="n">args</span><span class="o">.</span><span class="n">strip</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">&quot;You should provide an argument to this function: the object to edit.&quot;</span><span class="p">)</span>
<span class="k">return</span>
<span class="n">obj</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">caller</span><span class="o">.</span><span class="n">search</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">args</span><span class="o">.</span><span class="n">strip</span><span class="p">(),</span> <span class="n">global_search</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
<span class="k">if</span> <span class="ow">not</span> <span class="n">obj</span><span class="p">:</span>
<span class="k">return</span>
<span class="n">menu</span> <span class="o">=</span> <span class="n">GenericBuildingMenu</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">obj</span><span class="p">)</span>
<span class="n">menu</span><span class="o">.</span><span class="n">open</span><span class="p">()</span></div></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>Versions</h3>
<ul>
<li><a href="building_menu.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> &#187;</li>
<li class="nav-item nav-item-1"><a href="../../index.html" >Module code</a> &#187;</li>
<li class="nav-item nav-item-2"><a href="../../evennia.html" >evennia</a> &#187;</li>
<li class="nav-item nav-item-this"><a href="">evennia.contrib.building_menu</a></li>
</ul>
<div class="develop">develop branch</div>
</div>
<div class="footer" role="contentinfo">
&#169; Copyright 2020, The Evennia developer community.
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 3.2.1.
</div>
</body>
</html>