Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support TeX-like left..right construct #2179

Merged
merged 2 commits into from
Nov 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions packages/math/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,18 @@ To keep them small, you should put braces around the expression:
\Vert v \Vert = \sqrt{x^2 + y^2} \text{ vs. } {\Vert v \Vert} = \sqrt{x^2 + y^2}
\end{math}

Alternatively, you can use the \code{\\left} and \code{\\right} commands to automatically adjust the size of the delimiters to the inner content.
Since SILE does it automatically for paired delimiters, it only really useful if you took a TeX formula using these commands and want to keep it as is, or if you want to use delimiters that are not paired in an obvious way.
In this construct, the period is also supported for a null delimiter, as with TeX.

\begin[type=autodoc:codeblock]{raw}
\left\rangle \frac{\zeta}{2} \right\langle \quad \left\}\frac{\zeta}{2} \right.
\end{raw}

\begin[mode=display]{math}
\left\rangle \frac{\zeta}{2} \right\langle \quad \left\}\frac{\zeta}{2} \right.
\end{math}

\noindent To print a brace in a formula, you need to escape it with a backslash.

\paragraph{Token kinds}
Expand Down
72 changes: 71 additions & 1 deletion packages/math/texlike.lua
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,21 @@ local mathGrammar = function (_ENV)
digit^1 -- Integer (digits only, ex: 123)
) / tostring
local pos_natural = R("19") * digit^0 / tonumber

-- \left and \right delimiters = The TeXbook p. 148.
-- Characters with a delcode in TeX: The TeXbook p. 341
-- These are for use in \left...\right pairs.
-- We add the period (null delimiter) from p. 149-150.
-- We don't include the backslash here and handle it just after.
local delcode = S"([</|)]>."
-- Left/right is followed by a delimiter with delcode, or a command.
-- We use the delcode or backslash as terminator: commands such as
-- \rightarrow must still be allowed.
local leftright = function (s) return P(s) * (delcode + P"\\") end

local ctrl_word = R("AZ", "az")^1
local ctrl_symbol = P(1) - S"{}\\"
local ctrl_sequence_name = C(ctrl_word + ctrl_symbol) / 1
local ctrl_sequence_name = C(ctrl_word + ctrl_symbol) - leftright("left") - leftright("right") / 1
local comment = (
P"%" *
P(1-eol)^0 *
Expand All @@ -56,7 +68,57 @@ local mathGrammar = function (_ENV)
local group = P"{" * V"mathlist" * (P"}" + E("`}` expected"))
-- Simple amsmath-like \text command (no embedded math)
local textgroup = P"{" * C((1-P"}")^1) * (P"}" + E("`}` expected"))
-- TeX \left...\right group
local delim =
-- Delimiter with delcode
C(delcode) / function (d)
if d ~= "." then
return {
id = "atom",
d
}
end
return nil
end
-- Delimiter as escaped \{ or \}
+ P"\\" * C(S"{}") / function (d)
return {
id = "atom",
d
}
end
-- Delimiter as command ex. \langle
+ P"\\" * C(ctrl_sequence_name) / 1 / function (cmd)
return {
id = "command",
command = cmd
}
end

local leftrightgroup = P"\\left" * delim * V"mathlist" * P"\\right" * delim
/ function (left, subformula, right)
if not left and not right then
-- No delimiters, return the subformula as-is
return subformula
end
-- Rewrap the subformula in a flagged mathlist
local mrow = {
id = "mathlist",
options = {},
is_paired_explicit = true, -- Internal flag
subformula
}
if left then
table.insert(mrow, 1, left)
end
if right then
table.insert(mrow, right)
end
return mrow
end

local element_no_infix =
leftrightgroup + -- Important: before command
V"def" +
V"text" + -- Important: before command
V"command" +
Expand Down Expand Up @@ -412,6 +474,14 @@ local function compileToMathML_aux (_, arg_env, tree)
else
tree.command = "mrow"
end
elseif tree.is_paired_explicit then
-- We already did the re-wrapping of open/close delimiters in the parser
-- via \left...\right, doing it would not harm but would add an extra mrow,
-- which we can avoid directly to keep the tree minimal.
-- N.B. We could have used the same flag, but it's easier to debug this way.
tree.is_paired = true
tree.is_paired_explicit = nil
tree.command = "mrow"
else
-- Re-wrap content from opening to closing operator in an implicit mrow,
-- so stretchy operators apply to the correct span of content.
Expand Down
195 changes: 195 additions & 0 deletions tests/math-left-right-tex.expected
Original file line number Diff line number Diff line change
@@ -0,0 +1,195 @@
Set paper size 419.5275636 595.275597
Begin page
Mx 177.5243
My 43.9388
Set font Libertinus Math;10;400;Regular;normal;;;LTR
T 830 w=4.9700 (nil)
Mx 182.4943
Mx 3.6700
T 4133 a=4.9700 (nil)
Draw line 188.2143 41.0138 4.8900 0.6500
Mx 188.2143
My 36.7438
T 3411 w=4.8900 (nil)
Mx 188.3343
My 50.9388
T 19 w=4.6500 (nil)
Mx 193.8543
My 43.9388
Mx 3.6700
T 4141 a=4.9700 (nil)
Mx 201.0466
T 12 w=6.4800 (nil)
Mx 209.7488
T 9 w=3.5600 (nil)
Mx 213.3088
T 2768 w=5.4100 (nil)
Mx 220.9410
T 12 w=6.4800 (nil)
Mx 229.6432
T 18 w=4.6500 (nil)
Mx 234.2932
T 10 w=3.5600 (nil)
Mx 237.8532
My 38.9388
Set font Libertinus Math;8;400;Regular;normal;+ssty=1;;LTR
T 19 w=3.7200 (nil)
Mx 177.5243
My 84.2978
Set font Libertinus Math;10;400;Regular;normal;;;LTR
T 830 w=4.9700 (nil)
Mx 182.4943
Mx 3.6700
T 4133 a=4.9700 (nil)
Draw line 188.2143 81.3728 4.8900 0.6500
Mx 188.2143
My 77.1028
T 3411 w=4.8900 (nil)
Mx 188.3343
My 91.2978
T 19 w=4.6500 (nil)
Mx 193.8543
My 84.2978
Mx 3.6700
T 4141 a=4.9700 (nil)
Mx 201.0466
T 12 w=6.4800 (nil)
Mx 209.7488
T 9 w=3.5600 (nil)
Mx 213.3088
T 2768 w=5.4100 (nil)
Mx 220.9410
T 12 w=6.4800 (nil)
Mx 229.6432
T 18 w=4.6500 (nil)
Mx 234.2932
T 10 w=3.5600 (nil)
Mx 237.8532
My 79.2978
Set font Libertinus Math;8;400;Regular;normal;+ssty=1;;LTR
T 19 w=3.7200 (nil)
Mx 177.7838
My 124.6569
Set font Libertinus Math;10;400;Regular;normal;;;LTR
Mx 0.5000
T 4275 a=2.1000 (nil)
Draw line 180.6338 121.7319 4.8900 0.6500
Mx 180.6338
My 117.4619
T 3411 w=4.8900 (nil)
Mx 180.7538
My 131.6569
T 19 w=4.6500 (nil)
Mx 186.2738
My 124.6569
Mx 0.5000
T 4275 a=2.1000 (nil)
Mx 198.3738
Mx 0.5000
T 4275 a=2.1000 (nil)
Draw line 201.2238 121.7319 4.8900 0.6500
Mx 201.2238
My 117.4619
T 3411 w=4.8900 (nil)
Mx 201.3438
My 131.6569
T 19 w=4.6500 (nil)
Draw line 217.6138 121.7319 4.8900 0.6500
Mx 217.6138
My 117.4619
T 3411 w=4.8900 (nil)
Mx 217.7338
My 131.6569
T 19 w=4.6500 (nil)
Mx 223.2538
My 124.6569
Mx 0.5000
T 4275 a=2.1000 (nil)
Draw line 236.1038 121.7319 4.8900 0.6500
Mx 236.1038
My 117.4619
T 3411 w=4.8900 (nil)
Mx 236.2238
My 131.6569
T 19 w=4.6500 (nil)
Mx 180.5788
My 165.0160
Mx 3.8900
T 4327 a=4.8000 (nil)
Draw line 186.1288 162.0910 4.8900 0.6500
Mx 186.1288
My 157.8210
T 3411 w=4.8900 (nil)
Mx 186.2488
My 172.0160
T 19 w=4.6500 (nil)
Mx 191.7688
My 165.0160
Mx 3.8900
T 4335 a=4.8000 (nil)
Mx 206.5688
Mx 3.8900
T 4327 a=4.8000 (nil)
Draw line 212.1188 162.0910 4.8900 0.6500
Mx 212.1188
My 157.8210
T 3411 w=4.8900 (nil)
Mx 212.2388
My 172.0160
T 19 w=4.6500 (nil)
Draw line 228.5088 162.0910 4.8900 0.6500
Mx 228.5088
My 157.8210
T 3411 w=4.8900 (nil)
Mx 228.6288
My 172.0160
T 19 w=4.6500 (nil)
Mx 234.1488
My 165.0160
Mx 3.8900
T 4335 a=4.8000 (nil)
Mx 177.3288
My 205.3750
Mx 2.8500
T 4124 a=3.8900 (nil)
Draw line 181.9688 202.4500 4.8900 0.6500
Mx 181.9688
My 198.1800
T 3411 w=4.8900 (nil)
Mx 182.0888
My 212.3750
T 19 w=4.6500 (nil)
Mx 187.6088
My 205.3750
Mx 2.8400
T 4117 a=3.8900 (nil)
Mx 201.4988
Mx 2.4700
T 4157 a=4.1600 (nil)
Draw line 206.4088 202.4500 4.8900 0.6500
Mx 206.4088
My 198.1800
T 3411 w=4.8900 (nil)
Mx 206.5288
My 212.3750
T 19 w=4.6500 (nil)
Mx 212.0488
My 205.3750
Mx 2.4700
T 4149 a=4.1600 (nil)
Mx 226.2088
Mx 3.8900
T 4335 a=4.8000 (nil)
Draw line 231.7588 202.4500 4.8900 0.6500
Mx 231.7588
My 198.1800
T 3411 w=4.8900 (nil)
Mx 231.8788
My 212.3750
T 19 w=4.6500 (nil)
Mx 237.3988
My 205.3750
Mx 3.8900
T 4327 a=4.8000 (nil)
End page
Finish
39 changes: 39 additions & 0 deletions tests/math-left-right-tex.sil
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@

\begin[papersize=a5]{document}
\nofolios
\neverindent
\use[module=packages.math]

% Without \left...\right construct = default open-close pairing
\begin[mode=display]{math}
\Gamma(\frac{\zeta}{2}) + (x+1)^2
\end{math}

% With \left...\right construct = explicit open-close pairing
\begin[mode=display]{math}
\Gamma\left(\frac{\zeta}{2}\right) + \left(x+1\right)^2
\end{math}

% Left-right with unpaired atom, incl. null delimiter cases
\begin[mode=display]{math}
\left|\frac{\zeta}{2}\right|
\quad \left|\frac{\zeta}{2}\right.
\quad \left.\frac{\zeta}{2}\right|
\quad \left.\frac{\zeta}{2}\right.
\end{math}

% Left-right with paired command
\begin[mode=display]{math}
\left\langle\frac{\zeta}{2}\right\rangle
\quad \left\langle\frac{\zeta}{2}\right.
\quad \left.\frac{\zeta}{2}\right\rangle
\end{math}

% Left-right with unpaired command
\begin[mode=display]{math}
\left\}\frac{\zeta}{2}\right\{
\quad \left]\frac{\zeta}{2}\right[
\quad \left\rangle\frac{\zeta}{2}\right\langle
\end{math}

\end{document}
Loading