{-# 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)
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 = fromString . show
renderBuilder = Builder.fromText . render
renderDefault :: Render a => a -> Text
renderDefault = toStrict . Builder.toLazyText . renderBuilder
instance Render Text where
render = protectText
renderAppend :: Render a => [a] -> Text
renderAppend = mconcat . fmap render
renderAppendBuilder :: Render a => [a] -> Builder
renderAppendBuilder = foldMap renderBuilder
renderChars :: Render a => Char -> [a] -> Text
renderChars c = mconcat . intersperse (fromString [c]) . fmap render
renderCharsBuilder :: Render a => Char -> [a] -> Builder
renderCharsBuilder c = mconcat . intersperse (Builder.singleton c) . fmap renderBuilder
renderCommas :: Render a => [a] -> Text
renderCommas = renderChars ','
renderCommasBuilder :: Render a => [a] -> Builder
renderCommasBuilder = renderCharsBuilder ','
renderFile :: Render a => FilePath -> a -> IO ()
renderFile f = B.writeFile f . encodeUtf8 . render
readFileTex :: FilePath -> IO Text
readFileTex = fmap decodeUtf8 . B.readFile
rendertex :: (Render a,LaTeXC l) => a -> l
rendertex = fromLaTeX . TeXRaw . render
instance Render Measure where
render (Pt x) = render x <> "pt"
render (Mm x) = render x <> "mm"
render (Cm x) = render x <> "cm"
render (In x) = render x <> "in"
render (Ex x) = render x <> "ex"
render (Em x) = render x <> "em"
render (CustomMeasure x) = render x
instance Render LaTeX where
renderBuilder (TeXRaw t) = Builder.fromText t
renderBuilder (TeXComm name []) = "\\" <> fromString name <> "{}"
renderBuilder (TeXComm name args) =
"\\"
<> fromString name
<> renderAppendBuilder args
renderBuilder (TeXCommS name) = "\\" <> fromString name
renderBuilder (TeXEnv name args c) =
"\\begin{"
<> fromString name
<> "}"
<> renderAppendBuilder args
<> renderBuilder c
<> "\\end{"
<> fromString name
<> "}"
renderBuilder (TeXMath Dollar l) = "$" <> renderBuilder l <> "$"
renderBuilder (TeXMath DoubleDollar l) = "$$" <> renderBuilder l <> "$$"
renderBuilder (TeXMath Square l) = "\\[" <> renderBuilder l <> "\\]"
renderBuilder (TeXMath Parentheses l) = "\\(" <> renderBuilder l <> "\\)"
renderBuilder (TeXLineBreak m b) = "\\\\" <> maybe mempty (\x -> "[" <> renderBuilder x <> "]") m <> ( if b then "*" else mempty )
renderBuilder (TeXBraces l) = "{" <> renderBuilder l <> "}"
renderBuilder (TeXComment c) =
let xs = Data.Text.lines c
in if null xs then "%\n"
else Builder.fromText $ Data.Text.unlines $ fmap ("%" <>) xs
renderBuilder (TeXSeq l1 l2) = renderBuilder l1 <> renderBuilder l2
renderBuilder TeXEmpty = mempty
render = renderDefault
instance Render TeXArg where
renderBuilder (FixArg l) = "{" <> renderBuilder l <> "}"
renderBuilder (OptArg l) = "[" <> renderBuilder l <> "]"
renderBuilder (MOptArg []) = mempty
renderBuilder (MOptArg ls) = "[" <> renderCommasBuilder ls <> "]"
renderBuilder (SymArg l) = "<" <> renderBuilder l <> ">"
renderBuilder (MSymArg []) = mempty
renderBuilder (MSymArg ls) = "<" <> renderCommasBuilder ls <> ">"
renderBuilder (ParArg l) = "(" <> renderBuilder l <> ")"
renderBuilder (MParArg []) = mempty
renderBuilder (MParArg ls) = "(" <> renderCommasBuilder ls <> ")"
render = renderDefault
showFloat :: RealFloat a => a -> String
showFloat x = showFFloat (Just 5) x []
instance Render Int where
renderBuilder = Builder.decimal
render = renderDefault
instance Render Integer where
renderBuilder = Builder.decimal
render = renderDefault
instance Render Float where
renderBuilder = Builder.formatRealFloat Builder.Fixed (Just 5)
render = renderDefault
instance Render Double where
renderBuilder = Builder.formatRealFloat Builder.Fixed (Just 5)
render = renderDefault
instance Render Word8 where
renderBuilder = Builder.decimal
render = renderDefault
instance Render Bool where
render True = "true"
render _ = "false"
instance Render a => Render [a] where
renderBuilder xs = "[" <> renderCommasBuilder xs <> "]"
render = renderDefault