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 # hack to load all modules in the muff package
11 for module in muff.__all__:
12 exec("import " + module)
14 # see if the menupath can be retrieved from muffconf
16 if muffconf.get("files", "menus"): pass
18 # otherwise, reload muffconf
19 except AttributeError:
22 # now we can safely nab the menu path setting and build a list of data files
23 menu_path = muffconf.get("files", "menus")
24 menu_files_index = ConfigParser.SafeConfigParser()
25 menu_files_index.read(menu_path + "/index")
27 for each_file in menu_files_index.get("index", "files").split():
28 menu_files.append(menu_path + "/" + each_file)
31 menu_data = ConfigParser.SafeConfigParser()
32 menu_data.read(menu_files)
34 def get_menu(state, error=None, echoing=True, choices={}):
35 """Show the correct menu text to a user."""
37 # begin with a telnet echo command sequence if needed
38 message = get_echo_sequence(state, echoing)
40 # get the description or error text
41 message += get_menu_description(state, error)
43 # get menu choices for the current state
44 message += get_formatted_menu_choices(state, choices)
46 # try to get a prompt, if it was defined
47 message += get_menu_prompt(state)
49 # throw in the default choice, if it exists
50 message += get_formatted_default_menu_choice(state)
52 # display a message indicating if echo is off
53 message += get_echo_message(state)
55 # return the assembly of various strings defined above
58 def menu_echo_on(state):
59 """True if echo is on, false if it is off."""
61 return menu_data.getboolean(state, "echo")
65 def get_echo_sequence(state, echoing):
66 """Build the appropriate IAC ECHO sequence as needed."""
68 # if the user has echo on and the menu specifies it should be turned
69 # off, send: iac + will + echo + null
70 if echoing and not menu_echo_on(state): return chr(255) + chr(251) + chr(1) + chr(0)
72 # if echo is not set to off in the menu and the user curently has echo
73 # off, send: iac + wont + echo + null
74 elif not echoing and menu_echo_on(state): return chr(255) + chr(252) + chr(1) + chr(0)
76 # default is not to send an echo control sequence at all
79 def get_echo_message(state):
80 """Return a message indicating that echo is off."""
81 if menu_echo_on(state): return ""
82 else: return "(won't echo) "
84 def get_default_menu_choice(state):
85 """Return the default choice for a menu."""
87 return menu_data.get(state, "default")
90 def get_formatted_default_menu_choice(state):
91 """Default menu choice foratted for inclusion in a prompt string."""
92 default = get_default_menu_choice(state)
93 if default: return "[$(red)" + default + "$(nrm)] "
96 def get_menu_description(state, error):
97 """Get the description or error text."""
99 # an error condition was raised by the handler
102 # try to get an error message matching the condition
105 return "$(red)" + menu_data.get(state, "error_" + error) + "$(nrm)$(eol)$(eol)"
107 # otherwise, use a generic one
109 return "$(red)That is not a valid choice...$(nrm)$(eol)$(eol)"
111 # there was no error condition
114 # try to get a menu description for the current state
116 return menu_data.get(state, "description") + "$(eol)$(eol)"
118 # otherwise, leave it blank
122 def get_menu_prompt(state):
123 """Try to get a prompt, if it was defined."""
125 return menu_data.get(state, "prompt") + " "
129 def get_menu_choices(user):
130 """Return a dict of choice:meaning."""
132 for option in menu_data.options(user.state):
133 if option.startswith("choice_"):
134 choices[option.split("_", 2)[1]] = menu_data.get(user.state, option)
135 elif option.startswith("create_"):
136 choices[option.split("_", 2)[1]] = eval(menu_data.get(user.state, option))
139 def get_formatted_menu_choices(state, choices):
140 """Returns a formatted string of menu choices."""
142 choice_keys = choices.keys()
144 for choice in choice_keys:
145 choice_output += " [$(red)" + choice + "$(nrm)] " + choices[choice] + "$(eol)"
146 if choice_output: choice_output += "$(eol)"
149 def get_menu_branches(state):
150 """Return a dict of choice:branch."""
153 for option in menu_data.options(state):
154 if option.startswith("branch_"):
155 branches[option.split("_", 2)[1]] = menu_data.get(state, option)
160 def get_default_branch(state):
161 """Return the default branch."""
163 return menu_data.get(state, "branch")
167 def get_choice_branch(user, choice):
168 """Returns the new state matching the given choice."""
169 branches = get_menu_branches(user.state)
170 if not choice: choice = get_default_menu_choice(user.state)
171 if choice in branches.keys(): return branches[choice]
172 elif choice in user.menu_choices.keys(): return get_default_branch(user.state)
175 def get_menu_actions(state):
176 """Return a dict of choice:branch."""
179 for option in menu_data.options(state):
180 if option.startswith("action_"):
181 actions[option.split("_", 2)[1]] = menu_data.get(state, option)
186 def get_default_action(state):
187 """Return the default action."""
189 return menu_data.get(state, "action")
193 def get_choice_action(user, choice):
194 """Run any indicated script for the given choice."""
195 actions = get_menu_actions(user.state)
196 if not choice: choice = get_default_menu_choice(user.state)
197 if choice in actions.keys(): return actions[choice]
198 elif choice in user.menu_choices.keys(): return get_default_action(user.state)