我正在使用 Sphinx 为我的项目生成文档。
在这个项目中,我在 yaml 文件中描述了可用命令的列表,一旦加载,就会以
{command-name : command-description}
的形式生成字典,例如:
commands = {"copy" : "Copy the highlighted text in the clipboard",
"paste" : "Paste the clipboard text to cursor location",
...}
我想知道的是如果狮身人面像中有一种方法可以在
make html
循环期间加载yaml文件,则以某种reStructuredText格式(例如定义列表)翻译python字典并包含在我的 html 输出。
我希望我的
.rst
文件看起来像:
Available commands
==================
The commands available in bla-bla-bla...
.. magic-directive-that-execute-python-code::
:maybe python code or name of python file here:
并在内部转换为:
Available commands
==================
The commands available in bla-bla-bla...
copy
Copy the highlighted text in the clipboard
paste
Paste the clipboard text to cursor location
在翻译成 HTML 之前。
最后我找到了一种方法来实现我想要的。方法如下:
generate-includes.py
),它将生成 reStructuredText 并将其保存在 myrst.inc
文件中。 (在我的示例中,这将是加载和解析 YAML 的脚本,但这无关紧要)。 确保这个文件是可执行的!!!在文档的主要 .rst 文档中使用
include
指令,在您希望插入动态生成的文档的位置:
.. include:: myrst.inc
修改 sphinx Makefile 以便在构建时生成所需的 .inc 文件:
myrst.inc:
./generate-includes.py
html: myrst.inc
...(other stuff here)
使用make html
.正常构建您的文档
基于Michael的代码和内置include指令的改进:
import sys
from os.path import basename
try:
from StringIO import StringIO
except ImportError:
from io import StringIO
from docutils.parsers.rst import Directive
from docutils import nodes, statemachine
class ExecDirective(Directive):
"""Execute the specified python code and insert the output into the document"""
has_content = True
def run(self):
oldStdout, sys.stdout = sys.stdout, StringIO()
tab_width = self.options.get('tab-width', self.state.document.settings.tab_width)
source = self.state_machine.input_lines.source(self.lineno - self.state_machine.input_offset - 1)
try:
exec('\n'.join(self.content))
text = sys.stdout.getvalue()
lines = statemachine.string2lines(text, tab_width, convert_whitespace=True)
self.state_machine.insert_input(lines, source)
return []
except Exception:
return [nodes.error(None, nodes.paragraph(text = "Unable to execute python code at %s:%d:" % (basename(source), self.lineno)), nodes.paragraph(text = str(sys.exc_info()[1])))]
finally:
sys.stdout = oldStdout
def setup(app):
app.add_directive('exec', ExecDirective)
这个更早地导入输出,以便它直接通过解析器。它也适用于 Python 3。
我需要同样的东西,所以我拼凑了一个似乎有效的新指令(我对自定义 Sphinx 指令一无所知,但到目前为止它有效):
import sys
from os.path import basename
from StringIO import StringIO
from sphinx.util.compat import Directive
from docutils import nodes
class ExecDirective(Directive):
"""Execute the specified python code and insert the output into the document"""
has_content = True
def run(self):
oldStdout, sys.stdout = sys.stdout, StringIO()
try:
exec '\n'.join(self.content)
return [nodes.paragraph(text = sys.stdout.getvalue())]
except Exception, e:
return [nodes.error(None, nodes.paragraph(text = "Unable to execute python code at %s:%d:" % (basename(self.src), self.srcline)), nodes.paragraph(text = str(e)))]
finally:
sys.stdout = oldStdout
def setup(app):
app.add_directive('exec', ExecDirective)
使用方法如下:
.. exec::
print "Python code!"
print "This text will show up in the document"
Sphinx 没有任何内置的东西可以做你喜欢的事。您可以创建一个自定义指令来处理您的文件,或者在单独的步骤中生成 reStructuredText 并使用 include 指令包含生成的 reStructuredText 文件。
我知道这个问题很老,但也许其他人也会发现它有用。
听起来你实际上不需要执行任何python代码,但你只需要重新格式化文件的内容。在那种情况下,您可能想看看 sphinx-jinja (https://pypi.python.org/pypi/sphinx-jinja)。
您可以在
conf.py
中加载您的YAML文件:
jinja_contexts = yaml.load(yourFileHere)
然后您可以使用 jinja 模板写出内容并将它们视为 reST 输入。
Sphinx 确实支持自定义扩展,这可能是执行此操作的最佳方式http://sphinx.pocoo.org/ext/tutorial.html。
不是完全你想要的答案,但可能是一个近似值:yaml2rst。它是从 YAML 到 RST 的转换器。不对 YAML 本身做任何明确的事情,而是寻找注释行(以
#
开头)并将它们拉出到 RST 块中(YAML 进入 code-block
s)。允许一种有文化的 YAML。
此外,语法突出显示的 YAML 非常可读(见鬼,这是 YAML,不是 JSON!)。