diff options
author | John MacFarlane <jgm@berkeley.edu> | 2017-06-29 17:07:30 +0200 |
---|---|---|
committer | John MacFarlane <jgm@berkeley.edu> | 2017-06-29 17:07:30 +0200 |
commit | cb25326fa313690c3c67caa2a8b44642409fd24c (patch) | |
tree | b817e86583cb7463b0b6f36acea22a220b5b54a4 | |
parent | 780a65f8a87b40d1a9ee269cd7a51699c42d497e (diff) | |
download | pandoc-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).
-rw-r--r-- | src/Text/Pandoc/Lua.hs | 56 |
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 |