'Initialize the menu tree and start the caller onto the first node.
Args:
caller (Object, Player or Session): The user of the menu.
menudata (str, module or dict): The full or relative path to the module
holding the menu tree data. All global functions in this module
whose name doesn\'t start with \'_ \' will be parsed as menu nodes.
Also the module itself is accepted as input. Finally, a dictionary
menu tree can be given directly. This must then be a mapping
`{"nodekey":callable,...}` where `callable` must be called as
and return the data expected of a menu node. This allows for
dynamic menu creation.
startnode (str, optional): The starting node name in the menufile.
cmdset_mergetype (str, optional): \'Replace\' (default) means the menu
commands will be exclusive - no other normal commands will
be usable while the user is in the menu. \'Union\' means the
menu commands will be integrated with the existing commands
(it will merge with `merge_priority`), if so, make sure that
the menu\'s command names don\'t collide with existing commands
in an unexpected way. Also the CMD_NOMATCH and CMD_NOINPUT will
be overloaded by the menu cmdset. Other cmdser mergetypes
has little purpose for the menu.
cmdset_priority (int, optional): The merge priority for the
menu command set. The default (1) is usually enough for most
types of menus.
auto_quit (bool, optional): Allow user to use "q", "quit" or
"exit" to leave the menu at any point. Recommended during
development!
auto_look (bool, optional): Automatically make "looK" or "l" to
re-show the last node. Turning this off means you have to handle
re-showing nodes yourself, but may be useful if you need to
use "l" for some other purpose.
auto_help (bool, optional): Automatically make "help" or "h" show
the current help entry for the node. If turned off, eventual
help must be handled manually, but it may be useful if you
need \'h\' for some other purpose, for example.
cmd_on_exit (callable, str or None, optional): When exiting the menu
(either by reaching a node with no options or by using the
in-built quit command (activated with `allow_quit`), this
callback function or command string will be executed.
The callback function takes two parameters, the caller then the
EvMenu object. This is called after cleanup is complete.
Set to None to not call any command.
nodetext_formatter (callable, optional): This callable should be on
the form `function(nodetext, has_options, caller=None)`, where `nodetext` is the
node text string and `has_options` a boolean specifying if there
are options associated with this node. It must return a formatted
string. `caller` is optionally a reference to the user of the menu.
`caller` is optionally a reference to the user of the menu.
options_formatter (callable, optional): This callable should be on
the form `function(optionlist, caller=None)`, where ` optionlist is a list
of option dictionaries, like
[{"key":..., "desc",..., "goto": ..., "exec",...}, ...]
Each dictionary describes each possible option. Note that this
will also be called if there are no options, and so should be
able to handle an empty list. This should
be formatted into an options list and returned as a string,
including the required separator to use between the node text
and the options. If not given the default EvMenu style will be used.
`caller` is optionally a reference to the user of the menu.
node_formatter (callable, optional): This callable should be on the
form `func(nodetext, optionstext, caller=None)` where the arguments are strings
representing the node text and options respectively (possibly prepared
by `nodetext_formatter`/`options_formatter` or by the default styles).
It should return a string representing the final look of the node. This
can e.g. be used to create line separators that take into account the
dynamic width of the parts. `caller` is optionally a reference to the
user of the menu.
input_parser (callable, optional): This callable is responsible for parsing the
options dict from a node and has the form `func(menuobject, raw_string, caller)`,
where menuobject is the active `EvMenu` instance, `input_string` is the
incoming text from the caller and `caller` is the user of the menu.
It should use the helper method of the menuobject to goto new nodes, show
help texts etc. See the default `evtable_parse_input` function for help
with parsing.
persistent (bool, optional): Make the Menu persistent (i.e. it will
survive a reload. This will make the Menu cmdset persistent. Use
with caution - if your menu is buggy you may end up in a state
you can\'t get out of! Also note that persistent mode requires
that all formatters, menu nodes and callables are possible to
*pickle*. When the server is reloaded, the latest node shown will be completely
re-run with the same input arguments - so be careful if you are counting
up some persistent counter or similar - the counter may be run twice if
reload happens on the node that does that.
startnode_input (str, optional): Send an input text to `startnode` as if
a user input text from a fictional previous node. When the server reloads,
the latest visited node will be re-run using this kwarg.
session (Session, optional): This is useful when calling EvMenu from a player
in multisession mode > 2. Note that this session only really relevant
for the very first display of the first node - after that, EvMenu itself
will keep the session updated from the command input. So a persistent
menu will *not* be using this same session anymore after a reload.
Kwargs:
any (any): All kwargs will become initialization variables on `caller.ndb._menutree`,
to be available at run.
Raises:
EvMenuError: If the start/end node is not found in menu tree.
Notes:
While running, the menu is stored on the caller as `caller.ndb._menutree`. Also
the current Session (from the Command, so this is still valid in multisession
environments) is available through `caller.ndb._menutree._session`. The `_menutree`
property is a good one for storing intermediary data on between nodes since it
will be automatically deleted when the menu closes.
In persistent mode, all nodes, formatters and callbacks in the menu must be
possible to be *pickled*, this excludes e.g. callables that are class methods
or functions defined dynamically or as part of another function. In
non-persistent mode no such restrictions exist.'

def __init__(self, caller, menudata, startnode='start', cmdset_mergetype='Replace', cmdset_priority=1, auto_quit=True, auto_look=True, auto_help=True, cmd_on_exit='look', nodetext_formatter=dedent_strip_nodetext_formatter, options_formatter=evtable_options_formatter, node_formatter=underline_node_formatter, input_parser=evtable_parse_input, persistent=False, startnode_input='', session=None, **kwargs):

    self._startnode = startnode
    self._menutree = self._parse_menudata(menudata)
    self._nodetext_formatter = nodetext_formatter
    self._options_formatter = options_formatter
    self._node_formatter = node_formatter
    self._input_parser = input_parser
    self._persistent = persistent
    if (startnode not in self._menutree):
        raise EvMenuError(("Start    node    '%s'    not    in    menu    tree!" % startnode))
    self.caller = caller
    self.auto_quit = auto_quit
    self.auto_look = auto_look
    self.auto_help = auto_help
    self._session = session
    if isinstance(cmd_on_exit, str):
        self.cmd_on_exit = (lambda caller, menu: caller.execute_cmd(cmd_on_exit, session=menu._session))
    elif callable(cmd_on_exit):
        self.cmd_on_exit = cmd_on_exit
    else:
        self.cmd_on_exit = None
    self.default = None
    self.nodetext = None
    self.helptext = None
    self.options = None
    if set(('_startnode', '_menutree', '_nodetext_formatter', '_options_formatter', 'node_formatter', '_input_parser', '_peristent', 'cmd_on_exit', 'default', 'nodetext', 'helptext', 'options')).intersection(set(kwargs.keys())):
        raise RuntimeError('One    or    more    of    the    EvMenu    `**kwargs`    is    reserved    by    EvMenu    for    internal    use.')
    for (key, val) in kwargs.iteritems():
        setattr(self, key, val)
    self.caller.ndb._menutree = self
    if persistent:
        try:
            caller.attributes.add('_menutree_saved', ((menudata,), {'startnode': startnode, 'cmdset_mergetype': cmdset_mergetype, 'cmdset_priority': cmdset_priority, 'auto_quit': auto_quit, 'auto_look': auto_look, 'auto_help': auto_help, 'cmd_on_exit': cmd_on_exit, 'nodetext_formatter': nodetext_formatter, 'options_formatter': options_formatter, 'node_formatter': node_formatter, 'input_parser': input_parser, 'persistent': persistent}))
            caller.attributes.add('_menutree_saved_startnode', (startnode, startnode_input))
        except Exception as err:
            caller.msg(_ERROR_PERSISTENT_SAVING.format(error=err), session=self._session)
            logger.log_trace(_TRACE_PERSISTENT_SAVING)
            persistent = False
    menu_cmdset = EvMenuCmdSet()
    menu_cmdset.mergetype = (str(cmdset_mergetype).lower().capitalize() or 'Replace')
    menu_cmdset.priority = int(cmdset_priority)
    self.caller.cmdset.add(menu_cmdset, permanent=persistent)
    self.goto(self._startnode, startnode_input)
