import click


def select(choices, prompt="Please choose one", default=0, required=True):
    """ Let the user pick one of several choices.


    :param choices:     Available choices along with their description
    :type choices:      iterable of (object, str) tuples
    :param default:     Index of default choice
    :type default:      int
    :param required:    If true, `None` can be returned
    :returns:           The object the user picked or None.
    """
    choices = list(choices)
    for idx, choice in enumerate(choices):
        _, choice_label = choice
        if '\x1b' not in choice_label:
            choice_label = click.style(choice_label, fg='blue')
        click.echo(
            u"{key} {description}".format(
                key=click.style(u"[{}]".format(idx), fg='green'),
                description=choice_label))
    while True:
        choice_idx = click.prompt(prompt, default=default, type=int, err=True)
        cutoff = -1 if not required else 0
        if choice_idx < cutoff or choice_idx >= len(choices):
            click.echo(
                "Value must be between {} and {}!"
                .format(cutoff, len(choices)-1), err=True)
        elif choice_idx == -1:
            return None
        else:
            return choices[choice_idx][0]