{-# LANGUAGE OverloadedStrings #-}
module Text.TeXMath.Writers.StarMath
  ( writeStarMath
  ) where

import Data.Char (isLetter)
import Data.Generics (everywhere, mkT)
import qualified Data.List as List
import qualified Data.Text as T
import qualified Text.TeXMath.Shared as S
import Text.TeXMath.Unicode.ToUnicode (toUnicodeChar)
import Text.TeXMath.Types
  ( Alignment(..)
  , DisplayType(..)
  , Exp(..)
  , FractionType(..)
  , TeXSymbolType(..)
  , TextType(..)
  )
import Text.TeXMath.Writers.TeX (writeTeX)

-- | Render TeXMath expressions as StarMath syntax.
-- Falls back to TeX output for expressions that are not yet supported.
writeStarMath :: DisplayType -> [Exp] -> T.Text
writeStarMath :: DisplayType -> [Exp] -> Text
writeStarMath DisplayType
dt [Exp]
exps =
  case DisplayType -> [Exp] -> Maybe Text
renderExps DisplayType
dt ([Exp] -> [Exp]
normalizeExps ((forall a. Data a => a -> a) -> forall a. Data a => a -> a
everywhere ((Exp -> Exp) -> a -> a
forall a b. (Typeable a, Typeable b) => (b -> b) -> a -> a
mkT ((Exp -> Exp) -> a -> a) -> (Exp -> Exp) -> a -> a
forall a b. (a -> b) -> a -> b
$ DisplayType -> Exp -> Exp
S.handleDownup DisplayType
dt) [Exp]
exps)) of
    Just Text
rendered -> Text -> Text
T.strip Text
rendered
    Maybe Text
Nothing       -> [Exp] -> Text
writeTeX [Exp]
exps

data AlignContext = AlignDefault | AlignLeftCtx | AlignRightCtx
  deriving (AlignContext -> AlignContext -> Bool
(AlignContext -> AlignContext -> Bool)
-> (AlignContext -> AlignContext -> Bool) -> Eq AlignContext
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: AlignContext -> AlignContext -> Bool
== :: AlignContext -> AlignContext -> Bool
$c/= :: AlignContext -> AlignContext -> Bool
/= :: AlignContext -> AlignContext -> Bool
Eq)

renderExps :: DisplayType -> [Exp] -> Maybe T.Text
renderExps :: DisplayType -> [Exp] -> Maybe Text
renderExps DisplayType
dt = DisplayType -> AlignContext -> [Exp] -> Maybe Text
renderExpsIn DisplayType
dt AlignContext
AlignDefault

normalizeExps :: [Exp] -> [Exp]
normalizeExps :: [Exp] -> [Exp]
normalizeExps =
  [Exp] -> [Exp]
normalizeBareBars
  ([Exp] -> [Exp]) -> ([Exp] -> [Exp]) -> [Exp] -> [Exp]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Exp] -> [Exp]
normalizeEvaluationBars
  ([Exp] -> [Exp]) -> ([Exp] -> [Exp]) -> [Exp] -> [Exp]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Exp] -> [Exp]
mergeAdjacentUnicodeSerifStyled
  ([Exp] -> [Exp]) -> ([Exp] -> [Exp]) -> [Exp] -> [Exp]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Exp] -> [Exp]
normalizeBareBraces
  ([Exp] -> [Exp]) -> ([Exp] -> [Exp]) -> [Exp] -> [Exp]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Exp -> Exp) -> [Exp] -> [Exp]
forall a b. (a -> b) -> [a] -> [b]
map Exp -> Exp
normalizeExp

normalizeExp :: Exp -> Exp
normalizeExp :: Exp -> Exp
normalizeExp Exp
e =
  case Exp
e of
    EGrouped [Exp]
xs            -> [Exp] -> Exp
EGrouped ([Exp] -> [Exp]
normalizeExps [Exp]
xs)
    EStyled TextType
sty [Exp]
xs         -> TextType -> [Exp] -> Exp
EStyled TextType
sty ([Exp] -> [Exp]
normalizeExps [Exp]
xs)
    EFraction FractionType
ft Exp
num Exp
den   -> FractionType -> Exp -> Exp -> Exp
EFraction FractionType
ft (Exp -> Exp
normalizeExp Exp
num) (Exp -> Exp
normalizeExp Exp
den)
    ESqrt Exp
x                -> Exp -> Exp
ESqrt (Exp -> Exp
normalizeExp Exp
x)
    ERoot Exp
idx Exp
rad          -> Exp -> Exp -> Exp
ERoot (Exp -> Exp
normalizeExp Exp
idx) (Exp -> Exp
normalizeExp Exp
rad)
    EDelimited Text
op Text
cl [InEDelimited]
xs    -> Text -> Text -> [InEDelimited] -> Exp
EDelimited Text
op Text
cl ((InEDelimited -> InEDelimited) -> [InEDelimited] -> [InEDelimited]
forall a b. (a -> b) -> [a] -> [b]
map InEDelimited -> InEDelimited
normalizeDelimitedPiece [InEDelimited]
xs)
    ESub Exp
base Exp
sub          -> Exp -> Exp -> Exp
ESub (Exp -> Exp
normalizeExp Exp
base) (Exp -> Exp
normalizeExp Exp
sub)
    ESuper Exp
base Exp
sup        -> Exp -> Exp -> Exp
ESuper (Exp -> Exp
normalizeExp Exp
base) (Exp -> Exp
normalizeExp Exp
sup)
    ESubsup Exp
base Exp
sub Exp
sup   -> Exp -> Exp -> Exp -> Exp
ESubsup (Exp -> Exp
normalizeExp Exp
base) (Exp -> Exp
normalizeExp Exp
sub) (Exp -> Exp
normalizeExp Exp
sup)
    EOver Bool
b Exp
base Exp
over      -> Bool -> Exp -> Exp -> Exp
EOver Bool
b (Exp -> Exp
normalizeExp Exp
base) (Exp -> Exp
normalizeExp Exp
over)
    EUnder Bool
b Exp
base Exp
under    -> Bool -> Exp -> Exp -> Exp
EUnder Bool
b (Exp -> Exp
normalizeExp Exp
base) (Exp -> Exp
normalizeExp Exp
under)
    EUnderover Bool
b Exp
base Exp
u Exp
o  -> Bool -> Exp -> Exp -> Exp -> Exp
EUnderover Bool
b (Exp -> Exp
normalizeExp Exp
base) (Exp -> Exp
normalizeExp Exp
u) (Exp -> Exp
normalizeExp Exp
o)
    EArray [Alignment]
aligns [ArrayLine]
rows     -> [Alignment] -> [ArrayLine] -> Exp
EArray [Alignment]
aligns ((ArrayLine -> ArrayLine) -> [ArrayLine] -> [ArrayLine]
forall a b. (a -> b) -> [a] -> [b]
map (([Exp] -> [Exp]) -> ArrayLine -> ArrayLine
forall a b. (a -> b) -> [a] -> [b]
map [Exp] -> [Exp]
normalizeExps) [ArrayLine]
rows)
    EPhantom Exp
x             -> Exp -> Exp
EPhantom (Exp -> Exp
normalizeExp Exp
x)
    Exp
_                      -> Exp
e

normalizeDelimitedPiece :: Either T.Text Exp -> Either T.Text Exp
normalizeDelimitedPiece :: InEDelimited -> InEDelimited
normalizeDelimitedPiece InEDelimited
p =
  case InEDelimited
p of
    Left Text
t  -> Text -> InEDelimited
forall a b. a -> Either a b
Left Text
t
    Right Exp
e -> Exp -> InEDelimited
forall a b. b -> Either a b
Right (Exp -> Exp
normalizeExp Exp
e)

normalizeBareBars :: [Exp] -> [Exp]
normalizeBareBars :: [Exp] -> [Exp]
normalizeBareBars [] = []
normalizeBareBars (Exp
x : [Exp]
xs)
  | Just Text
sym <- Exp -> Maybe Text
bareBarSymbol Exp
x =
      case Text -> [Exp] -> [Exp] -> Maybe ([Exp], Maybe (Exp -> Exp), [Exp])
collectBareDelimited Text
sym [] [Exp]
xs of
        Just ([Exp]
mid, Maybe (Exp -> Exp)
trailingScript, [Exp]
rest) ->
          let delimited :: Exp
delimited = Text -> Text -> [InEDelimited] -> Exp
EDelimited Text
sym Text
sym ((Exp -> InEDelimited) -> [Exp] -> [InEDelimited]
forall a b. (a -> b) -> [a] -> [b]
map Exp -> InEDelimited
forall a b. b -> Either a b
Right [Exp]
mid)
              scripted :: Exp
scripted = Exp -> ((Exp -> Exp) -> Exp) -> Maybe (Exp -> Exp) -> Exp
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Exp
delimited ((Exp -> Exp) -> Exp -> Exp
forall a b. (a -> b) -> a -> b
$ Exp
delimited) Maybe (Exp -> Exp)
trailingScript
          in Exp
scripted Exp -> [Exp] -> [Exp]
forall a. a -> [a] -> [a]
: [Exp] -> [Exp]
normalizeBareBars [Exp]
rest
        Maybe ([Exp], Maybe (Exp -> Exp), [Exp])
_ ->
          Exp
x Exp -> [Exp] -> [Exp]
forall a. a -> [a] -> [a]
: [Exp] -> [Exp]
normalizeBareBars [Exp]
xs
normalizeBareBars (Exp
x:[Exp]
xs) = Exp
x Exp -> [Exp] -> [Exp]
forall a. a -> [a] -> [a]
: [Exp] -> [Exp]
normalizeBareBars [Exp]
xs

normalizeBareBraces :: [Exp] -> [Exp]
normalizeBareBraces :: [Exp] -> [Exp]
normalizeBareBraces [] = []
normalizeBareBraces (ESymbol TeXSymbolType
Open Text
"{" : [Exp]
xs) =
  case [Exp] -> [Exp] -> Maybe ([Exp], [Exp])
collectBareBraces [] [Exp]
xs of
    Just ([Exp]
mid, [Exp]
rest) -> Text -> Text -> [InEDelimited] -> Exp
EDelimited Text
"{" Text
"}" ((Exp -> InEDelimited) -> [Exp] -> [InEDelimited]
forall a b. (a -> b) -> [a] -> [b]
map Exp -> InEDelimited
forall a b. b -> Either a b
Right [Exp]
mid) Exp -> [Exp] -> [Exp]
forall a. a -> [a] -> [a]
: [Exp] -> [Exp]
normalizeBareBraces [Exp]
rest
    Maybe ([Exp], [Exp])
Nothing          -> TeXSymbolType -> Text -> Exp
ESymbol TeXSymbolType
Open Text
"{" Exp -> [Exp] -> [Exp]
forall a. a -> [a] -> [a]
: [Exp] -> [Exp]
normalizeBareBraces [Exp]
xs
normalizeBareBraces (Exp
x:[Exp]
xs) = Exp
x Exp -> [Exp] -> [Exp]
forall a. a -> [a] -> [a]
: [Exp] -> [Exp]
normalizeBareBraces [Exp]
xs

mergeAdjacentUnicodeSerifStyled :: [Exp] -> [Exp]
mergeAdjacentUnicodeSerifStyled :: [Exp] -> [Exp]
mergeAdjacentUnicodeSerifStyled [] = []
mergeAdjacentUnicodeSerifStyled (EStyled TextType
sty [Exp]
xs : EStyled TextType
sty' [Exp]
ys : [Exp]
rest)
  | TextType
sty TextType -> TextType -> Bool
forall a. Eq a => a -> a -> Bool
== TextType
sty' Bool -> Bool -> Bool
&& TextType -> Bool
isUnicodeSerifStyle TextType
sty =
      [Exp] -> [Exp]
mergeAdjacentUnicodeSerifStyled (TextType -> [Exp] -> Exp
EStyled TextType
sty ([Exp]
xs [Exp] -> [Exp] -> [Exp]
forall a. Semigroup a => a -> a -> a
<> [Rational -> Exp
ESpace Rational
1] [Exp] -> [Exp] -> [Exp]
forall a. Semigroup a => a -> a -> a
<> [Exp]
ys) Exp -> [Exp] -> [Exp]
forall a. a -> [a] -> [a]
: [Exp]
rest)
mergeAdjacentUnicodeSerifStyled (Exp
x:[Exp]
xs) = Exp
x Exp -> [Exp] -> [Exp]
forall a. a -> [a] -> [a]
: [Exp] -> [Exp]
mergeAdjacentUnicodeSerifStyled [Exp]
xs

isUnicodeSerifStyle :: TextType -> Bool
isUnicodeSerifStyle :: TextType -> Bool
isUnicodeSerifStyle TextType
sty =
  TextType
sty TextType -> [TextType] -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem`
    [ TextType
TextScript
    , TextType
TextFraktur
    , TextType
TextDoubleStruck
    , TextType
TextBoldScript
    , TextType
TextBoldFraktur
    ]

normalizeEvaluationBars :: [Exp] -> [Exp]
normalizeEvaluationBars :: [Exp] -> [Exp]
normalizeEvaluationBars = [Exp] -> [Exp]
forall a. [a] -> [a]
reverse ([Exp] -> [Exp]) -> ([Exp] -> [Exp]) -> [Exp] -> [Exp]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Exp] -> [Exp] -> [Exp]
go []
 where
  go :: [Exp] -> [Exp] -> [Exp]
go [Exp]
acc [] = [Exp]
acc
  go [Exp]
acc (Exp
cur : [Exp]
xs)
    | Just Exp -> Exp
script <- Exp -> Maybe (Exp -> Exp)
evaluationBarScript Exp
cur
    , Just ([Exp]
rest, Exp
target) <- [Exp] -> Maybe ([Exp], Exp)
takeEvaluationTarget [Exp]
acc =
        [Exp] -> [Exp] -> [Exp]
go (Exp -> Exp
script Exp
target Exp -> [Exp] -> [Exp]
forall a. a -> [a] -> [a]
: [Exp]
rest) [Exp]
xs
    | Bool
otherwise =
        [Exp] -> [Exp] -> [Exp]
go (Exp
cur Exp -> [Exp] -> [Exp]
forall a. a -> [a] -> [a]
: [Exp]
acc) [Exp]
xs

evaluationBarScript :: Exp -> Maybe (Exp -> Exp)
evaluationBarScript :: Exp -> Maybe (Exp -> Exp)
evaluationBarScript Exp
cur =
  case Exp
cur of
    ESub Exp
base Exp
sub
      | Exp -> Bool
isEvaluationBarBase Exp
base ->
          (Exp -> Exp) -> Maybe (Exp -> Exp)
forall a. a -> Maybe a
Just (\Exp
target -> Exp -> Exp -> Exp
ESub (Text -> Text -> [InEDelimited] -> Exp
EDelimited Text
"." Text
"|" [Exp -> InEDelimited
forall a b. b -> Either a b
Right Exp
target]) Exp
sub)
    ESuper Exp
base Exp
sup
      | Exp -> Bool
isEvaluationBarBase Exp
base ->
          (Exp -> Exp) -> Maybe (Exp -> Exp)
forall a. a -> Maybe a
Just (\Exp
target -> Exp -> Exp -> Exp
ESuper (Text -> Text -> [InEDelimited] -> Exp
EDelimited Text
"." Text
"|" [Exp -> InEDelimited
forall a b. b -> Either a b
Right Exp
target]) Exp
sup)
    ESubsup Exp
base Exp
sub Exp
sup
      | Exp -> Bool
isEvaluationBarBase Exp
base ->
          (Exp -> Exp) -> Maybe (Exp -> Exp)
forall a. a -> Maybe a
Just (\Exp
target -> Exp -> Exp -> Exp -> Exp
ESubsup (Text -> Text -> [InEDelimited] -> Exp
EDelimited Text
"." Text
"|" [Exp -> InEDelimited
forall a b. b -> Either a b
Right Exp
target]) Exp
sub Exp
sup)
    Exp
_ -> Maybe (Exp -> Exp)
forall a. Maybe a
Nothing

takeEvaluationTarget :: [Exp] -> Maybe ([Exp], Exp)
takeEvaluationTarget :: [Exp] -> Maybe ([Exp], Exp)
takeEvaluationTarget [] = Maybe ([Exp], Exp)
forall a. Maybe a
Nothing
takeEvaluationTarget (Exp
e : [Exp]
rest) =
  case Exp
e of
    EDelimited{} -> ([Exp], Exp) -> Maybe ([Exp], Exp)
forall a. a -> Maybe a
Just ([Exp]
rest, Exp
e)
    ESymbol TeXSymbolType
Close Text
c
      | Just ([Exp]
rest', Exp
target) <- Text -> [Exp] -> Maybe ([Exp], Exp)
takeDelimitedTarget Text
c [Exp]
rest ->
          ([Exp], Exp) -> Maybe ([Exp], Exp)
forall a. a -> Maybe a
Just ([Exp]
rest', Exp
target)
    Exp
_ -> ([Exp], Exp) -> Maybe ([Exp], Exp)
forall a. a -> Maybe a
Just ([Exp]
rest, Exp
e)

takeDelimitedTarget :: T.Text -> [Exp] -> Maybe ([Exp], Exp)
takeDelimitedTarget :: Text -> [Exp] -> Maybe ([Exp], Exp)
takeDelimitedTarget Text
closeTxt = Integer -> [Exp] -> [Exp] -> Maybe ([Exp], Exp)
forall {a}.
(Num a, Eq a) =>
a -> [Exp] -> [Exp] -> Maybe ([Exp], Exp)
go Integer
0 []
 where
  openTxt :: Maybe Text
openTxt =
    case Text
closeTxt of
      Text
")" -> Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"("
      Text
"]" -> Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"["
      Text
"}" -> Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"{"
      Text
_   -> Maybe Text
forall a. Maybe a
Nothing

  go :: a -> [Exp] -> [Exp] -> Maybe ([Exp], Exp)
go a
_ [Exp]
_ [] = Maybe ([Exp], Exp)
forall a. Maybe a
Nothing
  go a
depth [Exp]
inner (Exp
e : [Exp]
rest) =
    case (Maybe Text
openTxt, Exp
e) of
      (Just Text
open, ESymbol TeXSymbolType
Close Text
c)
        | Text
c Text -> Text -> Bool
forall a. Eq a => a -> a -> Bool
== Text
closeTxt ->
            a -> [Exp] -> [Exp] -> Maybe ([Exp], Exp)
go (a
depth a -> a -> a
forall a. Num a => a -> a -> a
+ a
1) (Exp
e Exp -> [Exp] -> [Exp]
forall a. a -> [a] -> [a]
: [Exp]
inner) [Exp]
rest
      (Just Text
open, ESymbol TeXSymbolType
Open Text
o)
        | Text
o Text -> Text -> Bool
forall a. Eq a => a -> a -> Bool
== Text
open ->
            if a
depth a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
0
               then ([Exp], Exp) -> Maybe ([Exp], Exp)
forall a. a -> Maybe a
Just ([Exp]
rest, Text -> Text -> [InEDelimited] -> Exp
EDelimited Text
open Text
closeTxt ((Exp -> InEDelimited) -> [Exp] -> [InEDelimited]
forall a b. (a -> b) -> [a] -> [b]
map Exp -> InEDelimited
forall a b. b -> Either a b
Right [Exp]
inner))
               else a -> [Exp] -> [Exp] -> Maybe ([Exp], Exp)
go (a
depth a -> a -> a
forall a. Num a => a -> a -> a
- a
1) (Exp
e Exp -> [Exp] -> [Exp]
forall a. a -> [a] -> [a]
: [Exp]
inner) [Exp]
rest
      (Maybe Text, Exp)
_ ->
        a -> [Exp] -> [Exp] -> Maybe ([Exp], Exp)
go a
depth (Exp
e Exp -> [Exp] -> [Exp]
forall a. a -> [a] -> [a]
: [Exp]
inner) [Exp]
rest

isEvaluationBarBase :: Exp -> Bool
isEvaluationBarBase :: Exp -> Bool
isEvaluationBarBase Exp
e =
  case Exp
e of
    EScaled Rational
_ (ESymbol TeXSymbolType
Open Text
"|")  -> Bool
True
    EScaled Rational
_ (ESymbol TeXSymbolType
Close Text
"|") -> Bool
True
    Exp
_                             -> Bool
False

collectBareBraces :: [Exp] -> [Exp] -> Maybe ([Exp], [Exp])
collectBareBraces :: [Exp] -> [Exp] -> Maybe ([Exp], [Exp])
collectBareBraces [Exp]
_ [] = Maybe ([Exp], [Exp])
forall a. Maybe a
Nothing
collectBareBraces [Exp]
acc (ESymbol TeXSymbolType
Close Text
"}" : [Exp]
xs) = ([Exp], [Exp]) -> Maybe ([Exp], [Exp])
forall a. a -> Maybe a
Just ([Exp] -> [Exp]
forall a. [a] -> [a]
reverse [Exp]
acc, [Exp]
xs)
collectBareBraces [Exp]
acc (Exp
x:[Exp]
xs) = [Exp] -> [Exp] -> Maybe ([Exp], [Exp])
collectBareBraces (Exp
xExp -> [Exp] -> [Exp]
forall a. a -> [a] -> [a]
:[Exp]
acc) [Exp]
xs

collectBareDelimited :: T.Text -> [Exp] -> [Exp]
                     -> Maybe ([Exp], Maybe (Exp -> Exp), [Exp])
collectBareDelimited :: Text -> [Exp] -> [Exp] -> Maybe ([Exp], Maybe (Exp -> Exp), [Exp])
collectBareDelimited Text
_ [Exp]
acc [] = Maybe ([Exp], Maybe (Exp -> Exp), [Exp])
forall a. Maybe a
Nothing
collectBareDelimited Text
sym [Exp]
acc (Exp
y:[Exp]
ys)
  | Text -> Exp -> Bool
matchesBareBar Text
sym Exp
y = ([Exp], Maybe (Exp -> Exp), [Exp])
-> Maybe ([Exp], Maybe (Exp -> Exp), [Exp])
forall a. a -> Maybe a
Just ([Exp] -> [Exp]
forall a. [a] -> [a]
reverse [Exp]
acc, Maybe (Exp -> Exp)
forall a. Maybe a
Nothing, [Exp]
ys)
  | Just Exp -> Exp
apply <- Text -> Exp -> Maybe (Exp -> Exp)
scriptedBareBar Text
sym Exp
y = ([Exp], Maybe (Exp -> Exp), [Exp])
-> Maybe ([Exp], Maybe (Exp -> Exp), [Exp])
forall a. a -> Maybe a
Just ([Exp] -> [Exp]
forall a. [a] -> [a]
reverse [Exp]
acc, (Exp -> Exp) -> Maybe (Exp -> Exp)
forall a. a -> Maybe a
Just Exp -> Exp
apply, [Exp]
ys)
  | Bool
otherwise = Text -> [Exp] -> [Exp] -> Maybe ([Exp], Maybe (Exp -> Exp), [Exp])
collectBareDelimited Text
sym (Exp
yExp -> [Exp] -> [Exp]
forall a. a -> [a] -> [a]
:[Exp]
acc) [Exp]
ys

bareBarSymbol :: Exp -> Maybe T.Text
bareBarSymbol :: Exp -> Maybe Text
bareBarSymbol Exp
e =
  case Exp
e of
    ESymbol TeXSymbolType
_ Text
"|" -> Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"|"
    ESymbol TeXSymbolType
_ Text
"∣" -> Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"|"
    ESymbol TeXSymbolType
_ Text
"∥" -> Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"∥"
    Exp
_             -> Maybe Text
forall a. Maybe a
Nothing

matchesBareBar :: T.Text -> Exp -> Bool
matchesBareBar :: Text -> Exp -> Bool
matchesBareBar Text
sym Exp
e =
  case Exp -> Maybe Text
bareBarSymbol Exp
e of
    Just Text
sym' -> Text
sym Text -> Text -> Bool
forall a. Eq a => a -> a -> Bool
== Text
sym'
    Maybe Text
Nothing   -> Bool
False

scriptedBareBar :: T.Text -> Exp -> Maybe (Exp -> Exp)
scriptedBareBar :: Text -> Exp -> Maybe (Exp -> Exp)
scriptedBareBar Text
sym Exp
e =
  case Exp
e of
    ESub Exp
base Exp
sub
      | Text -> Exp -> Bool
matchesBareBar Text
sym Exp
base -> (Exp -> Exp) -> Maybe (Exp -> Exp)
forall a. a -> Maybe a
Just (\Exp
del -> Exp -> Exp -> Exp
ESub Exp
del Exp
sub)
    ESuper Exp
base Exp
sup
      | Text -> Exp -> Bool
matchesBareBar Text
sym Exp
base -> (Exp -> Exp) -> Maybe (Exp -> Exp)
forall a. a -> Maybe a
Just (\Exp
del -> Exp -> Exp -> Exp
ESuper Exp
del Exp
sup)
    ESubsup Exp
base Exp
sub Exp
sup
      | Text -> Exp -> Bool
matchesBareBar Text
sym Exp
base -> (Exp -> Exp) -> Maybe (Exp -> Exp)
forall a. a -> Maybe a
Just (\Exp
del -> Exp -> Exp -> Exp -> Exp
ESubsup Exp
del Exp
sub Exp
sup)
    Exp
_ -> Maybe (Exp -> Exp)
forall a. Maybe a
Nothing

renderExpsIn :: DisplayType -> AlignContext -> [Exp] -> Maybe T.Text
renderExpsIn :: DisplayType -> AlignContext -> [Exp] -> Maybe Text
renderExpsIn DisplayType
dt AlignContext
ctx [Exp]
exps = do
  [Text]
rendered <- (Exp -> Maybe Text) -> [Exp] -> Maybe [Text]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> [a] -> m [b]
mapM (DisplayType -> AlignContext -> Exp -> Maybe Text
renderExpIn DisplayType
dt AlignContext
ctx) [Exp]
exps
  let pieces :: [(Exp, Text)]
pieces = [Exp] -> [Text] -> [(Exp, Text)]
forall a b. [a] -> [b] -> [(a, b)]
zip [Exp]
exps [Text]
rendered
  let merged :: Text
merged = [(Exp, Text)] -> Text
mergePieces [(Exp, Text)]
pieces
  let withLhs :: Text
withLhs =
        if [Exp] -> Bool
startsWithInfixNeedingLhs [Exp]
exps
           then Text
"{} " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> Text
T.stripStart Text
merged
           else Text
merged
  Text -> Maybe Text
forall a. a -> Maybe a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Text -> Maybe Text) -> Text -> Maybe Text
forall a b. (a -> b) -> a -> b
$ if [Exp] -> Bool
endsWithInfixNeedingRhs [Exp]
exps
            then Text -> Text
T.stripEnd Text
withLhs Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" {}"
            else Text
withLhs

mergePieces :: [(Exp, T.Text)] -> T.Text
mergePieces :: [(Exp, Text)] -> Text
mergePieces [] = Text
""
mergePieces ((Exp
e0, Text
t0) : [(Exp, Text)]
rest) = (Exp, Text) -> Text
forall a b. (a, b) -> b
snd ((Exp, Text) -> Text) -> (Exp, Text) -> Text
forall a b. (a -> b) -> a -> b
$ ((Exp, Text) -> (Exp, Text) -> (Exp, Text))
-> (Exp, Text) -> [(Exp, Text)] -> (Exp, Text)
forall b a. (b -> a -> b) -> b -> [a] -> b
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
List.foldl' (Exp, Text) -> (Exp, Text) -> (Exp, Text)
step (Exp
e0, Text
t0) [(Exp, Text)]
rest
 where
  step :: (Exp, Text) -> (Exp, Text) -> (Exp, Text)
step (Exp
prevE, Text
acc) (Exp
curE, Text
curT) =
    if Text -> Bool
T.null Text
curT
       then (Exp
prevE, Text
acc)
       else
         (Exp
curE, Bool -> Text -> Text -> Text
appendRendered (Exp -> Exp -> Bool
needsSeparator Exp
prevE Exp
curE) Text
acc Text
curT)

appendRendered :: Bool -> T.Text -> T.Text -> T.Text
appendRendered :: Bool -> Text -> Text -> Text
appendRendered Bool
needSep Text
left Text
right
  | Text -> Bool
T.null Text
left = Text -> Text
T.stripStart Text
right
  | Text -> Bool
T.null Text
right = Text -> Text
T.stripEnd Text
left
  | Bool
otherwise =
      let leftHadWs :: Bool
leftHadWs = Text -> Bool
endsWithAsciiSpace Text
left
          rightHadWs :: Bool
rightHadWs = Text -> Bool
startsWithAsciiSpace Text
right
          left' :: Text
left' = (Char -> Bool) -> Text -> Text
T.dropWhileEnd Char -> Bool
isAsciiSpaceChar Text
left
          right' :: Text
right' = (Char -> Bool) -> Text -> Text
T.dropWhile Char -> Bool
isAsciiSpaceChar Text
right
          sep :: Text
sep = if Bool
leftHadWs Bool -> Bool -> Bool
|| Bool
rightHadWs Bool -> Bool -> Bool
|| Bool
needSep then Text
" " else Text
""
      in Text
left' Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
sep Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
right'

startsWithAsciiSpace :: T.Text -> Bool
startsWithAsciiSpace :: Text -> Bool
startsWithAsciiSpace Text
t =
  case Text -> Maybe (Char, Text)
T.uncons Text
t of
    Just (Char
c, Text
_) -> Char -> Bool
isAsciiSpaceChar Char
c
    Maybe (Char, Text)
Nothing     -> Bool
False

endsWithAsciiSpace :: T.Text -> Bool
endsWithAsciiSpace :: Text -> Bool
endsWithAsciiSpace Text
t =
  case Text -> Maybe (Text, Char)
T.unsnoc Text
t of
    Just (Text
_, Char
c) -> Char -> Bool
isAsciiSpaceChar Char
c
    Maybe (Text, Char)
Nothing     -> Bool
False

isAsciiSpaceChar :: Char -> Bool
isAsciiSpaceChar :: Char -> Bool
isAsciiSpaceChar Char
c = Char
c Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
' ' Bool -> Bool -> Bool
|| Char
c Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'\t' Bool -> Bool -> Bool
|| Char
c Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'\n'

needsSeparator :: Exp -> Exp -> Bool
needsSeparator :: Exp -> Exp -> Bool
needsSeparator Exp
prevE Exp
curE
  | Exp -> Bool
isGreekIdentifierExp Exp
prevE Bool -> Bool -> Bool
&& Exp -> Bool
isIdentifierLike Exp
curE = Bool
True
  | Exp -> Bool
isGreekIdentifierExp Exp
prevE Bool -> Bool -> Bool
&& Exp -> Bool
isRootLike Exp
curE        = Bool
True
  | Exp -> Bool
isGreekIdentifierExp Exp
prevE Bool -> Bool -> Bool
&& Exp -> Bool
isTerminatingPunctuation Exp
curE = Bool
True
  | Exp -> Bool
isWordSymbolLike Exp
prevE Bool -> Bool -> Bool
&& Exp -> Bool
isIdentifierLike Exp
curE      = Bool
True
  | Exp -> Bool
isWordSymbolLike Exp
prevE Bool -> Bool -> Bool
&& Exp -> Bool
isOpenLike Exp
curE            = Bool
True
  | Exp -> Bool
isWordStyledExp Exp
prevE Bool -> Bool -> Bool
&& Exp -> Bool
isIdentifierLike Exp
curE       = Bool
True
  | Exp -> Bool
isAccentCommandExp Exp
prevE Bool -> Bool -> Bool
&& Exp -> Bool
isIdentifierLike Exp
curE    = Bool
True
  | Exp -> Bool
isAccentCommandExp Exp
prevE Bool -> Bool -> Bool
&& Exp -> Bool
isOpenLike Exp
curE          = Bool
True
  | Exp -> Bool
isAccentCommandExp Exp
prevE Bool -> Bool -> Bool
&& Exp -> Bool
isRootLike Exp
curE          = Bool
True
  | Exp -> Bool
isMathOperatorExp Exp
prevE Bool -> Bool -> Bool
&& Exp -> Bool
isIdentifierLike Exp
curE     = Bool
True
  | Exp -> Bool
isUnaryMinusSymbol Exp
prevE Bool -> Bool -> Bool
&& Exp -> Bool
isIdentifierLike Exp
curE    = Bool
True
  | Exp -> Bool
isIdentifierLike Exp
prevE Bool -> Bool -> Bool
&& Exp -> Bool
isMathOperatorExp Exp
curE     = Bool
True
  | Exp -> Bool
isIdentifierLike Exp
prevE Bool -> Bool -> Bool
&& Exp -> Bool
isRootLike Exp
curE            = Bool
True
  | Exp -> Bool
isIdentifierLike Exp
prevE Bool -> Bool -> Bool
&& Exp -> Bool
isArrowScriptedExp Exp
curE    = Bool
True
  | Exp -> Bool
isIdentifierLike Exp
prevE Bool -> Bool -> Bool
&& Exp -> Bool
isScriptedMathOperatorExp Exp
curE = Bool
True
  | Exp -> Bool
isIdentifierLike Exp
prevE Bool -> Bool -> Bool
&& Exp -> Bool
isWordSymbolLike Exp
curE      = Bool
True
  | Exp -> Bool
isLargeOpScriptedExp Exp
prevE Bool -> Bool -> Bool
&& Exp -> Bool
isIdentifierLike Exp
curE  = Bool
True
  | Exp -> Bool
isLargeOpScriptedExp Exp
prevE Bool -> Bool -> Bool
&& Exp -> Bool
isFractionLike Exp
curE    = Bool
True
  | Exp -> Bool
isLargeOpScriptedExp Exp
prevE Bool -> Bool -> Bool
&& Exp -> Bool
isAccentCommandExp Exp
curE = Bool
True
  | Exp -> Bool
isScripted Exp
prevE Bool -> Bool -> Bool
&& Exp -> Bool
isIdentifierLike Exp
curE           = Bool
True
  | Exp -> Bool
isArrowScriptedExp Exp
prevE Bool -> Bool -> Bool
&& Exp -> Bool
isIdentifierLike Exp
curE   = Bool
True
  | Exp -> Bool
isScriptedMathOperatorExp Exp
prevE Bool -> Bool -> Bool
&& Exp -> Bool
isIdentifierLike Exp
curE = Bool
True
  | Exp -> Bool
isDelimited Exp
prevE Bool -> Bool -> Bool
&& Exp -> Bool
isDelimited Exp
curE               = Bool
True
  | Exp -> Bool
isCloseLike Exp
prevE Bool -> Bool -> Bool
&& Exp -> Bool
isIdentifierLike Exp
curE          = Bool
True
  | Exp -> Bool
isCloseLike Exp
prevE Bool -> Bool -> Bool
&& Exp -> Bool
isWordSymbolLike Exp
curE          = Bool
True
  | Exp -> Bool
isCloseLike Exp
prevE Bool -> Bool -> Bool
&& Exp -> Bool
isAccentCommandExp Exp
curE        = Bool
True
  | Exp -> Bool
isCloseLike Exp
prevE Bool -> Bool -> Bool
&& Exp -> Bool
isArrayLike Exp
curE               = Bool
True
  | Exp -> Bool
isIdentifierLike Exp
prevE Bool -> Bool -> Bool
&& Exp -> Bool
isWordStyledExp Exp
curE      = Bool
True
  | Exp -> Bool
isIdentifierLike Exp
prevE Bool -> Bool -> Bool
&& Exp -> Bool
isUprightMathTextExp Exp
curE = Bool
True
  | Exp -> Bool
isIdentifierLike Exp
prevE Bool -> Bool -> Bool
&& Exp -> Bool
isAccentCommandExp Exp
curE   = Bool
True
  | Exp -> Bool
isIdentifierLike Exp
prevE Bool -> Bool -> Bool
&& Exp -> Bool
isWideSpace Exp
curE          = Bool
True
  | Exp -> Bool
isIdentifierLike Exp
prevE Bool -> Bool -> Bool
&& Exp -> Bool
isDelimited Exp
curE          = Bool
True
  | Exp -> Bool
isIdentifierLike Exp
prevE Bool -> Bool -> Bool
&& Exp -> Bool
isNonNormalTextExp Exp
curE   = Bool
True
  | Exp -> Bool
isQuotedTextExp Exp
prevE Bool -> Bool -> Bool
&& Exp -> Bool
isItalicTextExp Exp
curE       = Bool
True
  | Bool
otherwise                                            = Bool
False

isGreekIdentifierExp :: Exp -> Bool
isGreekIdentifierExp :: Exp -> Bool
isGreekIdentifierExp Exp
e =
  case Exp
e of
    EIdentifier Text
t -> Text -> Maybe Text
greekName Text
t Maybe Text -> Maybe Text -> Bool
forall a. Eq a => a -> a -> Bool
/= Maybe Text
forall a. Maybe a
Nothing
    Exp
_             -> Bool
False

isIdentifierLike :: Exp -> Bool
isIdentifierLike :: Exp -> Bool
isIdentifierLike Exp
e =
  case Exp
e of
    EIdentifier{}   -> Bool
True
    ENumber{}       -> Bool
True
    EMathOperator{} -> Bool
True
    ESub{}          -> Bool
True
    ESuper{}        -> Bool
True
    ESubsup{}       -> Bool
True
    EStyled{}       -> Bool
True
    Exp
_               -> Bool
False

isMathOperatorExp :: Exp -> Bool
isMathOperatorExp :: Exp -> Bool
isMathOperatorExp Exp
e =
  case Exp
e of
    EMathOperator{} -> Bool
True
    Exp
_               -> Bool
False

isDelimited :: Exp -> Bool
isDelimited :: Exp -> Bool
isDelimited Exp
e =
  case Exp
e of
    EDelimited{} -> Bool
True
    Exp
_            -> Bool
False

isArrayLike :: Exp -> Bool
isArrayLike :: Exp -> Bool
isArrayLike Exp
e =
  case Exp
e of
    EArray{} -> Bool
True
    Exp
_        -> Bool
False

isFractionLike :: Exp -> Bool
isFractionLike :: Exp -> Bool
isFractionLike Exp
e =
  case Exp
e of
    EFraction{} -> Bool
True
    Exp
_           -> Bool
False

isWideSpace :: Exp -> Bool
isWideSpace :: Exp -> Bool
isWideSpace Exp
e =
  case Exp
e of
    ESpace Rational
w -> Rational
w Rational -> Rational -> Bool
forall a. Ord a => a -> a -> Bool
>= Rational
1
    Exp
_        -> Bool
False

isWordSymbolLike :: Exp -> Bool
isWordSymbolLike :: Exp -> Bool
isWordSymbolLike Exp
e =
  case Exp
e of
    ESymbol TeXSymbolType
_ Text
"∀" -> Bool
True
    ESymbol TeXSymbolType
_ Text
"∃" -> Bool
True
    ESymbol TeXSymbolType
_ Text
"∇" -> Bool
True
    ESymbol TeXSymbolType
_ Text
"∂" -> Bool
True
    ESymbol TeXSymbolType
_ Text
"¬" -> Bool
True
    ESymbol TeXSymbolType
_ Text
"∧" -> Bool
True
    ESymbol TeXSymbolType
_ Text
"∨" -> Bool
True
    ESymbol TeXSymbolType
_ Text
"and" -> Bool
True
    ESymbol TeXSymbolType
_ Text
"or" -> Bool
True
    Exp
_             -> Bool
False

isOpenLike :: Exp -> Bool
isOpenLike :: Exp -> Bool
isOpenLike Exp
e =
  case Exp
e of
    ESymbol TeXSymbolType
Open Text
_ -> Bool
True
    Exp
_              -> Bool
False

isRootLike :: Exp -> Bool
isRootLike :: Exp -> Bool
isRootLike Exp
e =
  case Exp
e of
    ESqrt{} -> Bool
True
    ERoot{} -> Bool
True
    Exp
_       -> Bool
False

isWordStyledExp :: Exp -> Bool
isWordStyledExp :: Exp -> Bool
isWordStyledExp Exp
e =
  case Exp
e of
    EStyled TextType
TextNormal [Exp
x]     -> Exp -> Bool
isWordStyledExp Exp
x
    EStyled TextType
TextItalic [Exp]
_       -> Bool
True
    EStyled TextType
TextBold [Exp]
_         -> Bool
True
    EStyled TextType
TextScript [Exp]
_       -> Bool
True
    EStyled TextType
TextFraktur [Exp]
_      -> Bool
True
    EStyled TextType
TextDoubleStruck [Exp]
_ -> Bool
True
    Exp
_                          -> Bool
False

isUprightMathTextExp :: Exp -> Bool
isUprightMathTextExp :: Exp -> Bool
isUprightMathTextExp Exp
e =
  case Exp
e of
    EStyled TextType
TextNormal [EIdentifier Text
_] -> Bool
True
    Exp
_                                  -> Bool
False

isItalicTextExp :: Exp -> Bool
isItalicTextExp :: Exp -> Bool
isItalicTextExp Exp
e =
  case Exp
e of
    EText TextType
TextItalic Text
_ -> Bool
True
    Exp
_                  -> Bool
False

isQuotedTextExp :: Exp -> Bool
isQuotedTextExp :: Exp -> Bool
isQuotedTextExp Exp
e =
  case Exp
e of
    EText TextType
TextNormal Text
_ -> Bool
True
    Exp
_                  -> Bool
False

isNonNormalTextExp :: Exp -> Bool
isNonNormalTextExp :: Exp -> Bool
isNonNormalTextExp Exp
e =
  case Exp
e of
    EText TextType
sty Text
_ -> TextType
sty TextType -> TextType -> Bool
forall a. Eq a => a -> a -> Bool
/= TextType
TextNormal
    Exp
_           -> Bool
False

isAccentCommandExp :: Exp -> Bool
isAccentCommandExp :: Exp -> Bool
isAccentCommandExp Exp
e =
  case Exp
e of
    EOver Bool
_ Exp
_ Exp
over -> Exp -> Maybe Text
accentName Exp
over Maybe Text -> Maybe Text -> Bool
forall a. Eq a => a -> a -> Bool
/= Maybe Text
forall a. Maybe a
Nothing
    Exp
_              -> Bool
False

isTerminatingPunctuation :: Exp -> Bool
isTerminatingPunctuation :: Exp -> Bool
isTerminatingPunctuation Exp
e =
  case Exp
e of
    ESymbol TeXSymbolType
_ Text
"." -> Bool
True
    ESymbol TeXSymbolType
_ Text
"," -> Bool
True
    ESymbol TeXSymbolType
_ Text
";" -> Bool
True
    ESymbol TeXSymbolType
_ Text
":" -> Bool
True
    Exp
_             -> Bool
False

isCloseLike :: Exp -> Bool
isCloseLike :: Exp -> Bool
isCloseLike Exp
e =
  case Exp
e of
    ESymbol TeXSymbolType
Close Text
_ -> Bool
True
    EDelimited{}    -> Bool
True
    Exp
_               -> Bool
False

isScripted :: Exp -> Bool
isScripted :: Exp -> Bool
isScripted Exp
e =
  case Exp
e of
    ESub{}    -> Bool
True
    ESuper{}  -> Bool
True
    ESubsup{} -> Bool
True
    Exp
_         -> Bool
False

isArrowScriptedExp :: Exp -> Bool
isArrowScriptedExp :: Exp -> Bool
isArrowScriptedExp Exp
e =
  case Exp
e of
    EUnder Bool
_ Exp
base Exp
_       -> Exp -> Bool
isArrowBase Exp
base
    EOver Bool
_ Exp
base Exp
_        -> Exp -> Bool
isArrowBase Exp
base
    EUnderover Bool
_ Exp
base Exp
_ Exp
_ -> Exp -> Bool
isArrowBase Exp
base
    ESub Exp
base Exp
_           -> Exp -> Bool
isArrowBase Exp
base
    ESuper Exp
base Exp
_         -> Exp -> Bool
isArrowBase Exp
base
    ESubsup Exp
base Exp
_ Exp
_      -> Exp -> Bool
isArrowBase Exp
base
    Exp
_                     -> Bool
False

isScriptedMathOperatorExp :: Exp -> Bool
isScriptedMathOperatorExp :: Exp -> Bool
isScriptedMathOperatorExp Exp
e =
  case Exp
e of
    ESub Exp
base Exp
_           -> Exp -> Bool
isMathOperatorExp Exp
base
    ESuper Exp
base Exp
_         -> Exp -> Bool
isMathOperatorExp Exp
base
    ESubsup Exp
base Exp
_ Exp
_      -> Exp -> Bool
isMathOperatorExp Exp
base
    EUnder Bool
_ Exp
base Exp
_       -> Exp -> Bool
isMathOperatorExp Exp
base
    EOver Bool
_ Exp
base Exp
_        -> Exp -> Bool
isMathOperatorExp Exp
base
    EUnderover Bool
_ Exp
base Exp
_ Exp
_ -> Exp -> Bool
isMathOperatorExp Exp
base
    Exp
_                     -> Bool
False

isArrowBase :: Exp -> Bool
isArrowBase :: Exp -> Bool
isArrowBase Exp
e =
  case Exp
e of
    ESymbol TeXSymbolType
_ Text
"←" -> Bool
True
    ESymbol TeXSymbolType
_ Text
"→" -> Bool
True
    ESymbol TeXSymbolType
_ Text
"↔" -> Bool
True
    ESymbol TeXSymbolType
_ Text
"⇐" -> Bool
True
    ESymbol TeXSymbolType
_ Text
"⇒" -> Bool
True
    ESymbol TeXSymbolType
_ Text
"⇔" -> Bool
True
    ESymbol TeXSymbolType
_ Text
"↦" -> Bool
True
    Exp
_             -> Bool
False

isUnaryMinusSymbol :: Exp -> Bool
isUnaryMinusSymbol :: Exp -> Bool
isUnaryMinusSymbol Exp
e =
  case Exp
e of
    ESymbol TeXSymbolType
t Text
"-" -> TeXSymbolType
t TeXSymbolType -> TeXSymbolType -> Bool
forall a. Eq a => a -> a -> Bool
/= TeXSymbolType
Bin
    ESymbol TeXSymbolType
t Text
"−" -> TeXSymbolType
t TeXSymbolType -> TeXSymbolType -> Bool
forall a. Eq a => a -> a -> Bool
/= TeXSymbolType
Bin
    Exp
_             -> Bool
False

isLargeOpScriptedExp :: Exp -> Bool
isLargeOpScriptedExp :: Exp -> Bool
isLargeOpScriptedExp Exp
e =
  case Exp
e of
    EUnder Bool
_ Exp
base Exp
_       -> Exp -> Maybe Text
largeOpName Exp
base Maybe Text -> Maybe Text -> Bool
forall a. Eq a => a -> a -> Bool
/= Maybe Text
forall a. Maybe a
Nothing
    EOver Bool
_ Exp
base Exp
_        -> Exp -> Maybe Text
largeOpName Exp
base Maybe Text -> Maybe Text -> Bool
forall a. Eq a => a -> a -> Bool
/= Maybe Text
forall a. Maybe a
Nothing
    EUnderover Bool
_ Exp
base Exp
_ Exp
_ -> Exp -> Maybe Text
largeOpName Exp
base Maybe Text -> Maybe Text -> Bool
forall a. Eq a => a -> a -> Bool
/= Maybe Text
forall a. Maybe a
Nothing
    ESub Exp
base Exp
_      -> Exp -> Maybe Text
largeOpName Exp
base Maybe Text -> Maybe Text -> Bool
forall a. Eq a => a -> a -> Bool
/= Maybe Text
forall a. Maybe a
Nothing
    ESuper Exp
base Exp
_    -> Exp -> Maybe Text
largeOpName Exp
base Maybe Text -> Maybe Text -> Bool
forall a. Eq a => a -> a -> Bool
/= Maybe Text
forall a. Maybe a
Nothing
    ESubsup Exp
base Exp
_ Exp
_ -> Exp -> Maybe Text
largeOpName Exp
base Maybe Text -> Maybe Text -> Bool
forall a. Eq a => a -> a -> Bool
/= Maybe Text
forall a. Maybe a
Nothing
    Exp
_                -> Bool
False

startsWithInfixNeedingLhs :: [Exp] -> Bool
startsWithInfixNeedingLhs :: [Exp] -> Bool
startsWithInfixNeedingLhs [Exp]
exps =
  case [Exp]
exps of
    (Exp
e : [Exp]
_) -> Exp -> Bool
needsNeutralLhs Exp
e
    [Exp]
_                 -> Bool
False

endsWithInfixNeedingRhs :: [Exp] -> Bool
endsWithInfixNeedingRhs :: [Exp] -> Bool
endsWithInfixNeedingRhs [Exp]
exps =
  case [Exp] -> [Exp]
forall a. [a] -> [a]
reverse [Exp]
exps of
    (Exp
e : [Exp]
_) -> Exp -> Bool
needsNeutralRhs Exp
e
    [Exp]
_       -> Bool
False

needsNeutralLhs :: Exp -> Bool
needsNeutralLhs :: Exp -> Bool
needsNeutralLhs = Exp -> Bool
isInfixLikeExp

needsNeutralRhs :: Exp -> Bool
needsNeutralRhs :: Exp -> Bool
needsNeutralRhs = Exp -> Bool
isInfixLikeExp

needsNeutralScriptOperands :: Exp -> Bool
needsNeutralScriptOperands :: Exp -> Bool
needsNeutralScriptOperands Exp
e =
  Exp -> Bool
isInfixLikeExp Exp
e Bool -> Bool -> Bool
&& Bool -> Bool
not (Exp -> Bool
isAtomicScriptOperator Exp
e)

isAtomicScriptOperator :: Exp -> Bool
isAtomicScriptOperator :: Exp -> Bool
isAtomicScriptOperator Exp
e =
  case Exp
e of
    ESymbol TeXSymbolType
_ Text
"∘" -> Bool
True
    Exp
_             -> Bool
False

isInfixLikeExp :: Exp -> Bool
isInfixLikeExp :: Exp -> Bool
isInfixLikeExp Exp
e =
  case Exp
e of
    ESymbol TeXSymbolType
t Text
s
      | TeXSymbolType
t TeXSymbolType -> TeXSymbolType -> Bool
forall a. Eq a => a -> a -> Bool
== TeXSymbolType
Bin -> Bool
True
      | TeXSymbolType
t TeXSymbolType -> TeXSymbolType -> Bool
forall a. Eq a => a -> a -> Bool
== TeXSymbolType
Rel -> Bool
True
      | Bool
otherwise -> Text
s Text -> [Text] -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem`
          [ Text
"×", Text
"⋅", Text
"·", Text
"∘"
          , Text
"∈", Text
"∉", Text
"∋"
          , Text
"∩", Text
"∪"
          , Text
"⊂", Text
"⊆", Text
"⊃", Text
"⊇"
          , Text
"≤", Text
"≥", Text
"≠", Text
"≈", Text
"≡", Text
"∝"
          , Text
"∥", Text
"⊥"
          , Text
"±", Text
"∓"
          , Text
"/", Text
"←", Text
"→", Text
"↔", Text
"⇐", Text
"⇒", Text
"⇔", Text
"↦"
          ]
    Exp
_ -> Bool
False

renderExpIn :: DisplayType -> AlignContext -> Exp -> Maybe T.Text
renderExpIn :: DisplayType -> AlignContext -> Exp -> Maybe Text
renderExpIn DisplayType
dt AlignContext
ctx Exp
e =
  case Exp
e of
    ENumber Text
t       -> Text -> Maybe Text
forall a. a -> Maybe a
Just Text
t
    EIdentifier Text
t   -> Text -> Maybe Text
forall a. a -> Maybe a
Just (Text -> Text
renderIdentifier Text
t)
    EMathOperator Text
t -> Text -> Maybe Text
forall a. a -> Maybe a
Just (Text -> Text
renderMathOperator Text
t)
    ESymbol TeXSymbolType
t Text
s     -> Text -> Maybe Text
forall a. a -> Maybe a
Just (TeXSymbolType -> Text -> Text
renderSymbol TeXSymbolType
t Text
s)
    EText TextType
sty Text
t     -> Text -> Maybe Text
forall a. a -> Maybe a
Just (TextType -> Text -> Text
renderTextAtom TextType
sty Text
t)
    ESpace Rational
w        -> Text -> Maybe Text
forall a. a -> Maybe a
Just (Rational -> Text
renderSpace Rational
w)
    EGrouped [Exp]
xs     -> (Text
"{" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<>) (Text -> Text) -> (Text -> Text) -> Text -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"}") (Text -> Text) -> Maybe Text -> Maybe Text
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> DisplayType -> AlignContext -> [Exp] -> Maybe Text
renderExpsIn DisplayType
dt AlignContext
ctx [Exp]
xs
    EStyled TextType
sty [Exp]
xs  -> DisplayType -> AlignContext -> TextType -> [Exp] -> Maybe Text
renderStyled DisplayType
dt AlignContext
ctx TextType
sty [Exp]
xs

    EFraction FractionType
frac Exp
num Exp
den -> do
      Text
num' <- DisplayType -> AlignContext -> Exp -> Maybe Text
renderExpIn DisplayType
dt AlignContext
AlignDefault Exp
num
      Text
den' <- DisplayType -> AlignContext -> Exp -> Maybe Text
renderExpIn DisplayType
dt AlignContext
AlignDefault Exp
den
      let num'' :: Text
num'' = AlignContext -> Text -> Text
maybeCenterFractionArg AlignContext
ctx Text
num'
      let den'' :: Text
den'' = AlignContext -> Text -> Text
maybeCenterFractionArg AlignContext
ctx Text
den'
      Text -> Maybe Text
forall a. a -> Maybe a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Text -> Maybe Text) -> Text -> Maybe Text
forall a b. (a -> b) -> a -> b
$ case FractionType
frac of
        FractionType
NoLineFrac -> Text
"binom" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> Text
asDelimitedArg Text
num'' Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> Text
asDelimitedArg Text
den''
        FractionType
InlineFrac -> Text -> Text -> Text
renderInlineFraction Text
num'' Text
den''
        FractionType
NormalFrac
          | DisplayType
dt DisplayType -> DisplayType -> Bool
forall a. Eq a => a -> a -> Bool
== DisplayType
DisplayInline -> Text -> Text -> Text
renderInlineFraction Text
num'' Text
den''
        FractionType
_          -> Text
"{" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
num'' Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" over " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
den'' Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"}"

    ESqrt Exp
x -> (Text
"sqrt {" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<>) (Text -> Text) -> (Text -> Text) -> Text -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"}") (Text -> Text) -> Maybe Text -> Maybe Text
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> DisplayType -> AlignContext -> Exp -> Maybe Text
renderExpIn DisplayType
dt AlignContext
ctx Exp
x
    ERoot Exp
idx Exp
rad -> do
      Text
idx' <- DisplayType -> AlignContext -> Exp -> Maybe Text
renderExpIn DisplayType
dt AlignContext
ctx Exp
idx
      Text
rad' <- DisplayType -> AlignContext -> Exp -> Maybe Text
renderExpIn DisplayType
dt AlignContext
ctx Exp
rad
      Text -> Maybe Text
forall a. a -> Maybe a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Text -> Maybe Text) -> Text -> Maybe Text
forall a b. (a -> b) -> a -> b
$ Text
"nroot {" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
idx' Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"} {" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
rad' Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"}"

    EScaled Rational
_ (ESymbol TeXSymbolType
Open Text
"|") ->
      Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"mline"
    EScaled Rational
_ (ESymbol TeXSymbolType
Close Text
"|") ->
      Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"mline"
    EScaled Rational
_ Exp
x ->
      DisplayType -> AlignContext -> Exp -> Maybe Text
renderExpIn DisplayType
dt AlignContext
ctx Exp
x

    EDelimited Text
op Text
cl [InEDelimited]
xs -> do
      Text
body <- DisplayType -> AlignContext -> [InEDelimited] -> Maybe Text
renderDelimitedBody DisplayType
dt AlignContext
ctx [InEDelimited]
xs
      let op' :: Text
op' = DelimSide -> Text -> Text
delimToken DelimSide
DelimLeft Text
op
      let cl' :: Text
cl' = DelimSide -> Text -> Text
delimToken DelimSide
DelimRight Text
cl
      Text -> Maybe Text
forall a. a -> Maybe a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Text -> Maybe Text) -> Text -> Maybe Text
forall a b. (a -> b) -> a -> b
$ Text
"left " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
op' Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
body Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" right " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
cl'

    ESub Exp
base Exp
sub -> do
      Text
base' <- DisplayType -> AlignContext -> Exp -> Maybe Text
renderExpIn DisplayType
dt AlignContext
ctx Exp
base
      Text
sub'  <- DisplayType -> AlignContext -> Exp -> Maybe Text
renderScriptArg DisplayType
dt AlignContext
ctx Exp
sub
      Text -> Maybe Text
forall a. a -> Maybe a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Text -> Maybe Text) -> Text -> Maybe Text
forall a b. (a -> b) -> a -> b
$ Exp -> Text -> Text
renderScriptBase Exp
base Text
base' Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"_" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
sub'

    ESuper Exp
base Exp
sup -> do
      Text
baseRendered <- DisplayType -> AlignContext -> Exp -> Maybe Text
renderExpIn DisplayType
dt AlignContext
ctx Exp
base
      case Exp -> Maybe Text
renderPrimeSuffix Exp
sup of
        Just Text
primes ->
          Text -> Maybe Text
forall a. a -> Maybe a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Text -> Maybe Text) -> Text -> Maybe Text
forall a b. (a -> b) -> a -> b
$ Exp -> Text -> Text
renderScriptBase Exp
base Text
baseRendered Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
primes
        Maybe Text
Nothing -> do
          Text
supRendered <- DisplayType -> AlignContext -> Exp -> Maybe Text
renderScriptArg DisplayType
dt AlignContext
ctx Exp
sup
          Text -> Maybe Text
forall a. a -> Maybe a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Text -> Maybe Text) -> Text -> Maybe Text
forall a b. (a -> b) -> a -> b
$ Exp -> Text -> Text
renderScriptBase Exp
base Text
baseRendered Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"^" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
supRendered

    ESubsup Exp
base Exp
sub Exp
sup -> do
      Text
baseRendered <- DisplayType -> AlignContext -> Exp -> Maybe Text
renderExpIn DisplayType
dt AlignContext
ctx Exp
base
      Text
subRendered <- DisplayType -> AlignContext -> Exp -> Maybe Text
renderScriptArg DisplayType
dt AlignContext
ctx Exp
sub
      case Exp -> Maybe Text
renderPrimeSuffix Exp
sup of
        Just Text
primes ->
          Text -> Maybe Text
forall a. a -> Maybe a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Text -> Maybe Text) -> Text -> Maybe Text
forall a b. (a -> b) -> a -> b
$ Exp -> Text -> Text
renderScriptBase Exp
base Text
baseRendered Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"_" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
subRendered Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
primes
        Maybe Text
Nothing -> do
          Text
supRendered <- DisplayType -> AlignContext -> Exp -> Maybe Text
renderScriptArg DisplayType
dt AlignContext
ctx Exp
sup
          Text -> Maybe Text
forall a. a -> Maybe a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Text -> Maybe Text) -> Text -> Maybe Text
forall a b. (a -> b) -> a -> b
$ Exp -> Text -> Text
renderScriptBase Exp
base Text
baseRendered Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"_" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
subRendered Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"^" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
supRendered

    EOver Bool
_ Exp
base Exp
over
      | Just Text
arrow <- Exp -> Maybe Text
arrowScriptOpName Exp
base -> do
          if Exp -> Bool
isEmptyScriptArg Exp
over
             then Text -> Maybe Text
forall a. a -> Maybe a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Text
arrow
             else do
               Text
over' <- DisplayType -> AlignContext -> Exp -> Maybe Text
renderScriptArg DisplayType
dt AlignContext
ctx Exp
over
               Text -> Maybe Text
forall a. a -> Maybe a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Text -> Maybe Text) -> Text -> Maybe Text
forall a b. (a -> b) -> a -> b
$ Text
arrow Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" csup " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> Text
centerScriptArg Text
over'
      | Just Text
op <- Exp -> Maybe Text
centeredScriptOpName Exp
base -> do
          Text
over' <- DisplayType -> AlignContext -> Exp -> Maybe Text
renderScriptArg DisplayType
dt AlignContext
ctx Exp
over
          Text -> Maybe Text
forall a. a -> Maybe a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Text -> Maybe Text) -> Text -> Maybe Text
forall a b. (a -> b) -> a -> b
$ Text
"{" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
op Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"} csup " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> Text
centerScriptArg Text
over'
      | Just Text
brace <- Exp -> Maybe Text
braceAnnotationName Exp
over -> do
          Text
base' <- DisplayType -> AlignContext -> Exp -> Maybe Text
renderExpIn DisplayType
dt AlignContext
ctx Exp
base
          Text -> Maybe Text
forall a. a -> Maybe a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Text -> Maybe Text) -> Text -> Maybe Text
forall a b. (a -> b) -> a -> b
$ Exp -> Text -> Text
renderScriptBase Exp
base Text
base' Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
brace
      | Exp -> Bool
isBraceAnnotatedExp Exp
base -> do
          Text
base' <- DisplayType -> AlignContext -> Exp -> Maybe Text
renderExpIn DisplayType
dt AlignContext
ctx Exp
base
          Text
over' <- DisplayType -> AlignContext -> Exp -> Maybe Text
renderBraceLabel DisplayType
dt AlignContext
ctx Exp
over
          Text -> Maybe Text
forall a. a -> Maybe a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Text -> Maybe Text) -> Text -> Maybe Text
forall a b. (a -> b) -> a -> b
$ Text
base' Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
over'
      | Just Text
accent <- Exp -> Maybe Text
accentName Exp
over -> do
          Text
base' <- DisplayType -> AlignContext -> Exp -> Maybe Text
renderExpIn DisplayType
dt AlignContext
ctx Exp
base
          Text -> Maybe Text
forall a. a -> Maybe a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Text -> Maybe Text) -> Text -> Maybe Text
forall a b. (a -> b) -> a -> b
$ Text
accent Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Exp -> Text -> Text
renderAccentArg Exp
base Text
base'
      | Just Text
op <- Exp -> Maybe Text
limitOpName Exp
base -> do
          Text
over' <- DisplayType -> AlignContext -> Exp -> Maybe Text
renderLimitArg DisplayType
dt AlignContext
ctx Exp
over
          Text -> Maybe Text
forall a. a -> Maybe a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Text -> Maybe Text) -> Text -> Maybe Text
forall a b. (a -> b) -> a -> b
$ Text
op Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" to " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
over' Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" "
      | Bool
otherwise -> Maybe Text
forall a. Maybe a
Nothing

    EUnder Bool
_ Exp
base Exp
under ->
      case Exp -> Maybe Text
arrowScriptOpName Exp
base of
        Just Text
arrow ->
          if Exp -> Bool
isEmptyScriptArg Exp
under
             then Text -> Maybe Text
forall a. a -> Maybe a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Text
arrow
             else do
               Text
under' <- DisplayType -> AlignContext -> Exp -> Maybe Text
renderScriptArg DisplayType
dt AlignContext
ctx Exp
under
               Text -> Maybe Text
forall a. a -> Maybe a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Text -> Maybe Text) -> Text -> Maybe Text
forall a b. (a -> b) -> a -> b
$ Text
arrow Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" csub " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> Text
centerScriptArg Text
under'
        Maybe Text
Nothing ->
          case Exp -> Maybe Text
underlineMarkerName Exp
under of
            Just Text
marker -> do
              Text
base' <- DisplayType -> AlignContext -> Exp -> Maybe Text
renderExpIn DisplayType
dt AlignContext
ctx Exp
base
              Text -> Maybe Text
forall a. a -> Maybe a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Text -> Maybe Text) -> Text -> Maybe Text
forall a b. (a -> b) -> a -> b
$ Text
marker Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Exp -> Text -> Text
renderAccentArg Exp
base Text
base'
            Maybe Text
Nothing ->
              case Exp -> Maybe Text
braceAnnotationName Exp
under of
                Just Text
brace -> do
                  Text
base' <- DisplayType -> AlignContext -> Exp -> Maybe Text
renderExpIn DisplayType
dt AlignContext
ctx Exp
base
                  Text -> Maybe Text
forall a. a -> Maybe a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Text -> Maybe Text) -> Text -> Maybe Text
forall a b. (a -> b) -> a -> b
$ Exp -> Text -> Text
renderScriptBase Exp
base Text
base' Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
brace
                Maybe Text
Nothing ->
                  if Exp -> Bool
isBraceAnnotatedExp Exp
base
                     then do
                       Text
base' <- DisplayType -> AlignContext -> Exp -> Maybe Text
renderExpIn DisplayType
dt AlignContext
ctx Exp
base
                       Text
under' <- DisplayType -> AlignContext -> Exp -> Maybe Text
renderBraceLabel DisplayType
dt AlignContext
ctx Exp
under
                       Text -> Maybe Text
forall a. a -> Maybe a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Text -> Maybe Text) -> Text -> Maybe Text
forall a b. (a -> b) -> a -> b
$ Text
base' Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
under'
                     else
                       case Exp -> Maybe Text
centeredScriptOpName Exp
base of
                         Just Text
op -> do
                           Text
under' <- DisplayType -> AlignContext -> Exp -> Maybe Text
renderScriptArg DisplayType
dt AlignContext
ctx Exp
under
                           Text -> Maybe Text
forall a. a -> Maybe a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Text -> Maybe Text) -> Text -> Maybe Text
forall a b. (a -> b) -> a -> b
$ Text
"{" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
op Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"} csub " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> Text
centerScriptArg Text
under'
                         Maybe Text
Nothing ->
                           case Exp -> Maybe Text
limitOpName Exp
base of
                             Just Text
op -> do
                               Text
under' <- DisplayType -> AlignContext -> Exp -> Maybe Text
renderLimitArg DisplayType
dt AlignContext
ctx Exp
under
                               Text -> Maybe Text
forall a. a -> Maybe a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Text -> Maybe Text) -> Text -> Maybe Text
forall a b. (a -> b) -> a -> b
$ Text
op Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" from " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
under' Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" "
                             Maybe Text
Nothing -> do
                               Text
base' <- DisplayType -> AlignContext -> Exp -> Maybe Text
renderExpIn DisplayType
dt AlignContext
ctx Exp
base
                               Text
under' <- DisplayType -> AlignContext -> Exp -> Maybe Text
renderScriptArg DisplayType
dt AlignContext
ctx Exp
under
                               Text -> Maybe Text
forall a. a -> Maybe a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Text -> Maybe Text) -> Text -> Maybe Text
forall a b. (a -> b) -> a -> b
$ Exp -> Text -> Text
renderScriptBase Exp
base Text
base' Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"_" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
under'
    EUnderover Bool
_ Exp
base Exp
under Exp
over ->
      case Exp -> Maybe Text
arrowScriptOpName Exp
base of
        Just Text
arrow ->
          case (Exp -> Bool
isEmptyScriptArg Exp
under, Exp -> Bool
isEmptyScriptArg Exp
over) of
            (Bool
True, Bool
True) -> Text -> Maybe Text
forall a. a -> Maybe a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Text
arrow
            (Bool
False, Bool
True) -> do
              Text
under' <- DisplayType -> AlignContext -> Exp -> Maybe Text
renderScriptArg DisplayType
dt AlignContext
ctx Exp
under
              Text -> Maybe Text
forall a. a -> Maybe a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Text -> Maybe Text) -> Text -> Maybe Text
forall a b. (a -> b) -> a -> b
$ Text
arrow Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" csub " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> Text
centerScriptArg Text
under'
            (Bool
True, Bool
False) -> do
              Text
over' <- DisplayType -> AlignContext -> Exp -> Maybe Text
renderScriptArg DisplayType
dt AlignContext
ctx Exp
over
              Text -> Maybe Text
forall a. a -> Maybe a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Text -> Maybe Text) -> Text -> Maybe Text
forall a b. (a -> b) -> a -> b
$ Text
arrow Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" csup " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> Text
centerScriptArg Text
over'
            (Bool
False, Bool
False) -> do
              Text
under' <- DisplayType -> AlignContext -> Exp -> Maybe Text
renderScriptArg DisplayType
dt AlignContext
ctx Exp
under
              Text
over' <- DisplayType -> AlignContext -> Exp -> Maybe Text
renderScriptArg DisplayType
dt AlignContext
ctx Exp
over
              Text -> Maybe Text
forall a. a -> Maybe a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Text -> Maybe Text) -> Text -> Maybe Text
forall a b. (a -> b) -> a -> b
$ Text
arrow Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" csub " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> Text
centerScriptArg Text
under'
                  Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" csup " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> Text
centerScriptArg Text
over'
        Maybe Text
Nothing ->
          case Exp -> Maybe Text
centeredScriptOpName Exp
base of
            Just Text
op -> do
              Text
under' <- DisplayType -> AlignContext -> Exp -> Maybe Text
renderScriptArg DisplayType
dt AlignContext
ctx Exp
under
              Text
over' <- DisplayType -> AlignContext -> Exp -> Maybe Text
renderScriptArg DisplayType
dt AlignContext
ctx Exp
over
              Text -> Maybe Text
forall a. a -> Maybe a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Text -> Maybe Text) -> Text -> Maybe Text
forall a b. (a -> b) -> a -> b
$ Text
"{" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
op Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"} csub " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> Text
centerScriptArg Text
under'
                  Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" csup " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> Text
centerScriptArg Text
over'
            Maybe Text
Nothing ->
              case Exp -> Maybe Text
limitOpName Exp
base of
                Just Text
op -> do
                  Text
under' <- DisplayType -> AlignContext -> Exp -> Maybe Text
renderLimitArg DisplayType
dt AlignContext
ctx Exp
under
                  Text
over'  <- DisplayType -> AlignContext -> Exp -> Maybe Text
renderLimitArg DisplayType
dt AlignContext
ctx Exp
over
                  Text -> Maybe Text
forall a. a -> Maybe a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Text -> Maybe Text) -> Text -> Maybe Text
forall a b. (a -> b) -> a -> b
$ Text
op Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" from " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
under' Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" to " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
over' Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" "
                Maybe Text
Nothing -> do
                  Text
base' <- DisplayType -> AlignContext -> Exp -> Maybe Text
renderExpIn DisplayType
dt AlignContext
ctx Exp
base
                  Text
under' <- DisplayType -> AlignContext -> Exp -> Maybe Text
renderScriptArg DisplayType
dt AlignContext
ctx Exp
under
                  Text
over' <- DisplayType -> AlignContext -> Exp -> Maybe Text
renderScriptArg DisplayType
dt AlignContext
ctx Exp
over
                  Text -> Maybe Text
forall a. a -> Maybe a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Text -> Maybe Text) -> Text -> Maybe Text
forall a b. (a -> b) -> a -> b
$ Exp -> Text -> Text
renderScriptBase Exp
base Text
base' Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"_" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
under' Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"^" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
over'
    EArray [Alignment]
aligns [ArrayLine]
rows -> DisplayType -> [Alignment] -> [ArrayLine] -> Maybe Text
renderMatrix DisplayType
dt [Alignment]
aligns [ArrayLine]
rows
    EPhantom Exp
x         -> do
      Text
x' <- DisplayType -> AlignContext -> Exp -> Maybe Text
renderExpIn DisplayType
dt AlignContext
ctx Exp
x
      Text -> Maybe Text
forall a. a -> Maybe a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Text -> Maybe Text) -> Text -> Maybe Text
forall a b. (a -> b) -> a -> b
$ Text
"phantom " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Exp -> Text -> Text
renderPhantomArg Exp
x Text
x'
    Exp
_                  -> Maybe Text
forall a. Maybe a
Nothing

renderDelimitedBody :: DisplayType -> AlignContext -> [Either T.Text Exp] -> Maybe T.Text
renderDelimitedBody :: DisplayType -> AlignContext -> [InEDelimited] -> Maybe Text
renderDelimitedBody DisplayType
dt AlignContext
ctx [InEDelimited]
xs = do
  [DelimitedChunk]
chunks <- (InEDelimited -> Maybe DelimitedChunk)
-> [InEDelimited] -> Maybe [DelimitedChunk]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> [a] -> m [b]
mapM (DisplayType -> AlignContext -> InEDelimited -> Maybe DelimitedChunk
renderDelimitedChunk DisplayType
dt AlignContext
ctx) [InEDelimited]
xs
  Text -> Maybe Text
forall a. a -> Maybe a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Text -> Maybe Text) -> Text -> Maybe Text
forall a b. (a -> b) -> a -> b
$ Text -> Text
T.strip ([DelimitedChunk] -> Text
mergeDelimitedChunks [DelimitedChunk]
chunks)

data DelimitedChunk = DelimRaw T.Text | DelimExp Exp T.Text

renderDelimitedChunk :: DisplayType -> AlignContext -> Either T.Text Exp -> Maybe DelimitedChunk
renderDelimitedChunk :: DisplayType -> AlignContext -> InEDelimited -> Maybe DelimitedChunk
renderDelimitedChunk DisplayType
dt AlignContext
ctx InEDelimited
p =
  case InEDelimited
p of
    Left Text
t  -> DelimitedChunk -> Maybe DelimitedChunk
forall a. a -> Maybe a
Just (DelimitedChunk -> Maybe DelimitedChunk)
-> DelimitedChunk -> Maybe DelimitedChunk
forall a b. (a -> b) -> a -> b
$ Text -> DelimitedChunk
DelimRaw (Text
" " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> DelimSide -> Text -> Text
delimToken DelimSide
DelimMiddle Text
t Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" ")
    Right Exp
x -> Exp -> Text -> DelimitedChunk
DelimExp Exp
x (Text -> DelimitedChunk) -> Maybe Text -> Maybe DelimitedChunk
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> DisplayType -> AlignContext -> Exp -> Maybe Text
renderExpIn DisplayType
dt AlignContext
ctx Exp
x

mergeDelimitedChunks :: [DelimitedChunk] -> T.Text
mergeDelimitedChunks :: [DelimitedChunk] -> Text
mergeDelimitedChunks [] = Text
""
mergeDelimitedChunks (DelimitedChunk
c0:[DelimitedChunk]
cs) = (Maybe Exp, Text) -> Text
forall a b. (a, b) -> b
snd ((Maybe Exp, Text) -> Text) -> (Maybe Exp, Text) -> Text
forall a b. (a -> b) -> a -> b
$ ((Maybe Exp, Text) -> DelimitedChunk -> (Maybe Exp, Text))
-> (Maybe Exp, Text) -> [DelimitedChunk] -> (Maybe Exp, Text)
forall b a. (b -> a -> b) -> b -> [a] -> b
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
List.foldl' (Maybe Exp, Text) -> DelimitedChunk -> (Maybe Exp, Text)
step (DelimitedChunk -> Maybe Exp
chunkExp DelimitedChunk
c0, DelimitedChunk -> Text
chunkText DelimitedChunk
c0) [DelimitedChunk]
cs
 where
  step :: (Maybe Exp, Text) -> DelimitedChunk -> (Maybe Exp, Text)
step (Maybe Exp
prevExp, Text
acc) DelimitedChunk
cur
    | Text -> Bool
T.null Text
curText = (Maybe Exp
prevExp, Text
acc)
    | Bool
otherwise =
        case DelimitedChunk
cur of
          DelimRaw Text
_ -> (Maybe Exp
forall a. Maybe a
Nothing, Bool -> Text -> Text -> Text
appendRendered Bool
False Text
acc Text
curText)
          DelimExp Exp
curExp Text
_ ->
            let needSep :: Bool
needSep = case Maybe Exp
prevExp of
                            Just Exp
pe -> Exp -> Exp -> Bool
needsSeparator Exp
pe Exp
curExp
                            Maybe Exp
Nothing -> Bool
False
            in (Exp -> Maybe Exp
forall a. a -> Maybe a
Just Exp
curExp, Bool -> Text -> Text -> Text
appendRendered Bool
needSep Text
acc Text
curText)
   where
    curText :: Text
curText = DelimitedChunk -> Text
chunkText DelimitedChunk
cur

  chunkText :: DelimitedChunk -> Text
chunkText DelimitedChunk
c =
    case DelimitedChunk
c of
      DelimRaw Text
t   -> Text
t
      DelimExp Exp
_ Text
t -> Text
t

  chunkExp :: DelimitedChunk -> Maybe Exp
chunkExp DelimitedChunk
c =
    case DelimitedChunk
c of
      DelimRaw Text
_   -> Maybe Exp
forall a. Maybe a
Nothing
      DelimExp Exp
e Text
_ -> Exp -> Maybe Exp
forall a. a -> Maybe a
Just Exp
e

renderMatrix :: DisplayType -> [Alignment] -> [[[Exp]]] -> Maybe T.Text
renderMatrix :: DisplayType -> [Alignment] -> [ArrayLine] -> Maybe Text
renderMatrix DisplayType
dt [Alignment]
aligns [ArrayLine]
rows = do
  [Text]
rows' <- (ArrayLine -> Maybe Text) -> [ArrayLine] -> Maybe [Text]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> [a] -> m [b]
mapM (DisplayType -> [Alignment] -> ArrayLine -> Maybe Text
renderMatrixRow DisplayType
dt [Alignment]
aligns) [ArrayLine]
rows
  Text -> Maybe Text
forall a. a -> Maybe a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Text -> Maybe Text) -> Text -> Maybe Text
forall a b. (a -> b) -> a -> b
$ Text
"matrix { " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> [Text] -> Text
T.intercalate Text
" ## " [Text]
rows' Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" }"

renderMatrixRow :: DisplayType -> [Alignment] -> [[Exp]] -> Maybe T.Text
renderMatrixRow :: DisplayType -> [Alignment] -> ArrayLine -> Maybe Text
renderMatrixRow DisplayType
dt [Alignment]
aligns ArrayLine
cells = do
  let explicitCenter :: Bool
explicitCenter = (Alignment -> Bool) -> [Alignment] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any (Alignment -> Alignment -> Bool
forall a. Eq a => a -> a -> Bool
/= Alignment
AlignCenter) [Alignment]
aligns
  let columnCount :: Int
columnCount = Int -> Int -> Int
forall a. Ord a => a -> a -> a
max ([Alignment] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Alignment]
aligns) (ArrayLine -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length ArrayLine
cells)
  let paddedCells :: ArrayLine
paddedCells = Int -> ArrayLine -> ArrayLine
forall a. Int -> [a] -> [a]
take Int
columnCount (ArrayLine
cells ArrayLine -> ArrayLine -> ArrayLine
forall a. [a] -> [a] -> [a]
++ [Exp] -> ArrayLine
forall a. a -> [a]
repeat [])
  [Text]
cells' <- [Maybe Text] -> Maybe [Text]
forall (t :: * -> *) (m :: * -> *) a.
(Traversable t, Monad m) =>
t (m a) -> m (t a)
forall (m :: * -> *) a. Monad m => [m a] -> m [a]
sequence
    [ DisplayType -> Bool -> Alignment -> [Exp] -> Maybe Text
renderMatrixCellWithAlign DisplayType
dt Bool
explicitCenter ([Alignment] -> Int -> Alignment
columnAlign [Alignment]
aligns Int
i) [Exp]
c
    | (Int
i, [Exp]
c) <- [Int] -> ArrayLine -> [(Int, [Exp])]
forall a b. [a] -> [b] -> [(a, b)]
zip [(Int
0 :: Int) ..] ArrayLine
paddedCells
    ]
  Text -> Maybe Text
forall a. a -> Maybe a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Text -> Maybe Text) -> Text -> Maybe Text
forall a b. (a -> b) -> a -> b
$ Text -> [Text] -> Text
T.intercalate Text
" # " [Text]
cells'

renderMatrixCell :: DisplayType -> AlignContext -> [Exp] -> Maybe T.Text
renderMatrixCell :: DisplayType -> AlignContext -> [Exp] -> Maybe Text
renderMatrixCell DisplayType
_ AlignContext
_ [] = Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"{}"
renderMatrixCell DisplayType
dt AlignContext
ctx [Exp]
xs = do
  Text
rendered <- DisplayType -> AlignContext -> [Exp] -> Maybe Text
renderExpsIn DisplayType
dt AlignContext
ctx [Exp]
xs
  let stripped :: Text
stripped = Text -> Text
T.strip Text
rendered
  Text -> Maybe Text
forall a. a -> Maybe a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Text -> Maybe Text) -> Text -> Maybe Text
forall a b. (a -> b) -> a -> b
$ if Text -> Bool
T.null Text
stripped then Text
"{}" else Text
stripped

renderMatrixCellWithAlign :: DisplayType -> Bool -> Alignment -> [Exp] -> Maybe T.Text
renderMatrixCellWithAlign :: DisplayType -> Bool -> Alignment -> [Exp] -> Maybe Text
renderMatrixCellWithAlign DisplayType
dt Bool
explicitCenter Alignment
align [Exp]
xs = do
  Text
cell <- DisplayType -> AlignContext -> [Exp] -> Maybe Text
renderMatrixCell DisplayType
dt (Alignment -> AlignContext
alignmentContext Alignment
align) [Exp]
xs
  Text -> Maybe Text
forall a. a -> Maybe a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Text -> Maybe Text) -> Text -> Maybe Text
forall a b. (a -> b) -> a -> b
$ case Alignment
align of
    Alignment
AlignLeft  -> Text
"alignl " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
cell
    Alignment
AlignRight -> Text
"alignr " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
cell
    Alignment
AlignCenter | Bool
explicitCenter -> Text
"alignc " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
cell
    Alignment
_                            -> Text
cell

columnAlign :: [Alignment] -> Int -> Alignment
columnAlign :: [Alignment] -> Int -> Alignment
columnAlign [Alignment]
aligns Int
i =
  case Int -> [Alignment] -> [Alignment]
forall a. Int -> [a] -> [a]
drop Int
i [Alignment]
aligns of
    (Alignment
a : [Alignment]
_) -> Alignment
a
    []      -> Alignment
AlignCenter

renderStyled :: DisplayType -> AlignContext -> TextType -> [Exp] -> Maybe T.Text
renderStyled :: DisplayType -> AlignContext -> TextType -> [Exp] -> Maybe Text
renderStyled DisplayType
dt AlignContext
ctx TextType
sty [Exp]
xs = do
  Text
body <- DisplayType -> AlignContext -> [Exp] -> Maybe Text
renderExpsIn DisplayType
dt AlignContext
ctx [Exp]
xs
  Text -> Maybe Text
forall a. a -> Maybe a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Text -> Maybe Text) -> Text -> Maybe Text
forall a b. (a -> b) -> a -> b
$ case TextType
sty of
    TextType
_
      | Just Text
unicodeBody <- TextType -> [Exp] -> Maybe Text
renderUnicodeSerifStyled TextType
sty [Exp]
xs ->
          Text
"nitalic " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> Text
styleArg Text
unicodeBody
    TextType
TextNormal
      | Just Text
ident <- [Exp] -> Maybe Text
singleUprightIdentifier [Exp]
xs ->
          Text
"nitalic " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> Text
renderTextNormalIdentifier Text
ident
      | Bool -> Bool
not ([Exp] -> Bool
hasStructuralScript [Exp]
xs)
      , Just Text
txt <- [Exp] -> Maybe Text
styledText [Exp]
xs -> Text -> Text
quoteText Text
txt
      | Just Text
txt <- DisplayType -> [Exp] -> Maybe Text
renderTextNormalStyled DisplayType
dt [Exp]
xs
      , [Exp] -> Bool
shouldForceUprightTextNormal [Exp]
xs -> Text
"nitalic{" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
txt Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"}"
      | Just Text
txt <- DisplayType -> [Exp] -> Maybe Text
renderTextNormalStyled DisplayType
dt [Exp]
xs -> Text
txt
    TextType
TextItalic       -> Text
"ital " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> Text
styleArg Text
body
    TextType
TextBold
      | [Exp] -> Bool
shouldForceUprightBold [Exp]
xs -> Text
"bold nitalic " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> Text
styleArg Text
body
      | Bool
otherwise -> Text
"bold " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> Text
styleArg Text
body
    TextType
TextBoldItalic   -> Text
"bold " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> Text
styleArg (Text
"ital " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> Text
styleArg Text
body)
    TextType
TextMonospace    -> Text
"font fixed nitalic " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> Text
styleArg Text
body
    TextType
TextSansSerif    -> Text
"font sans nitalic " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> Text
styleArg Text
body
    TextType
TextSansSerifBold -> Text
"bold " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> Text
styleArg (Text
"font sans nitalic " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> Text
styleArg Text
body)
    TextType
TextSansSerifBoldItalic -> Text
"bold " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> Text
styleArg (Text
"font sans ital " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> Text
styleArg Text
body)
    TextType
TextSansSerifItalic -> Text
"font sans ital " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> Text
styleArg Text
body
    TextType
TextScript       -> Text
"ital " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> Text
styleArg Text
body
    TextType
TextFraktur      -> Text
"bold " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> Text
styleArg Text
body
    TextType
TextDoubleStruck -> Text
"bold nitalic " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> Text
styleArg Text
body
    TextType
_                -> Text
body
 where
  styleArg :: Text -> Text
styleArg Text
t
    | Text -> Bool
T.null Text
t       = Text
"{}"
    | Text -> Int
T.length Text
t Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
1 = Text
t
    | Bool
otherwise      = Text
"{" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
t Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"}"

renderUnicodeSerifStyled :: TextType -> [Exp] -> Maybe T.Text
renderUnicodeSerifStyled :: TextType -> [Exp] -> Maybe Text
renderUnicodeSerifStyled TextType
sty [Exp]
xs =
  case TextType
sty of
    TextType
TextScript       -> TextType -> [Exp] -> Maybe Text
styledUnicodeText TextType
sty [Exp]
xs
    TextType
TextFraktur      -> TextType -> [Exp] -> Maybe Text
styledUnicodeText TextType
sty [Exp]
xs
    TextType
TextDoubleStruck -> TextType -> [Exp] -> Maybe Text
styledUnicodeText TextType
sty [Exp]
xs
    TextType
TextBoldScript   -> TextType -> [Exp] -> Maybe Text
styledUnicodeText TextType
sty [Exp]
xs
    TextType
TextBoldFraktur  -> TextType -> [Exp] -> Maybe Text
styledUnicodeText TextType
sty [Exp]
xs
    TextType
_                -> Maybe Text
forall a. Maybe a
Nothing

styledUnicodeText :: TextType -> [Exp] -> Maybe T.Text
styledUnicodeText :: TextType -> [Exp] -> Maybe Text
styledUnicodeText TextType
sty = ([Text] -> Text) -> Maybe [Text] -> Maybe Text
forall a b. (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap [Text] -> Text
T.concat (Maybe [Text] -> Maybe Text)
-> ([Exp] -> Maybe [Text]) -> [Exp] -> Maybe Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Exp -> Maybe Text) -> [Exp] -> Maybe [Text]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> [a] -> m [b]
mapM (TextType -> Exp -> Maybe Text
styledUnicodeExp TextType
sty)

styledUnicodeExp :: TextType -> Exp -> Maybe T.Text
styledUnicodeExp :: TextType -> Exp -> Maybe Text
styledUnicodeExp TextType
sty Exp
e =
  case Exp
e of
    EIdentifier Text
t        -> TextType -> Text -> Maybe Text
mapStyledUnicode TextType
sty Text
t
    ENumber Text
t            -> TextType -> Text -> Maybe Text
mapStyledUnicode TextType
sty Text
t
    EGrouped [Exp]
xs          -> TextType -> [Exp] -> Maybe Text
styledUnicodeText TextType
sty [Exp]
xs
    EStyled TextType
TextNormal [Exp]
xs -> TextType -> [Exp] -> Maybe Text
styledUnicodeText TextType
sty [Exp]
xs
    ESpace Rational
w
      | Rational
w Rational -> Rational -> Bool
forall a. Ord a => a -> a -> Bool
<= Rational
0          -> Text -> Maybe Text
forall a. a -> Maybe a
Just Text
""
      | Rational
w Rational -> Rational -> Bool
forall a. Ord a => a -> a -> Bool
>= Rational
2          -> Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"  "
      | Bool
otherwise       -> Text -> Maybe Text
forall a. a -> Maybe a
Just Text
" "
    Exp
_                   -> Maybe Text
forall a. Maybe a
Nothing

mapStyledUnicode :: TextType -> T.Text -> Maybe T.Text
mapStyledUnicode :: TextType -> Text -> Maybe Text
mapStyledUnicode TextType
sty Text
t = String -> Text
T.pack (String -> Text) -> Maybe String -> Maybe Text
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (Char -> Maybe Char) -> String -> Maybe String
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> [a] -> m [b]
mapM (\Char
c -> (TextType, Char) -> Maybe Char
toUnicodeChar (TextType
sty, Char
c)) (Text -> String
T.unpack Text
t)

hasStructuralScript :: [Exp] -> Bool
hasStructuralScript :: [Exp] -> Bool
hasStructuralScript = (Exp -> Bool) -> [Exp] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any Exp -> Bool
go
 where
  go :: Exp -> Bool
go Exp
e =
    case Exp
e of
      ESub{}                 -> Bool
True
      ESuper{}               -> Bool
True
      ESubsup{}              -> Bool
True
      EGrouped [Exp]
xs            -> [Exp] -> Bool
hasStructuralScript [Exp]
xs
      EStyled TextType
TextNormal [Exp]
xs  -> [Exp] -> Bool
hasStructuralScript [Exp]
xs
      Exp
_                      -> Bool
False

styledText :: [Exp] -> Maybe T.Text
styledText :: [Exp] -> Maybe Text
styledText = ([Text] -> Text) -> Maybe [Text] -> Maybe Text
forall a b. (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap [Text] -> Text
T.concat (Maybe [Text] -> Maybe Text)
-> ([Exp] -> Maybe [Text]) -> [Exp] -> Maybe Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Exp -> Maybe Text) -> [Exp] -> Maybe [Text]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> [a] -> m [b]
mapM Exp -> Maybe Text
styledTextExp

styledTextExp :: Exp -> Maybe T.Text
styledTextExp :: Exp -> Maybe Text
styledTextExp Exp
e =
  case Exp
e of
    ENumber Text
t         -> Text -> Maybe Text
forall a. a -> Maybe a
Just Text
t
    EIdentifier Text
t     -> Text -> Maybe Text
forall a. a -> Maybe a
Just Text
t
    EText TextType
_ Text
t         -> Text -> Maybe Text
forall a. a -> Maybe a
Just Text
t
    ESpace Rational
w
      | Rational
w Rational -> Rational -> Bool
forall a. Ord a => a -> a -> Bool
<= Rational
0        -> Text -> Maybe Text
forall a. a -> Maybe a
Just Text
""
      | Rational
w Rational -> Rational -> Bool
forall a. Ord a => a -> a -> Bool
>= Rational
2        -> Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"  "
      | Bool
otherwise     -> Text -> Maybe Text
forall a. a -> Maybe a
Just Text
" "
    EGrouped [Exp]
xs       -> [Exp] -> Maybe Text
styledText [Exp]
xs
    EStyled TextType
TextNormal [Exp]
xs -> [Exp] -> Maybe Text
styledText [Exp]
xs
    ESub Exp
base Exp
sub     -> do
      Text
base' <- Exp -> Maybe Text
styledTextExp Exp
base
      Text
sub'  <- Exp -> Maybe Text
styledTextNonNumericExp Exp
sub
      Text -> Maybe Text
forall a. a -> Maybe a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Text -> Maybe Text) -> Text -> Maybe Text
forall a b. (a -> b) -> a -> b
$ Text
base' Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"_" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
sub'
    ESuper Exp
base Exp
sup   -> do
      Text
base' <- Exp -> Maybe Text
styledTextExp Exp
base
      Text
sup'  <- Exp -> Maybe Text
styledTextNonNumericExp Exp
sup
      Text -> Maybe Text
forall a. a -> Maybe a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Text -> Maybe Text) -> Text -> Maybe Text
forall a b. (a -> b) -> a -> b
$ Text
base' Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"^" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
sup'
    ESubsup Exp
base Exp
sub Exp
sup -> do
      Text
base' <- Exp -> Maybe Text
styledTextExp Exp
base
      Text
sub'  <- Exp -> Maybe Text
styledTextNonNumericExp Exp
sub
      Text
sup'  <- Exp -> Maybe Text
styledTextNonNumericExp Exp
sup
      Text -> Maybe Text
forall a. a -> Maybe a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Text -> Maybe Text) -> Text -> Maybe Text
forall a b. (a -> b) -> a -> b
$ Text
base' Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"_" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
sub' Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"^" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
sup'
    ESymbol TeXSymbolType
_ Text
s
      | Text -> Bool
isPlainTextSymbol Text
s -> Text -> Maybe Text
forall a. a -> Maybe a
Just Text
s
    Exp
_ -> Maybe Text
forall a. Maybe a
Nothing

styledTextNonNumericExp :: Exp -> Maybe T.Text
styledTextNonNumericExp :: Exp -> Maybe Text
styledTextNonNumericExp Exp
e = do
  Text
txt <- Exp -> Maybe Text
styledTextExp Exp
e
  if (Char -> Bool) -> Text -> Bool
T.any Char -> Bool
isAsciiDigit Text
txt
     then Maybe Text
forall a. Maybe a
Nothing
     else Text -> Maybe Text
forall a. a -> Maybe a
Just Text
txt

isAsciiDigit :: Char -> Bool
isAsciiDigit :: Char -> Bool
isAsciiDigit Char
c = Char
c Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
>= Char
'0' Bool -> Bool -> Bool
&& Char
c Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
<= Char
'9'

isPlainTextSymbol :: T.Text -> Bool
isPlainTextSymbol :: Text -> Bool
isPlainTextSymbol Text
s =
  Text
s Text -> [Text] -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem`
    [ Text
"_", Text
",", Text
".", Text
":", Text
";", Text
"-", Text
"−", Text
"/", Text
"(", Text
")", Text
"[", Text
"]"
    , Text
"+", Text
"=", Text
"'", Text
"′"
    ]

renderTextNormalStyled :: DisplayType -> [Exp] -> Maybe T.Text
renderTextNormalStyled :: DisplayType -> [Exp] -> Maybe Text
renderTextNormalStyled DisplayType
dt [Exp]
xs = do
  let xs' :: [Exp]
xs' = [Exp] -> [Exp]
quoteStarMathKeywordRuns [Exp]
xs
  [Text]
rendered <- (Exp -> Maybe Text) -> [Exp] -> Maybe [Text]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> [a] -> m [b]
mapM (DisplayType -> Exp -> Maybe Text
renderTextNormalExp DisplayType
dt) [Exp]
xs'
  Text -> Maybe Text
forall a. a -> Maybe a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Text -> Maybe Text) -> Text -> Maybe Text
forall a b. (a -> b) -> a -> b
$ [(Exp, Text)] -> Text
mergePieces ([Exp] -> [Text] -> [(Exp, Text)]
forall a b. [a] -> [b] -> [(a, b)]
zip [Exp]
xs' [Text]
rendered)

quoteStarMathKeywordRuns :: [Exp] -> [Exp]
quoteStarMathKeywordRuns :: [Exp] -> [Exp]
quoteStarMathKeywordRuns [] = []
quoteStarMathKeywordRuns xs :: [Exp]
xs@(Exp
x : [Exp]
rest)
  | Just Text
_ <- Exp -> Maybe Text
asciiIdentifierWord Exp
x =
      let (Text
word, [Exp]
wordExps, [Exp]
rest') = [Exp] -> (Text, [Exp], [Exp])
takeIdentifierWordRun [Exp]
xs
      in if Text -> Bool
isStarMathReservedWord Text
word
            then TextType -> Text -> Exp
EText TextType
TextNormal Text
word Exp -> [Exp] -> [Exp]
forall a. a -> [a] -> [a]
: [Exp] -> [Exp]
quoteStarMathKeywordRuns [Exp]
rest'
            else [Exp]
wordExps [Exp] -> [Exp] -> [Exp]
forall a. Semigroup a => a -> a -> a
<> [Exp] -> [Exp]
quoteStarMathKeywordRuns [Exp]
rest'
  | Bool
otherwise = Exp
x Exp -> [Exp] -> [Exp]
forall a. a -> [a] -> [a]
: [Exp] -> [Exp]
quoteStarMathKeywordRuns [Exp]
rest

takeIdentifierWordRun :: [Exp] -> (T.Text, [Exp], [Exp])
takeIdentifierWordRun :: [Exp] -> (Text, [Exp], [Exp])
takeIdentifierWordRun = [Text] -> [Exp] -> [Exp] -> (Text, [Exp], [Exp])
go [] []
 where
  go :: [Text] -> [Exp] -> [Exp] -> (Text, [Exp], [Exp])
go [Text]
pieces [Exp]
exps (Exp
e : [Exp]
rest)
    | Just Text
piece <- Exp -> Maybe Text
asciiIdentifierWord Exp
e = [Text] -> [Exp] -> [Exp] -> (Text, [Exp], [Exp])
go (Text
piece Text -> [Text] -> [Text]
forall a. a -> [a] -> [a]
: [Text]
pieces) (Exp
e Exp -> [Exp] -> [Exp]
forall a. a -> [a] -> [a]
: [Exp]
exps) [Exp]
rest
  go [Text]
pieces [Exp]
exps [Exp]
rest = ([Text] -> Text
T.concat ([Text] -> [Text]
forall a. [a] -> [a]
reverse [Text]
pieces), [Exp] -> [Exp]
forall a. [a] -> [a]
reverse [Exp]
exps, [Exp]
rest)

asciiIdentifierWord :: Exp -> Maybe T.Text
asciiIdentifierWord :: Exp -> Maybe Text
asciiIdentifierWord Exp
e =
  case Exp
e of
    EIdentifier Text
t
      | Bool -> Bool
not (Text -> Bool
T.null Text
t) Bool -> Bool -> Bool
&& (Char -> Bool) -> Text -> Bool
T.all Char -> Bool
isAsciiAlpha Text
t -> Text -> Maybe Text
forall a. a -> Maybe a
Just Text
t
    Exp
_ -> Maybe Text
forall a. Maybe a
Nothing

renderTextNormalExp :: DisplayType -> Exp -> Maybe T.Text
renderTextNormalExp :: DisplayType -> Exp -> Maybe Text
renderTextNormalExp DisplayType
dt Exp
e =
  case Exp
e of
    ENumber Text
t       -> Text -> Maybe Text
forall a. a -> Maybe a
Just Text
t
    EIdentifier Text
t   -> Text -> Maybe Text
forall a. a -> Maybe a
Just (Text -> Text
renderIdentifier Text
t)
    EText TextType
sty Text
t     -> Text -> Maybe Text
forall a. a -> Maybe a
Just (TextType -> Text -> Text
renderTextAtom TextType
sty Text
t)
    ESpace Rational
w        -> Text -> Maybe Text
forall a. a -> Maybe a
Just (Rational -> Text
renderSpace Rational
w)
    EGrouped [Exp]
xs     -> DisplayType -> [Exp] -> Maybe Text
renderTextNormalStyled DisplayType
dt [Exp]
xs
    EStyled TextType
TextNormal [Exp]
xs -> DisplayType -> [Exp] -> Maybe Text
renderTextNormalStyled DisplayType
dt [Exp]
xs
    EStyled TextType
TextBold [Exp]
xs -> do
      Text
body <- DisplayType -> AlignContext -> [Exp] -> Maybe Text
renderExpsIn DisplayType
dt AlignContext
AlignDefault [Exp]
xs
      Text -> Maybe Text
forall a. a -> Maybe a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Text -> Maybe Text) -> Text -> Maybe Text
forall a b. (a -> b) -> a -> b
$ Text
"bold nitalic " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> Text
styleArg Text
body
    EStyled TextType
sty [Exp]
xs  -> DisplayType -> AlignContext -> TextType -> [Exp] -> Maybe Text
renderStyled DisplayType
dt AlignContext
AlignDefault TextType
sty [Exp]
xs
    ESub Exp
base Exp
sub   -> do
      Text
base' <- DisplayType -> Exp -> Maybe Text
renderTextNormalExp DisplayType
dt Exp
base
      Text
sub'  <- DisplayType -> Exp -> Maybe Text
renderTextNormalExp DisplayType
dt Exp
sub
      Text -> Maybe Text
forall a. a -> Maybe a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Text -> Maybe Text) -> Text -> Maybe Text
forall a b. (a -> b) -> a -> b
$ Text
base' Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"_" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
sub'
    ESuper Exp
base Exp
sup -> do
      Text
base' <- DisplayType -> Exp -> Maybe Text
renderTextNormalExp DisplayType
dt Exp
base
      Text
sup'  <- DisplayType -> Exp -> Maybe Text
renderTextNormalExp DisplayType
dt Exp
sup
      Text -> Maybe Text
forall a. a -> Maybe a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Text -> Maybe Text) -> Text -> Maybe Text
forall a b. (a -> b) -> a -> b
$ Text
base' Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"^" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
sup'
    ESubsup Exp
base Exp
sub Exp
sup -> do
      Text
base' <- DisplayType -> Exp -> Maybe Text
renderTextNormalExp DisplayType
dt Exp
base
      Text
sub'  <- DisplayType -> Exp -> Maybe Text
renderTextNormalExp DisplayType
dt Exp
sub
      Text
sup'  <- DisplayType -> Exp -> Maybe Text
renderTextNormalExp DisplayType
dt Exp
sup
      Text -> Maybe Text
forall a. a -> Maybe a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Text -> Maybe Text) -> Text -> Maybe Text
forall a b. (a -> b) -> a -> b
$ Text
base' Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"_" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
sub' Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"^" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
sup'
    ESymbol TeXSymbolType
t Text
s     -> Text -> Maybe Text
forall a. a -> Maybe a
Just (Text -> Text
T.strip (TeXSymbolType -> Text -> Text
renderSymbol TeXSymbolType
t Text
s))
    Exp
_               -> Maybe Text
forall a. Maybe a
Nothing

shouldForceUprightTextNormal :: [Exp] -> Bool
shouldForceUprightTextNormal :: [Exp] -> Bool
shouldForceUprightTextNormal = (Exp -> Bool) -> [Exp] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all Exp -> Bool
isUprightTextNormalExp

shouldForceUprightBold :: [Exp] -> Bool
shouldForceUprightBold :: [Exp] -> Bool
shouldForceUprightBold = (Exp -> Bool) -> [Exp] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all Exp -> Bool
isUprightBoldExp

isUprightBoldExp :: Exp -> Bool
isUprightBoldExp :: Exp -> Bool
isUprightBoldExp Exp
e =
  case Exp
e of
    ENumber{}            -> Bool
True
    EIdentifier Text
t        -> (Char -> Bool) -> Text -> Bool
T.all Char -> Bool
isAsciiAlphaNum Text
t
    EText{}              -> Bool
True
    ESpace{}             -> Bool
True
    ESymbol TeXSymbolType
_ Text
s          -> Text -> Bool
isPlainTextSymbol Text
s
    EGrouped [Exp]
xs          -> [Exp] -> Bool
shouldForceUprightBold [Exp]
xs
    EStyled TextType
TextNormal [Exp]
xs -> [Exp] -> Bool
shouldForceUprightBold [Exp]
xs
    ESub Exp
base Exp
sub        -> Exp -> Bool
isUprightBoldExp Exp
base Bool -> Bool -> Bool
&& Exp -> Bool
isUprightBoldExp Exp
sub
    ESuper Exp
base Exp
sup      -> Exp -> Bool
isUprightBoldExp Exp
base Bool -> Bool -> Bool
&& Exp -> Bool
isUprightBoldExp Exp
sup
    ESubsup Exp
base Exp
sub Exp
sup -> Exp -> Bool
isUprightBoldExp Exp
base
                         Bool -> Bool -> Bool
&& Exp -> Bool
isUprightBoldExp Exp
sub
                         Bool -> Bool -> Bool
&& Exp -> Bool
isUprightBoldExp Exp
sup
    Exp
_                    -> Bool
False

isUprightTextNormalExp :: Exp -> Bool
isUprightTextNormalExp :: Exp -> Bool
isUprightTextNormalExp Exp
e =
  case Exp
e of
    ENumber{}              -> Bool
True
    EIdentifier{}          -> Bool
True
    EText{}                -> Bool
True
    ESpace{}               -> Bool
True
    ESymbol TeXSymbolType
_ Text
s            -> Text -> Bool
isPlainTextSymbol Text
s
    EGrouped [Exp]
xs            -> [Exp] -> Bool
shouldForceUprightTextNormal [Exp]
xs
    EStyled TextType
TextNormal [Exp]
xs  -> [Exp] -> Bool
shouldForceUprightTextNormal [Exp]
xs
    ESub Exp
base Exp
sub          -> Exp -> Bool
isUprightTextNormalExp Exp
base Bool -> Bool -> Bool
&& Exp -> Bool
isUprightTextNormalExp Exp
sub
    ESuper Exp
base Exp
sup        -> Exp -> Bool
isUprightTextNormalExp Exp
base Bool -> Bool -> Bool
&& Exp -> Bool
isUprightTextNormalExp Exp
sup
    ESubsup Exp
base Exp
sub Exp
sup   -> Exp -> Bool
isUprightTextNormalExp Exp
base
                           Bool -> Bool -> Bool
&& Exp -> Bool
isUprightTextNormalExp Exp
sub
                           Bool -> Bool -> Bool
&& Exp -> Bool
isUprightTextNormalExp Exp
sup
    Exp
_                      -> Bool
False

isAsciiAlpha :: Char -> Bool
isAsciiAlpha :: Char -> Bool
isAsciiAlpha Char
c =
  (Char
c Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
>= Char
'A' Bool -> Bool -> Bool
&& Char
c Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
<= Char
'Z') Bool -> Bool -> Bool
||
  (Char
c Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
>= Char
'a' Bool -> Bool -> Bool
&& Char
c Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
<= Char
'z')

isAsciiAlphaNum :: Char -> Bool
isAsciiAlphaNum :: Char -> Bool
isAsciiAlphaNum Char
c =
  Char -> Bool
isAsciiAlpha Char
c Bool -> Bool -> Bool
||
  (Char
c Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
>= Char
'0' Bool -> Bool -> Bool
&& Char
c Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
<= Char
'9')

styleArg :: T.Text -> T.Text
styleArg :: Text -> Text
styleArg Text
t
  | Text -> Bool
T.null Text
t        = Text
"{}"
  | Text -> Int
T.length Text
t Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
1 = Text
t
  | Bool
otherwise       = Text
"{" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
t Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"}"

singleUprightIdentifier :: [Exp] -> Maybe T.Text
singleUprightIdentifier :: [Exp] -> Maybe Text
singleUprightIdentifier [Exp]
xs =
  case [Exp]
xs of
    [EIdentifier Text
t] -> Text -> Maybe Text
forall a. a -> Maybe a
Just Text
t
    [Exp]
_               -> Maybe Text
forall a. Maybe a
Nothing

alignmentContext :: Alignment -> AlignContext
alignmentContext :: Alignment -> AlignContext
alignmentContext Alignment
a =
  case Alignment
a of
    Alignment
AlignLeft  -> AlignContext
AlignLeftCtx
    Alignment
AlignRight -> AlignContext
AlignRightCtx
    Alignment
_          -> AlignContext
AlignDefault

maybeCenterFractionArg :: AlignContext -> T.Text -> T.Text
maybeCenterFractionArg :: AlignContext -> Text -> Text
maybeCenterFractionArg AlignContext
ctx Text
t
  | AlignContext
ctx AlignContext -> AlignContext -> Bool
forall a. Eq a => a -> a -> Bool
== AlignContext
AlignLeftCtx Bool -> Bool -> Bool
|| AlignContext
ctx AlignContext -> AlignContext -> Bool
forall a. Eq a => a -> a -> Bool
== AlignContext
AlignRightCtx = Text
"{alignc " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> Text
asArg Text
t Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"}"
  | Bool
otherwise = Text
t
 where
  asArg :: Text -> Text
asArg Text
x =
    let s :: Text
s = Text -> Text
T.strip Text
x
    in if Text -> Bool
T.null Text
s
          then Text
"{}"
          else if Text -> Int
T.length Text
s Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
1
                  then Text
s
          else if HasCallStack => Text -> Char
Text -> Char
T.head Text
s Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'{' Bool -> Bool -> Bool
&& HasCallStack => Text -> Char
Text -> Char
T.last Text
s Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'}'
                          then Text
s
                          else Text
"{" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
s Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"}"

asDelimitedArg :: T.Text -> T.Text
asDelimitedArg :: Text -> Text
asDelimitedArg Text
t =
  let s :: Text
s = Text -> Text
T.strip Text
t
  in if Text -> Bool
T.null Text
s
        then Text
"{}"
        else if HasCallStack => Text -> Char
Text -> Char
T.head Text
s Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'{' Bool -> Bool -> Bool
&& HasCallStack => Text -> Char
Text -> Char
T.last Text
s Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'}'
                then Text
s
                else Text
"{" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
s Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"}"

renderInlineFraction :: T.Text -> T.Text -> T.Text
renderInlineFraction :: Text -> Text -> Text
renderInlineFraction Text
num Text
den =
  Text
"size*0.7 {" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
num Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" over " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
den Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"}"

renderSpace :: Rational -> T.Text
renderSpace :: Rational -> Text
renderSpace Rational
w
  | Rational
w Rational -> Rational -> Bool
forall a. Ord a => a -> a -> Bool
<= Rational
0    = Text
""
  | Rational
w Rational -> Rational -> Bool
forall a. Ord a => a -> a -> Bool
>= Rational
2    = Text
"~~ "
  | Rational
w Rational -> Rational -> Bool
forall a. Ord a => a -> a -> Bool
>= Rational
1    = Text
"~ "
  | Bool
otherwise = Text
" "

renderIdentifier :: T.Text -> T.Text
renderIdentifier :: Text -> Text
renderIdentifier Text
ident =
  case Text -> Maybe Text
greekName Text
ident of
    Just Text
name
      | Text -> Bool
shouldItalicizeGreek Text
ident -> Text
"%i" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
name
      | Bool
otherwise                  -> Text
"%" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
name
    Maybe Text
Nothing -> Text
ident

renderTextNormalIdentifier :: T.Text -> T.Text
renderTextNormalIdentifier :: Text -> Text
renderTextNormalIdentifier Text
ident =
  case Text -> Maybe Text
greekName Text
ident of
    Just{}  -> Text -> Text
renderIdentifier Text
ident
    Maybe Text
Nothing
      | Text -> Bool
isStarMathReservedWord Text
ident -> Text -> Text
quoteText Text
ident
      | Bool
otherwise                    -> Text
ident

isStarMathReservedWord :: T.Text -> Bool
isStarMathReservedWord :: Text -> Bool
isStarMathReservedWord Text
t =
  Text
t Text -> [Text] -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem`
    [ Text
"alignc", Text
"alignl", Text
"alignr"
    , Text
"and", Text
"approx"
    , Text
"bar", Text
"binom", Text
"bold", Text
"breve"
    , Text
"cdot", Text
"check", Text
"circ", Text
"cos", Text
"cosh", Text
"cot", Text
"csub", Text
"csup"
    , Text
"dlarrow", Text
"dlrarrow", Text
"dot", Text
"dotsaxis", Text
"dotsdown", Text
"dotslow"
    , Text
"dotsup", Text
"dotsvert", Text
"downarrow", Text
"drarrow"
    , Text
"emptyset", Text
"equiv", Text
"exists", Text
"exp"
    , Text
"fixed", Text
"font", Text
"forall", Text
"from", Text
"func"
    , Text
"gg"
    , Text
"hat"
    , Text
"in", Text
"infinity", Text
"int", Text
"intersection", Text
"ital", Text
"iiint"
    , Text
"langle", Text
"lbrace", Text
"lceil", Text
"ldbracket", Text
"ldline", Text
"left"
    , Text
"leftarrow", Text
"leftrightarrow", Text
"lfloor", Text
"lim", Text
"liminf"
    , Text
"limsup", Text
"ll", Text
"lline", Text
"ln", Text
"log"
    , Text
"mapsto", Text
"matrix", Text
"max", Text
"min", Text
"minusplus", Text
"mline"
    , Text
"nabla", Text
"neg", Text
"none", Text
"notin", Text
"nitalic", Text
"nroot"
    , Text
"or", Text
"ortho", Text
"over", Text
"overbrace", Text
"overline", Text
"owns"
    , Text
"parallel", Text
"phantom", Text
"plusminus", Text
"partial", Text
"prod", Text
"prop"
    , Text
"rangle", Text
"rbrace", Text
"rceil", Text
"rdbracket", Text
"rdline", Text
"rfloor"
    , Text
"right", Text
"rline"
    , Text
"sans", Text
"sin", Text
"sinh", Text
"sqrt", Text
"subset", Text
"subseteq", Text
"sum"
    , Text
"supset", Text
"supseteq"
    , Text
"tilde", Text
"times", Text
"to", Text
"toward"
    , Text
"underbrace", Text
"underline", Text
"union", Text
"uparrow"
    , Text
"vec"
    ]

renderMathOperator :: T.Text -> T.Text
renderMathOperator :: Text -> Text
renderMathOperator Text
t
  | Text
t Text -> Text -> Bool
forall a. Eq a => a -> a -> Bool
== Text
"min" = Text
"func min"
  | Text
t Text -> Text -> Bool
forall a. Eq a => a -> a -> Bool
== Text
"max" = Text
"func max"
  | Text -> Bool
isBareMathOperator Text
t = Text
t
  | Text -> Bool
shouldQuoteMathOperator Text
t = Text
"func " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> Text
quoteText Text
t
  | Bool
otherwise                 = Text
"func " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
t

isBareMathOperator :: T.Text -> Bool
isBareMathOperator :: Text -> Bool
isBareMathOperator Text
t =
  Text
t Text -> [Text] -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem`
    [ Text
"min", Text
"max", Text
"log", Text
"sin", Text
"cos", Text
"cosh", Text
"sinh"
    , Text
"cot", Text
"ln", Text
"exp"
    ]

shouldQuoteMathOperator :: T.Text -> Bool
shouldQuoteMathOperator :: Text -> Bool
shouldQuoteMathOperator = Bool -> Bool
not (Bool -> Bool) -> (Text -> Bool) -> Text -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Char -> Bool) -> Text -> Bool
T.all Char -> Bool
isLetter

shouldItalicizeGreek :: T.Text -> Bool
shouldItalicizeGreek :: Text -> Bool
shouldItalicizeGreek Text
ident =
  case Text
ident of
    Text
"α" -> Bool
True
    Text
"β" -> Bool
True
    Text
"γ" -> Bool
True
    Text
"δ" -> Bool
True
    Text
"ϵ" -> Bool
True
    Text
"ε" -> Bool
True
    Text
"ζ" -> Bool
True
    Text
"η" -> Bool
True
    Text
"θ" -> Bool
True
    Text
"ϑ" -> Bool
True
    Text
"ι" -> Bool
True
    Text
"κ" -> Bool
True
    Text
"λ" -> Bool
True
    Text
"μ" -> Bool
True
    Text
"ν" -> Bool
True
    Text
"ξ" -> Bool
True
    Text
"ο" -> Bool
True
    Text
"π" -> Bool
True
    Text
"ϖ" -> Bool
True
    Text
"ρ" -> Bool
True
    Text
"ϱ" -> Bool
True
    Text
"𝜚" -> Bool
True
    Text
"σ" -> Bool
True
    Text
"ς" -> Bool
True
    Text
"𝜍" -> Bool
True
    Text
"τ" -> Bool
True
    Text
"υ" -> Bool
True
    Text
"ϕ" -> Bool
True
    Text
"φ" -> Bool
True
    Text
"χ" -> Bool
True
    Text
"ψ" -> Bool
True
    Text
"ω" -> Bool
True
    Text
_   -> Bool
False

greekName :: T.Text -> Maybe T.Text
greekName :: Text -> Maybe Text
greekName Text
ident =
  case Text
ident of
    Text
"α" -> Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"alpha"
    Text
"β" -> Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"beta"
    Text
"γ" -> Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"gamma"
    Text
"δ" -> Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"delta"
    Text
"ϵ" -> Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"epsilon"
    Text
"ε" -> Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"varepsilon"
    Text
"ζ" -> Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"zeta"
    Text
"η" -> Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"eta"
    Text
"θ" -> Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"theta"
    Text
"ϑ" -> Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"vartheta"
    Text
"ι" -> Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"iota"
    Text
"κ" -> Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"kappa"
    Text
"λ" -> Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"lambda"
    Text
"μ" -> Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"mu"
    Text
"ν" -> Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"nu"
    Text
"ξ" -> Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"xi"
    Text
"ο" -> Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"omicron"
    Text
"π" -> Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"pi"
    Text
"ϖ" -> Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"varpi"
    Text
"ρ" -> Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"rho"
    Text
"ϱ" -> Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"varrho"
    Text
"𝜚" -> Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"varrho"
    Text
"σ" -> Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"sigma"
    Text
"ς" -> Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"varsigma"
    Text
"𝜍" -> Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"varsigma"
    Text
"τ" -> Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"tau"
    Text
"υ" -> Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"upsilon"
    Text
"ϕ" -> Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"phi"
    Text
"φ" -> Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"varphi"
    Text
"χ" -> Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"chi"
    Text
"ψ" -> Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"psi"
    Text
"ω" -> Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"omega"
    Text
"Γ" -> Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"GAMMA"
    Text
"Δ" -> Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"DELTA"
    Text
"Θ" -> Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"THETA"
    Text
"Λ" -> Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"LAMBDA"
    Text
"Ξ" -> Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"XI"
    Text
"Π" -> Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"PI"
    Text
"Σ" -> Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"SIGMA"
    Text
"Υ" -> Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"UPSILON"
    Text
"Φ" -> Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"PHI"
    Text
"Ψ" -> Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"PSI"
    Text
"Ω" -> Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"OMEGA"
    Text
_   -> Maybe Text
forall a. Maybe a
Nothing

renderScriptBase :: Exp -> T.Text -> T.Text
renderScriptBase :: Exp -> Text -> Text
renderScriptBase Exp
e Text
rendered0 =
  let rendered :: Text
rendered = Text -> Text
T.strip Text
rendered0
  in if Exp -> Bool
isEmptyScriptBase Exp
e Bool -> Bool -> Bool
|| Text -> Bool
T.null Text
rendered
        then Text
"{}"
        else if Text -> Bool
isWrapped Text
rendered
        then Text
rendered
        else if Exp -> Bool
isAtomic Exp
e
        then Text
rendered
        else Text
"{" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
rendered Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"}"

renderScriptArg :: DisplayType -> AlignContext -> Exp -> Maybe T.Text
renderScriptArg :: DisplayType -> AlignContext -> Exp -> Maybe Text
renderScriptArg DisplayType
dt AlignContext
ctx Exp
e = do
  Text
rendered0 <-
    if Exp -> Bool
needsNeutralScriptOperands Exp
e
       then DisplayType -> AlignContext -> [Exp] -> Maybe Text
renderExpsIn DisplayType
dt AlignContext
ctx [Exp
e]
       else DisplayType -> AlignContext -> Exp -> Maybe Text
renderExpIn DisplayType
dt AlignContext
ctx Exp
e
  let rendered :: Text
rendered = Text -> Text
T.strip Text
rendered0
  Text -> Maybe Text
forall a. a -> Maybe a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Text -> Maybe Text) -> Text -> Maybe Text
forall a b. (a -> b) -> a -> b
$ if (Exp -> Bool
isAtomic Exp
e Bool -> Bool -> Bool
&& Bool -> Bool
not (Exp -> Bool
needsNeutralScriptOperands Exp
e)) Bool -> Bool -> Bool
|| Text -> Bool
isQuotedText Text
rendered
            then Text
rendered
            else Text
"{" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
rendered Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"}"

renderPrimeSuffix :: Exp -> Maybe T.Text
renderPrimeSuffix :: Exp -> Maybe Text
renderPrimeSuffix Exp
e =
  case Exp
e of
    ESymbol TeXSymbolType
Pun Text
"'"  -> Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"'"
    ESymbol TeXSymbolType
Pun Text
"′"  -> Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"'"
    ESymbol TeXSymbolType
Pun Text
"″"  -> Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"''"
    ESymbol TeXSymbolType
Pun Text
"‴"  -> Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"'''"
    Exp
_                -> Maybe Text
forall a. Maybe a
Nothing

renderLimitArg :: DisplayType -> AlignContext -> Exp -> Maybe T.Text
renderLimitArg :: DisplayType -> AlignContext -> Exp -> Maybe Text
renderLimitArg DisplayType
dt AlignContext
ctx Exp
e =
  case Exp
e of
    EGrouped [Exp]
xs -> do
      Text
rendered <- DisplayType -> AlignContext -> [Exp] -> Maybe Text
renderExpsIn DisplayType
dt AlignContext
ctx [Exp]
xs
      let stripped :: Text
stripped = Text -> Text
T.strip Text
rendered
      Text -> Maybe Text
forall a. a -> Maybe a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Text -> Maybe Text) -> Text -> Maybe Text
forall a b. (a -> b) -> a -> b
$
        if Text -> Bool
T.null Text
stripped
           then Text
"{}"
           else if [Exp] -> Bool
containsRelationLike [Exp]
xs
                   then Text
stripped
           else if Text -> Bool
isQuotedText Text
stripped Bool -> Bool -> Bool
|| Text -> Bool
isWrapped Text
stripped Bool -> Bool -> Bool
|| Text -> Int
T.length Text
stripped Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
1
                   then Text
stripped
                   else Text
"{" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
stripped Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"}"
    Exp
_           -> Text -> Text
T.strip (Text -> Text) -> Maybe Text -> Maybe Text
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> DisplayType -> AlignContext -> Exp -> Maybe Text
renderExpIn DisplayType
dt AlignContext
ctx Exp
e

containsRelationLike :: [Exp] -> Bool
containsRelationLike :: [Exp] -> Bool
containsRelationLike = (Exp -> Bool) -> [Exp] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any Exp -> Bool
isRelationLike
 where
  isRelationLike :: Exp -> Bool
isRelationLike Exp
expn =
    case Exp
expn of
      ESymbol TeXSymbolType
Rel Text
_ -> Bool
True
      ESymbol TeXSymbolType
Bin Text
_ -> Bool
True
      EGrouped [Exp]
ys   -> [Exp] -> Bool
containsRelationLike [Exp]
ys
      Exp
_             -> Bool
False

renderAccentArg :: Exp -> T.Text -> T.Text
renderAccentArg :: Exp -> Text -> Text
renderAccentArg Exp
e Text
rendered0 =
  let rendered :: Text
rendered = Text -> Text
T.strip Text
rendered0
  in if Exp -> Bool
isAtomic Exp
e
        then Text
rendered
        else Text
"{" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
rendered Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"}"

renderPhantomArg :: Exp -> T.Text -> T.Text
renderPhantomArg :: Exp -> Text -> Text
renderPhantomArg Exp
e Text
rendered0 =
  let rendered :: Text
rendered = Text -> Text
T.strip Text
rendered0
  in if Exp -> Bool
isAtomic Exp
e
        then Text
rendered
        else if Text -> Bool
isWrapped Text
rendered
        then Text
rendered
        else Text
"{" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
rendered Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"}"

centerScriptArg :: T.Text -> T.Text
centerScriptArg :: Text -> Text
centerScriptArg Text
rendered
  | Text -> Bool
isWrapped Text
rendered = Text
rendered
  | Bool
otherwise          = Text
"{" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
rendered Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"}"

isWrapped :: T.Text -> Bool
isWrapped :: Text -> Bool
isWrapped Text
t = Text -> Int
T.length Text
t Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
2 Bool -> Bool -> Bool
&& HasCallStack => Text -> Char
Text -> Char
T.head Text
t Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'{' Bool -> Bool -> Bool
&& HasCallStack => Text -> Char
Text -> Char
T.last Text
t Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'}'

isAtomic :: Exp -> Bool
isAtomic :: Exp -> Bool
isAtomic Exp
e =
  case Exp
e of
    ENumber{}       -> Bool
True
    EIdentifier{}   -> Bool
True
    EMathOperator{} -> Bool
True
    EText{}         -> Bool
True
    ESymbol{}       -> Bool
True
    Exp
_               -> Bool
False

isEmptyScriptBase :: Exp -> Bool
isEmptyScriptBase :: Exp -> Bool
isEmptyScriptBase Exp
e =
  case Exp
e of
    EIdentifier Text
t -> Text -> Bool
T.null Text
t
    Exp
_             -> Bool
False

isEmptyScriptArg :: Exp -> Bool
isEmptyScriptArg :: Exp -> Bool
isEmptyScriptArg Exp
e =
  case Exp
e of
    EGrouped []   -> Bool
True
    EIdentifier Text
t -> Text -> Bool
T.null Text
t
    Exp
_             -> Bool
False

isBraceAnnotatedExp :: Exp -> Bool
isBraceAnnotatedExp :: Exp -> Bool
isBraceAnnotatedExp Exp
e =
  case Exp
e of
    EOver Bool
_ Exp
_ Exp
over  -> Exp -> Maybe Text
braceAnnotationName Exp
over Maybe Text -> Maybe Text -> Bool
forall a. Eq a => a -> a -> Bool
/= Maybe Text
forall a. Maybe a
Nothing
    EUnder Bool
_ Exp
_ Exp
under -> Exp -> Maybe Text
braceAnnotationName Exp
under Maybe Text -> Maybe Text -> Bool
forall a. Eq a => a -> a -> Bool
/= Maybe Text
forall a. Maybe a
Nothing
    Exp
_               -> Bool
False

braceAnnotationName :: Exp -> Maybe T.Text
braceAnnotationName :: Exp -> Maybe Text
braceAnnotationName Exp
e =
  case Exp
e of
    ESymbol TeXSymbolType
TOver Text
"\9182"  -> Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"overbrace"
    ESymbol TeXSymbolType
TOver Text
"\9140"  -> Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"overbrace"
    ESymbol TeXSymbolType
TUnder Text
"\9183" -> Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"underbrace"
    ESymbol TeXSymbolType
TUnder Text
"\9141" -> Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"underbrace"
    Exp
_                       -> Maybe Text
forall a. Maybe a
Nothing

underlineMarkerName :: Exp -> Maybe T.Text
underlineMarkerName :: Exp -> Maybe Text
underlineMarkerName Exp
e =
  case Exp
e of
    ESymbol TeXSymbolType
TUnder Text
"_" -> Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"underline"
    Exp
_                  -> Maybe Text
forall a. Maybe a
Nothing

renderBraceLabel :: DisplayType -> AlignContext -> Exp -> Maybe T.Text
renderBraceLabel :: DisplayType -> AlignContext -> Exp -> Maybe Text
renderBraceLabel DisplayType
dt AlignContext
ctx Exp
e = do
  Text
rendered0 <- DisplayType -> AlignContext -> Exp -> Maybe Text
renderExpIn DisplayType
dt AlignContext
ctx Exp
e
  let rendered :: Text
rendered = Text -> Text
T.strip Text
rendered0
  Text -> Maybe Text
forall a. a -> Maybe a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Text -> Maybe Text) -> Text -> Maybe Text
forall a b. (a -> b) -> a -> b
$ if Text -> Bool
isQuotedText Text
rendered Bool -> Bool -> Bool
|| Exp -> Bool
isAtomic Exp
e
            then Text
rendered
            else Text
"{" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
rendered Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"}"

arrowScriptOpName :: Exp -> Maybe T.Text
arrowScriptOpName :: Exp -> Maybe Text
arrowScriptOpName Exp
e =
  case Exp
e of
    ESymbol TeXSymbolType
_ Text
"←" -> Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"leftarrow"
    ESymbol TeXSymbolType
_ Text
"→" -> Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"toward"
    ESymbol TeXSymbolType
_ Text
"↔" -> Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"leftrightarrow"
    ESymbol TeXSymbolType
_ Text
"⇐" -> Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"dlarrow"
    ESymbol TeXSymbolType
_ Text
"⇒" -> Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"drarrow"
    ESymbol TeXSymbolType
_ Text
"⇔" -> Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"dlrarrow"
    ESymbol TeXSymbolType
_ Text
"↦" -> Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"mapsto"
    ESymbol TeXSymbolType
_ Text
"↑" -> Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"uparrow"
    ESymbol TeXSymbolType
_ Text
"↓" -> Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"downarrow"
    Exp
_             -> Maybe Text
forall a. Maybe a
Nothing

accentName :: Exp -> Maybe T.Text
accentName :: Exp -> Maybe Text
accentName Exp
e =
  case Exp
e of
    ESymbol TeXSymbolType
Accent Text
s -> Text -> Maybe Text
accentFromChar Text
s
    ESymbol TeXSymbolType
TOver Text
s  -> Text -> Maybe Text
overAccentFromChar Text
s
    ESymbol TeXSymbolType
_ Text
s      -> Text -> Maybe Text
accentFromChar Text
s
    Exp
_                -> Maybe Text
forall a. Maybe a
Nothing

overAccentFromChar :: T.Text -> Maybe T.Text
overAccentFromChar :: Text -> Maybe Text
overAccentFromChar Text
s =
  case Text
s of
    Text
"\772"  -> Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"overline"
    Text
"\8254" -> Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"overline"
    Text
"¯"     -> Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"overline"
    Text
_       -> Text -> Maybe Text
accentFromChar Text
s

accentFromChar :: T.Text -> Maybe T.Text
accentFromChar :: Text -> Maybe Text
accentFromChar Text
s =
  case Text
s of
    Text
"\775"  -> Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"dot"
    Text
"˙"     -> Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"dot"
    Text
"\776"  -> Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"ddot"
    Text
"¨"     -> Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"ddot"
    Text
"\770"  -> Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"hat"
    Text
"ˆ"     -> Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"hat"
    Text
"\780"  -> Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"check"
    Text
"ˇ"     -> Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"check"
    Text
"\771"  -> Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"tilde"
    Text
"˜"     -> Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"tilde"
    Text
"\772"  -> Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"bar"
    Text
"\8254" -> Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"bar"
    Text
"¯"     -> Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"bar"
    Text
"\8407" -> Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"vec"
    Text
"→"     -> Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"vec"
    Text
"\774"  -> Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"breve"
    Text
"˘"     -> Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"breve"
    Text
_       -> Maybe Text
forall a. Maybe a
Nothing

data DelimSide = DelimLeft | DelimRight | DelimMiddle

delimToken :: DelimSide -> T.Text -> T.Text
delimToken :: DelimSide -> Text -> Text
delimToken DelimSide
side Text
raw =
  case Text
raw of
    Text
""  -> Text
"none"
    Text
"." -> Text
"none"
    Text
"(" -> Text
"("
    Text
")" -> Text
")"
    Text
"[" -> Text
"["
    Text
"]" -> Text
"]"
    Text
"{" -> case DelimSide
side of
      DelimSide
DelimLeft   -> Text
"lbrace"
      DelimSide
DelimRight  -> Text
"rbrace"
      DelimSide
DelimMiddle -> Text
"{"
    Text
"}" -> case DelimSide
side of
      DelimSide
DelimLeft   -> Text
"lbrace"
      DelimSide
DelimRight  -> Text
"rbrace"
      DelimSide
DelimMiddle -> Text
"}"
    Text
"|" -> case DelimSide
side of
      DelimSide
DelimLeft   -> Text
"lline"
      DelimSide
DelimRight  -> Text
"rline"
      DelimSide
DelimMiddle -> Text
"mline"
    Text
"∣" -> case DelimSide
side of
      DelimSide
DelimLeft   -> Text
"lline"
      DelimSide
DelimRight  -> Text
"rline"
      DelimSide
DelimMiddle -> Text
"mline"
    Text
"∥" -> case DelimSide
side of
      DelimSide
DelimLeft   -> Text
"ldline"
      DelimSide
DelimRight  -> Text
"rdline"
      DelimSide
DelimMiddle -> Text
"mline"
    Text
"⟨" -> Text
"langle"
    Text
"⟩" -> Text
"rangle"
    Text
"⌊" -> Text
"lfloor"
    Text
"⌋" -> Text
"rfloor"
    Text
"⌈" -> Text
"lceil"
    Text
"⌉" -> Text
"rceil"
    Text
"⟦" -> Text
"ldbracket"
    Text
"⟧" -> Text
"rdbracket"
    Text
_   -> Text
raw

renderSymbol :: TeXSymbolType -> T.Text -> T.Text
renderSymbol :: TeXSymbolType -> Text -> Text
renderSymbol TeXSymbolType
t Text
s =
  case Text
s of
    Text
"∫" -> Text
"int "
    Text
"∑" -> Text
"sum "
    Text
"←" -> Text
" leftarrow "
    Text
"→" -> Text
" toward "
    Text
"↔" -> Text
" leftrightarrow "
    Text
"⇐" -> Text
" dlarrow "
    Text
"⇒" -> Text
" drarrow "
    Text
"⇔" -> Text
" dlrarrow "
    Text
"↑" -> Text
" uparrow "
    Text
"↓" -> Text
" downarrow "
    Text
"↦" -> Text
" mapsto "
    Text
"\8230 " -> Text
" dotslow "
    Text
"… " -> Text
" dotslow "
    Text
"\8230" -> Text
" dotslow "
    Text
"…" -> Text
" dotslow "
    Text
"\8943" -> Text
" dotsaxis "
    Text
"⋯" -> Text
" dotsaxis "
    Text
"⋮" -> Text
" dotsvert "
    Text
"⋱" -> Text
" dotsdown "
    Text
"⋰" -> Text
" dotsup "
    Text
"∈" -> Text
" in "
    Text
"∉" -> Text
" notin "
    Text
"∋" -> Text
" owns "
    Text
"∩" -> Text
" intersection "
    Text
"∪" -> Text
" union "
    Text
"⊂" -> Text
" subset "
    Text
"⊆" -> Text
" subseteq "
    Text
"⊃" -> Text
" supset "
    Text
"⊇" -> Text
" supseteq "
    Text
"≤" -> Text
" <= "
    Text
"≥" -> Text
" >= "
    Text
"≠" -> Text
" <> "
    Text
"≈" -> Text
" approx "
    Text
"≡" -> Text
" equiv "
    Text
"\8810" -> Text
" ll "
    Text
"≪" -> Text
" ll "
    Text
"\8811" -> Text
" gg "
    Text
"≫" -> Text
" gg "
    Text
"∝" -> Text
" prop "
    Text
"∥" -> Text
" parallel "
    Text
"⊥" -> Text
" ortho "
    Text
"±" -> Text
" plusminus "
    Text
"∓" -> Text
" minusplus "
    Text
"×" -> Text
" times "
    Text
"⋅" -> Text
" cdot "
    Text
"·" -> Text
" cdot "
    Text
"∘" -> Text
" circ "
    Text
"/" -> Text
" / "
    Text
"∂" -> Text
"partial"
    Text
"∇" -> Text
"nabla"
    Text
"∀" -> Text
"forall"
    Text
"∃" -> Text
"exists"
    Text
"¬" -> Text
"neg"
    Text
"∧" -> Text
"and"
    Text
"∨" -> Text
"or"
    Text
"∞" -> Text
"infinity"
    Text
"∅" -> Text
"emptyset"
    Text
"+" -> Text
" + "
    Text
"-" | TeXSymbolType
t TeXSymbolType -> TeXSymbolType -> Bool
forall a. Eq a => a -> a -> Bool
== TeXSymbolType
Bin  -> Text
" - "
    Text
"-"             -> Text
"-"
    Text
"−" | TeXSymbolType
t TeXSymbolType -> TeXSymbolType -> Bool
forall a. Eq a => a -> a -> Bool
== TeXSymbolType
Bin  -> Text
" - "
    Text
"−"             -> Text
"-"
    Text
"<" -> Text
" < "
    Text
">" -> Text
" > "
    Text
"=" -> Text
" = "
    Text
"," -> Text
", "
    Text
";" -> Text
"; "
    Text
":" -> Text
" : "
    Text
"!" -> Text
" ! "
    Text
"'" -> Text
"'"
    Text
"′" -> Text
"'"
    Text
"″" -> Text
"''"
    Text
"‴" -> Text
"'''"
    Text
_   | Text -> Bool
isWordLiteralSymbol Text
s -> Text -> Text
quoteText Text
s
        | Bool
otherwise             -> Text
s

isWordLiteralSymbol :: T.Text -> Bool
isWordLiteralSymbol :: Text -> Bool
isWordLiteralSymbol Text
s =
  Bool -> Bool
not (Text -> Bool
T.null Text
s) Bool -> Bool -> Bool
&& (Char -> Bool) -> Text -> Bool
T.all Char -> Bool
isWordLiteralChar Text
s

isWordLiteralChar :: Char -> Bool
isWordLiteralChar :: Char -> Bool
isWordLiteralChar Char
c =
  (Char
c Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
>= Char
'A' Bool -> Bool -> Bool
&& Char
c Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
<= Char
'Z') Bool -> Bool -> Bool
||
  (Char
c Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
>= Char
'a' Bool -> Bool -> Bool
&& Char
c Char -> Char -> Bool
forall a. Ord a => a -> a -> Bool
<= Char
'z') Bool -> Bool -> Bool
||
  Char
c Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
' ' Bool -> Bool -> Bool
|| Char
c Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'-'

quoteText :: T.Text -> T.Text
quoteText :: Text -> Text
quoteText Text
t = Text
"\"" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> Text
escapeQuotes Text
t Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"\""

escapeQuotes :: T.Text -> T.Text
escapeQuotes :: Text -> Text
escapeQuotes = HasCallStack => Text -> Text -> Text -> Text
Text -> Text -> Text -> Text
T.replace Text
"\"" Text
"\\\""

isQuotedText :: T.Text -> Bool
isQuotedText :: Text -> Bool
isQuotedText Text
t =
  Text -> Int
T.length Text
t Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= Int
2 Bool -> Bool -> Bool
&& HasCallStack => Text -> Char
Text -> Char
T.head Text
t Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'"' Bool -> Bool -> Bool
&& HasCallStack => Text -> Char
Text -> Char
T.last Text
t Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'"'

largeOpName :: Exp -> Maybe T.Text
largeOpName :: Exp -> Maybe Text
largeOpName Exp
e =
  case Exp
e of
    ESymbol TeXSymbolType
Op Text
"\8747" -> Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"int"
    ESymbol TeXSymbolType
Op Text
"\8751" -> Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"iiint"
    ESymbol TeXSymbolType
Op Text
"\8721" -> Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"sum"
    ESymbol TeXSymbolType
Op Text
"\8719" -> Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"prod"
    ESymbol TeXSymbolType
Op Text
"\8899" -> Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"oper ∪"
    ESymbol TeXSymbolType
Op Text
"\8898" -> Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"oper ∩"
    ESymbol TeXSymbolType
Op Text
"∫"     -> Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"int"
    ESymbol TeXSymbolType
Op Text
"∭"     -> Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"iiint"
    ESymbol TeXSymbolType
Op Text
"∑"     -> Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"sum"
    ESymbol TeXSymbolType
Op Text
"∏"     -> Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"prod"
    ESymbol TeXSymbolType
Op Text
"⋃"     -> Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"oper ∪"
    ESymbol TeXSymbolType
Op Text
"⋂"     -> Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"oper ∩"
    Exp
_                  -> Maybe Text
forall a. Maybe a
Nothing

limitOpName :: Exp -> Maybe T.Text
limitOpName :: Exp -> Maybe Text
limitOpName Exp
e =
  case Exp -> Maybe Text
largeOpName Exp
e of
    Just Text
op -> Text -> Maybe Text
forall a. a -> Maybe a
Just Text
op
    Maybe Text
Nothing ->
      case Exp
e of
        EMathOperator Text
"lim"    -> Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"lim"
        EMathOperator Text
"liminf" -> Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"liminf"
        EMathOperator Text
"limsup" -> Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"limsup"
        EMathOperator Text
"min"    -> Maybe Text
forall a. Maybe a
Nothing
        EMathOperator Text
"max"    -> Maybe Text
forall a. Maybe a
Nothing
        Exp
_                      -> Maybe Text
forall a. Maybe a
Nothing

centeredScriptOpName :: Exp -> Maybe T.Text
centeredScriptOpName :: Exp -> Maybe Text
centeredScriptOpName Exp
e =
  case Exp
e of
    EMathOperator Text
"min" -> Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"func min"
    EMathOperator Text
"max" -> Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"func max"
    EMathOperator Text
"det" -> Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"func det"
    EMathOperator Text
"Pr"  -> Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"func Pr"
    EMathOperator Text
"gcd" -> Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"func gcd"
    EMathOperator Text
"lim" -> Maybe Text
forall a. Maybe a
Nothing
    EMathOperator Text
"liminf" -> Maybe Text
forall a. Maybe a
Nothing
    EMathOperator Text
"limsup" -> Maybe Text
forall a. Maybe a
Nothing
    EMathOperator Text
t     -> Text -> Maybe Text
forall a. a -> Maybe a
Just (Text -> Text
renderMathOperator Text
t)
    Exp
_                   -> Maybe Text
forall a. Maybe a
Nothing
renderTextAtom :: TextType -> T.Text -> T.Text
renderTextAtom :: TextType -> Text -> Text
renderTextAtom TextType
sty Text
t =
  case TextType
sty of
    TextType
TextItalic    -> Text
"ital " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> Text
styleArg Text
t
    TextType
TextBold      -> Text
"bold " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> Text
styleArg (Text -> Text
quoteText Text
t)
    TextType
TextMonospace -> Text
"font fixed " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> Text
quoteText Text
t
    TextType
TextSansSerif -> Text
"font sans " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> Text
quoteText Text
t
    TextType
_             -> Text -> Text
quoteText Text
t