1 """Menu objects for the MUFF Engine"""
3 # Copyright (c) 2005 mudpy, Jeremy Stanley <fungi@yuggoth.org>, all rights reserved.
4 # Licensed per terms in the LICENSE file distributed with this software.
6 # muff uses menu data stored in ini-style files supported by ConfigParser
9 # os.listdir is needed to get a file listing from a config directory
12 # re.match is used to find menu options based on the choice_ prefix
15 # hack to load all modules in the muff package
17 for module in muff.__all__:
18 exec("import " + module)
20 # see if the menupath can be retrieved from muffconf
22 if muffconf.get("files", "menus"): pass
24 # otherwise, reload muffconf
25 except AttributeError:
28 # now we can safely nab the menu path setting and build a list of data files
29 menu_path = muffconf.get("files", "menus")
30 menu_files_index = ConfigParser.SafeConfigParser()
31 menu_files_index.read(menu_path + "/index")
33 for each_file in menu_files_index.get("index", "files").split():
34 menu_files.append(menu_path + "/" + each_file)
37 menu_data = ConfigParser.SafeConfigParser()
38 menu_data.read(menu_files)
40 def get_default(user):
41 """Return the default choice for a menu."""
42 return menu_data.get(user.state, "default")
45 """Show the correct menu text to a user."""
47 # the menu hasn't been shown yet since the user's last input
48 if not user.menu_seen:
50 # echo is currently on for the user, so don't add an extra eol
54 # echo is currently off for the user, so add an extra eol
58 # if the user has echo on and the menu specifies it should be
59 # turned off, send: iac + will + echo + null
61 if menu_data.get(user.state, "echo") == "off" and user.echoing:
62 echo = chr(255) + chr(251) + chr(1) + chr(0)
67 # if echo is not set to off in the menu and the user curently
68 # has echo off, send: iac + wont + echo + null
71 echo = chr(255) + chr(252) + chr(1) + chr(0)
76 # and error condition was raised by the handler
79 # try to get an error message matching the condition
82 description = "$(red)" + menu_data.get(user.state, "error_" + user.error) + "$(nrm)$(eol)$(eol)"
84 # otherwise, use a generic one
86 description = "$(red)That is not a valid choice...$(nrm)$(eol)$(eol)"
88 # now clear the error condition
91 # there was no error condition raised by the handler
94 # try to get a menu description for the current state
96 description = menu_data.get(user.state, "description") + "$(eol)$(eol)"
98 # otherwise, leave it blank
102 # try to get menu choices for the current state
105 # build a dict of choice:meaning
107 for option in menu_data.options(user.state):
108 if re.match("choice_", option):
109 choices[option.split("_")[1]] = menu_data.get(user.state, option)
111 # make a sorted list of choices
112 choice_keys = choices.keys()
115 # concatenate them all into a list for display
117 for choice in choice_keys:
118 choicestring += " [$(red)" + choice + "$(nrm)] " + choices[choice] + "$(eol)"
120 # throw in an additional blank line after the choices,
123 choicestring += "$(eol)"
125 # there were no choices, so leave them blank
129 # try to get a prompt, if it was defined
131 prompt = menu_data.get(user.state, "prompt") + " "
133 # otherwise, leave it blank
137 # throw in the default choice, if it exists
139 default = "[$(red)" + menu_data.get(user.state, "default") + "$(nrm)] "
141 # otherwise, leave it blank
145 # echo is on, so don't display a message about it
149 # echo is off, so let the user know
151 echoing = "(won't echo) "
153 # assemble and send the various strings defined above
154 user.send(echo + spacer + description + choicestring + prompt + default + echoing, "")
156 # flag that the menu has now been displayed
157 user.menu_seen = True