Plugins » Math and code

These plu­gins use ex­tern­al lib­rar­ies to pro­duce beau­ti­ful math and code ren­der­ing dir­ectly from your reST sources.

Math

For Pel­ic­an, down­load the m/math.py and latex2s­vg.py files, put them in­clud­ing the m/ dir­ect­ory in­to one of your PLUGIN_PATHS and add m.math pack­age to your PLUGINS in pelicanconf.py. This plu­gin as­sumes pres­ence of m.htmls­an­ity.

PLUGINS += ['m.htmlsanity', 'm.math']
M_MATH_RENDER_AS_CODE = False
M_MATH_CACHE_FILE = 'm.math.cache'

For the Py­thon doc theme, it’s enough to men­tion it in PLUGINS. The m.htmls­an­ity plu­gin is avail­able al­ways, no need to men­tion it ex­pli­citly:

PLUGINS += ['m.code']

For the Doxy­gen theme, this fea­ture is built­in. Use either the @f[ com­mand for block-level math or the @f$ com­mand for in­line math. It’s pos­sible to add ex­tra CSS classes by pla­cing @m_class in a para­graph be­fore the ac­tu­al math block (or right be­fore in­line math), see the Doxy­gen theme-spe­cif­ic com­mands for more in­form­a­tion. The M_MATH_CACHE_FILE and M_MATH_RENDER_AS_CODE op­tions are sup­por­ted as well.

In ad­di­tion you need some LaTeX dis­tri­bu­tion in­stalled. Use your dis­tri­bu­tion pack­age man­ager, for ex­ample on Ubuntu:

sudo apt install \
    texlive-base \
    texlive-latex-extra \
    texlive-fonts-extra \
    texlive-fonts-recommended

The plu­gin over­rides the built­in doc­utils math dir­ect­ive and math in­ter­preted text role and:

  • In­stead of re­ly­ing on Math­ML or Math­Jax, con­verts in­put LaTeX math for­mula to a SVG file, which is then em­bed­ded dir­ectly to the page. All glyphs are con­ver­ted to paths.
  • Size is rep­res­en­ted us­ing CSS em units so the for­mula fol­lows sur­round­ing text size.
  • Adds a pos­sib­il­ity to col­or the whole for­mula or parts of it us­ing col­ors that fol­low the cur­rent theme.
  • Adds a <title> con­tain­ing the ori­gin­al for­mula to the gen­er­ated <svg> ele­ment for ac­cess­ib­il­ity.

Put math blocks in­to the .. math:: dir­ect­ive; if you want to col­or the equa­tions, add cor­res­pond­ing CSS class via a :class: op­tion.

.. math::
    :class: m-success

    \boldsymbol{A} = \begin{pmatrix}
        \frac{2n}{s_x} & 0 & 0 & 0 \\
        0 & \frac{2n}{s_y} & 0 & 0 \\
        0 & 0 & \frac{n + f}{n - f} & \frac{2nf}{n - f} \\
        0 & 0 & -1 & 0
    \end{pmatrix}
\boldsymbol{A} = \begin{pmatrix} \frac{2n}{s_x} & 0 & 0 & 0 \\ 0 & \frac{2n}{s_y} & 0 & 0 \\ 0 & 0 & \frac{n + f}{n - f} & \frac{2nf}{n - f} \\ 0 & 0 & -1 & 0 \end{pmatrix}

In­line math can be wrapped in the :math: in­ter­preted text role. If you want to add ad­di­tion­al CSS classes, de­rive a cus­tom role from it.

.. role:: math-info(math)
    :class: m-info

Quaternion-conjugated dual quaternion is :math-info:`\hat q^* = q_0^* + q_\epsilon^*`,
while dual-conjugation gives :math:`\overline{\hat q} = q_0 - \epsilon q_\epsilon`.

Qua­ternion-con­jug­ated dual qua­ternion is \hat q^* = q_0^* + q_\epsilon^* , while dual-con­jug­a­tion gives \overline{\hat q} = q_0 - \epsilon q_\epsilon .

The res­ult­ing SVG fol­lows font size of sur­round­ing text, so you can use math even out­side of main page copy:

.. button-success:: https://tauday.com/

    The :math:`\tau` manifesto

    they say :math:`\pi` is wrong

The xcolor pack­age is en­abled by de­fault to­geth­er with names match­ing CSS col­or classes. You can use it to high­light dif­fer­ent parts of the for­mula:

.. math::

    \boldsymbol{A} = \begin{pmatrix}
        {\color{m-info} s_x} & 0 & 0 & {\color{m-success} t_x} \\
        0 & {\color{m-info} s_y} & 0 & {\color{m-success} t_y} \\
        0 & 0 & {\color{m-info} s_z} & {\color{m-success} t_z} \\
        0 & 0 & 0 & 1
    \end{pmatrix}
\boldsymbol{A} = \begin{pmatrix} {\color{m-info} s_x} & 0 & 0 & {\color{m-success} t_x} \\ 0 & {\color{m-info} s_y} & 0 & {\color{m-success} t_y} \\ 0 & 0 & {\color{m-info} s_z} & {\color{m-success} t_z} \\ 0 & 0 & 0 & 1 \end{pmatrix}

The M_MATH_CACHE_FILE set­ting (de­fault­ing to m.math.cache in the site root dir­ect­ory) de­scribes a file used for cach­ing rendered LaTeX math for­mu­las for speed­ing up sub­sequent runs. Cached out­put that’s no longer needed is peri­od­ic­ally pruned and new for­mu­las ad­ded to the file. Set it to None to dis­able cach­ing.

Math fig­ure

See the m.com­pon­ents plu­gin for de­tails about code fig­ures us­ing the .. math-figure:: dir­ect­ive.

.. math-figure:: Infinite projection matrix

    .. math::
        :class: m-success

        \boldsymbol{A} = \begin{pmatrix}
            \frac{2n}{s_x} & 0 & 0 & 0 \\
            0 & \frac{2n}{s_y} & 0 & 0 \\
            0 & 0 & -1 & -2n \\
            0 & 0 & -1 & 0
        \end{pmatrix}

    With :math:`f = \infty`.
\boldsymbol{A} = \begin{pmatrix} \frac{2n}{s_x} & 0 & 0 & 0 \\ 0 & \frac{2n}{s_y} & 0 & 0 \\ 0 & 0 & -1 & -2n \\ 0 & 0 & -1 & 0 \end{pmatrix}
In­fin­ite pro­jec­tion mat­rix

With f = \infty .

Code

For Pel­ic­an, down­load the m/code.py and an­s­ilex­er.py files, put them in­clud­ing the m/ dir­ect­ory in­to one of your PLUGIN_PATHS and add m.code pack­age to your PLUGINS in pelicanconf.py. This plu­gin as­sumes pres­ence of m.htmls­an­ity.

PLUGINS += ['m-htmlsanity', 'm.code']
M_CODE_FILTERS_PRE = []
M_CODE_FILTERS_POST = []

For the Py­thon doc theme, it’s enough to men­tion it in PLUGINS. The m.htmls­an­ity plu­gin is avail­able al­ways, no need to men­tion it ex­pli­citly:

PLUGINS += ['m.code']

For the Doxy­gen theme, this fea­ture is built­in. Use the @code{.ext} com­mand either in a block or in­line, the vari­ous @include and @snippet com­mands sup­port it as well. Lan­guage de­tec­tion is done from the value of .ext in the @code com­mand and from the in­clude/snip­pet fi­le­name for the oth­ers. It’s pos­sible to add ex­tra CSS classes by pla­cing @m_class in a para­graph be­fore the ac­tu­al code block (or right be­fore in­line code), see the Doxy­gen theme-spe­cif­ic com­mands for more in­form­a­tion. There’s no pos­sib­il­ity to high­light par­tic­u­lar code lines.

In ad­di­tion you need to have Pyg­ments in­stalled. Get it via pip or your dis­tri­bu­tion pack­age man­ager:

pip3 install Pygments

The plu­gin over­rides the built­in doc­utils code dir­ect­ive and code in­ter­preted text role, re­places Pel­ic­an code-block dir­ect­ive and:

  • Wraps Pyg­ments out­put in <code> ele­ment for in­line code and <pre> ele­ment for code blocks with .m-code CSS class ap­plied.
  • Re­moves use­less CSS classes from the out­put.
  • Adds a :filters: op­tion. See Fil­ters be­low.

Put code blocks in­to the .. code:: dir­ect­ive and spe­cify the lan­guage via a para­met­er. Use :hl-lines: op­tion to high­light lines; if you want to add ad­di­tion­al CSS classes, use the :class: op­tion.

.. code:: c++
    :hl-lines: 4 5
    :class: m-inverted

    #include <iostream>

    int main() {
        std::cout << "Hello world!" << std::endl;
        return 0;
    }
#include <iostream>

int main() {
    std::cout << "Hello world!" << std::endl;
    return 0;
}

Omit­ting the lan­guage para­met­er renders a plain code block without any high­ligh­ing. In that case the class: op­tion is still re­cog­nized (and the .m-code CSS class ad­ded as well) but :hl-lines: is ig­nored.

The built­in in­clude dir­ect­ive is also patched to use the im­proved code dir­ect­ive, and:

  • Drops the rarely use­ful :encoding:, :literal: and :name: op­tions
  • Adds a :hl-lines: op­tion to have the same be­ha­vi­or as the .. code:: dir­ect­ive
  • Adds a :start-on: and :strip-prefix: op­tions, and im­proves :end-before:. See Ad­vanced file in­clu­sion be­low.

Simply spe­cify ex­tern­al code snip­pets fi­le­name and set the lan­guage us­ing the :code: op­tion. All op­tions of the .. code:: dir­ect­ive are sup­por­ted as well.

.. include:: snippet.cpp
    :code: c++
    :start-line: 2
int main() {
    std::cout << "Hello world!" << std::endl;
    return 0;
}

For in­line code high­light­ing, use :code: in­ter­preted text role. To spe­cify which lan­guage should be high­lighted, de­rive a cus­tom role from it. Like with the .. code:: dir­ect­ive it’s pos­sible to sup­ply CSS classes via the :class: op­tion, and if you omit the :language: op­tion you get a plain in­line code without any high­light­ing but :class: still ap­plied, and the .m-code CSS class ad­ded as well.

.. role:: cmake(code)
    :language: cmake

.. role:: cpp(code)
    :language: cpp

With the :cmake:`add_executable(foo bar.cpp)` CMake command you can create an
executable from a file that contains just :cpp:`int main() { return 666; }` and
nothing else.

With the add_executable(foo bar.cpp) CMake com­mand you can cre­ate an ex­ecut­able from a file that con­tains just int main() { return 666; } and noth­ing else.

Colored ter­min­al out­put

Use the ansi pseudo-lan­guage for high­light­ing colored ter­min­al out­put. The plu­gin will take care of the rest like us­ing the cus­tom Pyg­ments lex­er and as­sign­ing a prop­er CSS class. Be­cause AN­SI es­cape codes might cause prob­lems with some ed­it­ors and look con­fus­ing when viewed via git diff on the ter­min­al, it’s best to have the list­ings in ex­tern­al files and use .. include:::

.. include:: console.ansi
    :code: ansi
![mosra@don-perverzo m.css]$ ls
CONTRIBUTING.rst  CREDITS.rst  doc            plugins        README.rst
COPYING           css          documentation  pelican-theme  site

ASan reports:

=>0x0c287fff8030: 00[fc]fc fc fc fc fc fc fc fc fc fa fa fa fa fa

There’s sup­port for the ba­sic fore­ground and back­ground col­or sets, 256 palette col­ors us­ing the \033[38;5;{p}m or \033[48;5;{p}m col­or se­quences, and 24bit col­ors us­ing the \033[38;2;{r};{g};{b}m and \033[48;2;{r};{g};{b}m col­or se­quences. The non-bright ba­sic fore­ground col­ors can be in­de­pend­ently brightened us­ing the \033[1m col­or se­quence:

██ ██ ██ ██ ██ ▓▓ ▒▒

      ░░ ▒▒ ▓▓ ██

Code fig­ure

See the m.com­pon­ents plu­gin for de­tails about code fig­ures us­ing the .. code-figure:: dir­ect­ive.

Ad­vanced file in­clu­sion

Com­pared to the built­in in­clude dir­ect­ive, the m.css-patched vari­ant ad­di­tion­ally provides a :strip-prefix: op­tion that strips a pre­fix from each in­cluded line. This can be used for ex­ample to re­move ex­cess­ive in­dent­a­tion from code blocks. To avoid trail­ing whitespace, you can wrap the value in quotes. Re­using the snip­pet from above, show­ing only the code in­side main():

.. include:: snippet.cpp
    :code: c++
    :start-line: 3
    :end-line: 5
    :strip-prefix: '    '
std::cout << "Hello world!" << std::endl;
return 0;

This isn’t lim­ited to just whitespace though — since the .. include:: dir­ect­ive works for in­clud­ing re­Struc­tured­Text as well, it can be used to em­bed parts of self-con­tained py­thon scripts on the page. Con­sider this file, two-sins.py:

"""
This is a reST markup explaining the following code, compatible with
`Sphinx Gallery <https://sphinx-gallery.github.io/>`_.
"""

# You can convert the file to a Jupyter notebook using the
# sphx_glr_python_to_jupyter.py utility from Sphinx Gallery.

import math

sin = math.sin(0.13587)
print(sin)

#%%
# And a sum with itself turns it into two sins, because the following holds:
#
# .. math::
#
#   2 a = a + a
#

two_sins = sin + sin
if two_sins != 2*sin:
    print("Assumptions broken. Restart the universe.")

Em­bed­ding it on a page, mixed to­geth­er with oth­er con­tent (and un­im­port­ant parts omit­ted), can look like be­low. The :start-on: op­tion can be used to pin to a par­tic­u­lar line (in­stead of skip­ping it like :start-after: does) and an empty :end-before: will in­clude everything un­til the next blank line. Fi­nally, :strip-prefix: strips the lead­ing # from the com­ments em­bed­ded in Py­thon code:

.. include:: two-sins.py
    :start-after: """
    :end-before: """

.. code-figure::

    .. include:: two-sins.py
        :start-on: sin =
        :end-before:
        :code: py

    0.13545234412104434

.. include:: two-sins.py
    :start-on: # And a sum with itself
    :strip-prefix: '# '
    :end-before:

.. include:: two-sins.py
    :start-on: two_sins
    :code: py

This is a reST markup ex­plain­ing the fol­low­ing code, com­pat­ible with Sphinx Gal­lery.

sin = math.sin(0.13587)
print(sin)

0.13545234412104434

And a sum with it­self turns it in­to two sins, be­cause the fol­low­ing holds:

2 a = a + a
two_sins = sin + sin
if two_sins != 2*sin:
    print("Assumptions broken. Restart the universe.")

Fil­ters

It’s pos­sible to sup­ply fil­ters that get ap­plied both be­fore and after a code snip­pet is rendered us­ing the M_CODE_FILTERS_PRE and M_CODE_FILTERS_POST op­tions. It’s a dict with keys be­ing the lex­er name 1 and val­ues be­ing fil­ter func­tions. Each func­tion that gets string as an in­put and is ex­pec­ted to re­turn a mod­i­fied string. In the fol­low­ing ex­ample, all CSS code snip­pets have the hexa­decim­al col­or lit­er­als an­not­ated with a col­or swatch:

import re

_css_colors_src = re.compile(r"""<span class="mh">#(?P<hex>[0-9a-f]{6})</span>""")
_css_colors_dst = r"""<span class="mh">#\g<hex><span class="m-code-color" style="background-color: #\g<hex>;"></span></span>"""

M_CODE_FILTERS_POST = {
    'CSS': lambda code: _css_colors_src.sub(_css_colors_dst, code)
}
.. code:: css

    p.green {
      color: #3bd267;
    }
p.green {
  color: #3bd267;
}

In the above case, the fil­ter gets ap­plied glob­ally to all code snip­pets of giv­en lan­guage. Some­times it might be de­sir­able to ap­ply a fil­ter only to spe­cif­ic code snip­pet — in that case, the dict key is a tuple of (lexer, filter) where the second item is a fil­ter name. This fil­ter name is then ref­er­enced from the :filters: op­tion of the .. code:: and .. include:: dir­ect­ives as well as the in­line :code: text role. Mul­tiple fil­ters can be spe­cified when sep­ar­ated by spaces.

M_CODE_FILTERS_PRE = {
    ('C++', 'codename'): lambda code: code.replace('DirtyMess', 'P300::V1'),
    ('C++', 'fix_typography'): lambda code: code.replace(' :', ':'),
}
.. code:: cpp
    :filters: codename fix_typography

    for(auto& a : DirtyMess::managedEntities()) {
        // ...
    }
for(auto& a: P300::V1::managedEntities()) {
    // ...
}
1.
^ In or­der to have an unique map­ping, the fil­ters can’t use the ali­ases — for ex­ample C++ code can be high­lighted us­ing either c++ or cpp as a lan­guage name and the dict would need to have an entry for each. An unique lex­er name is the name field used in the par­tic­u­lar lex­er source, you can also see the names in the lan­guage drop­down on the of­fi­cial web­site.