pau*_*ier 5 python latex restructuredtext python-sphinx
使用Sphinx和reStructuredText,是否可以定义数学宏来在数学Latex公式中进行替换?
基本上,我想有类似的东西
.. |bnabla| replace:: :math:`\boldsymbol{\nabla}`
.. |vv| replace:: :math:`\textbf{v}`
.. math:: \rho \mbox{D}_t |vv| = - |bnabla| p + \rho \textbf{g} + \eta |bnabla|^2 |vv|,
where |vv| is the velocity and |bnabla| is the nabla operator.
Then follow many other equations with |vv| and |bnabla|...
Run Code Online (Sandbox Code Playgroud)
但它根本不起作用.首先,在数学模式中不替换标志,其次,即使它们被替换,:math:语句也不能在.. math::块中起作用.在Sphinx中改变这两种行为是不是一个好主意而不是复杂化?
另一种解决方案是使用乳胶宏,就像在这个问题中在Sphinx中创建LaTeX数学宏一样,但我认为最终的代码在我的例子中用本地第一个替换更简单.我想有明确的公式,也可以在文本模式下阅读.
此外,我使用MathJax扩展,所以我不能使用变量pngmath_latex_preamble.我可以将这个解决方案用于MathJax /sf/answers/1348798461/,但它似乎相当复杂,并且再一次使用"本地"第一次替换,代码会更清晰.
我意识到,对于许多人来说,mathmacro直接在reStructuredText中实现替换指令是非常方便和有用的(即在Python包docutils中).新指令应该像这样工作:
定义:
.. |bnabla| mathmacro:: \boldsymbol{\nabla}
.. |vv| mathmacro:: \textbf{v}
Run Code Online (Sandbox Code Playgroud)
这些数学宏可以直接包含在文本中,如下所示
|bnabla| is the nabla operator,
Run Code Online (Sandbox Code Playgroud)
这应该产生这样的内联方程
:math:`\boldsymbol{\nabla}` is the nabla operator.
Run Code Online (Sandbox Code Playgroud)
这些宏也可以包含在内联方程中:
This is an inline equation :math:`\vv = \bnabla f`,
Run Code Online (Sandbox Code Playgroud)
这相当于
:math:`\textbf{v} = \boldsymbol{\nabla}f`
Run Code Online (Sandbox Code Playgroud)
它们也可以包含在块方程中
.. math:: \vv = \bnabla f
Run Code Online (Sandbox Code Playgroud)
这相当于
.. math:: \textbf{v} = \boldsymbol{\nabla}f.
Run Code Online (Sandbox Code Playgroud)
但是,我真的不熟悉docutils如何在内部工作.我特别注意到MathBlock指令(在docutils/parsers/rst/directives/body.py中定义)不会调用其输入的任何解析,因此在数学模式中没有替换.
我不知道是否有可能改变替换指令的行为,使得替换是切割器并适应调用它的上下文,文本,内联数学或块数学.
有人可以给我一些关于如何实现这个有用的新功能的线索吗?
由于我确实需要一个好的解决方案来满足这一需求,所以我自己解决了这个问题。我介绍一下结果,因为它对其他人可能有用。
我还将该解决方案调整为Sphinx扩展,可以在此处找到。
我必须定义一个新的替换指令,并重新定义数学指令和角色。所有这些都在文件mathmacro.py中完成:
"""
'Proof of concept' for a new reStructuredText directive *mathmacro*.
Use for example with::
python mathmacro.py example.rst example.html
"""
import re
from docutils.parsers.rst.directives.misc import Replace
from docutils.parsers.rst.directives.body import MathBlock
from docutils.parsers.rst.roles import math_role
def multiple_replacer(replace_dict):
"""Return a function replacing doing multiple replacements.
The produced function replace `replace_dict.keys()` by
`replace_dict.values`, respectively.
"""
def replacement_function(match):
s = match.group(0)
end = s[-1]
if re.match(r'[\W_]', end):
return replace_dict[s[:-1]]+end
else:
return replace_dict[s]
pattern = re.compile("|".join([re.escape(k)+r'[\W_\Z]|'+re.escape(k)+r'\Z'
for k in replace_dict.keys()]),
re.M)
return lambda string: pattern.sub(replacement_function, string)
class MathMacro(Replace):
"""Directive defining a math macro."""
def run(self):
if not hasattr(self.state.document, 'math_macros'):
self.state.document.math_macros = {}
latex_key = '\\'+self.state.parent.rawsource.split('|')[1]
self.state.document.math_macros[latex_key] = ''.join(self.content)
self.state.document.math_macros_replace = \
multiple_replacer(self.state.document.math_macros)
self.content[0] = ':math:`'+self.content[0]
self.content[-1] = self.content[-1]+'`'
return super(MathMacro, self).run()
class NewMathBlock(MathBlock):
"""New math block directive parsing the latex code."""
def run(self):
try:
multiple_replace = self.state.document.math_macros_replace
except AttributeError:
pass
else:
if self.state.document.math_macros:
for i, c in enumerate(self.content):
self.content[i] = multiple_replace(c)
return super(NewMathBlock, self).run()
def new_math_role(role, rawtext, text, lineno, inliner,
options={}, content=[]):
"""New math role parsing the latex code."""
try:
multiple_replace = inliner.document.math_macros_replace
except AttributeError:
pass
else:
if inliner.document.math_macros:
rawtext = multiple_replace(rawtext)
return math_role(role, rawtext, text, lineno, inliner,
options=options, content=content)
if __name__ == '__main__':
from docutils.parsers.rst.directives import register_directive
from docutils.parsers.rst.roles import register_canonical_role
register_directive('mathmacro', MathMacro)
register_directive('math', NewMathBlock)
register_canonical_role('math', new_math_role)
from docutils.core import publish_cmdline, default_description
description = ('Generates (X)HTML documents '
'from standalone reStructuredText sources. '
+default_description)
publish_cmdline(writer_name='html', description=description)
Run Code Online (Sandbox Code Playgroud)
文件example.rst的内容:
Here, I show how to use a new mathmacro substitution directive in
reStructuredText. I think even this small example demonstrates that it
is useful.
First some math without math macros. Let's take the example of the
incompressible Navier-Stokes equation:
.. math:: \mbox{D}_t \textbf{v} =
-\boldsymbol{\nabla} p + \nu \boldsymbol{\nabla} ^2 \textbf{v}.
where :math:`\mbox{D}_t` is the convective derivative,
:math:`\textbf{v}` the velocity, :math:`\boldsymbol{\nabla}` the
nabla operator, :math:`\nu` the viscosity and
:math:`\boldsymbol{\nabla}^2` the Laplacian operator.
.. |Dt| mathmacro:: \mbox{D}_t
.. |bnabla| mathmacro:: \boldsymbol{\nabla}
.. |vv| mathmacro:: \textbf{v}
Now, let's use some math macros and try to get the same result... The
Navier-Stokes equation can now be written like this:
.. math:: \Dt \vv = - \bnabla p + \nu \bnabla^2 \vv
where |Dt| is the convective derivative, |vv| the velocity, |bnabla|
the nabla operator, :math:`\nu` the viscosity and :math:`\bnabla^2`
the Laplacian operator.
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1351 次 |
| 最近记录: |