diff --git a/CHANGES b/CHANGES index 0c968dbfa8d..119932aefab 100644 --- a/CHANGES +++ b/CHANGES @@ -22,6 +22,12 @@ Incompatible changes * Due to the scoping changes for :rst:dir:`productionlist` some uses of :rst:role:`token` must be modified to include the scope which was previously ignored. +* #6462: double backslashes in domain directives are no longer replaced by + single backslashes as default. Each class derived from ObjectDescription + may reenable the stripping for it self. A new configuration value + :confval:`signature_backslash_strip_domain_override` can be used by users + to reenable it per domain as well. Setting it to ``[]`` will reinstate the + old behaviour with backslash stripping in every domain. Deprecated ---------- diff --git a/doc/usage/configuration.rst b/doc/usage/configuration.rst index 4c139695e3e..74c84f86295 100644 --- a/doc/usage/configuration.rst +++ b/doc/usage/configuration.rst @@ -634,6 +634,17 @@ General configuration .. versionchanged:: 1.1 Now also removes ````. +.. confval:: signature_backslash_strip_domain_override + + A list of domain names for which to forcibly reinstate backslash stripping. + The value ``None`` means "no domains" while ``[]`` means every domain + (i.e., the behaviour before version 3.0). + Default is ``None``. + When backslash stripping is enabled then every occurrence of ``\\`` in a domain + directive will be changed to ``\``, even within string literals. + + .. versionadded:: 3.0 + .. _intl-options: diff --git a/sphinx/directives/__init__.py b/sphinx/directives/__init__.py index 9a2fb441205..05519e3968d 100644 --- a/sphinx/directives/__init__.py +++ b/sphinx/directives/__init__.py @@ -58,6 +58,7 @@ class ObjectDescription(SphinxDirective): required_arguments = 1 optional_arguments = 0 final_argument_whitespace = True + strip_backslashes = None option_spec = { 'noindex': directives.flag, } # type: Dict[str, DirectiveOption] @@ -93,8 +94,28 @@ def get_signatures(self) -> List[str]: Backslash-escaping of newlines is supported. """ lines = nl_escape_re.sub('', self.arguments[0]).split('\n') - # remove backslashes to support (dummy) escapes; helps Vim highlighting - return [strip_backslash_re.sub(r'\1', line.strip()) for line in lines] + + # Stripping of backslashes can be overridden by the user config, + # otherwise the object it self may have an opinion, and + # otherwise we don't do stripping. + do_stripping = False + conf_stripping = self.env.config.signature_backslash_strip_domain_override + if conf_stripping is None: + # no user config override, use the object opinion if any + if self.strip_backslashes is not None: + do_stripping = self.strip_backslashes + else: + # could be overridden by the user + if len(conf_stripping) == 0: + # override always (i.e., the old behaviour) + do_stripping = True + elif self.domain is not None: + do_stripping = self.domain in conf_stripping + if do_stripping: + # remove backslashes to support (dummy) escapes; helps Vim highlighting + return [strip_backslash_re.sub(r'\1', line.strip()) for line in lines] + else: + return [line.strip() for line in lines] def handle_signature(self, sig: str, signode: desc_signature) -> Any: """ @@ -291,6 +312,7 @@ def run(self) -> List[Node]: def setup(app: "Sphinx") -> Dict[str, Any]: + app.add_config_value("signature_backslash_strip_domain_override", None, 'env') directives.register_directive('default-role', DefaultRole) directives.register_directive('default-domain', DefaultDomain) directives.register_directive('describe', ObjectDescription)