sphinx-doc / sphinx

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

Using custom pygments styles #9105

Open 8thHalfHour opened 3 years ago

8thHalfHour commented 3 years ago

Describe the bug

There is a lot of conflicting information as to how to add custom pygments styles to Sphinx docs to be found online and in Sphinx theme issues, many of which seem to work for some people and not for others. Therefore, I would like to see an 'officially' recommended method of adding custom pygment styles to Sphinx added to the documentation so that it is very clear and easy to understand how to make a new style override any within the installed theme. Examples would be awesome.

To Reproduce

N/A

Expected behavior

There should be at least one detailed, easily consumable description of how to add custom pygments styles to Sphinx themes included in the official documentation.

Your project

N/A

Screenshots

N/A

Environment info

Additional context

A much more detailed explanation of the issue, expectations, and suggested resolution, is located at the original issue on RTD #1124. Please review.

tk0miya commented 3 years ago

At present, Sphinx provides the pygments_style configuration to switch the style of pygments. It takes a pygments style name that bundled with the pygments package, or the full-qualified name of your custom pygments style class. https://www.sphinx-doc.org/en/master/usage/configuration.html#confval-pygments_style

I agree with the explanation is not enough. So it would be nice if somebody will send a pull request to add an example.

tk0miya commented 3 years ago

Note: I don't understand adding a new API; Sphinx.add_pygments_style() is useful. The current implementation already supports loading a custom style via its full-qualified name. So I think a new API is not needed for this case.

cc: @Blendify

8thHalfHour commented 3 years ago

So, the following would be helpful to know:

  1. Where is a new pygments style placed for Sphinx to find it to refer to it? a. For instance, is there like a “pygments style” folder (and if so where is it and what file format does it expect , and if you don’t want to use that location, you can use an explicit path of your choosing?

b. What methods of installation are considered valid? (Manual to a specific location or something else?)

Where is this coming from?

While researching the answer for this, I have found discussions all over the Web with potential solutions. Some people claim to have had success with installing *.py versions as pygments plugins, others have claimed to implement using custom pygments.css somehow without mentioning where to put it or what to name it, some others were only able to make it work only by inserting a minimal CSS reset and overriding styles in their css/custom.css file, and still more found they needed to introduce a new templates/layout.html file with theming in order to make it work.

To make this even more frustrating, none of the answers is very specific (or at least not specific enough for some of us, lol) about how to make it work ourselves. I have personally tried every method I’ve mentioned, but I’m clearly missing something for each because I can’t get a single one to work.

Also, I believe there should be a way to just designate an entirely new pygments style somehow, rather than something hacky; overriding partial styles should be a more specialized solution.

  1. What does “fully-qualified” path mean here?

For instance, is it “fully-qualified” according to the html_static path like most everything else in the config.py? Or does it need to be explicit to the point of the volume name to the file name?

  1. Is it possible to have multiple pygments styles in a single documentation project (ex. for different parts of a book)?

  2. There are more questions to be answered in my original post (linked on the top of this one)

  3. Plenty examples of what any of this would look like.

tk0miya commented 3 years ago

What does “fully-qualified” path mean here?

Oh, sorry. It's python's keyword. The formal name is "Qualified name" (sorry, I added the "full" prefix wrongly. It's my bad). https://www.python.org/dev/peps/pep-3155/

It is the name of the python class or function including the module name. In other words, the name can be used for importing the pygments style class in the python interpreter.

Where is a new pygments style placed for Sphinx to find it to refer to it? What methods of installation are considered valid? (Manual to a specific location or something else?)

So you can put your pygments style class to everywhere you like. Please make sure it is importable from the python interpreter. My proposal is to put the script on to the ext directory on your project, and enable loading it via sys.path.append(os.path.abspath("./_ext")) in your conf.py.

Is it possible to have multiple pygments styles in a single documentation project (ex. for different parts of a book)?

It's not supported.

There are more questions to be answered in my original post (linked on the top of this one)

I'll take a look them later.

Blendify commented 3 years ago

I tried to build a working example:

from pygments.style import Style
from pygments.token import Keyword, Name, Comment, String, Error, Number, Operator, Generic

class YourStyle(Style):
    default_style = ""
    styles = {
        Comment:                'italic #888',
        Keyword:                'bold #005',
        Name:                   '#f00',
        Name.Function:          '#0f0',
        Name.Class:             'bold #0f0',
        String:                 'bg:#eee #111'
    }

pygments_style = YourStyle

However, the above doesn't work and not sure what is wrong.


Note: I don't understand adding a new API; Sphinx.add_pygments_style() is useful. The current implementation already supports loading a custom style via its full-qualified name. So I think a new API is not needed for this case.

cc: @Blendify

This would allow extensions to create multiple custom themes that the user can choose from.

tk0miya commented 3 years ago

@Blendify Please pass its qualified name of the class (ex. your.module.YourStyle) to pygments_style instead of class object.

Blendify commented 3 years ago

@tk0miya what would this be for the example above within the conf.py? sphinx.environment.BuildEnvironment.config.YourStyle?

tk0miya commented 3 years ago

Make your conf.py importable with set up sys.path, and pass conf.YourStyle. But my proposal is separate the class definition into an independent file.

webknjaz commented 3 years ago

@tk0miya what would this be for the example above within the conf.py? sphinx.environment.BuildEnvironment.config.YourStyle?

@Blendify it should be a string you would use in Python's import statement. Example: