{-# LANGUAGE OverloadedStrings #-}
module Text.LaTeX.Base.Render
(
Text
, module Data.String
, Render (..)
, renderAppend
, renderChars
, renderCommas
, renderFile
, rendertex
, readFileTex
, showFloat
) where
import Text.LaTeX.Base.Syntax
import Text.LaTeX.Base.Class
import Data.String
import Data.List (intersperse)
import qualified Data.ByteString as B
import Data.Word (Word8)
import Numeric (showFFloat)
import Data.Text (Text,lines,unlines,dropWhileEnd)
import Data.Text.Encoding
import Data.Text.Lazy (toStrict)
import Data.Text.Lazy.Builder (Builder)
import qualified Data.Text.Lazy.Builder as Builder
import qualified Data.Text.Lazy.Builder.Int as Builder
import qualified Data.Text.Lazy.Builder.RealFloat as Builder
class Show a => Render a where
render :: a -> Text
renderBuilder :: a -> Builder
render = String -> Text
forall a. IsString a => String -> a
fromString (String -> Text) -> (a -> String) -> a -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> String
forall a. Show a => a -> String
show
renderBuilder = Text -> Builder
Builder.fromText (Text -> Builder) -> (a -> Text) -> a -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Text
forall a. Render a => a -> Text
render
renderDefault :: Render a => a -> Text
renderDefault :: forall a. Render a => a -> Text
renderDefault = Text -> Text
toStrict (Text -> Text) -> (a -> Text) -> a -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Builder -> Text
Builder.toLazyText (Builder -> Text) -> (a -> Builder) -> a -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Builder
forall a. Render a => a -> Builder
renderBuilder
instance Render Text where
render :: Text -> Text
render = Text -> Text
protectText
renderAppend :: Render a => [a] -> Text
renderAppend :: forall a. Render a => [a] -> Text
renderAppend = [Text] -> Text
forall a. Monoid a => [a] -> a
mconcat ([Text] -> Text) -> ([a] -> [Text]) -> [a] -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (a -> Text) -> [a] -> [Text]
forall a b. (a -> b) -> [a] -> [b]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap a -> Text
forall a. Render a => a -> Text
render
renderAppendBuilder :: Render a => [a] -> Builder
renderAppendBuilder :: forall a. Render a => [a] -> Builder
renderAppendBuilder = (a -> Builder) -> [a] -> Builder
forall m a. Monoid m => (a -> m) -> [a] -> m
forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
foldMap a -> Builder
forall a. Render a => a -> Builder
renderBuilder
renderChars :: Render a => Char -> [a] -> Text
renderChars :: forall a. Render a => Char -> [a] -> Text
renderChars Char
c = [Text] -> Text
forall a. Monoid a => [a] -> a
mconcat ([Text] -> Text) -> ([a] -> [Text]) -> [a] -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> [Text] -> [Text]
forall a. a -> [a] -> [a]
intersperse (String -> Text
forall a. IsString a => String -> a
fromString [Char
c]) ([Text] -> [Text]) -> ([a] -> [Text]) -> [a] -> [Text]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (a -> Text) -> [a] -> [Text]
forall a b. (a -> b) -> [a] -> [b]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap a -> Text
forall a. Render a => a -> Text
render
renderCharsBuilder :: Render a => Char -> [a] -> Builder
renderCharsBuilder :: forall a. Render a => Char -> [a] -> Builder
renderCharsBuilder Char
c = [Builder] -> Builder
forall a. Monoid a => [a] -> a
mconcat ([Builder] -> Builder) -> ([a] -> [Builder]) -> [a] -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Builder -> [Builder] -> [Builder]
forall a. a -> [a] -> [a]
intersperse (Char -> Builder
Builder.singleton Char
c) ([Builder] -> [Builder]) -> ([a] -> [Builder]) -> [a] -> [Builder]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (a -> Builder) -> [a] -> [Builder]
forall a b. (a -> b) -> [a] -> [b]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap a -> Builder
forall a. Render a => a -> Builder
renderBuilder
renderCommas :: Render a => [a] -> Text
renderCommas :: forall a. Render a => [a] -> Text
renderCommas = Char -> [a] -> Text
forall a. Render a => Char -> [a] -> Text
renderChars Char
','
renderCommasBuilder :: Render a => [a] -> Builder
renderCommasBuilder :: forall a. Render a => [a] -> Builder
renderCommasBuilder = Char -> [a] -> Builder
forall a. Render a => Char -> [a] -> Builder
renderCharsBuilder Char
','
renderFile :: Render a => FilePath -> a -> IO ()
renderFile :: forall a. Render a => String -> a -> IO ()
renderFile String
f = String -> ByteString -> IO ()
B.writeFile String
f (ByteString -> IO ()) -> (a -> ByteString) -> a -> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> ByteString
encodeUtf8 (Text -> ByteString) -> (a -> Text) -> a -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Text
forall a. Render a => a -> Text
render
readFileTex :: FilePath -> IO Text
readFileTex :: String -> IO Text
readFileTex = (ByteString -> Text) -> IO ByteString -> IO Text
forall a b. (a -> b) -> IO a -> IO b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ByteString -> Text
decodeUtf8 (IO ByteString -> IO Text)
-> (String -> IO ByteString) -> String -> IO Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> IO ByteString
B.readFile
rendertex :: (Render a,LaTeXC l) => a -> l
rendertex :: forall a l. (Render a, LaTeXC l) => a -> l
rendertex = LaTeX -> l
forall l. LaTeXC l => LaTeX -> l
fromLaTeX (LaTeX -> l) -> (a -> LaTeX) -> a -> l
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> LaTeX
TeXRaw (Text -> LaTeX) -> (a -> Text) -> a -> LaTeX
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Text
forall a. Render a => a -> Text
render
instance Render Measure where
render :: Measure -> Text
render (Pt Double
x) = Double -> Text
forall a. Render a => a -> Text
render Double
x Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"pt"
render (Mm Double
x) = Double -> Text
forall a. Render a => a -> Text
render Double
x Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"mm"
render (Cm Double
x) = Double -> Text
forall a. Render a => a -> Text
render Double
x Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"cm"
render (In Double
x) = Double -> Text
forall a. Render a => a -> Text
render Double
x Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"in"
render (Ex Double
x) = Double -> Text
forall a. Render a => a -> Text
render Double
x Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"ex"
render (Em Double
x) = Double -> Text
forall a. Render a => a -> Text
render Double
x Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"em"
render (CustomMeasure LaTeX
x) = LaTeX -> Text
forall a. Render a => a -> Text
render LaTeX
x
instance Render LaTeX where
renderBuilder :: LaTeX -> Builder
renderBuilder (TeXRaw Text
t) = Text -> Builder
Builder.fromText Text
t
renderBuilder (TeXComm String
name []) = Builder
"\\" Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> String -> Builder
forall a. IsString a => String -> a
fromString String
name Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Builder
"{}"
renderBuilder (TeXComm String
name [TeXArg]
args) =
Builder
"\\"
Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> String -> Builder
forall a. IsString a => String -> a
fromString String
name
Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> [TeXArg] -> Builder
forall a. Render a => [a] -> Builder
renderAppendBuilder [TeXArg]
args
renderBuilder (TeXCommS String
name) = Builder
"\\" Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> String -> Builder
forall a. IsString a => String -> a
fromString String
name
renderBuilder (TeXEnv String
name [TeXArg]
args LaTeX
c) =
Builder
"\\begin{"
Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> String -> Builder
forall a. IsString a => String -> a
fromString String
name
Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Builder
"}"
Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> [TeXArg] -> Builder
forall a. Render a => [a] -> Builder
renderAppendBuilder [TeXArg]
args
Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> LaTeX -> Builder
forall a. Render a => a -> Builder
renderBuilder LaTeX
c
Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Builder
"\\end{"
Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> String -> Builder
forall a. IsString a => String -> a
fromString String
name
Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Builder
"}"
renderBuilder (TeXMath MathType
Dollar LaTeX
l) = Builder
"$" Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> LaTeX -> Builder
forall a. Render a => a -> Builder
renderBuilder LaTeX
l Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Builder
"$"
renderBuilder (TeXMath MathType
DoubleDollar LaTeX
l) = Builder
"$$" Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> LaTeX -> Builder
forall a. Render a => a -> Builder
renderBuilder LaTeX
l Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Builder
"$$"
renderBuilder (TeXMath MathType
Square LaTeX
l) = Builder
"\\[" Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> LaTeX -> Builder
forall a. Render a => a -> Builder
renderBuilder LaTeX
l Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Builder
"\\]"
renderBuilder (TeXMath MathType
Parentheses LaTeX
l) = Builder
"\\(" Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> LaTeX -> Builder
forall a. Render a => a -> Builder
renderBuilder LaTeX
l Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Builder
"\\)"
renderBuilder (TeXLineBreak Maybe Measure
m Bool
b) =
Builder
"\\\\" Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> (if Bool
b then Builder
"*" else Builder
forall a. Monoid a => a
mempty) Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<>
Builder
"[" Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Builder -> (Measure -> Builder) -> Maybe Measure -> Builder
forall b a. b -> (a -> b) -> Maybe a -> b
maybe (Measure -> Builder
forall a. Render a => a -> Builder
renderBuilder (Double -> Measure
Em Double
0.0)) Measure -> Builder
forall a. Render a => a -> Builder
renderBuilder Maybe Measure
m Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Builder
"]"
renderBuilder (TeXBraces LaTeX
l) = Builder
"{" Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> LaTeX -> Builder
forall a. Render a => a -> Builder
renderBuilder LaTeX
l Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Builder
"}"
renderBuilder (TeXComment Text
c) =
let xs :: [Text]
xs = Text -> [Text]
Data.Text.lines Text
c
in if [Text] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [Text]
xs then Builder
"%\n"
else Text -> Builder
Builder.fromText (Text -> Builder) -> Text -> Builder
forall a b. (a -> b) -> a -> b
$ [Text] -> Text
Data.Text.unlines ([Text] -> Text) -> [Text] -> Text
forall a b. (a -> b) -> a -> b
$ (Text -> Text) -> [Text] -> [Text]
forall a b. (a -> b) -> [a] -> [b]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (Text
"%" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<>) [Text]
xs
renderBuilder (TeXSeq LaTeX
l1 LaTeX
l2) = LaTeX -> Builder
forall a. Render a => a -> Builder
renderBuilder LaTeX
l1 Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> LaTeX -> Builder
forall a. Render a => a -> Builder
renderBuilder LaTeX
l2
renderBuilder LaTeX
TeXEmpty = Builder
forall a. Monoid a => a
mempty
render :: LaTeX -> Text
render = LaTeX -> Text
forall a. Render a => a -> Text
renderDefault
instance Render TeXArg where
renderBuilder :: TeXArg -> Builder
renderBuilder (FixArg LaTeX
l) = Builder
"{" Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> LaTeX -> Builder
forall a. Render a => a -> Builder
renderBuilder LaTeX
l Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Builder
"}"
renderBuilder (OptArg LaTeX
l) = Builder
"[" Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> LaTeX -> Builder
forall a. Render a => a -> Builder
renderBuilder LaTeX
l Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Builder
"]"
renderBuilder (MOptArg []) = Builder
forall a. Monoid a => a
mempty
renderBuilder (MOptArg [LaTeX]
ls) = Builder
"[" Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> [LaTeX] -> Builder
forall a. Render a => [a] -> Builder
renderCommasBuilder [LaTeX]
ls Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Builder
"]"
renderBuilder (SymArg LaTeX
l) = Builder
"<" Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> LaTeX -> Builder
forall a. Render a => a -> Builder
renderBuilder LaTeX
l Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Builder
">"
renderBuilder (MSymArg []) = Builder
forall a. Monoid a => a
mempty
renderBuilder (MSymArg [LaTeX]
ls) = Builder
"<" Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> [LaTeX] -> Builder
forall a. Render a => [a] -> Builder
renderCommasBuilder [LaTeX]
ls Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Builder
">"
renderBuilder (ParArg LaTeX
l) = Builder
"(" Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> LaTeX -> Builder
forall a. Render a => a -> Builder
renderBuilder LaTeX
l Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Builder
")"
renderBuilder (MParArg []) = Builder
forall a. Monoid a => a
mempty
renderBuilder (MParArg [LaTeX]
ls) = Builder
"(" Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> [LaTeX] -> Builder
forall a. Render a => [a] -> Builder
renderCommasBuilder [LaTeX]
ls Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Builder
")"
render :: TeXArg -> Text
render = TeXArg -> Text
forall a. Render a => a -> Text
renderDefault
showFloat :: RealFloat a => a -> String
showFloat :: forall a. RealFloat a => a -> String
showFloat a
x = Maybe Int -> a -> ShowS
forall a. RealFloat a => Maybe Int -> a -> ShowS
showFFloat (Int -> Maybe Int
forall a. a -> Maybe a
Just Int
5) a
x []
instance Render Int where
renderBuilder :: Int -> Builder
renderBuilder = Int -> Builder
forall a. Integral a => a -> Builder
Builder.decimal
render :: Int -> Text
render = Int -> Text
forall a. Render a => a -> Text
renderDefault
instance Render Integer where
renderBuilder :: Integer -> Builder
renderBuilder = Integer -> Builder
forall a. Integral a => a -> Builder
Builder.decimal
render :: Integer -> Text
render = Integer -> Text
forall a. Render a => a -> Text
renderDefault
instance Render Float where
renderBuilder :: Float -> Builder
renderBuilder = FPFormat -> Maybe Int -> Float -> Builder
forall a. RealFloat a => FPFormat -> Maybe Int -> a -> Builder
Builder.formatRealFloat FPFormat
Builder.Fixed (Int -> Maybe Int
forall a. a -> Maybe a
Just Int
5)
render :: Float -> Text
render = (Char -> Bool) -> Text -> Text
dropWhileEnd (Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'.') (Text -> Text) -> (Float -> Text) -> Float -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Char -> Bool) -> Text -> Text
dropWhileEnd (Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'0') (Text -> Text) -> (Float -> Text) -> Float -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Float -> Text
forall a. Render a => a -> Text
renderDefault
instance Render Double where
renderBuilder :: Double -> Builder
renderBuilder = FPFormat -> Maybe Int -> Double -> Builder
forall a. RealFloat a => FPFormat -> Maybe Int -> a -> Builder
Builder.formatRealFloat FPFormat
Builder.Fixed (Int -> Maybe Int
forall a. a -> Maybe a
Just Int
5)
render :: Double -> Text
render = (Char -> Bool) -> Text -> Text
dropWhileEnd (Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'.') (Text -> Text) -> (Double -> Text) -> Double -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Char -> Bool) -> Text -> Text
dropWhileEnd (Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'0') (Text -> Text) -> (Double -> Text) -> Double -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Double -> Text
forall a. Render a => a -> Text
renderDefault
instance Render Word8 where
renderBuilder :: Word8 -> Builder
renderBuilder = Word8 -> Builder
forall a. Integral a => a -> Builder
Builder.decimal
render :: Word8 -> Text
render = Word8 -> Text
forall a. Render a => a -> Text
renderDefault
instance Render Bool where
render :: Bool -> Text
render Bool
True = Text
"true"
render Bool
_ = Text
"false"
instance Render a => Render [a] where
renderBuilder :: [a] -> Builder
renderBuilder [a]
xs = Builder
"[" Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> [a] -> Builder
forall a. Render a => [a] -> Builder
renderCommasBuilder [a]
xs Builder -> Builder -> Builder
forall a. Semigroup a => a -> a -> a
<> Builder
"]"
render :: [a] -> Text
render = [a] -> Text
forall a. Render a => a -> Text
renderDefault