diff --git a/CHANGES b/CHANGES index cb4499c4e..33bce4e1a 100644 --- a/CHANGES +++ b/CHANGES @@ -116,6 +116,7 @@ Deprecated * ``sphinx.io.SphinxRSTFileInput`` * ``sphinx.registry.SphinxComponentRegistry.add_source_input()`` * ``sphinx.roles.abbr_role()`` +* ``sphinx.roles.menusel_role()`` * ``sphinx.roles.index_role()`` * ``sphinx.roles.indexmarkup_role()`` * ``sphinx.testing.util.remove_unicode_literal()`` diff --git a/doc/extdev/index.rst b/doc/extdev/index.rst index a7f84d2ea..2066e95cc 100644 --- a/doc/extdev/index.rst +++ b/doc/extdev/index.rst @@ -380,6 +380,11 @@ The following is a list of deprecated interfaces. - 4.0 - ``sphinx.roles.Abbreviation`` + * - ``sphinx.roles.menusel_role()`` + - 2.0 + - 4.0 + - ``sphinx.roles.GUILabel`` or ``sphinx.roles.MenuSelection`` + * - ``sphinx.roles.index_role()`` - 2.0 - 4.0 diff --git a/sphinx/roles.py b/sphinx/roles.py index c77feeb62..db3feddc3 100644 --- a/sphinx/roles.py +++ b/sphinx/roles.py @@ -325,6 +325,9 @@ _amp_re = re.compile(r'(? Tuple[List[nodes.Node], List[nodes.system_message]] # NOQA + warnings.warn('menusel_role() is deprecated. ' + 'Please use MenuSelection or GUILabel class instead.', + RemovedInSphinx40Warning, stacklevel=2) env = inliner.document.settings.env if not typ: assert env.temp_data['default_role'] @@ -357,6 +360,32 @@ def menusel_role(typ, rawtext, text, lineno, inliner, options={}, content=[]): return [node], [] +class GUILabel(SphinxRole): + amp_re = re.compile(r'(? Tuple[List[nodes.Node], List[nodes.system_message]] + node = nodes.inline(rawtext=self.rawtext, classes=[self.name]) + spans = self.amp_re.split(self.text) + node += nodes.Text(spans.pop(0)) + for span in spans: + span = span.replace('&&', '&') + + letter = nodes.Text(span[0]) + accelerator = nodes.inline('', '', letter, classes=['accelerator']) + node += accelerator + node += nodes.Text(span[1:]) + + return [node], [] + + +class MenuSelection(GUILabel): + def run(self): + # type: () -> Tuple[List[nodes.Node], List[nodes.system_message]] + self.text = self.text.replace('-->', '\N{TRIANGULAR BULLET}') # type: ignore + return super().run() + + _litvar_re = re.compile('{([^}]+)}') parens_re = re.compile(r'(\\*{|\\*})') @@ -507,8 +536,8 @@ specific_docroles = { 'pep': PEP(), 'rfc': RFC(), - 'guilabel': menusel_role, - 'menuselection': menusel_role, + 'guilabel': GUILabel(), + 'menuselection': MenuSelection(), 'file': emph_literal_role, 'samp': emph_literal_role, 'abbr': Abbreviation(), diff --git a/tests/test_markup.py b/tests/test_markup.py index 1aa544bf6..9d995ff98 100644 --- a/tests/test_markup.py +++ b/tests/test_markup.py @@ -225,6 +225,13 @@ def get_verifier(verify, verify_re): '-&- Bar
'), r'\sphinxguilabel{\sphinxaccelerator{F}oo -\&- \sphinxaccelerator{B}ar}', ), + ( + # no ampersands in guilabel + 'verify', + ':guilabel:`Foo`', + 'Foo
', + r'\sphinxguilabel{Foo}', + ), ( # non-interpolation of dashes in option role 'verify_re',