diff options
author | Hernan Grecco <hgrecco@gmail.com> | 2023-04-25 01:29:04 -0300 |
---|---|---|
committer | Hernan Grecco <hgrecco@gmail.com> | 2023-04-25 01:29:04 -0300 |
commit | 70e1b2590bdb7a7e4c0941a0a75c57d78a2ea01b (patch) | |
tree | 91e5dee776a45a1ac3b3fb95f1289a61f2135edd /pint | |
parent | 5794ffb8ae25e89ec57fa6e1743c6eafe69e4c0c (diff) | |
parent | 4357104a645e90b937a54318f4b5574f7282129f (diff) | |
download | pint-70e1b2590bdb7a7e4c0941a0a75c57d78a2ea01b.tar.gz |
Merge branch 'pr/1712'
Diffstat (limited to 'pint')
-rw-r--r-- | pint/formatting.py | 19 | ||||
-rw-r--r-- | pint/testsuite/test_unit.py | 27 |
2 files changed, 45 insertions, 1 deletions
diff --git a/pint/formatting.py b/pint/formatting.py index 554b381..f450d5f 100644 --- a/pint/formatting.py +++ b/pint/formatting.py @@ -10,6 +10,7 @@ from __future__ import annotations +import functools import re import warnings from typing import Callable, Dict @@ -178,10 +179,26 @@ def format_pretty(unit, registry, **options): ) +def latex_escape(string): + """ + Prepend characters that have a special meaning in LaTeX with a backslash. + """ + return functools.reduce( + lambda s, m: re.sub(m[0], m[1], s), + ( + (r"[\\]", r"\\textbackslash "), + (r"[~]", r"\\textasciitilde "), + (r"[\^]", r"\\textasciicircum "), + (r"([&%$#_{}])", r"\\\1"), + ), + str(string), + ) + + @register_unit_format("L") def format_latex(unit, registry, **options): preprocessed = { - r"\mathrm{{{}}}".format(u.replace("_", r"\_")): p for u, p in unit.items() + r"\mathrm{{{}}}".format(latex_escape(u)): p for u, p in unit.items() } formatted = formatter( preprocessed.items(), diff --git a/pint/testsuite/test_unit.py b/pint/testsuite/test_unit.py index ee1a5ee..98a4fcc 100644 --- a/pint/testsuite/test_unit.py +++ b/pint/testsuite/test_unit.py @@ -54,6 +54,33 @@ class TestUnit(QuantityTestCase): with subtests.test(spec): assert spec.format(x) == result + def test_latex_escaping(self, subtests): + ureg = UnitRegistry() + ureg.define(r"percent = 1e-2 = %") + x = ureg.Unit(UnitsContainer(percent=1)) + for spec, result in { + "L": r"\mathrm{percent}", + "L~": r"\mathrm{\%}", + "Lx": r"\si[]{\percent}", + "Lx~": r"\si[]{\%}", + }.items(): + with subtests.test(spec): + ureg.default_format = spec + assert f"{x}" == result, f"Failed for {spec}, {result}" + # no '#' here as it's a comment char when define()ing new units + ureg.define(r"weirdunit = 1 = \~_^&%$_{}") + x = ureg.Unit(UnitsContainer(weirdunit=1)) + for spec, result in { + "L": r"\mathrm{weirdunit}", + "L~": r"\mathrm{\textbackslash \textasciitilde \_\textasciicircum \&\%\$\_\{\}}", + "Lx": r"\si[]{\weirdunit}", + # TODO: Currently makes \si[]{\\~_^&%$_{}} (broken). What do we even want this to be? + # "Lx~": r"\si[]{\textbackslash \textasciitilde \_\textasciicircum \&\%\$\_\{\}}", + }.items(): + with subtests.test(spec): + ureg.default_format = spec + assert f"{x}" == result, f"Failed for {spec}, {result}" + def test_unit_default_formatting(self, subtests): ureg = UnitRegistry() x = ureg.Unit(UnitsContainer(meter=2, kilogram=1, second=-1)) |