# evennia.contrib.base_systems.building_menu.building_menu

Module containing the building menu system.

Evennia contributor: vincent-lg 2018

Building menus are in-game menus, not unlike EvMenu though using a different approach. Building menus have been specifically designed to edit information as a builder. Creating a building menu in a command allows builders quick-editing of a given object, like a room. If you follow the steps below to add the contrib, you will have access to an @edit command that will edit any default object offering to change its key and description.

1. Import the GenericBuildingCmd class from this contrib in your mygame/commands/default_cmdset.py file:

   >     from evennia.contrib.base_systems.building_menu import GenericBuildingCmd

2. Below, add the command in the CharacterCmdSet:

   >     # ... These lines should exist in the file
   >     class CharacterCmdSet(default_cmds.CharacterCmdSet):
   >         key = "DefaultCharacter"

   >         def at_cmdset_creation(self):
   >             super().at_cmdset_creation()
   >             # ... add the line below
   >             self.add(GenericBuildingCmd())

The @edit command will allow you to edit any object. You will need to specify the object name or ID as an argument. For instance: @edit here will edit the current room. However, building menus can perform much more than this very simple example, read on for more details.

Building menus can be set to edit about anything. Here is an example of output you could obtain when editing the room:

> Editing the room: Limbo(#2)

> [T]itle: the limbo room [D]escription

> > This is the limbo room. You can easily change this default description, either by using the |y@desc/edit|n command, or simply by entering this menu (enter |yd|n).

> [E]xits:

>   north to A parking(#4)

> [Q]uit this menu

From there, you can open the title choice by pressing t. You can then change the room title by simply entering text, and go back to the main menu entering @ (all this is customizable). Press q to quit this menu.

The first thing to do is to create a new module and place a class inheriting from BuildingMenu in it.

    from evennia.contrib.base_systems.building_menu.building_menu import BuildingMenu

    class RoomBuildingMenu(BuildingMenu):
        # ...

Next, override the init method. You can add choices (like the title, description, and exits choices as seen above) by using the add_choice method.

class RoomBuildingMenu(BuildingMenu):
  def init(self, room):

    self.add_choice(“title”, “t”, attr=”key”)

That will create the first choice, the title choice. If one opens your menu and enter t, she will be in the title choice. She can change the title (it will write in the room’s key attribute) and then go back to the main menu using @.

add_choice has a lot of arguments and offers a great deal of flexibility. The most useful ones is probably the usage of callbacks, as you can set almost any argument in add_choice to be a callback, a function that you have defined above in your module. This function will be called when the menu element is triggered.

Notice that in order to edit a description, the best method to call isn’t add_choice, but add_choice_edit. This is a convenient shortcut which is available to quickly open an EvEditor when entering this choice and going back to the menu when the editor closes.

class RoomBuildingMenu(BuildingMenu):
  def init(self, room):

    self.add_choice(“title”, “t”, attr=”key”) self.add_choice_edit(“description”, key=”d”, attr=”db.desc”)

When you wish to create a building menu, you just need to import your class, create it specifying your intended caller and object to edit, then call open:

    from <wherever> import RoomBuildingMenu

    class CmdEdit(Command):

        key = "redit"

        def func(self):
            menu = RoomBuildingMenu(self.caller, self.caller.location)
            menu.open()

This is a very short introduction. For more details, see the online tutorial (https://github.com/evennia/evennia/wiki/Building-menus) or read the heavily-documented code below.

`evennia.contrib.base_systems.building_menu.building_menu.``menu_setattr`(menu, choice, obj, string)

  Set the value at the specified attribute.

  Parameters

    - menu (BuildingMenu) – the menu object.

    - choice (Chocie) – the specific choice.

    - obj (Object) – the object to modify.

    - string (str) – the string with the new value.

  Note

  This function is supposed to be used as a default to BuildingMenu.add_choice, when an attribute name is specified (in the attr argument) but no function on_nomatch is defined.

`evennia.contrib.base_systems.building_menu.building_menu.``menu_quit`(caller, menu)

  Quit the menu, closing the CmdSet.

  Parameters

    - caller (Account or Object) – the caller.

    - menu (BuildingMenu) – the building menu to close.

  Note

  This callback is used by default when using the BuildingMenu.add_choice_quit method. This method is called automatically if the menu has no parent.

`evennia.contrib.base_systems.building_menu.building_menu.``menu_edit`(caller, choice, obj)

  Open the EvEditor to edit a specified attribute.

  Parameters

    - caller (Account or Object) – the caller.

    - choice (Choice) – the choice object.

    - obj (Object) – the object to edit.

class `evennia.contrib.base_systems.building_menu.building_menu.``CmdNoInput`(**kwargs)

  Bases: `evennia.commands.command.Command`

  No input has been found.

  `key` = '__noinput_command'
  `locks` = 'cmd:all()'
  `__init__`(**kwargs)

    The lockhandler works the same as for objects. optional kwargs will be set as properties on the Command at runtime, overloading evential same-named class properties.

  `func`()

    Display the menu or choice text.

  `aliases` = []
  `help_category` = 'general'
  `lock_storage` = 'cmd:all()'
  `search_index_entry` = {'aliases': '', 'category': 'general', 'key': '__noinput_command', 'no_prefix': ' ', 'tags': '', 'text': 'No input has been found.'}

class `evennia.contrib.base_systems.building_menu.building_menu.``CmdNoMatch`(**kwargs)

  Bases: `evennia.commands.command.Command`

  No input has been found.

  `key` = '__nomatch_command'
  `locks` = 'cmd:all()'
  `__init__`(**kwargs)

    The lockhandler works the same as for objects. optional kwargs will be set as properties on the Command at runtime, overloading evential same-named class properties.

  `func`()

    Call the proper menu or redirect to nomatch.

  `aliases` = []
  `help_category` = 'general'
  `lock_storage` = 'cmd:all()'
  `search_index_entry` = {'aliases': '', 'category': 'general', 'key': '__nomatch_command', 'no_prefix': ' ', 'tags': '', 'text': 'No input has been found.'}

class `evennia.contrib.base_systems.building_menu.building_menu.``BuildingMenuCmdSet`(cmdsetobj=None, key=None)

  Bases: `evennia.commands.cmdset.CmdSet`

  Building menu CmdSet.

  `key` = 'building_menu'
  `priority` = 5
  `at_cmdset_creation`()

    Populates the cmdset with commands.

  `path` = 'evennia.contrib.base_systems.building_menu.building_menu.BuildingMenuCmdSet'

class `evennia.contrib.base_systems.building_menu.building_menu.``Choice`(title, key=None, aliases=None, attr=None, text=None, glance=None, on_enter=None, on_nomatch=None, on_leave=None, menu=None, caller=None, obj=None)

  Bases: `object`

  A choice object, created by add_choice.

  `__init__`(title, key=None, aliases=None, attr=None, text=None, glance=None, on_enter=None, on_nomatch=None, on_leave=None, menu=None, caller=None, obj=None)

    Constructor.

    Parameters

      - title (str) – the choice’s title.

      - key (str, optional) – the key of the letters to type to access the choice. If not set, try to guess it based on the title.

      - aliases (list of str, optional) – the allowed aliases for this choice.

      - attr (str, optional) – the name of the attribute of ‘obj’ to set.

      - text (str or callable, optional) – a text to be displayed for this choice. It can be a callable.

      - glance (str or callable, optional) – an at-a-glance summary of the sub-menu shown in the main menu. It can be set to display the current value of the attribute in the main menu itself.

      - menu (BuildingMenu, optional) – the parent building menu.

      - on_enter (callable, optional) – a callable to call when the caller enters into the choice.

      - on_nomatch (callable, optional) – a callable to call when no match is entered in the choice.

      - on_leave (callable, optional) – a callable to call when the caller leaves the choice.

      - caller (Account or Object, optional) – the caller.

      - obj (Object, optional) – the object to edit.

  property `keys`

    Return a tuple of keys separated by sep_keys.

  `format_text`()

    Format the choice text and return it, or an empty string.

  `enter`(string)

    Called when the user opens the choice.

    Parameters

      string (str) – the entered string.

  `nomatch`(string)

    Called when the user entered something in the choice.

    Parameters

      string (str) – the entered string.

    Returns

      to_display (bool) – The return value of nomatch if set or True. The rule is that if no_match returns True, then the choice or menu is displayed.

  `leave`(string)

    Called when the user closes the choice.

    Parameters

      string (str) – the entered string.

class `evennia.contrib.base_systems.building_menu.building_menu.``BuildingMenu`(caller=None, obj=None, title='Building menu: {obj}', keys=None, parents=None, persistent=False)

  Bases: `object`

  Class allowing to create and set building menus to edit specific objects.

  A building menu is somewhat similar to EvMenu, but designed to edit objects by builders, although it can be used for players in some contexts. You could, for instance, create a building menu to edit a room with a sub-menu for the room’s key, another for the room’s description, another for the room’s exits, and so on.

  To add choices (simple sub-menus), you should call add_choice (see the full documentation of this method). With most arguments, you can specify either a plain string or a callback. This callback will be called when the operation is to be performed.

  Some methods are provided for frequent needs (see the add_choice_* methods). Some helper functions are defined at the top of this module in order to be used as arguments to add_choice in frequent cases.

  `keys_go_back` = ['@']
  `sep_keys` = '.'
  `joker_key` = '*'
  `min_shortcut` = 1
  `__init__`(caller=None, obj=None, title='Building menu: {obj}', keys=None, parents=None, persistent=False)

    Constructor, you shouldn’t override. See init instead.

    Parameters

      - caller (Account or Object) – the caller.

      - obj (Object) – the object to be edited, like a room.

      - title (str, optional) – the menu title.

      - keys (list of str, optional) – the starting menu keys (None to start from the first level).

      - parents (tuple, optional) – information for parent menus, automatically supplied.

      - persistent (bool, optional) – should this building menu survive a reload/restart?

    Note

    If some of these options have to be changed, it is preferable to do so in the init method and not to override __init__. For instance:

    > class RoomBuildingMenu(BuildingMenu):
    >   def init(self, room):

    >     self.title = “Menu for room: {obj.key}(#{obj.id})” # …

  property `current_choice`

    Return the current choice or None.

    Returns

      choice (Choice) – the current choice or None.

    Note

    We use the menu keys to identify the current position of the caller in the menu. The menu keys hold a list of keys that should match a choice to be usable.

  property `relevant_choices`

    Only return the relevant choices according to the current meny key.

    Returns

      relevant (list of Choice object) – the relevant choices.

    Note

    We use the menu keys to identify the current position of the caller in the menu. The menu keys hold a list of keys that should match a choice to be usable.

  `init`(obj)

    Create the sub-menu to edit the specified object.

    Parameters

      obj (Object) – the object to edit.

    Note

    This method is probably to be overridden in your subclasses. Use add_choice and its variants to create menu choices.

  `add_choice`(title, key=None, aliases=None, attr=None, text=None, glance=None, on_enter=None, on_nomatch=None, on_leave=None)

    Add a choice, a valid sub-menu, in the current builder menu.

    Parameters

      - title (str) – the choice’s title.

      - key (str, optional) – the key of the letters to type to access the sub-neu. If not set, try to guess it based on the choice title.

      - aliases (list of str, optional) – the aliases for this choice.

      - attr (str, optional) – the name of the attribute of ‘obj’ to set. This is really useful if you want to edit an attribute of the object (that’s a frequent need). If you don’t want to do so, just use the on_* arguments.

      - text (str or callable, optional) – a text to be displayed when the menu is opened It can be a callable.

      - glance (str or callable, optional) – an at-a-glance summary of the sub-menu shown in the main menu. It can be set to display the current value of the attribute in the main menu itself.

      - on_enter (callable, optional) – a callable to call when the caller enters into this choice.

      - on_nomatch (callable, optional) – a callable to call when the caller enters something in this choice. If you don’t set this argument but you have specified attr, then obj.**attr** will be set with the value entered by the user.

      - on_leave (callable, optional) – a callable to call when the caller leaves the choice.

    Returns

      choice (Choice) – the newly-created choice.

    Raises

      ValueError if the choice cannot be added. –

    Note

    Most arguments can be callables, like functions. This has the advantage of allowing great flexibility. If you specify a callable in most of the arguments, the callable should return the value expected by the argument (a str more often than not). For instance, you could set a function to be called to get the menu text, which allows for some filtering:

    > def text_exits(menu):

    >   return “Some text to display”

    > class RoomBuildingMenu(BuildingMenu):
    >   def init(self):

    >     self.add_choice(“exits”, key=”x”, text=text_exits)

    The allowed arguments in a callable are specific to the argument names (they are not sensitive to orders, not all arguments have to be present). For more information, see _call_or_get.

  `add_choice_edit`(title='description', key='d', aliases=None, attr='db.desc', glance='\n {obj.db.desc}', on_enter=None)

    Add a simple choice to edit a given attribute in the EvEditor.

    Parameters

      - title (str, optional) – the choice’s title.

      - key (str, optional) – the choice’s key.

      - aliases (list of str, optional) – the choice’s aliases.

      - glance (str or callable, optional) – the at-a-glance description.

      - on_enter (callable, optional) – a different callable to edit the attribute.

    Returns

      choice (Choice) – the newly-created choice.

    Note

    This is just a shortcut method, calling add_choice. If on_enter is not set, use menu_edit which opens an EvEditor to edit the specified attribute. When the caller closes the editor (with :q), the menu will be re-opened.

  `add_choice_quit`(title='quit the menu', key='q', aliases=None, on_enter=None)

    Add a simple choice just to quit the building menu.

    Parameters

      - title (str, optional) – the choice’s title.

      - key (str, optional) – the choice’s key.

      - aliases (list of str, optional) – the choice’s aliases.

      - on_enter (callable, optional) – a different callable to quit the building menu.

    Note

    This is just a shortcut method, calling add_choice. If on_enter is not set, use menu_quit which simply closes the menu and displays a message. It also removes the CmdSet from the caller. If you supply another callable instead, make sure to do the same.

  `open`()

    Open the building menu for the caller.

    Note

    This method should be called once when the building menu has been instanciated. From there, the building menu will be re-created automatically when the server reloads/restarts, assuming persistent is set to True.

  `open_parent_menu`()

    Open the parent menu, using self.parents.

    Note

    You probably don’t need to call this method directly, since the caller can go back to the parent menu using the keys_go_back automatically.

  `open_submenu`(submenu_class, submenu_obj, parent_keys=None)

    Open a sub-menu, closing the current menu and opening the new one.

    Parameters

      - submenu_class (str) – the submenu class as a Python path.

      - submenu_obj (Object) – the object to give to the submenu.

      - parent_keys (list of str, optional) – the parent keys when the submenu is closed.

    Note

    When the user enters @ in the submenu, she will go back to the current menu, with the parent_keys set as its keys. Therefore, you should set it on the keys of the choice that should be opened when the user leaves the submenu.

    Returns

      new_menu (BuildingMenu) – the new building menu or None.

  `move`(key=None, back=False, quiet=False, string='')

    Move inside the menu.

    Parameters

      - key (any) – the portion of the key to add to the current menu keys. If you wish to go back in the menu tree, don’t provide a key, just set back to True.

      - back (bool, optional) – go back in the menu (False by default).

      - quiet (bool, optional) – should the menu or choice be displayed afterward?

      - string (str, optional) – the string sent by the caller to move.

    Note

    This method will need to be called directly should you use more than two levels in your menu. For instance, in your room menu, if you want to have an “exits” option, and then be able to enter “north” in this choice to edit an exit. The specific exit choice could be a different menu (with a different class), but it could also be an additional level in your original menu. If that’s the case, you will need to use this method.

  `close`()

    Close the building menu, removing the CmdSet.

  `display_title`()

    Return the menu title to be displayed.

  `display_choice`(choice)

    Display the specified choice.

    Parameters

      choice (Choice) – the menu choice.

  `display`()

    Display the entire menu or a single choice, depending on the keys.

  static `restore`(caller)

    Restore the building menu for the caller.

    Parameters

      caller (Account or Object) – the caller.

    Note

    This method should be automatically called if a menu is saved in the caller, but the object itself cannot be found.

class `evennia.contrib.base_systems.building_menu.building_menu.``GenericBuildingMenu`(caller=None, obj=None, title='Building menu: {obj}', keys=None, parents=None, persistent=False)

  Bases: `evennia.contrib.base_systems.building_menu.building_menu.BuildingMenu`

  A generic building menu, allowing to edit any object.

  This is more a demonstration menu. By default, it allows to edit the object key and description. Nevertheless, it will be useful to demonstrate how building menus are meant to be used.

  `init`(obj)

    Build the meny, adding the ‘key’ and ‘description’ choices.

    Parameters

      obj (Object) – any object to be edited, like a character or room.

    Note

    The ‘quit’ choice will be automatically added, though you can call add_choice_quit to add this choice with different options.

class `evennia.contrib.base_systems.building_menu.building_menu.``GenericBuildingCmd`(**kwargs)

  Bases: `evennia.commands.command.Command`

  Generic building command.

  Syntax:

    @edit [object]

  Open a building menu to edit the specified object. This menu allows to change the object’s key and description.

  Examples

  @edit here @edit self @edit #142

  `key` = '@edit'
  `func`()

    This is the actual executing part of the command. It is called directly after self.parse(). See the docstring of this module for which object properties are available (beyond those set in self.parse())

  `aliases` = []
  `help_category` = 'general'
  `lock_storage` = 'cmd:all();'
  `search_index_entry` = {'aliases': '', 'category': 'general', 'key': '@edit', 'no_prefix': 'edit ', 'tags': '', 'text': "\n Generic building command.\n\n Syntax:\n @edit [object]\n\n Open a building menu to edit the specified object. This menu allows to\n change the object's key and description.\n\n Examples:\n @edit here\n @edit self\n @edit #142\n\n "}