Sphinx inline code highlight

旧时模样 提交于 2019-12-09 15:18:10

问题


I use Sphinx to make a website that contains code samples. I'm successful using the .. code-block directive to get syntax highlighting. But I can't get inline syntax highlighting using this code:

.. role:: bash(code)
   :language: bash

Test inline: :bash:`export FOO="bar"`.

.. code-block:: bash

    export FOO="bar"

which produces this output i.e. inline code not highlighted while block code is:

Problem to me is that the generated HTML for inline code contains long class names while it does not for code blocks. Here is the output HTML (indented for readability):

<p>Test inline:
    <tt class="code bash docutils literal">
        <span class="name builtin">
            <span class="pre">export</span>
        </span>
        <span class="name variable">
            <span class="pre">FOO</span>
        </span>
        <span class="operator">
            <span class="pre">=</span>
        </span>
        <span class="literal string double">
            <span class="pre">&quot;bar&quot;</span>
        </span>
    </tt>.
</p>


<p>Test code-block:</p>
<div class="highlight-bash">
    <div class="highlight">
        <pre>
            <span class="nb">export </span>
            <span class="nv">FOO</span>
            <span class="o">=</span>
            <span class="s2">&quot;bar&quot;</span>
        </pre>
    </div>
</div>

Any help would be very much appreciated.


回答1:


syntax_highlight is an ordinary docutils setting, which can be set in docutils.conf. This file is respected by Sphinx too, if placed in the Sphinx's configuration directory (where conf.py resides):

[restructuredtext parser]
syntax_highlight = short

This is much better than patching docutils or sphinx code or creating a long name CSS file.




回答2:


Found a better (sphinx-only) solution: in sphinx/builders/html.py find a line

from docutils.core import Publisher

and change it to:

from docutils.core import Publisher
def process_programmatic_settings(self, settings_spec,
                                  settings_overrides,
                                  config_section):
    if self.settings is None:
        defaults = (settings_overrides or {}).copy()
        # Propagate exceptions by default when used programmatically:
        defaults.setdefault('traceback', True)
        defaults.setdefault('syntax_highlight', 'short') # ADDED THIS LINE
        self.get_settings(settings_spec=settings_spec,
                          config_section=config_section,
                          **defaults)
Publisher.process_programmatic_settings = process_programmatic_settings

This solution is better then previous ones: since it doesn't double the amount of css rules, and doesn't modify docutils.

Still, ideal solution would only change conf.py. So there's a plenty space for improvement.




回答3:


OK I used this workaround: I generate a css file that contains both short and long names. I'm still interested in the "good" answer.

#!/usr/bin/env python

"""Generate a css file thanks to pygments that will contain both short
and long class names."""


import subprocess
import sys


PYGMENTIZE = 'pygmentize'


def parse_command_line():
    import argparse
    parser = argparse.ArgumentParser(description=__doc__)
    parser.add_argument('-s', '--style', default='colorful')
    parser.add_argument('-p', '--prefix', default='.highlight')
    return parser.parse_args()


def pygmentize(style, prefix='.highlight'):
    cmd = '{0} -f html -S {1} -a {2}'.format(PYGMENTIZE, style, prefix)
    # This will fail if pygmentize does not exist.
    try:
        p = subprocess.Popen(cmd.split(), stdout=subprocess.PIPE)
    except OSError:
        print >> sys.stderr, '{0}: command not found'.format(PYGMENTIZE)
        exit(1)

    out, err = p.communicate()
    if p.returncode != 0:
        exit(p.returncode)
    return out


def main():
    args = parse_command_line()
    style = args.style
    prefix = args.prefix

    # Print new css header.
    header = """\
/* 
 * This is pygment css style {0} generated with
 *     {1}
 */""".format(style, ' '.join(sys.argv))
    print header

    # Parse pygmentize output.
    # Find long names based on comments.
    content = pygmentize(style, prefix)
    s = content.splitlines()
    out = ''
    for line in s:
        start = line.find("/* ") + 3
        end = line.find(" */")
        # if line has a comment
        if start != 2:
            comment = line[start:end]
            name = '.' + comment.lower()
            arg = line[line.find('{ '): start - 4]
            out += '%(prefix)s %(name)s %(arg)s\n' % vars()

    print content
    print out


if __name__ == '__main__':
    main()



回答4:


When a sphinx theme has static/pygments.css -- then the file is not overwritten. So I just keep the file which contains both short and long names (which I obtained using regexp in emacs):

.highlight .hll { background-color: #ffffcc }
/* .highlight  { background: #eeffcc; } */
.highlight .c { color: #408090; font-style: italic } /* comment */
.highlight .comment { color: #408090; font-style: italic }
.highlight .err { border: 1px solid #ff0000 } /* error */
.highlight .error { border: 1px solid #ff0000 }
.highlight .k { color: #007020; font-weight: bold } /* keyword */
.highlight .keyword { color: #007020; font-weight: bold }
.highlight .o { color: #666666 } /* operator */
.highlight .operator { color: #666666 }
.highlight .cm { color: #408090; font-style: italic } /* comment.multiline */
.highlight .comment.multiline { color: #408090; font-style: italic }
.highlight .cp { color: #007020 } /* comment.preproc */
.highlight .comment.preproc { color: #007020 }
.highlight .c1 { color: #408090; font-style: italic } /* comment.single */
.highlight .comment.single { color: #408090; font-style: italic }
.highlight .cs { color: #408090; background-color: #fff0f0 } /* comment.special */
.highlight .comment.special { color: #408090; background-color: #fff0f0 }
.highlight .gd { color: #a00000 } /* generic.deleted */
.highlight .generic.deleted { color: #a00000 }
.highlight .ge { font-style: italic } /* generic.emph */
.highlight .generic.emph { font-style: italic }
.highlight .gr { color: #ff0000 } /* generic.error */
.highlight .generic.error { color: #ff0000 }
.highlight .gh { color: #000080; font-weight: bold } /* generic.heading */
.highlight .generic.heading { color: #000080; font-weight: bold }
.highlight .gi { color: #00a000 } /* generic.inserted */
.highlight .generic.inserted { color: #00a000 }
.highlight .go { color: #333333 } /* generic.output */
.highlight .generic.output { color: #333333 }
.highlight .gp { color: #c65d09; font-weight: bold } /* generic.prompt */
.highlight .generic.prompt { color: #c65d09; font-weight: bold }
.highlight .gs { font-weight: bold } /* generic.strong */
.highlight .generic.strong { font-weight: bold }
.highlight .gu { color: #800080; font-weight: bold } /* generic.subheading */
.highlight .generic.subheading { color: #800080; font-weight: bold }
.highlight .gt { color: #0044dd } /* generic.traceback */
.highlight .generic.traceback { color: #0044dd }
.highlight .kc { color: #007020; font-weight: bold } /* keyword.constant */
.highlight .keyword.constant { color: #007020; font-weight: bold }
.highlight .kd { color: #007020; font-weight: bold } /* keyword.declaration */
.highlight .keyword.declaration { color: #007020; font-weight: bold }
.highlight .kn { color: #007020; font-weight: bold } /* keyword.namespace */
.highlight .keyword.namespace { color: #007020; font-weight: bold }
.highlight .kp { color: #007020 } /* keyword.pseudo */
.highlight .keyword.pseudo { color: #007020 }
.highlight .kr { color: #007020; font-weight: bold } /* keyword.reserved */
.highlight .keyword.reserved { color: #007020; font-weight: bold }
.highlight .kt { color: #902000 } /* keyword.type */
.highlight .keyword.type { color: #902000 }
.highlight .m { color: #208050 } /* literal.number */
.highlight .literal.number { color: #208050 }
.highlight .s { color: #4070a0 } /* literal.string */
.highlight .literal.string { color: #4070a0 }
.highlight .na { color: #4070a0 } /* name.attribute */
.highlight .name.attribute { color: #4070a0 }
.highlight .nb { color: #007020 } /* name.builtin */
.highlight .name.builtin { color: #007020 }
.highlight .nc { color: #0e84b5; font-weight: bold } /* name.class */
.highlight .name.class { color: #0e84b5; font-weight: bold }
.highlight .no { color: #60add5 } /* name.constant */
.highlight .name.constant { color: #60add5 }
.highlight .nd { color: #555555; font-weight: bold } /* name.decorator */
.highlight .name.decorator { color: #555555; font-weight: bold }
.highlight .ni { color: #d55537; font-weight: bold } /* name.entity */
.highlight .name.entity { color: #d55537; font-weight: bold }
.highlight .ne { color: #007020 } /* name.exception */
.highlight .name.exception { color: #007020 }
.highlight .nf { color: #06287e } /* name.function */
.highlight .name.function { color: #06287e }
.highlight .nl { color: #002070; font-weight: bold } /* name.label */
.highlight .name.label { color: #002070; font-weight: bold }
.highlight .nn { color: #0e84b5; font-weight: bold } /* name.namespace */
.highlight .name.namespace { color: #0e84b5; font-weight: bold }
.highlight .nt { color: #062873; font-weight: bold } /* name.tag */
.highlight .name.tag { color: #062873; font-weight: bold }
.highlight .nv { color: #bb60d5 } /* name.variable */
.highlight .name.variable { color: #bb60d5 }
.highlight .ow { color: #007020; font-weight: bold } /* operator.word */
.highlight .operator.word { color: #007020; font-weight: bold }
.highlight .w { color: #bbbbbb } /* text.whitespace */
.highlight .text.whitespace { color: #bbbbbb }
.highlight .mf { color: #208050 } /* literal.number.float */
.highlight .literal.number.float { color: #208050 }
.highlight .mh { color: #208050 } /* literal.number.hex */
.highlight .literal.number.hex { color: #208050 }
.highlight .mi { color: #208050 } /* literal.number.integer */
.highlight .literal.number.integer { color: #208050 }
.highlight .mo { color: #208050 } /* literal.number.oct */
.highlight .literal.number.oct { color: #208050 }
.highlight .sb { color: #4070a0 } /* literal.string.backtick */
.highlight .literal.string.backtick { color: #4070a0 }
.highlight .sc { color: #4070a0 } /* literal.string.char */
.highlight .literal.string.char { color: #4070a0 }
.highlight .sd { color: #4070a0; font-style: italic } /* literal.string.doc */
.highlight .literal.string.doc { color: #4070a0; font-style: italic }
.highlight .s2 { color: #4070a0 } /* literal.string.double */
.highlight .literal.string.double { color: #4070a0 }
.highlight .se { color: #4070a0; font-weight: bold } /* literal.string.escape */
.highlight .literal.string.escape { color: #4070a0; font-weight: bold }
.highlight .sh { color: #4070a0 } /* literal.string.heredoc */
.highlight .literal.string.heredoc { color: #4070a0 }
.highlight .si { color: #70a0d0; font-style: italic } /* literal.string.interpol */
.highlight .literal.string.interpol { color: #70a0d0; font-style: italic }
.highlight .sx { color: #c65d09 } /* literal.string.other */
.highlight .literal.string.other { color: #c65d09 }
.highlight .sr { color: #235388 } /* literal.string.regex */
.highlight .literal.string.regex { color: #235388 }
.highlight .s1 { color: #4070a0 } /* literal.string.single */
.highlight .literal.string.single { color: #4070a0 }
.highlight .ss { color: #517918 } /* literal.string.symbol */
.highlight .literal.string.symbol { color: #517918 }
.highlight .bp { color: #007020 } /* name.builtin.pseudo */
.highlight .name.builtin.pseudo { color: #007020 }
.highlight .vc { color: #bb60d5 } /* name.variable.class */
.highlight .name.variable.class { color: #bb60d5 }
.highlight .vg { color: #bb60d5 } /* name.variable.global */
.highlight .name.variable.global { color: #bb60d5 }
.highlight .vi { color: #bb60d5 } /* name.variable.instance */
.highlight .name.variable.instance { color: #bb60d5 }
.highlight .il { color: #208050 } /* literal.number.integer.long */
.highlight .literal.number.integer.long { color: #208050 }

I run into another issue -- I'm using bootstrap theme, and it defines label too...




回答5:


Here's a better than previous workaround:

Change default --syntax-highlight option of docuitls. In

docutils/parsers/rst/__init__.py

Find

         ('Token name set for parsing code with Pygments: one of '
          '"long", "short", or "none (no parsing)". Default is "short".',
          ['--syntax-highlight'],
          {'choices': ['long', 'short', 'none'],
           'default': 'long', 'metavar': '<format>'}),

and chage the default to short:

           'default': 'short', 'metavar': '<format>'}),

The method to highlight inline code in sphnix is to register a new role:

.. role:: py(code)
   :language: py
   :class: highlight

This construct is from docutils, not from sphinx. Then one can change the docutils's default, to get the desired output (short classes). A better solution would be to set the value during the init of the class in sphinx. But where that happens might not be easy to find.

This solution is much better than the previous since it doesn't double the number of css rules to match to color the code.




回答6:


This can be fixed by adding sphinxcontrib.inlinesyntaxhighlight extension in conf.py:

extensions = [ 'sphinxcontrib.inlinesyntaxhighlight' ]

# use language set by highlight directive if no language is set by role
inline_highlight_respect_highlight = False

# use language set by highlight directive if no role is set
inline_highlight_literals = False

Sphinx documentation here : http://sphinxcontrib-inlinesyntaxhighlight.readthedocs.io/en/latest/

Extension available here: https://bitbucket.org/klorenz/sphinxcontrib-inlinesyntaxhighlight



来源:https://stackoverflow.com/questions/21591107/sphinx-inline-code-highlight

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!