def ask_choice(<EOL>*prompt: Token, choices: List[Any], func_desc: Optional[FuncDesc] = None<EOL>) -> Any:
if func_desc is None:<EOL><INDENT>func_desc = lambda x: str(x)<EOL><DEDENT>tokens = get_ask_tokens(prompt)<EOL>info(*tokens)<EOL>choices.sort(key=func_desc)<EOL>for i, choice in enumerate(choices, start=<NUM_LIT:1>):<EOL><INDENT>choice_desc = func_desc(choice)<EOL>info("<STR_LIT:U+0020>", blue, "<STR_LIT>" % i, reset, choice_desc)<EOL><DEDENT>keep_asking = True<EOL>res = None<EOL>while keep_asking:<EOL><INDENT>answer = read_input()<EOL>if not answer:<EOL><INDENT>return None<EOL><DEDENT>try:<EOL><INDENT>index = int(answer)<EOL><DEDENT>except ValueError:<EOL><INDENT>info("<STR_LIT>")<EOL>continue<EOL><DEDENT>if index not in range(<NUM_LIT:1>, len(choices) + <NUM_LIT:1>):<EOL><INDENT>info(str(index), "<STR_LIT>")<EOL>continue<EOL><DEDENT>res = choices[index - <NUM_LIT:1>]<EOL>keep_asking = False<EOL><DEDENT>return res<EOL>
Ask the user to choose from a list of choices.

    :return: the selected choice

    ``func_desc`` will be called on every list item for displaying
    and sorting the list. If not given, will default to
    the identity function.

    Will loop until:
        * the user enters a valid index
        * or leaves the prompt empty

    In the last case, None will be returned