Математика латекс макросы в настройки и Сфинкса
Используя Sphinx и reStructuredText, Можно ли определить математические макросы для выполнения подстановок в Формуле math 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|...
Но это совсем не работает. Во-первых, флаги не подставляются в математическом режиме, а во-вторых, даже если они были подставлены, оператор :math:
не работает в блоке .. math::
. Было бы хорошей идеей и не усложнять, чтобы изменить эти два поведения в Сфинкс?
Другим решением было бы использовать макросы latex, как в этом вопросе создание макросов LaTeX math в Sphinx, но я думаю, что окончательный код будет проще читать с локальными первыми заменами, как в моем примере. Я хотел бы иметь четкие формулы, которые также можно читать в текстовом режиме.
Кроме того, я использую расширение MathJax, поэтому я не могу использовать переменную pngmath_latex_preamble. Я мог бы использовать это решение для MathJax https://stackoverflow.com/a/19268549/1779806 но это кажется довольно сложным, и снова код был бы более ясным с "локальными" первыми заменами.
Правка:
Я понял, что для многих людей было бы очень удобно и полезно реализовать директиву подстановкиmathmacro
непосредственно в reStructuredText (т. е. в пакете Python docutils). Новая директива должна работать следующим образом:
Определение:
.. |bnabla| mathmacro:: boldsymbol{nabla}
.. |vv| mathmacro:: textbf{v}
Эти математические макросы могут быть включены непосредственно в тексте, как в
|bnabla| is the nabla operator,
Который должен произвести встроенное уравнение, подобное этому
:math:`boldsymbol{nabla}` is the nabla operator.
Эти макросы также могут быть включены в встроенные уравнения:
This is an inline equation :math:`vv = bnabla f`,
Который должен быть эквивалентен
:math:`textbf{v} = boldsymbol{nabla}f`
Они также могут быть включены в уравнение блока
.. math:: vv = bnabla f
Который должен быть эквивалентен
.. math:: textbf{v} = boldsymbol{nabla}f.
Однако я действительно не знаком с тем, как docutils работает внутри компании. Я замечаю, в частности, что директива MathBlock (определенная в docutils/parsers/rst/directives/body.py) не вызывает никакого разбора его входных данных, поэтому в математическом режиме нет подстановки.
Я не знаю, можно ли изменить поведение директивы подстановки таким образом, чтобы подстановка была кливерной и адаптировалась к контексту, из которого она вызывается, в тексте, В встроенной математике или в блочной математике.
Может ли кто-нибудь подсказать мне, как реализовать эту полезную новую функцию?
1 ответ:
Поскольку мне действительно нужно было хорошее решение для этой потребности, я разработал его сам... Это помогает мне некоторое время, и решение, возможно, не идеально, но, по крайней мере, оно хорошо работает. Я представляю результат, так как он может быть полезен для других людей.
Я также адаптировал решение как расширение Сфинкса, которое можно найти здесь.
Я должен был определить новую директиву замещения и переопределить директиву и роль математики. Все это делается в файле 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)
В содержание примера файла.первый:
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.