aboutsummaryrefslogtreecommitdiff
path: root/src/Text/Pandoc/Lua.hs
diff options
context:
space:
mode:
authorJohn MacFarlane <jgm@berkeley.edu>2017-06-29 17:07:30 +0200
committerJohn MacFarlane <jgm@berkeley.edu>2017-06-29 17:07:30 +0200
commitcb25326fa313690c3c67caa2a8b44642409fd24c (patch)
treeb817e86583cb7463b0b6f36acea22a220b5b54a4 /src/Text/Pandoc/Lua.hs
parent780a65f8a87b40d1a9ee269cd7a51699c42d497e (diff)
downloadpandoc-cb25326fa313690c3c67caa2a8b44642409fd24c.tar.gz
Text.Pandoc.Lua: more code simplification.
Also, now we check before running walkM that the function table actually does contain something relevant. E.g. if your filter just defines Str, there's no need to run walkM for blocks, meta, or the whole document. This should help performance a bit (and it does, in my tests).
Diffstat (limited to 'src/Text/Pandoc/Lua.hs')
-rw-r--r--src/Text/Pandoc/Lua.hs56
1 files changed, 26 insertions, 30 deletions
diff --git a/src/Text/Pandoc/Lua.hs b/src/Text/Pandoc/Lua.hs
index fd7bba0ac..87fb8fd6b 100644
--- a/src/Text/Pandoc/Lua.hs
+++ b/src/Text/Pandoc/Lua.hs
@@ -2,6 +2,7 @@
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE DeriveDataTypeable #-}
+{-# LANGUAGE ScopedTypeVariables #-}
{-
Copyright © 2017 Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>
@@ -34,10 +35,11 @@ module Text.Pandoc.Lua ( LuaException(..),
pushPandocModule ) where
import Control.Exception
-import Control.Monad (unless, when, (>=>))
+import Control.Monad (unless, when, (>=>), mplus)
import Control.Monad.Trans (MonadIO (..))
-import Data.Data (toConstr)
+import Data.Data (toConstr, showConstr, dataTypeOf, dataTypeConstrs, Data)
import Data.Map (Map)
+import Data.Maybe (isJust)
import Data.Typeable (Typeable)
import Scripting.Lua (LuaState, StackValue (..))
import Text.Pandoc.Definition
@@ -91,44 +93,38 @@ runAll = foldr ((>=>) . walkMWithLuaFilter) return
walkMWithLuaFilter :: LuaFilter -> Pandoc -> IO Pandoc
walkMWithLuaFilter (LuaFilter lua fnMap) =
- walkM (execInlineLuaFilter lua fnMap) >=>
- walkM (execBlockLuaFilter lua fnMap) >=>
- walkM (execMetaLuaFilter lua fnMap) >=>
- walkM (execDocLuaFilter lua fnMap)
+ (if hasOneOf (constructorsFor (dataTypeOf (Str [])))
+ then walkM (tryFilter lua fnMap :: Inline -> IO Inline)
+ else return)
+ >=>
+ (if hasOneOf (constructorsFor (dataTypeOf (Para [])))
+ then walkM (tryFilter lua fnMap :: Block -> IO Block)
+ else return)
+ >=>
+ (case Map.lookup "Meta" fnMap of
+ Just fn -> walkM (\(Pandoc meta blocks) -> do
+ meta' <- runFilterFunction lua fn meta
+ return $ Pandoc meta' blocks)
+ Nothing -> return)
+ >=>
+ (case Map.lookup "Pandoc" fnMap `mplus` Map.lookup "Doc" fnMap of
+ Just fn -> (runFilterFunction lua fn) :: Pandoc -> IO Pandoc
+ Nothing -> return)
+ where hasOneOf = any (\k -> isJust (Map.lookup k fnMap))
+ constructorsFor x = map show (dataTypeConstrs x)
type FunctionMap = Map String LuaFilterFunction
data LuaFilter = LuaFilter LuaState FunctionMap
newtype LuaFilterFunction = LuaFilterFunction { functionIndex :: Int }
-tryFilter :: StackValue a => LuaState -> FunctionMap -> String -> a -> IO a
-tryFilter lua fnMap filterFnName x =
+tryFilter :: (Data a, StackValue a) => LuaState -> FunctionMap -> a -> IO a
+tryFilter lua fnMap x =
+ let filterFnName = showConstr (toConstr x) in
case Map.lookup filterFnName fnMap of
Nothing -> return x
Just fn -> runFilterFunction lua fn x
-execDocLuaFilter :: LuaState
- -> FunctionMap
- -> Pandoc -> IO Pandoc
-execDocLuaFilter lua fnMap = tryFilter lua fnMap "Doc"
-
-execMetaLuaFilter :: LuaState
- -> FunctionMap
- -> Pandoc -> IO Pandoc
-execMetaLuaFilter lua fnMap (Pandoc meta blks) = do
- meta' <- tryFilter lua fnMap "Meta" meta
- return $ Pandoc meta' blks
-
-execBlockLuaFilter :: LuaState
- -> FunctionMap
- -> Block -> IO Block
-execBlockLuaFilter lua fnMap x = tryFilter lua fnMap (show (toConstr x)) x
-
-execInlineLuaFilter :: LuaState
- -> FunctionMap
- -> Inline -> IO Inline
-execInlineLuaFilter lua fnMap x = tryFilter lua fnMap (show (toConstr x)) x
-
instance StackValue LuaFilter where
valuetype _ = Lua.TTABLE
push = undefined