def truncate(text, max_len, fill="..."):
    """
    Truncate given text to a given maximum length.

    Parameters
    ----------
    text : str
        The text to truncate.
    max_len : int
        The maximum allowed length for `text`. If `text` is longer than
        `max_len` it will be shortened, otherwise it will remain unchanged.
    fill : str, optional
        The string that should be displayed at the end of the truncated text to
        indicate truncation. If `max_len` is too short, the fill may be omitted
        or changed. Defaults to `...`.

    Returns
    -------
    str
        The truncated (or unchanged) text, of length no greater than `max_len`
        (including any filling added at the end).
    """

    if max_len <= 0:
        return ""

    if max_len < len(fill):
        fill = "~"

    if len(text) > max_len:
        end_len = max(0, max_len - len(fill))
        text = text[:end_len] + fill

    try:
        assert len(text) <= max_len
    except AssertionError:
        raise AssertionError("{text} {max_len}".format(**locals()))
    return text