Skip to content

Commit

Permalink
Typst writer: Fix several issues with accents and attachments.
Browse files Browse the repository at this point in the history
Closes #245.
  • Loading branch information
jgm committed Jan 5, 2025
1 parent 9c068cb commit 1782269
Show file tree
Hide file tree
Showing 4 changed files with 170 additions and 37 deletions.
81 changes: 52 additions & 29 deletions src/Text/TeXMath/Writers/Typst.hs
Original file line number Diff line number Diff line change
Expand Up @@ -94,9 +94,12 @@ escInQuotes t =
needsEscape c = c == '\\' || c == '"'

writeExpS :: Exp -> Text
writeExpS (EGrouped es) = "(" <> writeExps es <> ")"
writeExpS e =
case writeExp e of
"" -> "()"
t | Just (c,_) <- T.uncons t
, c >= '\8988' && c <= '\8991'
-> "\\" <> t -- see #245
t | T.all (\c -> isDigit c || c == '.') t -> t
| T.all (\c -> isAlpha c || c == '.') t -> t
| otherwise -> "(" <> t <> ")"
Expand Down Expand Up @@ -143,36 +146,13 @@ writeExp (EOver _ (EOver _ b (ESymbol TOver "\9182")) e1) =
"overbrace(" <> writeExp b <> ", " <> writeExp e1 <> ")"
writeExp (EOver _ (EOver _ b (ESymbol TOver "\9140")) e1) =
"overbracket(" <> writeExp b <> ", " <> writeExp e1 <> ")"
writeExp (EOver _convertible b (ESymbol Accent ac))
= case getAccentCommand ac of
Just accCommand
| not (isGrouped b) -> accCommand <> inParens (writeExp b)
_ -> "accent" <> inParens (writeExp b <> ", " <> ac)
writeExp (EOver _convertible b e1) =
case e1 of
ESymbol Accent "`" -> "grave" <> inParens (writeExp b)
ESymbol Accent "\180" -> "acute" <> inParens (writeExp b)
ESymbol Accent "^" -> "hat" <> inParens (writeExp b)
ESymbol Accent "~" -> "tilde" <> inParens (writeExp b)
ESymbol Accent "." -> "dot" <> inParens (writeExp b)
ESymbol Accent "\168" -> "diaer" <> inParens (writeExp b)
ESymbol Accent "\175" -> "macron" <> inParens (writeExp b)
ESymbol Accent "\711" -> "caron" <> inParens (writeExp b)
ESymbol Accent "\728" -> "breve" <> inParens (writeExp b)
ESymbol Accent "\733" -> "acute.double" <> inParens (writeExp b)
ESymbol Accent "\768" -> "grave" <> inParens (writeExp b)
ESymbol Accent "\769" -> "acute" <> inParens (writeExp b)
ESymbol Accent "\770" -> "hat" <> inParens (writeExp b)
ESymbol Accent "\771" -> "tilde" <> inParens (writeExp b)
ESymbol Accent "\772" -> "macron" <> inParens (writeExp b)
ESymbol Accent "\773" -> "overline" <> inParens (writeExp b)
ESymbol Accent "\774" -> "breve" <> inParens (writeExp b)
ESymbol Accent "\775" -> "dot" <> inParens (writeExp b)
ESymbol Accent "\776" -> "dot.double" <> inParens (writeExp b)
ESymbol Accent "\777" -> "harpoon" <> inParens (writeExp b)
ESymbol Accent "\778" -> "circle" <> inParens (writeExp b)
ESymbol Accent "\779" -> "acute.double" <> inParens (writeExp b)
ESymbol Accent "\780" -> "caron" <> inParens (writeExp b)
ESymbol Accent "\781" -> "overline" <> inParens (writeExp b)
ESymbol Accent "\x2218" -> "circle" <> inParens (writeExp b)
ESymbol Accent "\x2192" -> "->" <> inParens (writeExp b)
ESymbol Accent "\x2190" -> "<-" <> inParens (writeExp b)
ESymbol Accent "\8407" -> "arrow" <> inParens (writeExp b)
ESymbol TOver "\9182" -> "overbrace" <> inParens (writeExp b)
ESymbol TOver "\9140" -> "overbracket" <> inParens (writeExp b)
ESymbol TOver "\175" -> "overline" <> inParens (writeExp b)
Expand All @@ -184,6 +164,7 @@ writeExp (EUnder _ (EUnder _ b (ESymbol TUnder "\9140")) e1) =
writeExp (EUnder _convertible b e1) =
case e1 of
ESymbol TUnder "_" -> "underline(" <> writeExp b <> ")"
ESymbol TUnder "\817" -> "underline(" <> writeExp b <> ")"
ESymbol TUnder "\9183" -> "underbrace(" <> writeExp b <> ")"
ESymbol TUnder "\9140" -> "underbracket(" <> writeExp b <> ")"
_ -> writeExpB b <> "_" <> writeExpS e1
Expand Down Expand Up @@ -317,3 +298,45 @@ typstSymbolMap :: M.Map Text Text
typstSymbolMap = M.fromList $
("\776", "dot.double") -- see #231
: [(s,name) | (name, _, s) <- typstSymbols]

getAccentCommand :: Text -> Maybe Text
getAccentCommand ac = do
case ac of
"`" -> Just "grave"
"\180" -> Just "acute"
"^" -> Just "hat"
"~" -> Just "tilde"
"." -> Just "dot"
"\168" -> Just "diaer"
"\175" -> Just "macron"
"\711" -> Just "caron"
"\728" -> Just "breve"
"\733" -> Just "acute.double"
"\768" -> Just "grave"
"\769" -> Just "acute"
"\770" -> Just "hat"
"\771" -> Just "tilde"
"\772" -> Just "macron"
"\773" -> Just "overline"
"\774" -> Just "breve"
"\775" -> Just "dot"
"\776" -> Just "dot.double"
"\777" -> Just "harpoon"
"\778" -> Just "circle"
"\779" -> Just "acute.double"
"\780" -> Just "caron"
"\781" -> Just "overline"
"\x2218" -> Just "circle"
"\x2192" -> Just "->"
"\x2190" -> Just "<-"
"\8254" -> Just "macron"
"\8400" -> Just "harpoon.lt"
"\8401" -> Just "harpoon"
"\8406" -> Just "arrow.l"
"\8407" -> Just "arrow"
"\8417" -> Just "arrow.l.r"
_ -> Nothing

isGrouped :: Exp -> Bool
isGrouped (EGrouped _) = True
isGrouped _ = False
110 changes: 110 additions & 0 deletions test/regression/245b.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
<<< tex
\begin{array}{c}
\text{Accents above:}\\
\text{\textbackslash grave} \grave{x}\\
\text{\textbackslash acute} \acute{x}\\
\text{\textbackslash hat} \hat{x}\\
\text{\textbackslash widehat} \widehat{x}\\
\text{\textbackslash tilde} \tilde{x}\\
\text{\textbackslash bar} \bar{x}\\
\text{\textbackslash overbar} \overbar{x}\\
\text{\textbackslash overline} \overline{x}\\
\text{\textbackslash breve} \breve{x}\\
\text{\textbackslash dot} \dot{x}\\
\text{\textbackslash ddot} \ddot{x}\\
\text{\textbackslash ovhook} \ovhook{x}\\
\text{\textbackslash ocirc} \ocirc{x}\\
\text{\textbackslash check} \check{x}\\
\text{\textbackslash candra} \candra{x}\\
\text{\textbackslash oturnedcomma} \oturnedcomma{x}\\
\text{\textbackslash ocommatopright} \ocommatopright{x}\\
\text{\textbackslash droang} \droang{x}\\
\text{\textbackslash leftharpoonaccent} \leftharpoonaccent{x}\\
\text{\textbackslash rightharpoonaccent} \rightharpoonaccent{x}\\
\text{\textbackslash overleftarrow} \overleftarrow{x}\\
\text{\textbackslash vec} \vec{x}\\
\text{\textbackslash dddot} \dddot{x}\\
\text{\textbackslash ddddot} \ddddot{x}\\
\text{\textbackslash overleftrightarrow} \overleftrightarrow{x}\\
\text{\textbackslash annuity} \annuity{x}\\
\text{\textbackslash widebridgeabove} \widebridgeabove{x}\\
\text{\textbackslash asteraccent} \asteraccent{x}\\
\text{Accents below:}\\
\text{\textbackslash wideutilde} \wideutilde{x}\\
\text{\textbackslash underbar} \underbar{x}\\
\text{\textbackslash underline} \underline{x}\\
\text{\textbackslash threeunderdot} \threeunderdot{x}\\
\text{\textbackslash underrightharpoondown} \underrightharpoondown{x}\\
\text{\textbackslash underleftharpoondown} \underleftharpoondown{x}\\
\text{\textbackslash underleftarrow} \underleftarrow{x}\\
\text{\textbackslash underrightarrow} \underrightarrow{x}\\
\text{\textbackslash underline} \underline{x}\\
\text{Trailing signs:}\\
\text{^\textbackslash prime} x^\prime\\
\text{^\textbackslash dprime} x^\dprime\\
\text{^\textbackslash trprime} x^\trprime\\
\text{^\textbackslash qprime} x^\qprime\\
\text{^\textbackslash backprime} x^\backprime\\
\text{^\textbackslash backdprime} x^\backdprime\\
\text{^\textbackslash backtrprime} x^\backtrprime\\
\text{^\textbackslash hyphenbullet} x^\hyphenbullet\\
\text{^\textbackslash ast} x^\ast\\
\text{^\textbackslash vysmwhtcircle} x^\vysmwhtcircle\\
\text{^\textbackslash vysmblkcircle} x^\vysmblkcircle\\
\text{^\textbackslash llcorner} x^\llcorner\\
\text{^\textbackslash ulcorner} x^\ulcorner\\
\end{array}
>>> typst
upright("Accents above:")\
upright("\\grave") grave(x)\
upright("\\acute") acute(x)\
upright("\\hat") hat(x)\
upright("\\widehat") hat(x)\
upright("\\tilde") tilde(x)\
upright("\\bar") macron(x)\
upright("\\overbar") macron(x)\
upright("\\overline") overline(x)\
upright("\\breve") breve(x)\
upright("\\dot") dot(x)\
upright("\\ddot") dot.double(x)\
upright("\\ovhook") harpoon(x)\
upright("\\ocirc") circle(x)\
upright("\\check") caron(x)\
upright("\\candra") accent(x, ̐)\
upright("\\oturnedcomma") accent(x, ̒)\
upright("\\ocommatopright") accent(x, ̕)\
upright("\\droang") accent(x, ̚)\
upright("\\leftharpoonaccent") harpoon.lt(x)\
upright("\\rightharpoonaccent") harpoon(x)\
upright("\\overleftarrow") arrow.l(x)\
upright("\\vec") arrow(x)\
upright("\\dddot") accent(x, ⃛)\
upright("\\ddddot") accent(x, ⃜)\
upright("\\overleftrightarrow") arrow.l.r(x)\
upright("\\annuity") accent(x, ⃧)\
upright("\\widebridgeabove") accent(x, ⃩)\
upright("\\asteraccent") accent(x, ⃰)\
upright("Accents below:")\
upright("\\wideutilde") accent(x, ̰)\
upright("\\underbar") underline(x)\
upright("\\underline") underline(x)\
upright("\\threeunderdot") accent(x, ⃨)\
upright("\\underrightharpoondown") accent(x, ⃬)\
upright("\\underleftharpoondown") accent(x, ⃭)\
upright("\\underleftarrow") accent(x, ⃮)\
upright("\\underrightarrow") accent(x, ⃯)\
upright("\\underline") underline(x)\
upright("Trailing signs:")\
upright("^\\prime") x^(')\
upright("^\\dprime") x^('')\
upright("^\\trprime") x^(''')\
upright("^\\qprime") x^('''')\
upright("^\\backprime") x^prime.rev\
upright("^\\backdprime") x^prime.double.rev\
upright("^\\backtrprime") x^prime.triple.rev\
upright("^\\hyphenbullet") x^(⁃)\
upright("^\\ast") x^(\*)\
upright("^\\vysmwhtcircle") x^circle.stroked.tiny\
upright("^\\vysmblkcircle") x^circle.filled.small\
upright("^\\llcorner") x^\⌞\
upright("^\\ulcorner") x^\⌜\
2 changes: 1 addition & 1 deletion test/writer/typst/08.test
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,4 @@
, EDelimited "(" ")" [ Right (EIdentifier "z") ]
]
>>> typst
lr(|z^(‾)|) = lr(|z|) \, lr(|(z^(‾))^n|) = lr(|z|)^n \, arg (z^n) = n arg (z)
lr(|macron(z)|) = lr(|z|) \, lr(|(macron(z))^n|) = lr(|z|)^n \, arg (z^n) = n arg (z)
14 changes: 7 additions & 7 deletions test/writer/typst/complex1.test
Original file line number Diff line number Diff line change
Expand Up @@ -606,13 +606,13 @@ upright("Cauchy-Schwarz Inequality") & (sum_(k = 1)^n a_k^() b_k^())_()^2 lt.eq
upright("Cauchy Formula") & f \( z \) thin dot.c "Ind"_gamma^() \( z \) = frac(1, 2 pi i) integral.cont_gamma^() frac(f \( xi \), xi - z) thin d xi\
upright("Cross Product") & V_1^() times V_2^() = mat(delim: "|", i, j, k; frac(partial X, partial u), frac(partial Y, partial u), 0; frac(partial X, partial v), frac(partial Y, partial v), 0)\
upright("Vandermonde Determinant") & mat(delim: "|", 1, 1, dots.h.c, 1; v_1^(), v_2^(), dots.h.c, v_n^(); v_1^2, v_2^2, dots.h.c, v_n^2; dots.v, dots.v, dots.down, dots.v; v_1^(n - 1), v_2^(n - 1), dots.h.c, v_n^(n - 1)) = product_(1 lt.eq i < j lt.eq n)^() \( v_j^() - v_i^() \)\
upright("Lorenz Equations") & x^(˙)_() & = & sigma \( y - x \)\
y^(˙)_() & = & rho x - y - x z\
z^(˙)_() & = & - beta z + x y\
upright("Maxwell's Equations") & {nabla zws times B^harpoon.lt_() - thin 1 / c thin frac(partial zws E^harpoon.lt_(), partial zws t) & = & frac(4 pi, c) thin j^harpoon.lt_()\
nabla zws dot.c E^harpoon.lt_() & = & 4 pi rho\
nabla zws times E^harpoon.lt_() thin + thin 1 / c thin frac(partial zws B^harpoon.lt_(), partial zws t) & = & 0^harpoon.lt_()\
nabla zws dot.c B^harpoon.lt_() & = & 0\
upright("Lorenz Equations") & accent(x, ˙)_() & = & sigma \( y - x \)\
accent(y, ˙)_() & = & rho x - y - x z\
accent(z, ˙)_() & = & - beta z + x y\
upright("Maxwell's Equations") & {nabla zws times accent(B, ↼)_() - thin 1 / c thin frac(partial zws accent(E, ↼)_(), partial zws t) & = & frac(4 pi, c) thin accent(j, ↼)_()\
nabla zws dot.c accent(E, ↼)_() & = & 4 pi rho\
nabla zws times accent(E, ↼)_() thin + thin 1 / c thin frac(partial zws accent(B, ↼)_(), partial zws t) & = & accent(0, ↼)_()\
nabla zws dot.c accent(B, ↼)_() & = & 0\
upright("Einstein Field Equations") & R_(mu nu)^() - 1 / 2 thin g_(mu nu)^() thin R = frac(8 pi G, c_()^4) thin T_(mu nu)^()\
upright("Ramanujan Identity") & frac(1, \( sqrt(phi sqrt(5)) - phi \) e_()^(25 / pi)) = 1 + frac(e_()^(- 2 pi), 1 + frac(e_()^(- 4 pi), 1 + frac(e_()^(- 6 pi), 1 + frac(e_()^(- 8 pi), 1 + dots.h))))\
upright("Another Ramanujan identity") & sum_(k = 1)^oo 1 / 2_()^(floor.l k dot.c zws phi floor.r) = frac(1, 2_()^0 + frac(1, 2_()^1 + dots.h.c))\
Expand Down

0 comments on commit 1782269

Please sign in to comment.