首页 > 解决方案 > 如何在 Sphinx 的 html 输出中随处包含源代码行号?

问题描述

假设我正在为我的 RestructuredText/Sphinx 东西编写一个自定义编辑器,并带有“实时”html 输出预览。输出是使用 Sphinx 构建的。

源文件是纯 RestructuredText。那里没有代码。

一个理想的功能是右键单击预览的某些部分会在源文件的正确行打开编辑器。

为此,一种方法是将该行号放在 html 文件的每个标记中,例如使用类(例如,class = "... lineno-124")。或者使用 html 注释。

请注意,我不想在我的源文件中添加更多内容,只是希望在输出的任何地方都包含行号。

一个大概的行号就足够了。

有人知道如何在狮身人面像中做到这一点,我的方式还是其他方式?

标签: python-sphinx

解决方案


I decided to add <a> tags with a specific class "lineno lineno-nnn" where nnn is the line number in the RestructuredText source.

The directive .. linenocomment:: nnn is inserted before each new block of unindented text in the source, before the actual parsing (using a 'source-read' event hook).

linenocomment is a custom directive that pushes the <a> tag at build time.

Half a solution is still a solution...

import docutils.nodes as dn
from docutils.parsers.rst import Directive

class linenocomment(dn.General,dn.Element):
    pass
def visit_linenocomment_html(self,node):
    self.body.append(self.starttag(node,'a',CLASS="lineno lineno-{}".format(node['lineno'])))
def depart_linenocomment_html(self,node):
    self.body.append('</a>')

class LineNoComment(Directive):

    required_arguments = 1
    optional_arguments = 0
    has_content = False
    add_index = False

    def run(self):

        node = linenocomment()
        node['lineno'] = self.arguments[0]

        return [node]

def insert_line_comments(app, docname, source):
    print(source)
    new_source = []
    last_line_empty = True
    lineno = 0
    for line in source[0].split('\n'):
        if line.strip() == '':
            last_line_empty = True
            new_source.append(line)
        elif line[0].isspace():
            new_source.append(line)
            last_line_empty = False
        elif not last_line_empty:
            new_source.append(line)
        else:
            last_line_empty = False
            new_source.append('.. linenocomment:: {}'.format(lineno))
            new_source.append('')
            new_source.append(line)
        lineno += 1
    source[0] = '\n'.join(new_source)
    print(source)

def setup(app):
    app.add_node(linenocomment,html=(visit_linenocomment_html,depart_linenocomment_html))
    app.add_directive('linenocomment', LineNoComment)
    app.connect('source-read',insert_line_comments)
    return {
        'version': 0.1
    }

推荐阅读