sphinx-doc / sphinx

The Sphinx documentation generator
https://www.sphinx-doc.org/
Other
6.6k stars 2.12k forks source link

Document suppressing cross-references via ! prefix #12940

Closed timhoffm closed 1 month ago

timhoffm commented 1 month ago

I just learned from the sphinx doc sources that one can disable cross-references by prefixing the reference with an exclamation mark.

The relevant source code seems to be:

https://github.com/sphinx-doc/sphinx/blob/341b0417d5ccc2b495276cd60c5c6d8accd2a72c/sphinx/util/docutils.py#L602-L603

I haven't found anything about this in the documentation. Is this an official feature? If so, we should document it.

AA-Turner commented 1 month ago

The main documentation is at (1), with (2) giving a precis. However, if an experienced user (read: you) has missed this, perhaps there's an opportunity for improvement or more cross-links?

  1. https://www.sphinx-doc.org/en/master/usage/referencing.html
  2. https://www.sphinx-doc.org/en/master/usage/domains/index.html#cross-referencing-syntax

There's also some Python-specific text on name resolution at the bottom of https://www.sphinx-doc.org/en/master/usage/domains/python.html, though unhelpfully there's no heading to link to:

Normally, names in these roles are searched first without any further qualification, then with the current module name prepended, then with the current module and class name (if any) prepended. If you prefix the name with a dot, this order is reversed. For example, in the documentation of Python’s codecs module, :py:func:`open` always refers to the built-in function, while :py:func:`.open` refers to codecs.open().

A similar heuristic is used to determine whether the name is an attribute of the currently documented class.

Also, if the name is prefixed with a dot, and no exact match is found, the target is taken as a suffix and all object names with that suffix are searched. For example, :py:meth:`.TarFile.close` references the tarfile.TarFile.close() function, even if the current module is not tarfile. Since this can get ambiguous, if there is more than one possible match, you will get a warning from Sphinx.

Note that you can combine the ~ and . prefixes: :py:meth:`~.TarFile.close` will reference the tarfile.TarFile.close() method, but the visible link caption will only be close().

A

timhoffm commented 1 month ago

Thanks for the links.

I have indeed missed this, likely because the description is quite dense. After I've seen examples in the docs, I've tried to find this in reverse, searching for `! and exclamation mark both in source and on the doc search site.

I'll come up with a suggestion how to improve the docs.

electric-coder commented 1 month ago

I'll come up with a suggestion how to improve the docs.

I'll make an argument that the exclamation mark ! functionality is "marginal" (if you're writing a cross-reference why would you want to disable linking given it's so convenient?). Hence it gets mentioned once (right at the top of the Cross-referencing syntax doc in one of three prominent bullet-points) and that's it. It's also straightforward and thus a trivial feature that doesn't cause any doubts to users who know about it.

Now, I do agree the exclamation mark ! itself needs more emphasis in that doc. The best option might be adding triple backticks around it for visibility. Or a simple pair of backticks with bold. Naming the punctuation mark explicitly might also emphasize it enough, so:

If you prefix the content with an exclamation mark !, no reference/hyperlink will be created.

It can make sense to add a trivial usage example, it might not have been done to avoid new users from wondering too much about a functionality that likely isn't a priority.

timhoffm commented 1 month ago

How to improve:


if you're writing a cross-reference why would you want to disable linking given it's so convenient?

There are cases where the target does not exist and you don't want warnings about that:

AA-Turner commented 1 month ago

I would strongly counter that suppressing cross-references is "marginal", it is an extremely useful feature. For example, when referencing the same object twice in a paragraph, keeping the same presentational style but only one link (for the first instance) is only possible with suppressed cross references. As Tim notes, references to functions that have been removed, or protocol functions, or third-party libraries without intersphinx, using reference suppression enables keeping the presentation of functions (e.g. automatic trailing brackets ()) and any custom CSS styles, but without reference failures.

It also enables easier find-and-replace in the future, as :role_name: is much easier to search for than simply the literal pattern.

For some statistics, in the Python documentation there are over three and a half thousand uses (~3,700) of :`! indicating a suppressed reference, and 53,000 uses of :` (for all interpreted text roles), so ~7% of all roles used (including those that don't support !).

A

electric-coder commented 1 month ago

add a "heading" to the bullet points

@timhoffm I think that's probably the clearest and most stylish choice!

@AA-Turner very insightful sum up of the use cases! Makes lots of sense.