Add Unicode math formatter
This commit is contained in:
@@ -0,0 +1,134 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import re
|
||||
|
||||
GREEK_AND_SYMBOLS = {
|
||||
r"\alpha": "α",
|
||||
r"\beta": "β",
|
||||
r"\gamma": "γ",
|
||||
r"\delta": "δ",
|
||||
r"\epsilon": "ε",
|
||||
r"\varepsilon": "ε",
|
||||
r"\zeta": "ζ",
|
||||
r"\eta": "η",
|
||||
r"\theta": "θ",
|
||||
r"\vartheta": "ϑ",
|
||||
r"\iota": "ι",
|
||||
r"\kappa": "κ",
|
||||
r"\lambda": "λ",
|
||||
r"\mu": "μ",
|
||||
r"\nu": "ν",
|
||||
r"\xi": "ξ",
|
||||
r"\pi": "π",
|
||||
r"\rho": "ρ",
|
||||
r"\sigma": "σ",
|
||||
r"\tau": "τ",
|
||||
r"\upsilon": "υ",
|
||||
r"\phi": "φ",
|
||||
r"\varphi": "φ",
|
||||
r"\chi": "χ",
|
||||
r"\psi": "ψ",
|
||||
r"\omega": "ω",
|
||||
r"\Gamma": "Γ",
|
||||
r"\Delta": "Δ",
|
||||
r"\Theta": "Θ",
|
||||
r"\Lambda": "Λ",
|
||||
r"\Xi": "Ξ",
|
||||
r"\Pi": "Π",
|
||||
r"\Sigma": "Σ",
|
||||
r"\Phi": "Φ",
|
||||
r"\Psi": "Ψ",
|
||||
r"\Omega": "Ω",
|
||||
r"\infty": "∞",
|
||||
r"\leq": "≤",
|
||||
r"\le": "≤",
|
||||
r"\geq": "≥",
|
||||
r"\ge": "≥",
|
||||
r"\neq": "≠",
|
||||
r"\ne": "≠",
|
||||
r"\approx": "≈",
|
||||
r"\times": "×",
|
||||
r"\cdot": "·",
|
||||
r"\pm": "±",
|
||||
r"\mp": "∓",
|
||||
r"\to": "→",
|
||||
r"\rightarrow": "→",
|
||||
r"\leftarrow": "←",
|
||||
r"\Rightarrow": "⇒",
|
||||
r"\Leftrightarrow": "⇔",
|
||||
r"\forall": "∀",
|
||||
r"\exists": "∃",
|
||||
r"\in": "∈",
|
||||
r"\notin": "∉",
|
||||
r"\subset": "⊂",
|
||||
r"\subseteq": "⊆",
|
||||
r"\cup": "∪",
|
||||
r"\cap": "∩",
|
||||
r"\emptyset": "∅",
|
||||
r"\mathbb{R}": "ℝ",
|
||||
r"\mathbb{C}": "ℂ",
|
||||
r"\mathbb{N}": "ℕ",
|
||||
r"\mathbb{Z}": "ℤ",
|
||||
r"\mathbb{Q}": "ℚ",
|
||||
r"\int": "∫",
|
||||
r"\sum": "∑",
|
||||
r"\prod": "∏",
|
||||
r"\partial": "∂",
|
||||
r"\nabla": "∇",
|
||||
}
|
||||
|
||||
SUPERSCRIPT = str.maketrans({
|
||||
"0": "⁰", "1": "¹", "2": "²", "3": "³", "4": "⁴",
|
||||
"5": "⁵", "6": "⁶", "7": "⁷", "8": "⁸", "9": "⁹",
|
||||
"+": "⁺", "-": "⁻", "=": "⁼", "(": "⁽", ")": "⁾",
|
||||
"n": "ⁿ", "i": "ⁱ",
|
||||
})
|
||||
|
||||
SUBSCRIPT = str.maketrans({
|
||||
"0": "₀", "1": "₁", "2": "₂", "3": "₃", "4": "₄",
|
||||
"5": "₅", "6": "₆", "7": "₇", "8": "₈", "9": "₉",
|
||||
"+": "₊", "-": "₋", "=": "₌", "(": "₍", ")": "₎",
|
||||
"a": "ₐ", "e": "ₑ", "h": "ₕ", "i": "ᵢ", "j": "ⱼ", "k": "ₖ",
|
||||
"l": "ₗ", "m": "ₘ", "n": "ₙ", "o": "ₒ", "p": "ₚ", "r": "ᵣ",
|
||||
"s": "ₛ", "t": "ₜ", "u": "ᵤ", "v": "ᵥ", "x": "ₓ",
|
||||
})
|
||||
|
||||
_GROUP_PATTERN = re.compile(r"([_^])\(([^()]+)\)|([_^])\{([^{}]+)\}|([_^])([A-Za-z0-9+\-=])")
|
||||
|
||||
|
||||
def _translate_script(value: str, marker: str) -> str:
|
||||
table = SUPERSCRIPT if marker == "^" else SUBSCRIPT
|
||||
converted = value.translate(table)
|
||||
return converted if converted != value else marker + value
|
||||
|
||||
|
||||
def _replace_script(match: re.Match[str]) -> str:
|
||||
marker = match.group(1) or match.group(3) or match.group(5)
|
||||
value = match.group(2) or match.group(4) or match.group(6)
|
||||
return _translate_script(value, marker)
|
||||
|
||||
|
||||
def format_math_text(text: str, mode: str = "plain") -> str:
|
||||
r"""Convert common UnicodeMath/LaTeX-like linear math to Unicode plain text.
|
||||
|
||||
This is meant for Word normal text insertion. It makes expressions such as
|
||||
z_1, x^2, \alpha and \infty render as z₁, x², α and ∞ without requiring the
|
||||
user to manually open Word's equation editor for every expression.
|
||||
"""
|
||||
if mode == "plain":
|
||||
return text
|
||||
if mode not in {"unicode", "unicode_math"}:
|
||||
raise ValueError("math_text_format doit être 'plain' ou 'unicode'")
|
||||
|
||||
formatted = text
|
||||
# Replace longer commands first so \subseteq wins before \subset.
|
||||
for command, replacement in sorted(GREEK_AND_SYMBOLS.items(), key=lambda item: len(item[0]), reverse=True):
|
||||
formatted = formatted.replace(command, replacement)
|
||||
|
||||
formatted = re.sub(r"\\vec\(([^()]+)\)", lambda match: match.group(1) + "⃗", formatted)
|
||||
formatted = formatted.replace(r"\sqrt", "√")
|
||||
previous = None
|
||||
while previous != formatted:
|
||||
previous = formatted
|
||||
formatted = _GROUP_PATTERN.sub(_replace_script, formatted)
|
||||
return formatted
|
||||
Reference in New Issue
Block a user