module Text.TeXMath.TeX (TeX(..),
renderTeX,
isControlSeq,
escapeLaTeX)
where
import Data.List (isPrefixOf)
import Data.Char (isLetter, isAlphaNum)
data TeX = ControlSeq String
| Token Char
| Literal String
| Grouped [TeX]
| Space
deriving (Show, Eq)
renderTeX :: TeX -> String -> String
renderTeX (Token c) cs = c:cs
renderTeX (Literal s) cs
| startsWith (not . isLetter)
(reverse s) = s ++ cs
| startsWith isLetter cs = s ++ (' ':cs)
| otherwise = s ++ cs
renderTeX (ControlSeq s) cs
| s == "\\ " = s ++ cs
| startsWith isAlphaNum cs = s ++ (' ':cs)
| otherwise = s ++ cs
renderTeX (Grouped [Grouped xs]) cs = renderTeX (Grouped xs) cs
renderTeX (Grouped xs) cs =
'{' : foldr renderTeX "" (trimSpaces xs) ++ "}" ++ cs
renderTeX Space "" = ""
renderTeX Space ('^':cs) = '^':cs
renderTeX Space ('_':cs) = '_':cs
renderTeX Space (' ':cs) = ' ':cs
renderTeX Space cs
| "\\limits" `isPrefixOf` cs = cs
| otherwise = ' ':cs
trimSpaces :: [TeX] -> [TeX]
trimSpaces = reverse . go . reverse . go
where go = dropWhile (== Space)
startsWith :: (Char -> Bool) -> String -> Bool
startsWith p (c:_) = p c
startsWith _ [] = False
isControlSeq :: String -> Bool
isControlSeq ['\\',c] = c /= ' '
isControlSeq ('\\':xs) = all isLetter xs
isControlSeq _ = False
escapeLaTeX :: Char -> TeX
escapeLaTeX c
| c `elem` "#$%&_{} " = Literal ("\\" ++ [c])
| c == '~' = ControlSeq "\\textasciitilde"
| c == '^' = Literal "\\textasciicircum"
| c == '\\' = ControlSeq "\\textbackslash"
| otherwise = Token c