Prompt a string with autocompletion

    :param complete: A function that returns a list of possible strings that
        should be completed on a given text.
        def complete(text: str) -> List[str]: ...

def prompt_autocomplete(prompt, complete, default=None, contains_spaces=True, 
                        show_default=True, prompt_suffix=': ', color=None):
    """
    Prompt a string with autocompletion

    :param complete: A function that returns a list of possible strings that
        should be completed on a given text.
        def complete(text: str) -> List[str]: ...
    """

    def real_completer(text, state):
        possibilities = complete(text) + [None]

        if possibilities:
            return possibilities[state]
        return None

    readline.set_completer_delims('\t\n' + ' ' * (not contains_spaces))
    readline.parse_and_bind("tab: complete")
    readline.set_completer(real_completer)
    
    if default is not None and show_default:
        prompt += ' [%s]' % default

    prompt += prompt_suffix

    colors = {
        'red': Fore.RED,
        'blue': Fore.BLUE,
        'green': Fore.GREEN,
        'cyan': Fore.CYAN,
        'magenta': Fore.MAGENTA,
        'yellow': Fore.YELLOW,
        'white': Fore.WHITE,
        'black': Fore.LIGHTBLACK_EX
    }

    if color:
        prompt = colors[color.lower()] + prompt + Fore.RESET

    if default is not None:
        r = input(prompt)
    else:
        while True:
            r = input(prompt)
            if r:
                break

    r = r or default

    # remove the autocompletion before quitting for future input()
    readline.parse_and_bind('tab: self-insert')
    readline.set_completer(None)

    return r