Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit d58306f

Browse files
committed
Correctly end tokens in mathtext parsing.
This avoids parsing `\sinx` as `\sin x` (it now raises an error instead), and removes the need for `accentprefixed` (because `\doteq` is treated as a single token now, instead of `\dot{eq}`). This also means that `\doteq` (and friends) are now correctly treated as relations (per `_relation_symbols`, thus changing the spacing around them); hence then change in baseline images. Adjust test strings accordingly to undo the spacing, to avoid regen'ing baselines. Also shaves ~2% off drawing all the current mathtext tests, i.e. ``` MPLBACKEND=agg python -c 'import time; from pylab import *; from matplotlib.tests.test_mathtext import math_tests; fig = figure(figsize=(3, 10)); fig.text(0, 0, "\n".join(filter(None, math_tests)), size=6); start = time.perf_counter(); [fig.canvas.draw() for _ in range(10)]; print((time.perf_counter() - start) / 10)' ``` (including adjustment for the removed test case), probably because accentprefixed was previously extremely commonly checked, being at the top of the placeable list; however, performance wasn't really the main goal here.
1 parent 56a5153 commit d58306f

17 files changed

+40
-1076
lines changed

lib/matplotlib/_mathtext.py

Lines changed: 20 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1718,13 +1718,27 @@ def set_names_and_parse_actions():
17181718

17191719
# Root definitions.
17201720

1721+
# In TeX parlance, a csname is a control sequence name (a "\foo").
1722+
def csnames(group, names):
1723+
ends_with_alpha = []
1724+
ends_with_nonalpha = []
1725+
for name in names:
1726+
if name[-1].isalpha():
1727+
ends_with_alpha.append(name)
1728+
else:
1729+
ends_with_nonalpha.append(name)
1730+
return Regex(r"\\(?P<{}>(?:{})(?![A-Za-z]){})".format(
1731+
group,
1732+
"|".join(map(re.escape, ends_with_alpha)),
1733+
"".join(f"|{s}" for s in map(re.escape, ends_with_nonalpha)),
1734+
))
1735+
17211736
p.float_literal = Regex(r"[-+]?([0-9]+\.?[0-9]*|\.[0-9]+)")
17221737
p.space = oneOf(self._space_widths)("space")
17231738

17241739
p.style_literal = oneOf(
17251740
[str(e.value) for e in self._MathStyle])("style_literal")
17261741

1727-
p.accentprefixed = "\\" + oneOf(self._accentprefixed)("sym")
17281742
p.symbol = Regex(
17291743
r"[a-zA-Z0-9 +\-*/<>=:,.;!\?&'@()\[\]|\U00000080-\U0001ffff]"
17301744
r"|\\[%${}\[\]_|]"
@@ -1733,7 +1747,7 @@ def set_names_and_parse_actions():
17331747
)("sym").leaveWhitespace()
17341748
p.unknown_symbol = Regex(r"\\[A-Za-z]*")("name")
17351749

1736-
p.font = "\\" + oneOf(self._fontnames)("font")
1750+
p.font = csnames("font", self._fontnames)
17371751
p.start_group = (
17381752
Optional(r"\math" + oneOf(self._fontnames)("font")) + "{")
17391753
p.end_group = Literal("}")
@@ -1770,11 +1784,10 @@ def set_names_and_parse_actions():
17701784
p.customspace <<= cmd(r"\hspace", "{" + p.float_literal("space") + "}")
17711785

17721786
p.accent <<= (
1773-
"\\"
1774-
+ oneOf([*self._accent_map, *self._wide_accents])("accent")
1787+
csnames("accent", [*self._accent_map, *self._wide_accents])
17751788
- p.placeable("sym"))
17761789

1777-
p.function <<= "\\" + oneOf(self._function_names)("name")
1790+
p.function <<= csnames("name", self._function_names)
17781791
p.operatorname <<= cmd(
17791792
r"\operatorname",
17801793
"{" + ZeroOrMore(p.simple | p.unknown_symbol)("name") + "}")
@@ -1815,10 +1828,8 @@ def set_names_and_parse_actions():
18151828
p.optional_group("annotation") + p.optional_group("body"))
18161829

18171830
p.placeable <<= (
1818-
p.accentprefixed # Must be before accent so named symbols that are
1819-
# prefixed with an accent name work
1820-
| p.accent # Must be before symbol as all accents are symbols
1821-
| p.symbol # Must be third to catch all named symbols and single
1831+
p.accent # Must be before symbol as all accents are symbols
1832+
| p.symbol # Must be second to catch all named symbols and single
18221833
# chars not in a group
18231834
| p.function
18241835
| p.operatorname
@@ -2014,8 +2025,6 @@ def symbol(self, s, loc, toks):
20142025
return [Hlist([char, self._make_space(0.2)], do_kern=True)]
20152026
return [char]
20162027

2017-
accentprefixed = symbol
2018-
20192028
def unknown_symbol(self, s, loc, toks):
20202029
raise ParseFatalException(s, loc, f"Unknown symbol: {toks['name']}")
20212030

@@ -2044,12 +2053,6 @@ def unknown_symbol(self, s, loc, toks):
20442053

20452054
_wide_accents = set(r"widehat widetilde widebar".split())
20462055

2047-
# make a lambda and call it to get the namespace right
2048-
_accentprefixed = (lambda am: [
2049-
p for p in tex2uni
2050-
if any(p.startswith(a) and a != p for a in am)
2051-
])(set(_accent_map))
2052-
20532056
def accent(self, s, loc, toks):
20542057
state = self.get_state()
20552058
thickness = state.get_current_underline_thickness()
Binary file not shown.
Binary file not shown.

lib/matplotlib/tests/baseline_images/test_mathtext/mathtext_cm_77.svg

Lines changed: 0 additions & 222 deletions
This file was deleted.
Binary file not shown.
Binary file not shown.

0 commit comments

Comments
 (0)