On Nov 12, 12:35 pm, pkienzle <pkien...@gmail.com> wrote:
> Following the hints in the extension API docs I created an extension
> which allows $tex$ instead of :math:`tex` in rst and py docstrings.
>
> Put this in your extensions directory and add "dollarmath" to your
> configuration file.
>
>   - Paul
>
> --dollarmath.py--
> # This program is public domain
> # Author: Paul Kienzle
> r"""
> Allow $math$ markup in text and docstrings, ignoring \$.
>
> The $math$ markup should be separated from the surrounding text by
> spaces.  To
> embed markup within a word, place backslash-space before and after.
> For
> convenience, the final $ can be followed by punctuation (period, comma
> or
> semicolon).
> """
>
> import re
>
> _dollar = re.compile(r"(?:^|(?<=\s))[$]([^\n]*?)(?<![\\])[$](?:$|(?=\s|
> [.,;\\]))")
> _notdollar = re.compile(r"\\[$]")
>
> def replace_dollar(content):
>     original = content
>     content = _dollar.sub(r":math:`\1`",content)
>     content = _notdollar.sub("$", content)
>     #if '$' in content:
>     #    import sys
>     #    sys.stdout.write("\n========> not converted\n")
>     #    sys.stdout.write(content)
>     #    sys.stdout.write("\n")
>     #elif '$' in original:
>     #    import sys
>     #    sys.stdout.write("\n========> converted\n")
>     #    sys.stdout.write(content)
>     #    sys.stdout.write("\n")
>     return content
>
> def rewrite_rst(app, docname, source):
>     source[0] = replace_dollar(source[0])
>
> def rewrite_autodoc(app, what, name, obj, options, lines):
>     lines[:] = [replace_dollar(L) for L in lines]
>
> def setup(app):
>     app.connect('source-read', rewrite_rst)
>     app.connect('autodoc-process-docstring', rewrite_autodoc)
>
> def test_dollar():
>     assert replace_dollar(u"no dollar")==u"no dollar"
>     assert replace_dollar(u"$only$")==u":math:`only`"
>     assert replace_dollar(u"$first$ is good")==u":math:`first` is
> good"
>     assert replace_dollar(u"so is $last$")==u"so is :math:`last`"
>     assert replace_dollar(u"and $mid$ too")==u"and :math:`mid` too"
>     assert replace_dollar(u"$first$, $mid$, $last
> $")==u":math:`first`, :math:`mid`, :math:`last`"
>     assert replace_dollar(u"dollar\$ escape")==u"dollar$ escape"
>     assert replace_dollar(u"dollar \$escape\$ too")==u"dollar $escape$
> too"
>     assert replace_dollar(u"emb\ $ed$\ ed")==u"emb\ :math:`ed`\ ed"
>     assert replace_dollar(u"$first$a")==u"$first$a"
>     assert replace_dollar(u"a$last$")==u"a$last$"
>     assert replace_dollar(u"a $mid$dle a")==u"a $mid$dle a"
>
> if __name__ == "__main__":
>     test_dollar()

In Sage [www.sagemath.org], we've been using the following function to
replace dollar signs with backticks (in Sage, we have

default_role = 'math'

in conf.py, so we just need `x=y`, not :math:`x=y`).  This one
replaces dollar signs even if they're not surrounded by white space.
I haven't tested it, but you might be able to use this as an
alternative for the function replace_dollar.

- John




def process_dollars(s):
    r"""
    Replace dollar signs with backticks.

    More precisely, do a regular expression search.  Replace a plain
    dollar sign ($) by a backtick (`).  Replace an escaped dollar sign
    (\\$) by a dollar sign ($).  Don't change a dollar sign preceded
or
    followed by a backtick (\`$ or \$`), because of strings like
    "``$HOME``".  Don't make any changes on lines starting with more
    spaces than the first nonempty line in ``s``, because those are
    indented and hence part of a block of code or examples.

    This also doesn't replaces dollar signs enclosed in curly braces,
    to avoid nested math environments.

    EXAMPLES::

        sage: from sage.misc.sagedoc import process_dollars
        sage: process_dollars('hello')
        'hello'
        sage: process_dollars('some math: $x=y$')
        'some math: `x=y`'

    Replace \\$ with $, and don't do anything when backticks are
involved::

        sage: process_dollars(r'a ``$REAL`` dollar sign: \$')
        'a ``$REAL`` dollar sign: $'

    Don't make any changes on lines indented more than the first
    nonempty line::

        sage: s = '\n first line\n     indented $x=y$'
        sage: s == process_dollars(s)
        True

    Don't replace dollar signs enclosed in curly braces::

        sage: process_dollars(r'f(n) = 0 \text{ if $n$ is prime}')
        'f(n) = 0 \\text{ if $n$ is prime}'

    This is not perfect::

        sage: process_dollars(r'$f(n) = 0 \text{ if $n$ is prime}$')
        '`f(n) = 0 \\text{ if $n$ is prime}$'

    The regular expression search doesn't find the last $.
    Fortunately, there don't seem to be any instances of this kind of
    expression in the Sage library, as of this writing.
    """
    if s.find("$") == -1:
        return s
    # find how much leading whitespace s has, for later comparison:
    # ignore all $ on lines which start with more whitespace.
    whitespace = re.match(r'\s*\S', s.lstrip('\n'))
    whitespace = ' ' * (whitespace.end() - 1) # leading whitespace
    # Indices will be a list of pairs of positions in s, to search
between.
    # If the following search has no matches, then indices will be (0,
len(s)).
    indices = [0]
    # This searches for "$blah$" inside a pair of curly braces --
    # don't change these, since they're probably coming from a nested
    # math environment.  So for each match, search to the left of its
    # start and to the right of its end, but not in between.
    for m in re.finditer(r"{[^{}$]*\$([^{}$]*)\$[^{}$]*}", s):
        indices[-1] = (indices[-1], m.start())
        indices.append(m.end())
    indices[-1] = (indices[-1], len(s))
    # regular expression for $ (not \$, `$, $`, and only on a line
    # with no extra leading whitespace).
    #
    # in detail:
    #   re.compile("^" # beginning of line
    #               + "(%s%)?" % whitespace
    #               + r"""(\S # non whitespace
    #                     .*?)? # non-greedy match any non-newline
characters
    #                     (?<!`|\\)\$(?!`) # $ with negative
lookbehind and lookahead
    #                  """, re.M | re.X)
    #
    # except that this doesn't work, so use the equivalent regular
    # expression without the 're.X' option.  Maybe 'whitespace' gets
    # eaten up by re.X?
    regexp = "^" + "(%s)?"%whitespace + r"(\S.*?)?(?<!`|\\)\$(?!`)"
    dollar = re.compile(regexp, re.M)
    # regular expression for \$
    slashdollar = re.compile(r"\\\$")
    for start, end in indices:
        while dollar.search(s, start, end):
            m = dollar.search(s, start, end)
            s = s[:m.end()-1] + "`" + s[m.end():]
        while slashdollar.search(s, start, end):
            m = slashdollar.search(s, start, end)
            s = s[:m.start()] + "$" + s[m.end():]
    return s

-- 
You received this message because you are subscribed to the Google Groups 
"sphinx-dev" group.
To post to this group, send email to sphinx-...@googlegroups.com.
To unsubscribe from this group, send email to 
sphinx-dev+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/sphinx-dev?hl=en.

Reply via email to