{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ViewPatterns #-}
{-
Copyright (C) 2012 John MacFarlane <jgm@berkeley.edu>

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-}

{- | Functions for writing a parsed formula as OMML.
-}

module Text.TeXMath.Writers.OMML (writeOMML)
where

import Text.XML.Light
import Text.TeXMath.Types
import Data.Generics (everywhere, mkT)
import Data.Char (isSymbol, isPunctuation)
import Data.Either (lefts, isLeft, rights)
import qualified Data.Text as T
import Data.List.Split  (splitWhen)

-- | Transforms an expression tree to an OMML XML Tree
writeOMML :: DisplayType -> [Exp] -> Element
writeOMML :: DisplayType -> [Exp] -> Element
writeOMML DisplayType
dt = [Element] -> Element
container ([Element] -> Element) -> ([Exp] -> [Element]) -> [Exp] -> Element
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Exp -> [Element]) -> [Exp] -> [Element]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap ([Element] -> Exp -> [Element]
showExp [])
            ([Exp] -> [Element]) -> ([Exp] -> [Exp]) -> [Exp] -> [Element]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (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]
handleDownup DisplayType
dt)
            ([Exp] -> [Exp]) -> ([Exp] -> [Exp]) -> [Exp] -> [Exp]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (forall a. Data a => a -> a) -> forall a. Data a => a -> a
everywhere (([InEDelimited] -> [InEDelimited]) -> a -> a
forall a b. (Typeable a, Typeable b) => (b -> b) -> a -> a
mkT (([InEDelimited] -> [InEDelimited]) -> a -> a)
-> ([InEDelimited] -> [InEDelimited]) -> a -> a
forall a b. (a -> b) -> a -> b
$ DisplayType -> [InEDelimited] -> [InEDelimited]
handleDownup' DisplayType
dt)
    where container :: [Element] -> Element
container = case DisplayType
dt of
                  DisplayType
DisplayBlock  -> \[Element]
x -> String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode String
"oMathPara"
                                    [ String -> Element -> Element
forall t. Node t => String -> t -> Element
mnode String
"oMathParaPr"
                                      (Element -> Element) -> Element -> Element
forall a b. (a -> b) -> a -> b
$ String -> String -> () -> Element
forall t. Node t => String -> String -> t -> Element
mnodeA String
"jc" String
"center" ()
                                    , String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode String
"oMath" [Element]
x ]
                  DisplayType
DisplayInline -> String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode String
"oMath"

-- Kept as String for Text.XML.Light
mnode :: Node t => String -> t -> Element
mnode :: String -> t -> Element
mnode String
s = QName -> t -> Element
forall t. Node t => QName -> t -> Element
node (String -> Maybe String -> Maybe String -> QName
QName String
s Maybe String
forall a. Maybe a
Nothing (String -> Maybe String
forall a. a -> Maybe a
Just String
"m"))

-- Kept as String for Text.XML.Light
mnodeA :: Node t => String -> String -> t -> Element
mnodeA :: String -> String -> t -> Element
mnodeA String
s String
v = Attr -> Element -> Element
add_attr (QName -> String -> Attr
Attr (String -> Maybe String -> Maybe String -> QName
QName String
"val" Maybe String
forall a. Maybe a
Nothing (String -> Maybe String
forall a. a -> Maybe a
Just String
"m")) String
v) (Element -> Element) -> (t -> Element) -> t -> Element
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> t -> Element
forall t. Node t => String -> t -> Element
mnode String
s

str :: [Element] -> T.Text -> Element
str :: [Element] -> Text -> Element
str []    Text
s = String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode String
"r" [ String -> String -> Element
forall t. Node t => String -> t -> Element
mnode String
"t" (String -> Element) -> String -> Element
forall a b. (a -> b) -> a -> b
$ Text -> String
T.unpack Text
s ]
str [Element]
props Text
s = String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode String
"r" [ String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode String
"rPr" [Element]
props
                        , String -> String -> Element
forall t. Node t => String -> t -> Element
mnode String
"t" (String -> Element) -> String -> Element
forall a b. (a -> b) -> a -> b
$ Text -> String
T.unpack Text
s ]

showFraction :: [Element] -> FractionType -> Exp -> Exp -> Element
showFraction :: [Element] -> FractionType -> Exp -> Exp -> Element
showFraction [Element]
props FractionType
ft Exp
x Exp
y =
  case FractionType
ft of
       FractionType
NormalFrac -> String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode String
"f" [ String -> Element -> Element
forall t. Node t => String -> t -> Element
mnode String
"fPr" (Element -> Element) -> Element -> Element
forall a b. (a -> b) -> a -> b
$
                                String -> String -> () -> Element
forall t. Node t => String -> String -> t -> Element
mnodeA String
"type" String
"bar" ()
                             , String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode String
"num" [Element]
x'
                             , String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode String
"den" [Element]
y']
       FractionType
DisplayFrac -> [Element] -> FractionType -> Exp -> Exp -> Element
showFraction [Element]
props FractionType
NormalFrac Exp
x Exp
y
       FractionType
InlineFrac -> String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode String
"f" [ String -> Element -> Element
forall t. Node t => String -> t -> Element
mnode String
"fPr" (Element -> Element) -> Element -> Element
forall a b. (a -> b) -> a -> b
$
                                 String -> String -> () -> Element
forall t. Node t => String -> String -> t -> Element
mnodeA String
"type" String
"lin" ()
                              , String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode String
"num" [Element]
x'
                              , String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode String
"den" [Element]
y']
       FractionType
NoLineFrac -> String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode String
"f" [ String -> Element -> Element
forall t. Node t => String -> t -> Element
mnode String
"fPr" (Element -> Element) -> Element -> Element
forall a b. (a -> b) -> a -> b
$
                                              String -> String -> () -> Element
forall t. Node t => String -> String -> t -> Element
mnodeA String
"type" String
"noBar" ()
                                             , String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode String
"num" [Element]
x'
                                             , String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode String
"den" [Element]
y'
                                             ]
    where x' :: [Element]
x' = [Element] -> Exp -> [Element]
showExp [Element]
props Exp
x
          y' :: [Element]
y' = [Element] -> Exp -> [Element]
showExp [Element]
props Exp
y

maximum' :: [Int] -> Int
maximum' :: [Int] -> Int
maximum' [] = Int
0
maximum' [Int]
xs = [Int] -> Int
forall (t :: * -> *) a. (Foldable t, Ord a) => t a -> a
maximum [Int]
xs

makeArray :: [Element] -> [Alignment] -> [ArrayLine] -> Element
makeArray :: [Element] -> [Alignment] -> [ArrayLine] -> Element
makeArray [Element]
props [Alignment]
as [ArrayLine]
rs = String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode String
"m" ([Element] -> Element) -> [Element] -> Element
forall a b. (a -> b) -> a -> b
$ Element
mProps Element -> [Element] -> [Element]
forall a. a -> [a] -> [a]
: (ArrayLine -> Element) -> [ArrayLine] -> [Element]
forall a b. (a -> b) -> [a] -> [b]
map ArrayLine -> Element
forall (t :: * -> *). Foldable t => [t Exp] -> Element
toMr [ArrayLine]
rs
  where mProps :: Element
mProps = String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode String
"mPr"
                  [ String -> String -> () -> Element
forall t. Node t => String -> String -> t -> Element
mnodeA String
"baseJc" String
"center" ()
                  , String -> String -> () -> Element
forall t. Node t => String -> String -> t -> Element
mnodeA String
"plcHide" String
"1" ()
                  , String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode String
"mcs" ([Element] -> Element) -> [Element] -> Element
forall a b. (a -> b) -> a -> b
$ (Alignment -> Element) -> [Alignment] -> [Element]
forall a b. (a -> b) -> [a] -> [b]
map Alignment -> Element
toMc [Alignment]
as' ]
        as' :: [Alignment]
as'    = Int -> [Alignment] -> [Alignment]
forall a. Int -> [a] -> [a]
take ([Int] -> Int
maximum' ([Int] -> Int) -> [Int] -> Int
forall a b. (a -> b) -> a -> b
$ (ArrayLine -> Int) -> [ArrayLine] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map ArrayLine -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [ArrayLine]
rs) ([Alignment] -> [Alignment]) -> [Alignment] -> [Alignment]
forall a b. (a -> b) -> a -> b
$ [Alignment]
as [Alignment] -> [Alignment] -> [Alignment]
forall a. [a] -> [a] -> [a]
++ [Alignment] -> [Alignment]
forall a. [a] -> [a]
cycle [Alignment
AlignCenter]
        toMr :: [t Exp] -> Element
toMr [t Exp]
r = String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode String
"mr" ([Element] -> Element) -> [Element] -> Element
forall a b. (a -> b) -> a -> b
$ (t Exp -> Element) -> [t Exp] -> [Element]
forall a b. (a -> b) -> [a] -> [b]
map (String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode String
"e" ([Element] -> Element) -> (t Exp -> [Element]) -> t Exp -> Element
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Exp -> [Element]) -> t Exp -> [Element]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap ([Element] -> Exp -> [Element]
showExp [Element]
props)) [t Exp]
r
        toMc :: Alignment -> Element
toMc Alignment
a = String -> Element -> Element
forall t. Node t => String -> t -> Element
mnode String
"mc" (Element -> Element) -> Element -> Element
forall a b. (a -> b) -> a -> b
$ String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode String
"mcPr"
                            [ String -> String -> () -> Element
forall t. Node t => String -> String -> t -> Element
mnodeA String
"mcJc" (Alignment -> String
forall p. IsString p => Alignment -> p
toAlign Alignment
a) ()
                            , String -> String -> () -> Element
forall t. Node t => String -> String -> t -> Element
mnodeA String
"count" String
"1" ()
                            ]
        toAlign :: Alignment -> p
toAlign Alignment
AlignLeft    = p
"left"
        toAlign Alignment
AlignRight   = p
"right"
        toAlign Alignment
AlignCenter  = p
"center"

makeText :: TextType -> T.Text -> Element
makeText :: TextType -> Text -> Element
makeText TextType
a Text
s = [Element] -> Text -> Element
str (String -> () -> Element
forall t. Node t => String -> t -> Element
mnode String
"nor" () Element -> [Element] -> [Element]
forall a. a -> [a] -> [a]
: TextType -> [Element]
setProps TextType
a) Text
s

defaultTo :: TextType -> [Element] -> [Element]
defaultTo :: TextType -> [Element] -> [Element]
defaultTo TextType
tt [] = TextType -> [Element]
setProps TextType
tt
defaultTo TextType
_  [Element]
ps = [Element]
ps

setProps :: TextType -> [Element]
setProps :: TextType -> [Element]
setProps TextType
tt =
  case TextType
tt of
       TextType
TextNormal       -> [String -> Element
sty String
"p"]
       TextType
TextBold         -> [String -> Element
sty String
"b"]
       TextType
TextItalic       -> [String -> Element
sty String
"i"]
       TextType
TextMonospace    -> [String -> Element
sty String
"p", String -> Element
scr String
"monospace"]
       TextType
TextSansSerif    -> [String -> Element
sty String
"p", String -> Element
scr String
"sans-serif"]
       TextType
TextDoubleStruck -> [String -> Element
sty String
"p", String -> Element
scr String
"double-struck"]
       TextType
TextScript       -> [String -> Element
sty String
"p", String -> Element
scr String
"script"]
       TextType
TextFraktur      -> [String -> Element
sty String
"p", String -> Element
scr String
"fraktur"]
       TextType
TextBoldItalic    -> [String -> Element
sty String
"bi"]
       TextType
TextSansSerifBold -> [String -> Element
sty String
"b", String -> Element
scr String
"sans-serif"]
       TextType
TextBoldScript    -> [String -> Element
sty String
"b", String -> Element
scr String
"script"]
       TextType
TextBoldFraktur   -> [String -> Element
sty String
"b", String -> Element
scr String
"fraktur"]
       TextType
TextSansSerifItalic -> [String -> Element
sty String
"i", String -> Element
scr String
"sans-serif"]
       TextType
TextSansSerifBoldItalic -> [String -> Element
sty String
"bi", String -> Element
scr String
"sans-serif"]
   where sty :: String -> Element
sty String
x = String -> String -> () -> Element
forall t. Node t => String -> String -> t -> Element
mnodeA String
"sty" String
x ()
         scr :: String -> Element
scr String
x = String -> String -> () -> Element
forall t. Node t => String -> String -> t -> Element
mnodeA String
"scr" String
x ()

handleDownup :: DisplayType -> [Exp] -> [Exp]
handleDownup :: DisplayType -> [Exp] -> [Exp]
handleDownup DisplayType
dt (Exp
exp' : [Exp]
xs) =
  case Exp
exp' of
       EOver Bool
convertible Exp
x Exp
y
         | Exp -> Bool
isNary Exp
x  ->
             [Exp] -> Exp
EGrouped [Bool -> Exp -> Exp -> Exp -> Exp
EUnderover Bool
convertible Exp
x Exp
emptyGroup Exp
y, Exp
next] Exp -> [Exp] -> [Exp]
forall a. a -> [a] -> [a]
: [Exp]
rest
         | Bool
convertible Bool -> Bool -> Bool
&& DisplayType
dt DisplayType -> DisplayType -> Bool
forall a. Eq a => a -> a -> Bool
== DisplayType
DisplayInline -> Exp -> Exp -> Exp
ESuper Exp
x Exp
y Exp -> [Exp] -> [Exp]
forall a. a -> [a] -> [a]
: [Exp]
xs
       EUnder Bool
convertible Exp
x Exp
y
         | Exp -> Bool
isNary Exp
x  ->
             [Exp] -> Exp
EGrouped [Bool -> Exp -> Exp -> Exp -> Exp
EUnderover Bool
convertible Exp
x Exp
y Exp
emptyGroup, Exp
next] Exp -> [Exp] -> [Exp]
forall a. a -> [a] -> [a]
: [Exp]
rest
         | Bool
convertible Bool -> Bool -> Bool
&& DisplayType
dt DisplayType -> DisplayType -> Bool
forall a. Eq a => a -> a -> Bool
== DisplayType
DisplayInline -> Exp -> Exp -> Exp
ESub Exp
x Exp
y Exp -> [Exp] -> [Exp]
forall a. a -> [a] -> [a]
: [Exp]
xs
       EUnderover Bool
convertible Exp
x Exp
y Exp
z
         | Exp -> Bool
isNary Exp
x  ->
             [Exp] -> Exp
EGrouped [Bool -> Exp -> Exp -> Exp -> Exp
EUnderover Bool
convertible Exp
x Exp
y Exp
z, Exp
next] Exp -> [Exp] -> [Exp]
forall a. a -> [a] -> [a]
: [Exp]
rest
         | Bool
convertible Bool -> Bool -> Bool
&& DisplayType
dt DisplayType -> DisplayType -> Bool
forall a. Eq a => a -> a -> Bool
== DisplayType
DisplayInline -> Exp -> Exp -> Exp -> Exp
ESubsup Exp
x Exp
y Exp
z Exp -> [Exp] -> [Exp]
forall a. a -> [a] -> [a]
: [Exp]
xs
       ESub Exp
x Exp
y
         | Exp -> Bool
isNary Exp
x  -> [Exp] -> Exp
EGrouped [Exp -> Exp -> Exp -> Exp
ESubsup Exp
x Exp
y Exp
emptyGroup, Exp
next] Exp -> [Exp] -> [Exp]
forall a. a -> [a] -> [a]
: [Exp]
rest
       ESuper Exp
x Exp
y
         | Exp -> Bool
isNary Exp
x  -> [Exp] -> Exp
EGrouped [Exp -> Exp -> Exp -> Exp
ESubsup Exp
x Exp
emptyGroup Exp
y, Exp
next] Exp -> [Exp] -> [Exp]
forall a. a -> [a] -> [a]
: [Exp]
rest
       ESubsup Exp
x Exp
y Exp
z
         | Exp -> Bool
isNary Exp
x  -> [Exp] -> Exp
EGrouped [Exp -> Exp -> Exp -> Exp
ESubsup Exp
x Exp
y Exp
z, Exp
next] Exp -> [Exp] -> [Exp]
forall a. a -> [a] -> [a]
: [Exp]
rest
       Exp
_             -> Exp
exp' Exp -> [Exp] -> [Exp]
forall a. a -> [a] -> [a]
: [Exp]
xs
    where (Exp
next, [Exp]
rest) = case [Exp]
xs of
                              (Exp
t:[Exp]
ts) -> (Exp
t,[Exp]
ts)
                              []     -> (Exp
emptyGroup, [])
          emptyGroup :: Exp
emptyGroup = [Exp] -> Exp
EGrouped []
handleDownup DisplayType
_ []            = []

-- TODO This duplication is ugly and inefficient.  See #92.
handleDownup' :: DisplayType -> [InEDelimited] -> [InEDelimited]
handleDownup' :: DisplayType -> [InEDelimited] -> [InEDelimited]
handleDownup' DisplayType
dt ((Right Exp
exp') : [InEDelimited]
xs) =
  case Exp
exp' of
       EOver Bool
convertible Exp
x Exp
y
         | Exp -> Bool
isNary Exp
x  ->
             Exp -> InEDelimited
forall a b. b -> Either a b
Right ([Exp] -> Exp
EGrouped [Bool -> Exp -> Exp -> Exp -> Exp
EUnderover Bool
convertible Exp
x Exp
emptyGroup Exp
y, Exp
next]) InEDelimited -> [InEDelimited] -> [InEDelimited]
forall a. a -> [a] -> [a]
:
             [InEDelimited]
rest
         | Bool
convertible Bool -> Bool -> Bool
&& DisplayType
dt DisplayType -> DisplayType -> Bool
forall a. Eq a => a -> a -> Bool
== DisplayType
DisplayInline -> Exp -> InEDelimited
forall a b. b -> Either a b
Right (Exp -> Exp -> Exp
ESuper Exp
x Exp
y) InEDelimited -> [InEDelimited] -> [InEDelimited]
forall a. a -> [a] -> [a]
: [InEDelimited]
xs
       EUnder Bool
convertible Exp
x Exp
y
         | Exp -> Bool
isNary Exp
x  ->
             Exp -> InEDelimited
forall a b. b -> Either a b
Right ([Exp] -> Exp
EGrouped [Bool -> Exp -> Exp -> Exp -> Exp
EUnderover Bool
convertible Exp
x Exp
y Exp
emptyGroup, Exp
next]) InEDelimited -> [InEDelimited] -> [InEDelimited]
forall a. a -> [a] -> [a]
:
             [InEDelimited]
rest
         | Bool
convertible Bool -> Bool -> Bool
&& DisplayType
dt DisplayType -> DisplayType -> Bool
forall a. Eq a => a -> a -> Bool
== DisplayType
DisplayInline -> Exp -> InEDelimited
forall a b. b -> Either a b
Right (Exp -> Exp -> Exp
ESub Exp
x Exp
y) InEDelimited -> [InEDelimited] -> [InEDelimited]
forall a. a -> [a] -> [a]
: [InEDelimited]
xs
       EUnderover Bool
convertible Exp
x Exp
y Exp
z
         | Exp -> Bool
isNary Exp
x  ->
             Exp -> InEDelimited
forall a b. b -> Either a b
Right ([Exp] -> Exp
EGrouped [Bool -> Exp -> Exp -> Exp -> Exp
EUnderover Bool
convertible Exp
x Exp
y Exp
z, Exp
next]) InEDelimited -> [InEDelimited] -> [InEDelimited]
forall a. a -> [a] -> [a]
: [InEDelimited]
rest
         | Bool
convertible Bool -> Bool -> Bool
&& DisplayType
dt DisplayType -> DisplayType -> Bool
forall a. Eq a => a -> a -> Bool
== DisplayType
DisplayInline -> Exp -> InEDelimited
forall a b. b -> Either a b
Right (Exp -> Exp -> Exp -> Exp
ESubsup Exp
x Exp
y Exp
z) InEDelimited -> [InEDelimited] -> [InEDelimited]
forall a. a -> [a] -> [a]
: [InEDelimited]
xs
       ESub Exp
x Exp
y
         | Exp -> Bool
isNary Exp
x  -> Exp -> InEDelimited
forall a b. b -> Either a b
Right ([Exp] -> Exp
EGrouped [Exp -> Exp -> Exp -> Exp
ESubsup Exp
x Exp
y Exp
emptyGroup, Exp
next]) InEDelimited -> [InEDelimited] -> [InEDelimited]
forall a. a -> [a] -> [a]
: [InEDelimited]
rest
       ESuper Exp
x Exp
y
         | Exp -> Bool
isNary Exp
x  -> Exp -> InEDelimited
forall a b. b -> Either a b
Right ([Exp] -> Exp
EGrouped [Exp -> Exp -> Exp -> Exp
ESubsup Exp
x Exp
emptyGroup Exp
y, Exp
next]) InEDelimited -> [InEDelimited] -> [InEDelimited]
forall a. a -> [a] -> [a]
: [InEDelimited]
rest
       ESubsup Exp
x Exp
y Exp
z
         | Exp -> Bool
isNary Exp
x  -> Exp -> InEDelimited
forall a b. b -> Either a b
Right ([Exp] -> Exp
EGrouped [Exp -> Exp -> Exp -> Exp
ESubsup Exp
x Exp
y Exp
z, Exp
next]) InEDelimited -> [InEDelimited] -> [InEDelimited]
forall a. a -> [a] -> [a]
: [InEDelimited]
rest
       Exp
_             -> Exp -> InEDelimited
forall a b. b -> Either a b
Right Exp
exp' InEDelimited -> [InEDelimited] -> [InEDelimited]
forall a. a -> [a] -> [a]
: [InEDelimited]
xs
    where (Exp
next, [InEDelimited]
rest) = case [InEDelimited]
xs of
                              (Right Exp
t:[InEDelimited]
ts) -> (Exp
t,[InEDelimited]
ts)
                              [InEDelimited]
_            -> (Exp
emptyGroup, [InEDelimited]
xs)
          emptyGroup :: Exp
emptyGroup = [Exp] -> Exp
EGrouped []
handleDownup' DisplayType
_ [InEDelimited]
xs = [InEDelimited]
xs

showExp :: [Element] -> Exp -> [Element]
showExp :: [Element] -> Exp -> [Element]
showExp [Element]
props Exp
e =
 case Exp
e of
   ENumber Text
x        -> [[Element] -> Text -> Element
str [Element]
props Text
x]
   EGrouped [EUnderover Bool
_ (ESymbol TeXSymbolType
Op Text
s) Exp
y Exp
z, Exp
w] ->
     [[Element] -> String -> Text -> Exp -> Exp -> Exp -> Element
makeNary [Element]
props String
"undOvr" Text
s Exp
y Exp
z Exp
w]
   EGrouped [ESubsup (ESymbol TeXSymbolType
Op Text
s) Exp
y Exp
z, Exp
w] ->
     [[Element] -> String -> Text -> Exp -> Exp -> Exp -> Element
makeNary [Element]
props String
"subSup" Text
s Exp
y Exp
z Exp
w]
   EGrouped []      -> [[Element] -> Text -> Element
str [Element]
props Text
"\x200B"] -- avoid dashed box, see #118
   EGrouped [Exp]
xs      -> (Exp -> [Element]) -> [Exp] -> [Element]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap ([Element] -> Exp -> [Element]
showExp [Element]
props) [Exp]
xs
   EDelimited Text
start Text
end [InEDelimited]
xs ->
                  [ String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode String
"d" ([Element] -> Element) -> [Element] -> Element
forall a b. (a -> b) -> a -> b
$ String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode String
"dPr"
                               [ String -> String -> () -> Element
forall t. Node t => String -> String -> t -> Element
mnodeA String
"begChr" (Text -> String
T.unpack Text
start) ()
                               , String -> String -> () -> Element
forall t. Node t => String -> String -> t -> Element
mnodeA String
"endChr" (Text -> String
T.unpack Text
end) ()
                               , String -> String -> () -> Element
forall t. Node t => String -> String -> t -> Element
mnodeA String
"sepChr" (Text -> String
T.unpack Text
sepchr) ()
                               , String -> () -> Element
forall t. Node t => String -> t -> Element
mnode String
"grow" () ]
                              Element -> [Element] -> [Element]
forall a. a -> [a] -> [a]
: ([Exp] -> Element) -> ArrayLine -> [Element]
forall a b. (a -> b) -> [a] -> [b]
map (String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode String
"e" ([Element] -> Element) -> ([Exp] -> [Element]) -> [Exp] -> Element
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Exp -> [Element]) -> [Exp] -> [Element]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap ([Element] -> Exp -> [Element]
showExp [Element]
props)) ArrayLine
es
                  ]
      where
       seps :: [Text]
seps = [InEDelimited] -> [Text]
forall a b. [Either a b] -> [a]
lefts [InEDelimited]
xs
       sepchr :: Text
sepchr = case [Text]
seps of
                  []    -> Text
""
                  (Text
s:[Text]
_) -> Text
s
       es :: ArrayLine
es   = ([InEDelimited] -> [Exp]) -> [[InEDelimited]] -> ArrayLine
forall a b. (a -> b) -> [a] -> [b]
map [InEDelimited] -> [Exp]
forall a b. [Either a b] -> [b]
rights ([[InEDelimited]] -> ArrayLine) -> [[InEDelimited]] -> ArrayLine
forall a b. (a -> b) -> a -> b
$ (InEDelimited -> Bool) -> [InEDelimited] -> [[InEDelimited]]
forall a. (a -> Bool) -> [a] -> [[a]]
splitWhen InEDelimited -> Bool
forall a b. Either a b -> Bool
isLeft [InEDelimited]
xs

   EIdentifier Text
""   -> [[Element] -> Text -> Element
str [Element]
props Text
"\x200B"]  -- 0-width space
                       -- to avoid the dashed box we get otherwise; see #118
   EIdentifier Text
x    -> [[Element] -> Text -> Element
str [Element]
props Text
x]
   EMathOperator Text
x  -> [TextType -> Text -> Element
makeText TextType
TextNormal Text
x]  -- TODO revisit, use props?
   ESymbol TeXSymbolType
ty Text
xs
    | Just (Char
c, Text
xs') <- Text -> Maybe (Char, Text)
T.uncons Text
xs
    , Text -> Bool
T.null Text
xs'
    , Char -> Bool
isSymbol Char
c Bool -> Bool -> Bool
|| Char -> Bool
isPunctuation Char
c
                    -> [[Element] -> Text -> Element
str (TextType -> [Element] -> [Element]
defaultTo TextType
TextNormal [Element]
props) Text
xs]
    | TeXSymbolType
ty TeXSymbolType -> [TeXSymbolType] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [TeXSymbolType
Op, TeXSymbolType
Bin, TeXSymbolType
Rel]
                    -> [String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode String
"box"
                        [ String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode String
"boxPr"
                          [ String -> String -> () -> Element
forall t. Node t => String -> String -> t -> Element
mnodeA String
"opEmu" String
"1" () ]
                        , String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode String
"e"
                          [[Element] -> Text -> Element
str (TextType -> [Element] -> [Element]
defaultTo TextType
TextNormal [Element]
props) Text
xs]
                        ]]
    | Bool
otherwise     -> [[Element] -> Text -> Element
str (TextType -> [Element] -> [Element]
defaultTo TextType
TextNormal [Element]
props) Text
xs]
   ESpace Rational
n
     | Rational
n Rational -> Rational -> Bool
forall a. Ord a => a -> a -> Bool
> Rational
0 Bool -> Bool -> Bool
&& Rational
n Rational -> Rational -> Bool
forall a. Ord a => a -> a -> Bool
<= Rational
0.17    -> [[Element] -> Text -> Element
str [Element]
props Text
"\x2009"]
     | Rational
n Rational -> Rational -> Bool
forall a. Ord a => a -> a -> Bool
> Rational
0.17 Bool -> Bool -> Bool
&& Rational
n Rational -> Rational -> Bool
forall a. Ord a => a -> a -> Bool
<= Rational
0.23 -> [[Element] -> Text -> Element
str [Element]
props Text
"\x2005"]
     | Rational
n Rational -> Rational -> Bool
forall a. Ord a => a -> a -> Bool
> Rational
0.23 Bool -> Bool -> Bool
&& Rational
n Rational -> Rational -> Bool
forall a. Ord a => a -> a -> Bool
<= Rational
0.28 -> [[Element] -> Text -> Element
str [Element]
props Text
"\x2004"]
     | Rational
n Rational -> Rational -> Bool
forall a. Ord a => a -> a -> Bool
> Rational
0.28 Bool -> Bool -> Bool
&& Rational
n Rational -> Rational -> Bool
forall a. Ord a => a -> a -> Bool
<= Rational
0.5  -> [[Element] -> Text -> Element
str [Element]
props Text
"\x2004"]
     | Rational
n Rational -> Rational -> Bool
forall a. Ord a => a -> a -> Bool
> Rational
0.5 Bool -> Bool -> Bool
&& Rational
n Rational -> Rational -> Bool
forall a. Ord a => a -> a -> Bool
<= Rational
1.8   -> [[Element] -> Text -> Element
str [Element]
props Text
"\x2001"]
     | Rational
n Rational -> Rational -> Bool
forall a. Ord a => a -> a -> Bool
> Rational
1.8               -> [[Element] -> Text -> Element
str [Element]
props Text
"\x2001\x2001"]
     | Bool
otherwise             -> [[Element] -> Text -> Element
str [Element]
props Text
"\x200B"]
       -- this is how the xslt sheet handles all spaces
   EUnder Bool
_ Exp
x (ESymbol TeXSymbolType
TUnder Text
t) | (Char -> Bool) -> Text -> Bool
T.all Char -> Bool
isBarChar Text
t ->
                       [String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode String
"bar" [ String -> Element -> Element
forall t. Node t => String -> t -> Element
mnode String
"barPr" (Element -> Element) -> Element -> Element
forall a b. (a -> b) -> a -> b
$
                                        String -> String -> () -> Element
forall t. Node t => String -> String -> t -> Element
mnodeA String
"pos" String
"bot" ()
                                    , String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode String
"e" ([Element] -> Element) -> [Element] -> Element
forall a b. (a -> b) -> a -> b
$ [Element] -> Exp -> [Element]
showExp [Element]
props Exp
x ]]
   EOver Bool
_ Exp
x (ESymbol TeXSymbolType
TOver Text
t) | (Char -> Bool) -> Text -> Bool
T.all Char -> Bool
isBarChar Text
t ->
                       [String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode String
"bar" [ String -> Element -> Element
forall t. Node t => String -> t -> Element
mnode String
"barPr" (Element -> Element) -> Element -> Element
forall a b. (a -> b) -> a -> b
$
                                        String -> String -> () -> Element
forall t. Node t => String -> String -> t -> Element
mnodeA String
"pos" String
"top" ()
                                    , String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode String
"e" ([Element] -> Element) -> [Element] -> Element
forall a b. (a -> b) -> a -> b
$ [Element] -> Exp -> [Element]
showExp [Element]
props Exp
x ]]
   EOver Bool
_ Exp
x (ESymbol TeXSymbolType
st (Text -> String
T.unpack -> String
y))
    | TeXSymbolType
st TeXSymbolType -> TeXSymbolType -> Bool
forall a. Eq a => a -> a -> Bool
== TeXSymbolType
Accent  -> [String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode String
"acc" [ String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode String
"accPr" [ String -> String -> () -> Element
forall t. Node t => String -> String -> t -> Element
mnodeA String
"chr" String
y () ]
                                    , String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode String
"e" ([Element] -> Element) -> [Element] -> Element
forall a b. (a -> b) -> a -> b
$ [Element] -> Exp -> [Element]
showExp [Element]
props Exp
x ]]
    | TeXSymbolType
st TeXSymbolType -> TeXSymbolType -> Bool
forall a. Eq a => a -> a -> Bool
== TeXSymbolType
TUnder  -> [String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode String
"groupChr" [ String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode String
"groupChrPr"
                                           [ String -> String -> () -> Element
forall t. Node t => String -> String -> t -> Element
mnodeA String
"chr" String
y ()
                                           , String -> String -> () -> Element
forall t. Node t => String -> String -> t -> Element
mnodeA String
"pos" String
"bot" ()
                                           , String -> String -> () -> Element
forall t. Node t => String -> String -> t -> Element
mnodeA String
"vertJc" String
"top" () ]
                                    , String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode String
"e" ([Element] -> Element) -> [Element] -> Element
forall a b. (a -> b) -> a -> b
$ [Element] -> Exp -> [Element]
showExp [Element]
props Exp
x ]]
    | TeXSymbolType
st TeXSymbolType -> TeXSymbolType -> Bool
forall a. Eq a => a -> a -> Bool
== TeXSymbolType
TOver   -> [String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode String
"groupChr" [ String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode String
"groupChrPr"
                                           [ String -> String -> () -> Element
forall t. Node t => String -> String -> t -> Element
mnodeA String
"chr" String
y ()
                                           , String -> String -> () -> Element
forall t. Node t => String -> String -> t -> Element
mnodeA String
"pos" String
"top" ()
                                           , String -> String -> () -> Element
forall t. Node t => String -> String -> t -> Element
mnodeA String
"vertJc" String
"bot" () ]
                                    , String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode String
"e" ([Element] -> Element) -> [Element] -> Element
forall a b. (a -> b) -> a -> b
$ [Element] -> Exp -> [Element]
showExp [Element]
props Exp
x ]]
   ESub Exp
x Exp
y         -> [String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode String
"sSub" [ String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode String
"e" ([Element] -> Element) -> [Element] -> Element
forall a b. (a -> b) -> a -> b
$ [Element] -> Exp -> [Element]
showExp [Element]
props Exp
x
                                     , String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode String
"sub" ([Element] -> Element) -> [Element] -> Element
forall a b. (a -> b) -> a -> b
$ [Element] -> Exp -> [Element]
showExp [Element]
props Exp
y]]
   ESuper Exp
x Exp
y       -> [String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode String
"sSup" [ String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode String
"e" ([Element] -> Element) -> [Element] -> Element
forall a b. (a -> b) -> a -> b
$ [Element] -> Exp -> [Element]
showExp [Element]
props Exp
x
                                     , String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode String
"sup" ([Element] -> Element) -> [Element] -> Element
forall a b. (a -> b) -> a -> b
$ [Element] -> Exp -> [Element]
showExp [Element]
props Exp
y]]
   ESubsup Exp
x Exp
y Exp
z    -> [String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode String
"sSubSup" [ String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode String
"e" ([Element] -> Element) -> [Element] -> Element
forall a b. (a -> b) -> a -> b
$ [Element] -> Exp -> [Element]
showExp [Element]
props Exp
x
                                        , String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode String
"sub" ([Element] -> Element) -> [Element] -> Element
forall a b. (a -> b) -> a -> b
$ [Element] -> Exp -> [Element]
showExp [Element]
props Exp
y
                                        , String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode String
"sup" ([Element] -> Element) -> [Element] -> Element
forall a b. (a -> b) -> a -> b
$ [Element] -> Exp -> [Element]
showExp [Element]
props Exp
z]]
   EUnder Bool
_ Exp
x Exp
y  -> [String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode String
"limLow" [ String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode String
"e" ([Element] -> Element) -> [Element] -> Element
forall a b. (a -> b) -> a -> b
$ [Element] -> Exp -> [Element]
showExp [Element]
props Exp
x
                                       , String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode String
"lim" ([Element] -> Element) -> [Element] -> Element
forall a b. (a -> b) -> a -> b
$ [Element] -> Exp -> [Element]
showExp [Element]
props Exp
y]]
   EOver Bool
_ Exp
x Exp
y   -> [String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode String
"limUpp" [ String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode String
"e" ([Element] -> Element) -> [Element] -> Element
forall a b. (a -> b) -> a -> b
$ [Element] -> Exp -> [Element]
showExp [Element]
props Exp
x
                                       , String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode String
"lim" ([Element] -> Element) -> [Element] -> Element
forall a b. (a -> b) -> a -> b
$ [Element] -> Exp -> [Element]
showExp [Element]
props Exp
y]]
   EUnderover Bool
c Exp
x Exp
y Exp
z -> [Element] -> Exp -> [Element]
showExp [Element]
props (Bool -> Exp -> Exp -> Exp
EUnder Bool
c (Bool -> Exp -> Exp -> Exp
EOver Bool
c Exp
x Exp
z) Exp
y)
   ESqrt Exp
x       -> [String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode String
"rad" [ String -> Element -> Element
forall t. Node t => String -> t -> Element
mnode String
"radPr" (Element -> Element) -> Element -> Element
forall a b. (a -> b) -> a -> b
$ String -> String -> () -> Element
forall t. Node t => String -> String -> t -> Element
mnodeA String
"degHide" String
"1" ()
                                      , String -> () -> Element
forall t. Node t => String -> t -> Element
mnode String
"deg" ()
                                      , String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode String
"e" ([Element] -> Element) -> [Element] -> Element
forall a b. (a -> b) -> a -> b
$ [Element] -> Exp -> [Element]
showExp [Element]
props Exp
x]]
   ERoot Exp
i Exp
x     -> [String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode String
"rad" [ String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode String
"deg" ([Element] -> Element) -> [Element] -> Element
forall a b. (a -> b) -> a -> b
$ [Element] -> Exp -> [Element]
showExp [Element]
props Exp
i
                                 , String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode String
"e" ([Element] -> Element) -> [Element] -> Element
forall a b. (a -> b) -> a -> b
$ [Element] -> Exp -> [Element]
showExp [Element]
props Exp
x]]
   EFraction FractionType
ft Exp
x Exp
y -> [[Element] -> FractionType -> Exp -> Exp -> Element
showFraction [Element]
props FractionType
ft Exp
x Exp
y]
   EPhantom Exp
x       -> [String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode String
"phant" [ String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode String
"phantPr"
                                            [ String -> String -> () -> Element
forall t. Node t => String -> String -> t -> Element
mnodeA String
"show" String
"0" () ]
                                          , String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode String
"e" ([Element] -> Element) -> [Element] -> Element
forall a b. (a -> b) -> a -> b
$ [Element] -> Exp -> [Element]
showExp [Element]
props Exp
x]]
   EBoxed   Exp
x       -> [String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode String
"borderBox" [ String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode String
"e" ([Element] -> Element) -> [Element] -> Element
forall a b. (a -> b) -> a -> b
$ [Element] -> Exp -> [Element]
showExp [Element]
props Exp
x]]
   EScaled Rational
_ Exp
x      -> [Element] -> Exp -> [Element]
showExp [Element]
props Exp
x -- no support for scaler?
   EArray [Alignment]
as [ArrayLine]
ls     -> [[Element] -> [Alignment] -> [ArrayLine] -> Element
makeArray [Element]
props [Alignment]
as [ArrayLine]
ls]
   EText TextType
a Text
s        -> [TextType -> Text -> Element
makeText TextType
a Text
s]
   EStyled TextType
a [Exp]
es     -> (Exp -> [Element]) -> [Exp] -> [Element]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap ([Element] -> Exp -> [Element]
showExp (TextType -> [Element]
setProps TextType
a)) [Exp]
es

isBarChar :: Char -> Bool
isBarChar :: Char -> Bool
isBarChar Char
c = Char
c Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'\x203E' Bool -> Bool -> Bool
|| Char
c Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'\x00AF' Bool -> Bool -> Bool
||
              Char
c Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'\x0304' Bool -> Bool -> Bool
|| Char
c Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'\x0333'

isNary :: Exp -> Bool
isNary :: Exp -> Bool
isNary (ESymbol TeXSymbolType
Op Text
_) = Bool
True
isNary Exp
_ = Bool
False

-- Kept as String for Text.XML.Light
makeNary :: [Element] -> String -> T.Text -> Exp -> Exp -> Exp -> Element
makeNary :: [Element] -> String -> Text -> Exp -> Exp -> Exp -> Element
makeNary [Element]
props String
t Text
s Exp
y Exp
z Exp
w =
  String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode String
"nary" [ String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode String
"naryPr"
                 [ String -> String -> () -> Element
forall t. Node t => String -> String -> t -> Element
mnodeA String
"chr" (Text -> String
T.unpack Text
s) ()
                 , String -> String -> () -> Element
forall t. Node t => String -> String -> t -> Element
mnodeA String
"limLoc" String
t ()
                 , String -> String -> () -> Element
forall t. Node t => String -> String -> t -> Element
mnodeA String
"subHide"
                    (if Exp
y Exp -> Exp -> Bool
forall a. Eq a => a -> a -> Bool
== [Exp] -> Exp
EGrouped [] then String
"1" else String
"0") ()
                 , String -> String -> () -> Element
forall t. Node t => String -> String -> t -> Element
mnodeA String
"supHide"
                    (if Exp
z Exp -> Exp -> Bool
forall a. Eq a => a -> a -> Bool
== [Exp] -> Exp
EGrouped [] then String
"1" else String
"0") ()
                 ]
               , String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode String
"sub" ([Element] -> Element) -> [Element] -> Element
forall a b. (a -> b) -> a -> b
$ [Element] -> Exp -> [Element]
showExp [Element]
props Exp
y
               , String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode String
"sup" ([Element] -> Element) -> [Element] -> Element
forall a b. (a -> b) -> a -> b
$ [Element] -> Exp -> [Element]
showExp [Element]
props Exp
z
               , String -> [Element] -> Element
forall t. Node t => String -> t -> Element
mnode String
"e" ([Element] -> Element) -> [Element] -> Element
forall a b. (a -> b) -> a -> b
$ [Element] -> Exp -> [Element]
showExp [Element]
props Exp
w ]