Math in reStructuredText with LaTeX

I would like to use a lightweight markup language to take notes in my college classes.

My editor of choice is gedit, and I found reStructuredText Tools for Gedit, which will run the reStructuredText processor and render the HTML in a pane in gedit. This is great, and 80% of the way there.

But for many of my classes I need to include math equations or greek characters in my notes. Although I'm not very familiar with LaTeX, my understanding is that it has these capabilities.

How can I use LaTeX in a reST document? Would the reST document need to be processed into LaTeX, then that rendered into HTML, or is there a better way? Would markdown make this easier? I can modify the gedit plugin if necessary.

Lastly, does anyone do this? Any other suggestions for taking class notes in a plain text editor?

Thanks!

46442 次浏览

LaTeX and ReST are two solutions to the same problem (whole-document markup), and I'm not sure that one would be happy living inside the other.

  • LaTeX first, then ReST: LaTeX needs to precisely position typographical elements in order to lay out equations (and everything else). ReST wouldn't take the LaTeX output (PostScript or similar) as input.
  • ReST first, then LaTeX: You'd have to write an output formatter for ReST that output LaTeX code, and define extensions in ReST to prevent it from misinterpreting your equations or other explicit TeX. Your output from LaTeX will still be something akin to PostScript or PDF.

I've seen code for using a subset of TeX to generate a graphic equation which is then pulled into HTML or similar (for example,Trac's LaTeX Formula macro), which may be the best available solution.

The problem is that reST doesn't really have plugins. You might choose an extensible framework such as Sphinx; a plugin for JSMath is already included, and a plugin for MathJax is also possible. Additionally Sphinx makes use of LaTeX to directly build PDF documents.

Another more lightweight solution consists in editing the reST template to include MathJax so that you can just use MathJax's (LaTeX-like) syntax in the document.

But usually I just use LaTeX directly for anything serious—the customization capabilities of these lightweight markup languages just aren't comprehensive enough for everything.

Pandoc's markdown extension permits inline or display LaTeX math; you just put it between (immediately adjoining) dollar signs like so: $\sqrt{-1}$'s and it's treated as you'd expect. I use this feature all the time, and don't think it's impractical at all. See the manual http://johnmacfarlane.net/pandoc/README.html#math

Once the markdown is parsed, pandoc can write HTML, LaTeX, ReST, RTF, DocBook, ODT, manpages etc., etc. If a LaTeX math context does not involve fancy LaTeX packages, it can even parse the math into MathML, so it renders immediately in HTML or RTF. (It supplies a number of options for dealing with LaTeX math in non-LaTeX documents.)

Pandoc also parses ReST (and HTML, and not-too-fancy LaTeX). I had thus hoped to give a solution involving the ReSt reader, but it seems to have no special machinery for dealing with math; see the discussion of issue 249 http://code.google.com/p/pandoc/issues/detail?id=249 I will study again more closely to see.

I don't think anyone has cooked up a pandoc plugin for Gedit yet (there is elaborate support in emacs and in TextMate, I know) -- that would be awesome!

This item from the Docutils FAQ describes one way to relatively easily include TeX math. You first define a role for interpreted text that passes the equation through directly to LaTeX:

.. role:: raw-latex(raw)
:format: latex

Then you can use that role in your text

The area of a circle is :raw-latex:`$\pi r^2$`

The FAQ entry also mentions a few other ways to do this, including a preprocessor approach that can be used to render the math to an image when generating HTML.

This is what I do:

  1. Add a role for math at the beginning of your reST document:

    .. role:: raw-math(raw)
    :format: latex html
  2. Write your maths like

    :raw-math:`$$ \frac{s}{\sqrt{N}} $$`

    (use $$ ... $$ if you want it in a block, or $ ... $ if you want it inline.)

  3. Generate html output like this:

    rst2html --stylesheet=/path/to/my_beautiful_stylesheet.css my_file.rst \
    | tidy -q | /path/to/itex2MML > my_file.xhtml

    This generates the html with rst2html, tidies up with tidy and then converts the latex maths into MathML with itex2MML, outputting on an xhtml file.

Notes:

  1. Style sheet is optional
  2. For itex2MML go here.
  3. The extension of your html file should be xhtml or xml, otherwise the maths won't show in your browser.

Breaking down your problem a bit, the first goal is to get the latex code output verbatim (except for cgi-escapes for <,>, etch.) into the html generated from your light markup of choice: once you have it there, it can easily be LaTex'ed by mathJax (highly recommended) or itex as mentioned by gozzilli.

First I should say that using markdown instead of ReST would probably be easier because ReST uses \ for escaping, so all LaTeX has to be protected. For an example of how nicely things work out with markdown and mathJax, go play around with the setup at mathoverflow.net.

Nevertheless, I will assume that you really want ReST (and mathJax) , in which case there are two ways ahead: use stock ReST (and cumbersome escaping), or add some LaTeX handlers to docutils.

Option 1 - Stock ReST:

For inline math, simply use verbatim plus whatever you tags your postprocessor is looking for: ``$x<\pi$``. For multi-line math, you want a literal block, but you need to set a class attribute for e.g. MathJaX to parse it, as it otherwise skips <pre> tags:

.. class:: mathjax_process


::


\begin{equation}
x<\pi
\end{equation}

Option 2: Extend you ReST processor

If you are willing to do a bit of hacking to extend your ReST processor, you can get a much nicer notation for the LaTeX literals, by defining a custom interpreted text role for inline latex (e.g. :latex:`x<\pi`) and a custom directive for multi line math, e.g.

.. latex::


\begin{equation}
x<\pi
\end{equation}

The inline math notation can even be shortened to `x<\pi` if you use default-role.

There are several ways to implement the role and directive. I have arrived at (roughly) the following which has the nice feature that (unlike most other hacks I have seen) it degrades to literal LaTex code for writers with no integrated post processing.

from docutils import nodes, utils
from docutils.parsers.rst import directives, Directive


class Latex(Directive):
""" Latex directive to display LaTeX as escaped literal wrapped in
<pre class="latex">.
"""
required_arguments = 0
optional_arguments = 0
has_content = True
def run(self):
self.assert_has_content()
prenode=nodes.literal_block(self.block_text,
'\n'.join(self.content),
classes=['latex'])
return [prenode]
directives.register_directive('latex', Latex)


def latex_role(role, rawtext, text, lineno, inliner, options={}, content=[]):
node = nodes.literal(rawtext,
'\(%s\)'%utils.unescape(text, 1),
classes=['latex'])
return [node],[]
register_local_role('latex', latex_role)

The above will use the class "latex" to mark stuff for processing, so you'll need to configure mathJax or equivalent to look for this class. Alternatively, change the code above to set the class to "mathjax_process" which is the default mathJax override class.

Instead of rst2html use rst2mathml.py.

It extends docutils with a latex-math mode. The contents of this mode is converted to MathML.

Note that version 0.8 of docutils (which parses reStructuredText) has support for LaTeX math. See http://article.gmane.org/gmane.text.docutils.user/6255 for many examples. The choices for the "--math-output" option are: MathML, HTML, MathJax, and LaTeX.

To expand on the previous answers, this is how I got MathJax working with ReST and Docutils, without needing LaTeX:

  1. Use LaTeX-style math within my ReST source, such as:

    The radar backscatter coefficient is $\sigma^0$.
    
  2. Include this somewhere within the file (I put mine at the bottom):

    .. raw:: html
    
    
    <script type="text/x-mathjax-config">
    MathJax.Hub.Config({
    extensions: ["tex2jax.js"],
    jax: ["input/TeX", "output/HTML-CSS"],
    tex2jax: {
    inlineMath: [ ['$','$'], ["\\(","\\)"] ],
    displayMath: [ ['$$','$$'], ["\\[","\\]"] ],
    processEscapes: true
    },
    "HTML-CSS": { availableFonts: ["TeX"] }
    });
    </script>
    <script type="text/javascript" src="http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script>
    
  3. Convert to HTML:

    rst2html report.rst report.html
    
  4. Load the HTML in a modern browser. The MathJax script is downloaded and applied to the HTML upon viewing. Everything looks great for me!

Many thanks to http://www.thales.math.uqam.ca/~labbes/Sage/rst2sws/ for the help!

UPDATE: I noticed that while the output HTML works fine in Firefox, it takes a long time for MathJax to operate in Chrome, and then it gives an error. I fixed it by changing the script source in the last line from

src="http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML"

to

src="http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS_HTML".

I believe the reason is while FireFox supports MathML, Chrome (Webkit, really) doesn't yet (at least not fully; you can test your browser's support here).

Because I have no need for MathML, just TeX, I use the corresponding MathJax version and it now loads quickly in Chrome without any errors. Besides, it would be much faster for you to type math TeX-style than MathML-style.

There is native support for a "math" role and directive (using LaTex input syntax) since Release 0.8 (2011-07-07).

Since version 0.8 it is supported natively: You shouldn't use any workaround anymore. The syntax is also very simple. It is the same as latex math, but without the enclosing $$

So you can simply write the following for a math block

.. math::


\frac{ \sum_{t=0}^{N}f(t,k) }{N}

Or if you want to write inline you can use this:

:math:`\frac{ \sum_{t=0}^{N}f(t,k) }{N}`

notice the delimiting backticks there.


UPDATE:

in newer versions it seems to be necessary to use a double-backslash for the math elements, so it's \\frac and not \frac