def add_search_index_criteria(prepend=False):
    """
    Add the search criteria used when calling :meth:`register() <cqparts.search.register>`
    on a :class:`Component <cqparts.Component>` as a table to the *docstring*.

    This is only intended to be used with *sphinx autodoc*.

    In your *sphinx* ``config.py`` file::

        from cqparts.utils.sphinx import add_search_index_criteria
        def setup(app):
            app.connect("autodoc-process-docstring", add_search_index_criteria())

    Then, when documenting your :class:`Part <cqparts.Part>` or
    :class:`Assembly <cqparts.Assembly>` the
    search criteria will also be documented in the output.

    :param prepend: if True, table is added to the beginning of the *docstring*.
                    otherwise, it's appended at the end.
    :type prepend: :class:`bool`
    """

    from ..search import class_criteria
    from .. import Component

    COLUMN_INFO = [
        # (<title>, <width>, <method>),
        ('Key', 50, lambda k, v: "``%s``" % k),
        ('Value', 10, lambda k, v: ', '.join("``%s``" % w for w in v)),
    ]  # note: last column width is irrelevant

    def param_lines(app, obj):
        doc_lines = []

        criteria = class_criteria.get(obj, {})
        row_seperator = ' '.join(('=' * w) for (_, w, _) in COLUMN_INFO)

        # Header
        if criteria:  # only add a header if it's relevant
            doc_lines += [
                "**Search Criteria:**",
                "",
                "This object can be found with :meth:`find() <cqparts.search.find>` ",
                "and :meth:`search() <cqparts.search.search>` using the following ",
                "search criteria.",
                "",
                row_seperator,
                ' '.join((("%%-%is" % w) % t) for (t, w, _) in COLUMN_INFO),
                row_seperator,
            ]

        # Add criteria
        for (key, value) in sorted(criteria.items(), key=lambda x: x[0]):
            doc_lines.append(' '.join(
                ("%%-%is" % w) % m(key, value)
                for (_, w, m) in COLUMN_INFO
            ))

        # Footer
        if criteria:
            doc_lines += [
                row_seperator,
                "",
            ]

        return doc_lines

    # Conditions for running above `param_lines` function (in order)
    conditions = [  # (all conditions must be met)
        lambda o: type(o) == type,
        lambda o: o is not Component,
        lambda o: issubclass(o, Component),
    ]

    def callback(app, what, name, obj, options, lines):
        # sphinx callback
        # (this method is what actually gets sent to the sphinx runtime)
        if all(c(obj) for c in conditions):
            new_lines = param_lines(app, obj)
            _add_lines(lines, new_lines, prepend=prepend)

    return callback