【问题标题】:Sphinx inline code highlightSphinx 内联代码高亮
【发布时间】:2014-03-02 16:50:54
【问题描述】:

我使用 Sphinx 制作了一个包含代码示例的网站。 我成功地使用了.. code-block 指令来获得语法高亮。 但我无法使用此代码获得内联语法突出显示:

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

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

.. code-block:: bash

    export FOO="bar"

产生此输出,即内联代码未突出显示,而块代码为:

对我来说的问题是,为内联代码生成的 HTML 包含长类名,而代码块则没有。 这是输出 HTML(为了便于阅读而缩进):

<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>

非常感谢任何帮助。

【问题讨论】:

  • 如果我是你,我也会添加pygments 标签。

标签: css syntax-highlighting python-sphinx restructuredtext pygments


【解决方案1】:

好的,我使用了这个解决方法:我生成了一个包含短名称和长名称的 css 文件。 我仍然对“好”的答案感兴趣。

#!/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()

【讨论】:

    【解决方案2】:

    当 sphinx 主题具有 static/pygments.css 时,该文件不会被覆盖。所以我只保留包含短名称和长名称的文件(我在 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 }
    

    我遇到了另一个问题——我正在使用引导主题,它也定义了label...

    【讨论】:

      【解决方案3】:

      这里有一个比previous 更好的解决方法:

      更改 docuitls 的默认 --syntax-highlight 选项。在

      docutils/parsers/rst/__init__.py
      

      查找

               ('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>'}),
      

      并将默认设置更改为short:

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

      sphnix中高亮内联代码的方法是注册一个新角色:

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

      这个结构来自 docutils,而不是 sphinx。然后可以更改 docutils 的默认值,以获得所需的输出(短类)。更好的解决方案是在 sphinx 类的初始化期间设置值。但是,发生这种情况的地方可能并不容易找到。

      此解决方案比 previous 好得多,因为它不会将匹配的 css 规则数量加倍来为代码着色。

      【讨论】:

      • docutils 解决方案非常好,并且有据可查。尽管如此,据我所知,它不能轻易应用于狮身人面像。所以,如果我做对了,一个兼容 sphinx 的解决方案仍然意味着双倍的 css。
      【解决方案4】:

      找到更好的(仅限 sphinx)解决方案:在 sphinx/builders/html.py 中找到一行

      from docutils.core import Publisher
      

      并将其更改为:

      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
      

      此解决方案比以前的解决方案更好:因为它不会使 css 规则的数量增加一倍,并且不会修改 docutils。

      不过,理想的解决方案只会改变conf.py。所以还有很大的改进空间。

      【讨论】:

      • docutils 解决方案非常好,并且有据可查。尽管如此,据我所知,它不能轻易应用于狮身人面像。所以,如果我得到正确的东西,一个 sphinx 兼容的解决方案仍然意味着双倍的 css。
      • @binoua:你是什么意思?我发布的三个答案中的每一个都解决了狮身人面像的问题。其中一个通过提供pygments.css 解决了这个问题,另一个修改了 docutils 上的默认选项,最后这个修改了 sphinx。
      • 感谢您的回答。 pygments.css 方法基本上是solution I came up to,即提供一个具有短名称和长名称的css。如果我错了,请纠正我,但其他两个解决方案意味着直接修改包(一种情况下是 docutils,另一种情况下是 sphinx),我同意这也是一个解决方案,但是,没有冒犯,不是很令人满意,因为这个补丁应该在之后应用docutils/sphinx 开发团队没有直接修复每个包更新。
      • @binoua:据我了解,您每次编译 sphinx 时都会生成 pygments.css。我的第一个答案没问题我只是想指出您可以将文件添加到主题中。您的解决方案将代码着色所需的 css 规则数量加倍,这将导致渲染速度变慢。如果这对你来说没问题 - 没问题。这两种需要修改的解决方案都很小而且容易:sphinx 或 docutils 的代码没有任何宗教色彩——可以对其进行调整,并在每次更新后再次调整。最后 - 可以将 sphinx 解决方案实现为扩展(自定义 html 构建器)。
      • 你说的完全正确:自定义 html 构建器绝对可以成为 sphinx 扩展(我没有想到这一点)。在我看来,这将是正确的解决方案。对于存档,由于上面的脚本,我实际上生成了一次 pygment.css。
      【解决方案5】:

      syntax_highlight是一个普通的docutils设置,可以在docutils.conf中设置。如果放置在 Sphinx 的 configuration directoryconf.py 所在的位置)中,该文件也受到 Sphinx 的尊重:

      [restructuredtext parser]
      syntax_highlight = short
      

      这比修补 docutilssphinx 代码或创建长名称 CSS 文件要好得多。

      【讨论】:

      • 这应该是公认的答案,是迄今为止最干净的解决方案。
      • 这修复了类名,但突出显示没有通过,除非我还在 .. role 指令上添加了 :class: highlight 作为选项,如 Adob​​e 的回答所示。
      【解决方案6】:

      这可以通过在conf.py 中添加'sphinxcontrib.inlinesyntaxhighlight' 扩展来解决:

      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
      

      Extension documentation

      该扩展程序在herePyPi 上可用。

      【讨论】:

        猜你喜欢
        • 2021-08-01
        • 1970-01-01
        • 1970-01-01
        • 2013-12-17
        • 1970-01-01
        • 1970-01-01
        • 2017-03-28
        • 2011-12-26
        相关资源
        最近更新 更多