toonarmycaptain/dionysus

Factor out menu choice

Aberta

#154 aberto em 21 de fev. de 2019

 (2 comentários) (0 reação) (0 responsável)Python (14 forks)auto 404
enhancementgood first issuesize/M

Métricas do repositório

Stars
 (10 estrelas)
Métricas de merge de PR
 (Nenhuma PRs mesclada em 30d)

Description

The code for taking user input to choose and run items from menus in main_menu.py and settings_menu.py deploy similar functionality which can be factored out.

take_settings_menu_input was recently refactored here and here not to use a flag to break the loop, matching the implementation in main_menu.py: https://github.com/toonarmycaptain/dionysus/blob/6046e12e01eb648d7c38d97f3948b911599ba020/dionysus_app/UI_menus/settings_menu.py#L41-L55)

To generalise the function I propose reintroducing a flag, returned by the functions corresponding to the options in a menu, that would indicate a return to a higher menu/scope. This also reintroduces using a function for breaking the loop/menu without action, as originally implemented in settings_menu.py (albeit with stdout user feedback).

This would allow any function to break the take/run menu selection loop with a flag returned to the calling menu logic, which may have a variety of uses - for example returning False if the action was unsuccessful could trigger feedback to the user before displaying the menu again eg Action unsuccessful. Please select another option: {menu options}. These implementations make assumptions about what the called functions return:

Assume only True is a relevant return value:

while True:
    chosen_option = input('>>> ')

    if chosen_option in possible_options:
        if possible_options[chosen_option]():  # or more explicitly: if possible_options[chosen_option]() is True:
            return True
        break  # Exit loop when chosen action finishes. Returns None.
    # else:
    print("Invalid input.")

Or to be able to return True or False flags: Assumes True and False are relevant return values.

while True:
    chosen_option = input('>>> ')

    if chosen_option in possible_options:
        return_flag = possible_options[chosen_option]()
        if return_flag is not None:
            return return_flag
        break  # Exit loop when chosen action finishes. Returns None.
    # else:
    print("Invalid input.")

Alternatively, assuming functions will return None, True or False - or equivalent values : A weakness of this approach is that there is a risk of bugs creeping in where functions happen to return an object (eg str, dict) that evaluates to True/False/None that the caller will then interpret as those values - which may be useful, or a source of bugs.

while True:
    chosen_option = input('>>> ')

    if chosen_option in possible_options:
        return possible_options[chosen_option]()
    # else:
    print("Invalid input.")

While the above is very elegant/simple, a more explicit implementation might be preferable:

while True:
    chosen_option = input('>>> ')

    if chosen_option in possible_options:
        return_flag = possible_options[chosen_option]()
        if return_flag is True or return_flag is  False or return_flag is  None:
            return return_flag
        break  # Exit loop when chosen action finishes. Returns None.
    # else:
    print("Invalid input.")

Guia do colaborador