From 5d598204db8eb604bce71ce7e6affa49d3720e90 Mon Sep 17 00:00:00 2001 From: Kyle Sunden Date: Mon, 14 Aug 2023 18:59:52 -0500 Subject: [PATCH] Backport PR #26173: Synchronize mathtext docs and handling --- doc/sphinxext/math_symbol_table.py | 103 +++++++----------- .../next_whats_new/mathtext_documentation.rst | 5 + .../mathtext_relation_operators.rst | 2 - doc/users/next_whats_new/mathtext_spacing.rst | 5 + lib/matplotlib/_mathtext.py | 81 +++++++++++--- lib/matplotlib/_mathtext_data.py | 6 +- 6 files changed, 120 insertions(+), 82 deletions(-) create mode 100644 doc/users/next_whats_new/mathtext_documentation.rst create mode 100644 doc/users/next_whats_new/mathtext_spacing.rst diff --git a/doc/sphinxext/math_symbol_table.py b/doc/sphinxext/math_symbol_table.py index 4a3912810264..a143326ab75b 100644 --- a/doc/sphinxext/math_symbol_table.py +++ b/doc/sphinxext/math_symbol_table.py @@ -1,7 +1,11 @@ +import re from docutils.parsers.rst import Directive from matplotlib import _mathtext, _mathtext_data +bb_pattern = re.compile("Bbb[A-Z]") +scr_pattern = re.compile("scr[a-zA-Z]") +frak_pattern = re.compile("frak[A-Z]") symbols = [ ["Lower-case Greek", @@ -18,6 +22,9 @@ ["Hebrew", 6, (r"\aleph", r"\beth", r"\gimel", r"\daleth")], + ["Latin named characters", + 6, + r"""\aa \AA \ae \AE \oe \OE \O \o \thorn \Thorn \ss \eth \dh \DH""".split()], ["Delimiters", 5, _mathtext.Parser._delims], @@ -27,85 +34,56 @@ ["Standard function names", 5, {fr"\{fn}" for fn in _mathtext.Parser._function_names}], - ["Binary operation and relation symbols", + ["Binary operation symbols", + 4, + _mathtext.Parser._binary_operators], + ["Relation symbols", 4, - r"""\ast \pm \slash \cap \star \mp \cup \cdot \uplus - \triangleleft \circ \odot \sqcap \triangleright \bullet \ominus - \sqcup \bigcirc \oplus \wedge \diamond \oslash \vee - \bigtriangledown \times \otimes \dag \bigtriangleup \div \wr - \ddag \barwedge \veebar \boxplus \curlywedge \curlyvee \boxminus - \Cap \Cup \boxtimes \bot \top \dotplus \boxdot \intercal - \rightthreetimes \divideontimes \leftthreetimes \equiv \leq \geq - \perp \cong \prec \succ \mid \neq \preceq \succeq \parallel \sim - \ll \gg \bowtie \simeq \subset \supset \Join \approx \subseteq - \supseteq \ltimes \asymp \sqsubset \sqsupset \rtimes \doteq - \sqsubseteq \sqsupseteq \smile \propto \dashv \vdash \frown - \models \in \ni \notin \approxeq \leqq \geqq \lessgtr \leqslant - \geqslant \lesseqgtr \backsim \lessapprox \gtrapprox \lesseqqgtr - \backsimeq \lll \ggg \gtreqqless \triangleq \lessdot \gtrdot - \gtreqless \circeq \lesssim \gtrsim \gtrless \bumpeq \eqslantless - \eqslantgtr \backepsilon \Bumpeq \precsim \succsim \between - \doteqdot \precapprox \succapprox \pitchfork \Subset \Supset - \fallingdotseq \subseteqq \supseteqq \risingdotseq \sqsubset - \sqsupset \varpropto \preccurlyeq \succcurlyeq \Vdash \therefore - \curlyeqprec \curlyeqsucc \vDash \because \blacktriangleleft - \blacktriangleright \Vvdash \eqcirc \trianglelefteq - \trianglerighteq \neq \vartriangleleft \vartriangleright \ncong - \nleq \ngeq \nsubseteq \nmid \nsupseteq \nparallel \nless \ngtr - \nprec \nsucc \subsetneq \nsim \supsetneq \nVDash \precnapprox - \succnapprox \subsetneqq \nvDash \precnsim \succnsim \supsetneqq - \nvdash \lnapprox \gnapprox \ntriangleleft \ntrianglelefteq - \lneqq \gneqq \ntriangleright \lnsim \gnsim \ntrianglerighteq - \coloneq \eqsim \nequiv \napprox \nsupset \doublebarwedge \nVdash - \Doteq \nsubset \eqcolon \ne - """.split()], + _mathtext.Parser._relation_symbols], ["Arrow symbols", 4, - r"""\leftarrow \longleftarrow \uparrow \Leftarrow \Longleftarrow - \Uparrow \rightarrow \longrightarrow \downarrow \Rightarrow - \Longrightarrow \Downarrow \leftrightarrow \updownarrow - \longleftrightarrow \updownarrow \Leftrightarrow - \Longleftrightarrow \Updownarrow \mapsto \longmapsto \nearrow - \hookleftarrow \hookrightarrow \searrow \leftharpoonup - \rightharpoonup \swarrow \leftharpoondown \rightharpoondown - \nwarrow \rightleftharpoons \leadsto \dashrightarrow - \dashleftarrow \leftleftarrows \leftrightarrows \Lleftarrow - \Rrightarrow \twoheadleftarrow \leftarrowtail \looparrowleft - \leftrightharpoons \curvearrowleft \circlearrowleft \Lsh - \upuparrows \upharpoonleft \downharpoonleft \multimap - \leftrightsquigarrow \rightrightarrows \rightleftarrows - \rightrightarrows \rightleftarrows \twoheadrightarrow - \rightarrowtail \looparrowright \rightleftharpoons - \curvearrowright \circlearrowright \Rsh \downdownarrows - \upharpoonright \downharpoonright \rightsquigarrow \nleftarrow - \nrightarrow \nLeftarrow \nRightarrow \nleftrightarrow - \nLeftrightarrow \to \Swarrow \Searrow \Nwarrow \Nearrow - \leftsquigarrow - """.split()], + _mathtext.Parser._arrow_symbols], + ["Dot symbols", + 4, + r"""\cdots \vdots \ldots \ddots \adots \Colon \therefore \because""".split()], + ["Black-board characters", + 6, + [fr"\{symbol}" for symbol in _mathtext_data.tex2uni + if re.match(bb_pattern, symbol)]], + ["Script characters", + 6, + [fr"\{symbol}" for symbol in _mathtext_data.tex2uni + if re.match(scr_pattern, symbol)]], + ["Fraktur characters", + 6, + [fr"\{symbol}" for symbol in _mathtext_data.tex2uni + if re.match(frak_pattern, symbol)]], ["Miscellaneous symbols", 4, r"""\neg \infty \forall \wp \exists \bigstar \angle \partial - \nexists \measuredangle \eth \emptyset \sphericalangle \clubsuit + \nexists \measuredangle \emptyset \sphericalangle \clubsuit \varnothing \complement \diamondsuit \imath \Finv \triangledown - \heartsuit \jmath \Game \spadesuit \ell \hbar \vartriangle \cdots - \hslash \vdots \blacksquare \ldots \blacktriangle \ddots \sharp + \heartsuit \jmath \Game \spadesuit \ell \hbar \vartriangle + \hslash \blacksquare \blacktriangle \sharp \increment \prime \blacktriangledown \Im \flat \backprime \Re \natural - \circledS \P \copyright \ss \circledR \S \yen \AA \checkmark \$ - \cent \triangle \QED \sinewave \nabla \mho""".split()] + \circledS \P \copyright \circledR \S \yen \checkmark \$ + \cent \triangle \QED \sinewave \dag \ddag \perthousand \ac + \lambdabar \L \l \degree \danger \maltese \clubsuitopen + \i \hermitmatrix \sterling \nabla \mho""".split()], ] def run(state_machine): def render_symbol(sym, ignore_variant=False): - if ignore_variant and sym != r"\varnothing": + if ignore_variant and sym not in (r"\varnothing", r"\varlrtriangle"): sym = sym.replace(r"\var", "\\") if sym.startswith("\\"): sym = sym.lstrip("\\") if sym not in (_mathtext.Parser._overunder_functions | _mathtext.Parser._function_names): sym = chr(_mathtext_data.tex2uni[sym]) - return f'\\{sym}' if sym in ('\\', '|') else sym + return f'\\{sym}' if sym in ('\\', '|', '+', '-', '*') else sym lines = [] for category, columns, syms in symbols: @@ -165,7 +143,10 @@ def setup(app): if sym[1:] not in _mathtext_data.tex2uni: print(sym) + # Add accents + all_symbols.update({v[1:]: k for k, v in _mathtext.Parser._accent_map.items()}) + all_symbols.update({v: v for v in _mathtext.Parser._wide_accents}) print("SYMBOLS NOT IN TABLE:") - for sym in _mathtext_data.tex2uni: + for sym, val in _mathtext_data.tex2uni.items(): if sym not in all_symbols: - print(sym) + print(f"{sym} = {chr(val)}") diff --git a/doc/users/next_whats_new/mathtext_documentation.rst b/doc/users/next_whats_new/mathtext_documentation.rst new file mode 100644 index 000000000000..2b7cd51b702c --- /dev/null +++ b/doc/users/next_whats_new/mathtext_documentation.rst @@ -0,0 +1,5 @@ +``mathtext`` documentation improvements +--------------------------------------- + +The documentation is updated to take information directly from the parser. This +means that (almost) all supported symbols, operators etc are shown at :ref:`mathtext`. diff --git a/doc/users/next_whats_new/mathtext_relation_operators.rst b/doc/users/next_whats_new/mathtext_relation_operators.rst index 7bc7f47bdddc..1f9773a845df 100644 --- a/doc/users/next_whats_new/mathtext_relation_operators.rst +++ b/doc/users/next_whats_new/mathtext_relation_operators.rst @@ -5,5 +5,3 @@ There has been a number of operators added and corrected when a Unicode font is In addition, correct spacing has been added to a number of the previous operators. Especially, the characters used for ``\gnapprox``, ``\lnapprox``, ``\leftangle``, and ``\rightangle`` have been corrected. - -All supported operators can be seen at :ref:`mathtext`. diff --git a/doc/users/next_whats_new/mathtext_spacing.rst b/doc/users/next_whats_new/mathtext_spacing.rst new file mode 100644 index 000000000000..42da810c3a39 --- /dev/null +++ b/doc/users/next_whats_new/mathtext_spacing.rst @@ -0,0 +1,5 @@ +``mathtext`` spacing corrections +-------------------------------- + +As consequence of the updated documentation, the spacing on a number of relational and +operator symbols were classified like that and therefore will be spaced properly. diff --git a/lib/matplotlib/_mathtext.py b/lib/matplotlib/_mathtext.py index 25a825b7b0d9..a2002c971296 100644 --- a/lib/matplotlib/_mathtext.py +++ b/lib/matplotlib/_mathtext.py @@ -1733,7 +1733,17 @@ class _MathStyle(enum.Enum): \cap \triangleleft \dagger \cup \triangleright \ddagger \uplus \lhd \amalg - \dotplus \dotminus'''.split()) + \dotplus \dotminus \Cap + \Cup \barwedge \boxdot + \boxminus \boxplus \boxtimes + \curlyvee \curlywedge \divideontimes + \doublebarwedge \leftthreetimes \rightthreetimes + \slash \veebar \barvee + \cupdot \intercal \amalg + \circledcirc \circleddash \circledast + \boxbar \obar \merge + \minuscolon \dotsminusdots + '''.split()) _relation_symbols = set(r''' = < > : @@ -1768,20 +1778,53 @@ class _MathStyle(enum.Enum): \trianglelefteq \ntrianglelefteq \trianglerighteq \ntrianglerighteq \blacktriangleleft \blacktriangleright \equalparallel \measuredrightangle \varlrtriangle - '''.split()) - - _arrow_symbols = set(r''' - \leftarrow \longleftarrow \uparrow - \Leftarrow \Longleftarrow \Uparrow - \rightarrow \longrightarrow \downarrow - \Rightarrow \Longrightarrow \Downarrow - \leftrightarrow \longleftrightarrow \updownarrow - \Leftrightarrow \Longleftrightarrow \Updownarrow - \mapsto \longmapsto \nearrow - \hookleftarrow \hookrightarrow \searrow - \leftharpoonup \rightharpoonup \swarrow - \leftharpoondown \rightharpoondown \nwarrow - \rightleftharpoons \leadsto'''.split()) + \Doteq \Bumpeq \Subset \Supset + \backepsilon \because \therefore \bot + \top \bumpeq \circeq \coloneq + \curlyeqprec \curlyeqsucc \eqcirc \eqcolon + \eqsim \fallingdotseq \gtrdot \gtrless + \ltimes \rtimes \lessdot \ne + \ncong \nequiv \ngeq \ngtr + \nleq \nless \nmid \notin + \nprec \nsubset \nsubseteq \nsucc + \nsupset \nsupseteq \pitchfork \preccurlyeq + \risingdotseq \subsetneq \succcurlyeq \supsetneq + \varpropto \vartriangleleft \scurel + \vartriangleright \rightangle \equal \backcong + \eqdef \wedgeq \questeq \between + \veeeq \disin \varisins \isins + \isindot \varisinobar \isinobar \isinvb + \isinE \nisd \varnis \nis + \varniobar \niobar \bagmember \ratio + \Equiv \stareq \measeq \arceq + \rightassert \rightModels \smallin \smallowns + \notsmallowns \nsimeq'''.split()) + + _arrow_symbols = set(r""" + \leftarrow \longleftarrow \uparrow \Leftarrow \Longleftarrow + \Uparrow \rightarrow \longrightarrow \downarrow \Rightarrow + \Longrightarrow \Downarrow \leftrightarrow \updownarrow + \longleftrightarrow \updownarrow \Leftrightarrow + \Longleftrightarrow \Updownarrow \mapsto \longmapsto \nearrow + \hookleftarrow \hookrightarrow \searrow \leftharpoonup + \rightharpoonup \swarrow \leftharpoondown \rightharpoondown + \nwarrow \rightleftharpoons \leadsto \dashrightarrow + \dashleftarrow \leftleftarrows \leftrightarrows \Lleftarrow + \Rrightarrow \twoheadleftarrow \leftarrowtail \looparrowleft + \leftrightharpoons \curvearrowleft \circlearrowleft \Lsh + \upuparrows \upharpoonleft \downharpoonleft \multimap + \leftrightsquigarrow \rightrightarrows \rightleftarrows + \rightrightarrows \rightleftarrows \twoheadrightarrow + \rightarrowtail \looparrowright \rightleftharpoons + \curvearrowright \circlearrowright \Rsh \downdownarrows + \upharpoonright \downharpoonright \rightsquigarrow \nleftarrow + \nrightarrow \nLeftarrow \nRightarrow \nleftrightarrow + \nLeftrightarrow \to \Swarrow \Searrow \Nwarrow \Nearrow + \leftsquigarrow \overleftarrow \overleftrightarrow \cwopencirclearrow + \downzigzagarrow \cupleftarrow \rightzigzagarrow \twoheaddownarrow + \updownarrowbar \twoheaduparrow \rightarrowbar \updownarrows + \barleftarrow \mapsfrom \mapsdown \mapsup \Ldsh \Rdsh + """.split()) _spaced_symbols = _binary_operators | _relation_symbols | _arrow_symbols @@ -2116,9 +2159,11 @@ def symbol(self, s, loc, toks): # such as ${ -2}$, $ -2$, or $ -2$. prev_char = next((c for c in s[:loc][::-1] if c != ' '), '') # Binary operators at start of string should not be spaced - if (c in self._binary_operators and - (len(s[:loc].split()) == 0 or prev_char == '{' or - prev_char in self._left_delims)): + # Also, operators in sub- or superscripts should not be spaced + if (self._in_subscript_or_superscript or ( + c in self._binary_operators and ( + len(s[:loc].split()) == 0 or prev_char == '{' or + prev_char in self._left_delims))): return [char] else: return [Hlist([self._make_space(0.2), diff --git a/lib/matplotlib/_mathtext_data.py b/lib/matplotlib/_mathtext_data.py index 40ba4f96f103..d37cdff22e57 100644 --- a/lib/matplotlib/_mathtext_data.py +++ b/lib/matplotlib/_mathtext_data.py @@ -800,6 +800,8 @@ 'eta' : 951, 'forall' : 8704, 'eth' : 240, + 'dh' : 240, + 'DH' : 208, 'colon' : 58, 'sqcup' : 8852, 'bigsqcup' : 10758, @@ -908,7 +910,7 @@ 'O' : 216, 'hookleftarrow' : 8617, 'trianglerighteq' : 8885, - 'nsime' : 8772, + 'nsimeq' : 8772, 'oe' : 339, 'nwarrow' : 8598, 'o' : 248, @@ -1090,6 +1092,8 @@ 'bagmember' : 8959, 'triangle' : 9651, 'iiiint' : 10764, + 'amalg' : 10815, + 'merge' : 10837, } # Each element is a 4-tuple of the form: