diff --git a/CHANGES b/CHANGES index 583bece5c41..9409e16aa3f 100644 --- a/CHANGES +++ b/CHANGES @@ -63,6 +63,7 @@ Features added ``no-scaled-link`` class * #7144: Add CSS class indicating its domain for each desc node * #7211: latex: Use babel for Chinese document when using XeLaTeX +* #7220: genindex: Show "main" index entries at first Bugs fixed ---------- diff --git a/sphinx/environment/adapters/indexentries.py b/sphinx/environment/adapters/indexentries.py index 1d135bd32bf..dbc94f846a8 100644 --- a/sphinx/environment/adapters/indexentries.py +++ b/sphinx/environment/adapters/indexentries.py @@ -7,7 +7,7 @@ :copyright: Copyright 2007-2020 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ -import bisect + import re import unicodedata from itertools import groupby @@ -52,8 +52,7 @@ def add_entry(word: str, subword: str, main: str, link: bool = True, except NoUri: pass else: - # maintain links in sorted/deterministic order - bisect.insort(entry[0], (main, uri)) + entry[0].append((main, uri)) domain = cast(IndexDomain, self.env.get_domain('index')) for fn, entries in domain.entries.items(): @@ -89,6 +88,16 @@ def add_entry(word: str, subword: str, main: str, link: bool = True, except ValueError as err: logger.warning(str(err), location=fn) + # sort the index entries for same keyword. + def keyfunc0(entry: Tuple[str, str]) -> Tuple[bool, str]: + main, uri = entry + return (not main, uri) # show main entries at first + + for indexentry in new.values(): + indexentry[0] = sorted(indexentry[0], key=keyfunc0) + for subentry in indexentry[1].values(): + subentry[0] = sorted(subentry[0], key=keyfunc0) # type: ignore + # sort the index entries; put all symbols at the front, even those # following the letters in ASCII, this is where the chr(127) comes from def keyfunc(entry: Tuple[str, List]) -> Tuple[str, str]: diff --git a/tests/test_environment_indexentries.py b/tests/test_environment_indexentries.py index 685b365992c..97882d44b33 100644 --- a/tests/test_environment_indexentries.py +++ b/tests/test_environment_indexentries.py @@ -112,6 +112,21 @@ def test_create_seealso_index(app): assert index[2] == ('S', [('Sphinx', [[], [('see also documentation tool', [])], None])]) +@pytest.mark.sphinx('dummy', freshenv=True) +def test_create_main_index(app): + text = (".. index:: !docutils\n" + ".. index:: docutils\n" + ".. index:: pip; install\n" + ".. index:: !pip; install\n") + restructuredtext.parse(app, text) + index = IndexEntries(app.env).create_index(app.builder) + assert len(index) == 2 + assert index[0] == ('D', [('docutils', [[('main', '#index-0'), + ('', '#index-1')], [], None])]) + assert index[1] == ('P', [('pip', [[], [('install', [('main', '#index-3'), + ('', '#index-2')])], None])]) + + @pytest.mark.sphinx('dummy', freshenv=True) def test_create_index_with_name(app): text = (".. index:: single: docutils\n"