Source code for sphinx_runpython.tools.latex_functions

import re
from typing import Dict, Optional, Tuple, Union

PREAMBLE = """
\\newcommand{\\vecteurno}[2]{#1,\\dots,#2}
\\newcommand{\\R}{\\mathbb{R}}
\\newcommand{\\pa}[1]{\\left(#1\\right)}
\\newcommand{\\cro}[1]{\\left[#1\\right]}
\\newcommand{\\acc}[1]{\\left\\{#1\\right\\}}
\\newcommand{\\vecteur}[2]{\\left(#1,\\dots,#2\\right)}
\\newcommand{\\N}[0]{\\mathbb{N}}
\\newcommand{\\indicatrice}[1]{ {1\\!\\!1}_{\\left\\{#1\\right\\}} }
\\newcommand{\\infegal}[0]{\\leqslant}
\\newcommand{\\supegal}[0]{\\geqslant}
\\newcommand{\\ensemble}[2]{\\left\\{#1,\\dots,#2\\right\\}}
\\newcommand{\\fleche}[1]{\\overrightarrow{#1}}
\\newcommand{\\intervalle}[2]{\\left\\{#1,\\cdots,#2\\right\\}}
\\newcommand{\\independent}[0]{\\perp \\!\\!\\! \\perp}
\\newcommand{\\esp}{\\mathbb{E}}
\\newcommand{\\espf}[2]{\\mathbb{E}_{#1}\\left(#2\\right)}
\\newcommand{\\var}{\\mathbb{V}}
\\newcommand{\\pr}[1]{\\mathbb{P}\\left(#1\\right)}
\\newcommand{\\loi}[0]{{\\cal L}}
\\newcommand{\\norm}[1]{\\left\\Vert#1\\right\\Vert}
\\newcommand{\\norme}[1]{\\left\\Vert#1\\right\\Vert}
\\newcommand{\\scal}[2]{\\left<#1,#2\\right>}
\\newcommand{\\dans}[0]{\\rightarrow}
\\newcommand{\\partialfrac}[2]{\\frac{\\partial #1}{\\partial #2}}
\\newcommand{\\partialdfrac}[2]{\\dfrac{\\partial #1}{\\partial #2}}
\\newcommand{\\trace}[1]{tr\\left(#1\\right)}
\\newcommand{\\sac}[0]{|}
\\newcommand{\\abs}[1]{\\left|#1\\right|}
\\newcommand{\\loinormale}[2]{{\\cal N} \\left(#1,#2\\right)}
\\newcommand{\\loibinomialea}[1]{{\\cal B} \\left(#1\\right)}
\\newcommand{\\loibinomiale}[2]{{\\cal B} \\left(#1,#2\\right)}
\\newcommand{\\loimultinomiale}[1]{{\\cal M} \\left(#1\\right)}
\\newcommand{\\variance}[1]{\\mathbb{V}\\left(#1\\right)}
\\newcommand{\\intf}[1]{\\left\\lfloor #1 \\right\\rfloor}
"""


[docs] def build_regex(text: Optional[str] = None) -> Dict[str, Union[str, Tuple[str, str]]]: """ Parses a preamble in latex and builds regular expressions based on it. """ if text is None: text = PREAMBLE lines = [_ for _ in text.split("\n") if "newcommand" in _] reg = re.compile(r"newcommand\{\\([a-zA-Z]+)\}(\[([0-9])\])?\{(.+)\}") res = {} for i, line in enumerate(lines): match = reg.search(line) assert match, f"Unable to match pattern reg={reg} in line {i}: {line!r}" name, n, pat = match.group(1), match.group(3), match.group(4) if n is None or int(n) == 0: res[name] = pat elif name in {"pa", "cro", "acc", "abs"}: # These can be nested expression. spl = line.split("#1") begin, end = spl[0][-1], spl[-1][-2] if begin == "{": begin = "\\{" if end == "}": end = "\\}" res[name] = ( lambda s, name=name, begin=begin, end=end: replace_nested_bracked( s, name=name, begin=begin, end=end ) ) else: look = f"\\\\{name} *" + "\\{(.+?)\\}" * int(n) for c in "\\": pat = pat.replace(c, f"\\{c}") for k in range(int(n)): pat = pat.replace(f"#{k+1}", f"\\{k+1}") res[name] = (look, pat) return res
def replace_nested_bracked(text: str, name: str, begin: str, end: str) -> str: """ Replaces brackets, nested brackets... """ find_left = f"\\{name}" + "{" if find_left not in text: return text content = [[]] i = 0 while i < len(text): if i + len(find_left) < len(text) and text[i : i + len(find_left)] == find_left: content.append([]) content[-1].append(f"\\left{begin}") i += len(find_left) elif text[i] == "{": content.append([]) content[-1].append(text[i]) i += 1 elif text[i] == "}": content[-1].append( f"\\right{end}" if content[-1][0].startswith("\\left") else text[i] ) content[-2].append("".join(content.pop())) i += 1 else: content[-1].append(text[i]) i += 1 return "".join(content[0])
[docs] def replace_latex_command( text: str, patterns: Optional[Dict[str, Union[str, Tuple[str, str]]]] = None, verbose: int = 0, ) -> str: """ Replaces a latex by its raw expression. :param text: text :param patterns: one in the known list or None for all :param verbose: verbosity :return: modified text The default patterns are defined by: .. runpython:: :showcode: from sphinx_runpython.tools.latex_functions import PREAMBLE print(PREAMBLE) With gives: .. runpython:: :showcode: import pprint from sphinx_runpython.tools.latex_functions import build_regex pprint.pprint(build_regex()) """ if patterns is None: patterns = build_regex() for k, v in patterns.items(): if verbose: text0 = text if isinstance(v, str): text = text.replace(f"\\{k}", v) if verbose and text != text0: print(f"[replace_latex_command] (1) {k!r}:[{text0}] -> [{text}]") elif isinstance(v, tuple) and len(v) == 2: try: text = re.sub(v[0], v[1], text) except re.error as e: raise AssertionError( f"Unable to replace pattern {v[0]!r} by {v[1]!r} for text={text!r}" ) from e if verbose and text != text0: print(f"[replace_latex_command] (2) {k!r}:[{text0}] -> [{text}]") elif callable(v): text = v(text) if verbose and text != text0: print(f"[replace_latex_command] (3) {k!r}:[{text0}] -> [{text}]") else: raise AssertionError(f"Unable to understand v={v!r} for k={k!r}") return text