import re


def list_items_to_text(docs):
    """
    Convert HTML list items to plain text.

    The result is in reST(reStructuredText) format, which is suitable for
    Python's Sphinx documentation generator, and is also very human readable.
    """
    docs = docs.strip()

    # Remove any <ul> tags (the <li> tags are all we need)
    docs = re.sub("</?ul[^>]*>", "", docs)

    # Iterate through all the <li> start and end tags, tracking the nested
    # list depth (-1 => not in a list, 0 => in top-level list, ...)
    result = ''
    depth = -1
    end_idx = 0

    for li_match in re.finditer(re.compile("</?li[^>]*>"), docs):
        li_start = li_match.start()
        li_end = li_match.end()
        li_text = li_match.group()

        # Add on the next segment of text. If we're in a list, remove any
        # other HTML tags it contains so list items are plain text.
        segment = docs[end_idx:li_start].strip()
        if depth >= 0: segment = re.sub("<[^>]+>", "", segment)

        if segment:
            if depth >= 0:
                # We're in a list, so add a bullet point marker to the first
                # line and align any later lines with the first line's text
                segment = re.sub("(?m)^\\s*", "  ", segment)
                segment = "* " + segment[2:]

                # Add more indentation according to the list nesting depth
                if depth > 0: segment = re.sub("(?m)^", "  "*depth, segment)

            # Add the segment, with a blank line before (and later, after)
            # for compatibility with Sphinx
            if result: result += "\n\n"
            result += segment
        end_idx = li_end

        # Track the list nesting depth
        if li_text.startswith("<li"): depth += 1
        elif depth >= 0: depth -= 1

    # Add the final segment (assumed to not be in a list)
    segment = docs[end_idx:].strip()
    if segment:
        if result: result += "\n\n"
        result += segment

    return result