docs: def generate(self, docnames=None):
          """Returns entries for index given by ``name``. If ``docnames`` is given,
          restrict to entries referring to these docnames.
  
          Retunrs tuple of ``(content, collapse)``. ``collapse`` is bool. When
          True, sub-entries should start collapsed for output formats that
          support collapsing.
  
          ``content`` is a sequence of ``(letter, entries)`` tuples. ``letter``
          is the "heading" for the given ``entries``, in this case the starting
          letter.
  
          ``entries`` is a sequence of single entries, where a single entry is a
          sequence ``[name, subtype, docname, anchor, extra, qualifier,
          description]``. These items are:
  
          * ``name`` - name of the index entry to be displayed
          * ``subtype`` - sub-entry related type:
  
            * 0 - normal entry
            * 1 - entry with sub-entries
            * 2 - sub-entry
  
          * ``docname`` - docname where the entry is located
          * ``anchor`` - anchor for the entry within docname
          * ``extra`` - extra info for the entry
          * ``qualifier`` - qualifier for the description
          * ``description`` - description for the entry
  
          Qualifier and description are not rendered in some output formats.
          """
          content = {}
  
          # list of prefixes to ignore
          ignores = self.domain.env.config['chapeldomain_modindex_common_prefix']
          ignores = sorted(ignores, key=len, reverse=True)
  
          # list of all modules, sorted by module name
          modules = sorted(iteritems(self.domain.data['modules']),
                           key=lambda x: x[0].lower())
  
          # sort out collapsible modules
          prev_modname = ''
          num_toplevels = 0
          for modname, (docname, synopsis, platforms, deprecated) in modules:
              # If given a list of docnames and current docname is not in it,
              # skip this docname for the index.
              if docnames and docname not in docnames:
                  continue
  
              for ignore in ignores:
                  if modname.startswith(ignore):
                      modname = modname[len(ignore):]
                      stripped = ignore
                      break
              else:
                  stripped = ''
  
              # we stripped the whole module name?
              if not modname:
                  modname, stripped = stripped, ''
  
              # Put the module in correct bucket (first letter).
              entries = content.setdefault(modname[0].lower(), [])
  
              package = modname.split('.')[0]
              if package != modname:
                  # it's a submodule!
                  if prev_modname == package:
                      # first submodule - make parent a group head
                      if entries:
                          entries[-1][1] = 1
                  elif not prev_modname.startswith(package):
                      # submodule without parent in list, add dummy entry
                      entries.append([stripped + package, 1, '', '', '', '', ''])
                  subtype = 2
              else:
                  num_toplevels += 1
                  subtype = 0
  
              qualifier = deprecated and _('Deprecated') or ''
              entries.append([stripped + modname, subtype, docname,
                              'module-' + stripped + modname, platforms,
                              qualifier, synopsis])
              prev_modname = modname
  
          # apply heuristics when to collapse modindex at page load: only
          # collapse if number of toplevel modules is larger than number of
          # submodules
          collapse = len(modules) - num_toplevels < num_toplevels
  
          # sort by first leter
          content = sorted(iteritems(content))
  
          return content, collapse