semdoc-0.1.0: src/Text/Semdoc/InlineHaskell.hs
module Text.Semdoc.InlineHaskell where
import qualified Control.Monad.State.Strict as CMS
import Data.Default.Class (Default (..))
import Text.Groom (groom)
import Text.Pandoc (Block (..), Format (..),
Inline (..))
import Text.Pandoc.Walk (walkM)
import Text.Regex.TDFA ((=~))
import Text.Semdoc.EvalExpr (EvalInput (..))
data Input = Input
{ inputsBlock :: [EvalInput Block]
, inputsInline :: [EvalInput Inline]
, currentModule :: String
, allModules :: [String]
}
instance Default Input where
def = Input
{ inputsBlock = []
, inputsInline = []
, currentModule = "Prelude"
, allModules = []
}
extractExprsInline :: Inline -> CMS.State Input Inline
extractExprsInline i =
case i of
RawInline (Format "latex") ('\\':'s':'h':'o':'w':'{':expr) -> doExtract expr
Code ("", [], []) ('\\':'s':'h':'o':'w':'{':expr) -> doExtract expr
_ -> return i
where
doExtract :: String -> CMS.State Input Inline
doExtract expr = do
let stmt = "it = " ++ init expr
input <- CMS.get
CMS.put input
{ inputsInline =
EvalInput (currentModule input) stmt : inputsInline input
}
return i
extractExprs :: Block -> CMS.State Input Block
extractExprs i =
case i of
CodeBlock ("", [], [("semdoc", "")]) code ->
doExtract code
CodeBlock ("", ["sourceCode", "literate", "haskell"], []) code ->
case code =~ "module ([A-Z][A-Za-z0-9_.]+)" of
[[_, modName]] -> do
input <- CMS.get
CMS.put input
{ currentModule = modName
, allModules = modName : allModules input
}
return i
_ ->
return i
CodeBlock {} -> return i
BulletList {} -> return i
OrderedList {} -> return i
Table {} -> return i
Plain {} -> walkM extractExprsInline i
Para {} -> walkM extractExprsInline i
Header {} -> walkM extractExprsInline i
_ -> error $ groom i
where
doExtract :: String -> CMS.State Input Block
doExtract stmt = do
input <- CMS.get
CMS.put input
{ inputsBlock =
EvalInput (currentModule input) stmt : inputsBlock input
}
return i
replaceExprsInline :: Inline -> CMS.State ([Block], [Inline]) Inline
replaceExprsInline i =
case i of
RawInline (Format "latex") ('\\':'s':'h':'o':'w':'{':_) -> doReplace
Code ("", [], []) ('\\':'s':'h':'o':'w':'{':_) -> doReplace
_ -> return i
where
doReplace :: CMS.State ([Block], [Inline]) Inline
doReplace = do
(resultsBlock, resultsInline) <- CMS.get
case resultsInline of
[] -> fail "insufficient results"
r:rs -> do
CMS.put (resultsBlock, rs)
return r
replaceExprs :: Block -> CMS.State ([Block], [Inline]) Block
replaceExprs i =
case i of
CodeBlock ("", [], [("semdoc", "")]) _ -> doReplace
CodeBlock {} -> return i
BulletList {} -> return i
OrderedList {} -> return i
Table {} -> return i
Plain {} -> walkM replaceExprsInline i
Para {} -> walkM replaceExprsInline i
Header {} -> walkM replaceExprsInline i
_ -> error $ groom i
where
doReplace :: CMS.State ([Block], [Inline]) Block
doReplace = do
(resultsBlock, resultsInline) <- CMS.get
case resultsBlock of
[] -> fail "insufficient results"
r:rs -> do
CMS.put (rs, resultsInline)
return r