X-Git-Url: https://mudpy.org/gitweb?p=mudpy.git;a=blobdiff_plain;f=lib%2Fmuff%2Fmuffmenu.py;h=daf65125dd323c7cf0944567f65749833cc61cd1;hp=cdf0d5c21868b175d688991af98448af4ad19956;hb=da136e612520ef6a3a19d99563e44b6518f91e7e;hpb=1ff00115321d800bec7313a3fdfc97a8b0b006fa diff --git a/lib/muff/muffmenu.py b/lib/muff/muffmenu.py index cdf0d5c..daf6512 100644 --- a/lib/muff/muffmenu.py +++ b/lib/muff/muffmenu.py @@ -6,12 +6,6 @@ # muff uses menu data stored in ini-style files supported by ConfigParser import ConfigParser -# os.listdir is needed to get a file listing from a config directory -import os - -# re.match is used to find menu options based on the choice_ prefix -import re - # hack to load all modules in the muff package import muff for module in muff.__all__: @@ -37,122 +31,170 @@ for each_file in menu_files_index.get("index", "files").split(): menu_data = ConfigParser.SafeConfigParser() menu_data.read(menu_files) -def get_default(user): - """Return the default choice for a menu.""" - return menu_data.get(user.state, "default") - -def get_menu(user): +def get_menu(state, error=None, echoing=True, choices={}): """Show the correct menu text to a user.""" - # the menu hasn't been shown yet since the user's last input - if not user.menu_seen: - - # echo is currently on for the user, so don't add an extra eol - if user.echoing: - spacer = "" + # begin with a telnet echo command sequence if needed + message = get_echo_sequence(state, echoing) - # echo is currently off for the user, so add an extra eol - else: - spacer = "$(eol)" + # get the description or error text + message += get_menu_description(state, error) - # if the user has echo on and the menu specifies it should be - # turned off, send: iac + will + echo + null - try: - if menu_data.get(user.state, "echo") == "off" and user.echoing: - echo = chr(255) + chr(251) + chr(1) + chr(0) - user.echoing = False - else: - echo = "" - - # if echo is not set to off in the menu and the user curently - # has echo off, send: iac + wont + echo + null - except: - if not user.echoing: - echo = chr(255) + chr(252) + chr(1) + chr(0) - user.echoing = True - else: - echo = "" - - # and error condition was raised by the handler - if user.error: + # get menu choices for the current state + message += get_formatted_menu_choices(state, choices) - # try to get an error message matching the condition - # and current state - try: - description = "$(red)" + menu_data.get(user.state, "error_" + user.error) + "$(nrm)$(eol)$(eol)" + # try to get a prompt, if it was defined + message += get_menu_prompt(state) - # otherwise, use a generic one - except: - description = "$(red)That is not a valid choice...$(nrm)$(eol)$(eol)" + # throw in the default choice, if it exists + message += get_formatted_default_menu_choice(state) - # now clear the error condition - user.error = "" + # display a message indicating if echo is off + message += get_echo_message(state) - # there was no error condition raised by the handler - else: + # return the assembly of various strings defined above + return message - # try to get a menu description for the current state - try: - description = menu_data.get(user.state, "description") + "$(eol)$(eol)" +def menu_echo_on(state): + """True if echo is on, false if it is off.""" + try: + return menu_data.getboolean(state, "echo") + except: + return True - # otherwise, leave it blank - except: - description = "" - - # try to get menu choices for the current state - try: +def get_echo_sequence(state, echoing): + """Build the appropriate IAC ECHO sequence as needed.""" - # build a dict of choice:meaning - choices = {} - for option in menu_data.options(user.state): - if re.match("choice_", option): - choices[option.split("_")[1]] = menu_data.get(user.state, option) + # if the user has echo on and the menu specifies it should be turned + # off, send: iac + will + echo + null + if echoing and not menu_echo_on(state): return chr(255) + chr(251) + chr(1) + chr(0) - # make a sorted list of choices - choice_keys = choices.keys() - choice_keys.sort() + # if echo is not set to off in the menu and the user curently has echo + # off, send: iac + wont + echo + null + elif not echoing and menu_echo_on(state): return chr(255) + chr(252) + chr(1) + chr(0) - # concatenate them all into a list for display - choicestring = "" - for choice in choice_keys: - choicestring += " [$(red)" + choice + "$(nrm)] " + choices[choice] + "$(eol)" + # default is not to send an echo control sequence at all + else: return "" - # throw in an additional blank line after the choices, - # if there were any - if choicestring: - choicestring += "$(eol)" +def get_echo_message(state): + """Return a message indicating that echo is off.""" + if menu_echo_on(state): return "" + else: return "(won't echo) " - # there were no choices, so leave them blank - except: - choicestring = "" - - # try to get a prompt, if it was defined +def get_default_menu_choice(state): + """Return the default choice for a menu.""" + try: + return menu_data.get(state, "default") + except: + return "" +def get_formatted_default_menu_choice(state): + """Default menu choice foratted for inclusion in a prompt string.""" + default = get_default_menu_choice(state) + if default: return "[$(red)" + default + "$(nrm)] " + else: return "" + +def get_menu_description(state, error): + """Get the description or error text.""" + + # an error condition was raised by the handler + if error: + + # try to get an error message matching the condition + # and current state try: - prompt = menu_data.get(user.state, "prompt") + " " + return "$(red)" + menu_data.get(state, "error_" + error) + "$(nrm)$(eol)$(eol)" - # otherwise, leave it blank + # otherwise, use a generic one except: - prompt = "" + return "$(red)That is not a valid choice...$(nrm)$(eol)$(eol)" + + # there was no error condition + else: - # throw in the default choice, if it exists + # try to get a menu description for the current state try: - default = "[$(red)" + menu_data.get(user.state, "default") + "$(nrm)] " + return menu_data.get(state, "description") + "$(eol)$(eol)" # otherwise, leave it blank except: - default = "" - - # echo is on, so don't display a message about it - if user.echoing: - echoing = "" - - # echo is off, so let the user know - else: - echoing = "(won't echo) " - - # assemble and send the various strings defined above - user.send(echo + spacer + description + choicestring + prompt + default + echoing, "") - - # flag that the menu has now been displayed - user.menu_seen = True + return "" + +def get_menu_prompt(state): + """Try to get a prompt, if it was defined.""" + try: + return menu_data.get(state, "prompt") + " " + except: + return "" + +def get_menu_choices(user): + """Return a dict of choice:meaning.""" + choices = {} + for option in menu_data.options(user.state): + if option.startswith("choice_"): + choices[option.split("_", 2)[1]] = menu_data.get(user.state, option) + elif option.startswith("create_"): + choices[option.split("_", 2)[1]] = eval(menu_data.get(user.state, option)) + return choices + +def get_formatted_menu_choices(state, choices): + """Returns a formatted string of menu choices.""" + choice_output = "" + choice_keys = choices.keys() + choice_keys.sort() + for choice in choice_keys: + choice_output += " [$(red)" + choice + "$(nrm)] " + choices[choice] + "$(eol)" + if choice_output: choice_output += "$(eol)" + return choice_output + +def get_menu_branches(state): + """Return a dict of choice:branch.""" + branches = {} + try: + for option in menu_data.options(state): + if option.startswith("branch_"): + branches[option.split("_", 2)[1]] = menu_data.get(state, option) + except: + pass + return branches + +def get_default_branch(state): + """Return the default branch.""" + try: + return menu_data.get(state, "branch") + except: + return "" + +def get_choice_branch(user, choice): + """Returns the new state matching the given choice.""" + branches = get_menu_branches(user.state) + if not choice: choice = get_default_menu_choice(user.state) + if choice in branches.keys(): return branches[choice] + elif choice in user.menu_choices.keys(): return get_default_branch(user.state) + else: return "" + +def get_menu_actions(state): + """Return a dict of choice:branch.""" + actions = {} + try: + for option in menu_data.options(state): + if option.startswith("action_"): + actions[option.split("_", 2)[1]] = menu_data.get(state, option) + except: + pass + return actions + +def get_default_action(state): + """Return the default action.""" + try: + return menu_data.get(state, "action") + except: + return "" + +def get_choice_action(user, choice): + """Run any indicated script for the given choice.""" + actions = get_menu_actions(user.state) + if not choice: choice = get_default_menu_choice(user.state) + if choice in actions.keys(): return actions[choice] + elif choice in user.menu_choices.keys(): return get_default_action(user.state) + else: return ""