semdoc-0.1.3: src/Text/Semdoc/Processor.hs
{-# LANGUAGE LambdaCase #-}
module Text.Semdoc.Processor where
import qualified Control.Monad.State.Strict as CMS
import qualified Data.Set as Set
import Text.Groom (groom)
import Text.Pandoc (Block (..))
import qualified Text.Pandoc as Pandoc
import Text.Pandoc.Error (PandocError)
import Text.Pandoc.Walk (walk, walkM)
import Text.Semdoc.EvalExpr (evalExpr)
import Text.Semdoc.InlineHaskell (Input (Input), extractExprs,
replaceExprs)
readerOpts :: Pandoc.ReaderOptions
readerOpts = Pandoc.def
{ Pandoc.readerExtensions = Set.fromList [Pandoc.Ext_literate_haskell]
, Pandoc.readerParseRaw = True
}
semdocExtensions :: Set.Set Pandoc.Extension
semdocExtensions =
Set.insert Pandoc.Ext_tex_math_dollars $
foldl (flip Set.delete) Pandoc.githubMarkdownExtensions
[ Pandoc.Ext_hard_line_breaks
, Pandoc.Ext_native_spans
, Pandoc.Ext_raw_html
, Pandoc.Ext_tex_math_single_backslash
]
eraseCodeBlocks :: Block -> Block
eraseCodeBlocks (CodeBlock ("", ["sourceCode", "literate", "haskell"], []) _) = Null
eraseCodeBlocks x = x
processDoc :: Pandoc.Pandoc -> IO String
processDoc doc@(Pandoc.Pandoc _ parsed) = do
putStrLn $ "[=] processing " ++ show (length parsed) ++ " toplevel blocks"
--putStrLn $ groom parsed
let Input exprsBlock exprsInline _ _ = snd . CMS.runState (walkM extractExprs doc) $ Pandoc.def
putStrLn $ "[=] evaluating " ++ show (length exprsBlock) ++ " block expressions"
resultsBlock <- evalExpr exprsBlock
putStrLn $ "[=] evaluating " ++ show (length exprsInline) ++ " inline expressions"
resultsInline <- evalExpr exprsInline
putStrLn $ "[=] inserting " ++ show (length resultsBlock, length resultsInline) ++ " (block/inline) results"
let (evaluated, remaining) = CMS.runState (walkM replaceExprs doc) (resultsBlock, resultsInline)
case remaining of
([], []) ->
let withoutCode = walk eraseCodeBlocks evaluated in
return $ writeMarkdown withoutCode
_ ->
fail $ "extra results: " ++ groom remaining
phaseEval :: String -> IO String
phaseEval text = do
putStrLn $ "[=] parsing " ++ show (length text) ++ " characters"
case Pandoc.readLaTeX readerOpts text of
Left parseError -> fail $ groom parseError
Right doc -> processDoc doc
readMarkdown :: String -> Either PandocError Pandoc.Pandoc
readMarkdown =
Pandoc.readMarkdown Pandoc.def
{ Pandoc.readerExtensions = semdocExtensions
, Pandoc.readerColumns = 79
}
writeMarkdown :: Pandoc.Pandoc -> String
writeMarkdown =
Pandoc.writeMarkdown Pandoc.def
{ Pandoc.writerExtensions = semdocExtensions
, Pandoc.writerColumns = 79
, Pandoc.writerSetextHeaders = False
, Pandoc.writerTeXLigatures = False
}