-
Notifications
You must be signed in to change notification settings - Fork 1
/
DecoratedTex.hs
69 lines (56 loc) · 2.26 KB
/
DecoratedTex.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
{-# LANGUAGE DeriveFunctor,
DeriveFoldable,
DeriveTraversable #-}
module DecoratedTex where
import Prelude hiding (mapM)
import Data.Foldable hiding (all)
import Data.Traversable
import Control.Monad.Except hiding (mapM)
import Control.Applicative
import Utils
import qualified Text.LaTeX.Base.Syntax as L
import Text.LaTeX.Base.Render
import qualified Data.Text as T
import Data.Char
newtype Ref = Ref String deriving (Show, Eq)
data Chunk loc
= Raw Text
| Braced (Block loc)
| Env String [Arg loc] (Block loc)
| Command String (Maybe [Arg loc])
| Reference loc
deriving (Show, Functor, Foldable, Traversable, Eq)
data Arg loc
= FixArg (Block loc)
| OptArg (Block loc)
deriving (Show, Functor, Foldable, Traversable, Eq)
newtype Block loc = Block { unBlock :: [Chunk loc] }
deriving (Show, Functor, Foldable, Traversable, Eq)
decorate :: (Monad m, Functor m) => L.LaTeX -> ExceptT String m (Block Ref)
decorate = fmap Block . mapM goChunk . flatten
where
flatten (L.TeXSeq x y) = flatten x ++ flatten y
flatten (L.TeXComment _) = []
flatten L.TeXEmpty = []
flatten t = [t]
-- TODO: Add support for various commands a la pandoc
goChunk (L.TeXRaw s) = pure $ Raw s
goChunk (L.TeXComm "ref" [L.FixArg r]) = Reference . Ref <$> extractLabel r
goChunk (L.TeXComm s args) = Command (strip s) . Just <$> goArgs args
goChunk (L.TeXCommS s) = pure $ Command (strip s) Nothing
goChunk (L.TeXEnv e args t) = Env e <$> goArgs args <*> decorate t
goChunk t = pure (Raw (render t))
-- TODO: Line numbers
extractLabel (L.TeXRaw s) -- TODO: Check if this is too restrictive on labels
| T.all isAlphaNum s = pure . strip $ T.unpack s
extractLabel _ = throwError "Invalid argument to ref"
goArgs = mapM goArg
goArg (L.FixArg t) = FixArg <$> decorate t
goArg (L.OptArg t) = OptArg <$> decorate t
goArg _ = error "DecoratedTex.decorate: arg translation not implemented"
spaceChunk :: Chunk loc -> Bool
spaceChunk (Raw s) = T.all isSpace s
spaceChunk (Braced (Block b)) = all spaceChunk b
spaceChunk (Env {}) = False
spaceChunk (Command {}) = False
spaceChunk (Reference _) = False