{-# LANGUAGE FlexibleContexts #-}
module Text.Pandoc.Lua.Filter ( LuaFilterFunction
, LuaFilter
, runFilterFile
, walkInlines
, walkBlocks
, module Text.Pandoc.Lua.Walk
) where
import Control.Applicative ((<|>))
import Control.Monad (mplus, (>=>))
import Control.Monad.Catch (finally, try)
import Data.Data (Data, DataType, dataTypeConstrs, dataTypeName, dataTypeOf,
showConstr, toConstr, tyconUQname)
import Data.Foldable (foldrM)
import Data.List (foldl')
import Data.Map (Map)
import Data.Maybe (fromMaybe)
import Foreign.Lua (Lua, Peekable, Pushable, StackIndex)
import Text.Pandoc.Definition
import Text.Pandoc.Error (PandocError)
import Text.Pandoc.Lua.Marshaling ()
import Text.Pandoc.Lua.Marshaling.List (List (..))
import Text.Pandoc.Lua.Walk (SingletonsList (..))
import Text.Pandoc.Walk (Walkable (walkM))
import qualified Data.Map.Strict as Map
import qualified Foreign.Lua as Lua
import qualified Text.Pandoc.Lua.Util as LuaUtil
runFilterFile :: FilePath -> Pandoc -> Lua Pandoc
runFilterFile :: String -> Pandoc -> Lua Pandoc
runFilterFile String
filterPath Pandoc
doc = do
StackIndex
top <- Lua StackIndex
Lua.gettop
Status
stat <- String -> Lua Status
LuaUtil.dofileWithTraceback String
filterPath
if Status
stat Status -> Status -> Bool
forall a. Eq a => a -> a -> Bool
/= Status
Lua.OK
then Lua Pandoc
forall a. Lua a
Lua.throwTopMessage
else do
StackIndex
newtop <- Lua StackIndex
Lua.gettop
[LuaFilter]
luaFilters <- if StackIndex
newtop StackIndex -> StackIndex -> StackIndex
forall a. Num a => a -> a -> a
- StackIndex
top StackIndex -> StackIndex -> Bool
forall a. Ord a => a -> a -> Bool
>= StackIndex
1
then StackIndex -> Lua [LuaFilter]
forall a. Peekable a => StackIndex -> Lua a
Lua.peek StackIndex
Lua.stackTop
else Lua ()
Lua.pushglobaltable Lua () -> Lua [LuaFilter] -> Lua [LuaFilter]
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> (LuaFilter -> [LuaFilter]) -> Lua LuaFilter -> Lua [LuaFilter]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (LuaFilter -> [LuaFilter] -> [LuaFilter]
forall a. a -> [a] -> [a]
:[]) Lua LuaFilter
forall a. Peekable a => Lua a
Lua.popValue
[LuaFilter] -> Pandoc -> Lua Pandoc
runAll [LuaFilter]
luaFilters Pandoc
doc
runAll :: [LuaFilter] -> Pandoc -> Lua Pandoc
runAll :: [LuaFilter] -> Pandoc -> Lua Pandoc
runAll = (LuaFilter -> (Pandoc -> Lua Pandoc) -> Pandoc -> Lua Pandoc)
-> (Pandoc -> Lua Pandoc) -> [LuaFilter] -> Pandoc -> Lua Pandoc
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr ((Pandoc -> Lua Pandoc)
-> (Pandoc -> Lua Pandoc) -> Pandoc -> Lua Pandoc
forall (m :: * -> *) a b c.
Monad m =>
(a -> m b) -> (b -> m c) -> a -> m c
(>=>) ((Pandoc -> Lua Pandoc)
-> (Pandoc -> Lua Pandoc) -> Pandoc -> Lua Pandoc)
-> (LuaFilter -> Pandoc -> Lua Pandoc)
-> LuaFilter
-> (Pandoc -> Lua Pandoc)
-> Pandoc
-> Lua Pandoc
forall b c a. (b -> c) -> (a -> b) -> a -> c
. LuaFilter -> Pandoc -> Lua Pandoc
walkMWithLuaFilter) Pandoc -> Lua Pandoc
forall (m :: * -> *) a. Monad m => a -> m a
return
newtype LuaFilterFunction = LuaFilterFunction Lua.Reference
newtype LuaFilter = LuaFilter (Map String LuaFilterFunction)
instance Peekable LuaFilter where
peek :: StackIndex -> Lua LuaFilter
peek StackIndex
idx = do
let constrs :: [String]
constrs = String
listOfInlinesFilterName
String -> [String] -> [String]
forall a. a -> [a] -> [a]
: String
listOfBlocksFilterName
String -> [String] -> [String]
forall a. a -> [a] -> [a]
: String
metaFilterName
String -> [String] -> [String]
forall a. a -> [a] -> [a]
: [String]
pandocFilterNames
[String] -> [String] -> [String]
forall a. [a] -> [a] -> [a]
++ [String]
blockElementNames
[String] -> [String] -> [String]
forall a. [a] -> [a] -> [a]
++ [String]
inlineElementNames
let go :: String
-> Map String LuaFilterFunction
-> Lua (Map String LuaFilterFunction)
go String
constr Map String LuaFilterFunction
acc = do
StackIndex -> String -> Lua ()
Lua.getfield StackIndex
idx String
constr
Maybe LuaFilterFunction
filterFn <- Lua (Maybe LuaFilterFunction)
registerFilterFunction
Map String LuaFilterFunction -> Lua (Map String LuaFilterFunction)
forall (m :: * -> *) a. Monad m => a -> m a
return (Map String LuaFilterFunction
-> Lua (Map String LuaFilterFunction))
-> Map String LuaFilterFunction
-> Lua (Map String LuaFilterFunction)
forall a b. (a -> b) -> a -> b
$ case Maybe LuaFilterFunction
filterFn of
Maybe LuaFilterFunction
Nothing -> Map String LuaFilterFunction
acc
Just LuaFilterFunction
fn -> String
-> LuaFilterFunction
-> Map String LuaFilterFunction
-> Map String LuaFilterFunction
forall k a. Ord k => k -> a -> Map k a -> Map k a
Map.insert String
constr LuaFilterFunction
fn Map String LuaFilterFunction
acc
Map String LuaFilterFunction -> LuaFilter
LuaFilter (Map String LuaFilterFunction -> LuaFilter)
-> Lua (Map String LuaFilterFunction) -> Lua LuaFilter
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (String
-> Map String LuaFilterFunction
-> Lua (Map String LuaFilterFunction))
-> Map String LuaFilterFunction
-> [String]
-> Lua (Map String LuaFilterFunction)
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> b -> m b) -> b -> t a -> m b
foldrM String
-> Map String LuaFilterFunction
-> Lua (Map String LuaFilterFunction)
go Map String LuaFilterFunction
forall k a. Map k a
Map.empty [String]
constrs
registerFilterFunction :: Lua (Maybe LuaFilterFunction)
registerFilterFunction :: Lua (Maybe LuaFilterFunction)
registerFilterFunction = do
Bool
isFn <- StackIndex -> Lua Bool
Lua.isfunction StackIndex
Lua.stackTop
if Bool
isFn
then LuaFilterFunction -> Maybe LuaFilterFunction
forall a. a -> Maybe a
Just (LuaFilterFunction -> Maybe LuaFilterFunction)
-> (Reference -> LuaFilterFunction)
-> Reference
-> Maybe LuaFilterFunction
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Reference -> LuaFilterFunction
LuaFilterFunction (Reference -> Maybe LuaFilterFunction)
-> Lua Reference -> Lua (Maybe LuaFilterFunction)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> StackIndex -> Lua Reference
Lua.ref StackIndex
Lua.registryindex
else Maybe LuaFilterFunction
forall a. Maybe a
Nothing Maybe LuaFilterFunction -> Lua () -> Lua (Maybe LuaFilterFunction)
forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ StackIndex -> Lua ()
Lua.pop StackIndex
1
pushFilterFunction :: LuaFilterFunction -> Lua ()
pushFilterFunction :: LuaFilterFunction -> Lua ()
pushFilterFunction (LuaFilterFunction Reference
fnRef) =
StackIndex -> Reference -> Lua ()
Lua.getref StackIndex
Lua.registryindex Reference
fnRef
elementOrList :: Peekable a => a -> Lua [a]
elementOrList :: forall a. Peekable a => a -> Lua [a]
elementOrList a
x = do
let topOfStack :: StackIndex
topOfStack = StackIndex
Lua.stackTop
Bool
elementUnchanged <- StackIndex -> Lua Bool
Lua.isnil StackIndex
topOfStack
if Bool
elementUnchanged
then [a
x] [a] -> Lua () -> Lua [a]
forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ StackIndex -> Lua ()
Lua.pop StackIndex
1
else do
Either PandocError a
mbres <- StackIndex -> Lua (Either PandocError a)
forall a. Peekable a => StackIndex -> Lua (Either PandocError a)
peekEither StackIndex
topOfStack
case Either PandocError a
mbres of
Right a
res -> [a
res] [a] -> Lua () -> Lua [a]
forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ StackIndex -> Lua ()
Lua.pop StackIndex
1
Left PandocError
_ -> StackIndex -> Lua [a]
forall a. Peekable a => StackIndex -> Lua [a]
Lua.peekList StackIndex
topOfStack Lua [a] -> Lua () -> Lua [a]
forall (m :: * -> *) a b. MonadMask m => m a -> m b -> m a
`finally` StackIndex -> Lua ()
Lua.pop StackIndex
1
popOption :: Peekable a => a -> Lua a
popOption :: forall a. Peekable a => a -> Lua a
popOption a
fallback = a -> Maybe a -> a
forall a. a -> Maybe a -> a
fromMaybe a
fallback (Maybe a -> a) -> (Optional a -> Maybe a) -> Optional a -> a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Optional a -> Maybe a
forall a. Optional a -> Maybe a
Lua.fromOptional (Optional a -> a) -> Lua (Optional a) -> Lua a
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Lua (Optional a)
forall a. Peekable a => Lua a
Lua.popValue
runOnSequence :: (Data a, Peekable a, Pushable a)
=> LuaFilter -> SingletonsList a -> Lua (SingletonsList a)
runOnSequence :: forall a.
(Data a, Peekable a, Pushable a) =>
LuaFilter -> SingletonsList a -> Lua (SingletonsList a)
runOnSequence (LuaFilter Map String LuaFilterFunction
fnMap) (SingletonsList [a]
xs) =
[a] -> SingletonsList a
forall a. [a] -> SingletonsList a
SingletonsList ([a] -> SingletonsList a) -> Lua [a] -> Lua (SingletonsList a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (a -> Lua [a]) -> [a] -> Lua [a]
forall (m :: * -> *) a. Monad m => (a -> m [a]) -> [a] -> m [a]
mconcatMapM a -> Lua [a]
forall a. (Data a, Peekable a, Pushable a) => a -> Lua [a]
tryFilter [a]
xs
where
tryFilter :: (Data a, Peekable a, Pushable a) => a -> Lua [a]
tryFilter :: forall a. (Data a, Peekable a, Pushable a) => a -> Lua [a]
tryFilter a
x =
let filterFnName :: String
filterFnName = Constr -> String
showConstr (a -> Constr
forall a. Data a => a -> Constr
toConstr a
x)
catchAllName :: String
catchAllName = String -> String
tyconUQname (String -> String) -> String -> String
forall a b. (a -> b) -> a -> b
$ DataType -> String
dataTypeName (a -> DataType
forall a. Data a => a -> DataType
dataTypeOf a
x)
in case String -> Map String LuaFilterFunction -> Maybe LuaFilterFunction
forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup String
filterFnName Map String LuaFilterFunction
fnMap Maybe LuaFilterFunction
-> Maybe LuaFilterFunction -> Maybe LuaFilterFunction
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> String -> Map String LuaFilterFunction -> Maybe LuaFilterFunction
forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup String
catchAllName Map String LuaFilterFunction
fnMap of
Just LuaFilterFunction
fn -> LuaFilterFunction -> a -> Lua ()
forall a. Pushable a => LuaFilterFunction -> a -> Lua ()
runFilterFunction LuaFilterFunction
fn a
x Lua () -> Lua [a] -> Lua [a]
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> a -> Lua [a]
forall a. Peekable a => a -> Lua [a]
elementOrList a
x
Maybe LuaFilterFunction
Nothing -> [a] -> Lua [a]
forall (m :: * -> *) a. Monad m => a -> m a
return [a
x]
runOnValue :: (Data a, Peekable a, Pushable a)
=> String -> LuaFilter -> a -> Lua a
runOnValue :: forall a.
(Data a, Peekable a, Pushable a) =>
String -> LuaFilter -> a -> Lua a
runOnValue String
filterFnName (LuaFilter Map String LuaFilterFunction
fnMap) a
x =
case String -> Map String LuaFilterFunction -> Maybe LuaFilterFunction
forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup String
filterFnName Map String LuaFilterFunction
fnMap of
Just LuaFilterFunction
fn -> LuaFilterFunction -> a -> Lua ()
forall a. Pushable a => LuaFilterFunction -> a -> Lua ()
runFilterFunction LuaFilterFunction
fn a
x Lua () -> Lua a -> Lua a
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> a -> Lua a
forall a. Peekable a => a -> Lua a
popOption a
x
Maybe LuaFilterFunction
Nothing -> a -> Lua a
forall (m :: * -> *) a. Monad m => a -> m a
return a
x
runFilterFunction :: Pushable a => LuaFilterFunction -> a -> Lua ()
runFilterFunction :: forall a. Pushable a => LuaFilterFunction -> a -> Lua ()
runFilterFunction LuaFilterFunction
lf a
x = do
LuaFilterFunction -> Lua ()
pushFilterFunction LuaFilterFunction
lf
a -> Lua ()
forall a. Pushable a => a -> Lua ()
Lua.push a
x
NumArgs -> NumResults -> Lua ()
LuaUtil.callWithTraceback NumArgs
1 NumResults
1
walkMWithLuaFilter :: LuaFilter -> Pandoc -> Lua Pandoc
walkMWithLuaFilter :: LuaFilter -> Pandoc -> Lua Pandoc
walkMWithLuaFilter LuaFilter
f =
LuaFilter -> Pandoc -> Lua Pandoc
forall a.
Walkable (SingletonsList Inline) a =>
LuaFilter -> a -> Lua a
walkInlines LuaFilter
f
(Pandoc -> Lua Pandoc)
-> (Pandoc -> Lua Pandoc) -> Pandoc -> Lua Pandoc
forall (m :: * -> *) a b c.
Monad m =>
(a -> m b) -> (b -> m c) -> a -> m c
>=> LuaFilter -> Pandoc -> Lua Pandoc
forall a. Walkable (List Inline) a => LuaFilter -> a -> Lua a
walkInlineLists LuaFilter
f
(Pandoc -> Lua Pandoc)
-> (Pandoc -> Lua Pandoc) -> Pandoc -> Lua Pandoc
forall (m :: * -> *) a b c.
Monad m =>
(a -> m b) -> (b -> m c) -> a -> m c
>=> LuaFilter -> Pandoc -> Lua Pandoc
forall a.
Walkable (SingletonsList Block) a =>
LuaFilter -> a -> Lua a
walkBlocks LuaFilter
f
(Pandoc -> Lua Pandoc)
-> (Pandoc -> Lua Pandoc) -> Pandoc -> Lua Pandoc
forall (m :: * -> *) a b c.
Monad m =>
(a -> m b) -> (b -> m c) -> a -> m c
>=> LuaFilter -> Pandoc -> Lua Pandoc
forall a. Walkable (List Block) a => LuaFilter -> a -> Lua a
walkBlockLists LuaFilter
f
(Pandoc -> Lua Pandoc)
-> (Pandoc -> Lua Pandoc) -> Pandoc -> Lua Pandoc
forall (m :: * -> *) a b c.
Monad m =>
(a -> m b) -> (b -> m c) -> a -> m c
>=> LuaFilter -> Pandoc -> Lua Pandoc
walkMeta LuaFilter
f
(Pandoc -> Lua Pandoc)
-> (Pandoc -> Lua Pandoc) -> Pandoc -> Lua Pandoc
forall (m :: * -> *) a b c.
Monad m =>
(a -> m b) -> (b -> m c) -> a -> m c
>=> LuaFilter -> Pandoc -> Lua Pandoc
walkPandoc LuaFilter
f
mconcatMapM :: (Monad m) => (a -> m [a]) -> [a] -> m [a]
mconcatMapM :: forall (m :: * -> *) a. Monad m => (a -> m [a]) -> [a] -> m [a]
mconcatMapM a -> m [a]
f = ([[a]] -> [a]) -> m [[a]] -> m [a]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap [[a]] -> [a]
forall a. Monoid a => [a] -> a
mconcat (m [[a]] -> m [a]) -> ([a] -> m [[a]]) -> [a] -> m [a]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (a -> m [a]) -> [a] -> m [[a]]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM a -> m [a]
f
hasOneOf :: LuaFilter -> [String] -> Bool
hasOneOf :: LuaFilter -> [String] -> Bool
hasOneOf (LuaFilter Map String LuaFilterFunction
fnMap) = (String -> Bool) -> [String] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any (String -> Map String LuaFilterFunction -> Bool
forall k a. Ord k => k -> Map k a -> Bool
`Map.member` Map String LuaFilterFunction
fnMap)
contains :: LuaFilter -> String -> Bool
contains :: LuaFilter -> String -> Bool
contains (LuaFilter Map String LuaFilterFunction
fnMap) = (String -> Map String LuaFilterFunction -> Bool
forall k a. Ord k => k -> Map k a -> Bool
`Map.member` Map String LuaFilterFunction
fnMap)
walkInlines :: Walkable (SingletonsList Inline) a => LuaFilter -> a -> Lua a
walkInlines :: forall a.
Walkable (SingletonsList Inline) a =>
LuaFilter -> a -> Lua a
walkInlines LuaFilter
lf =
let f :: SingletonsList Inline -> Lua (SingletonsList Inline)
f :: SingletonsList Inline -> Lua (SingletonsList Inline)
f = LuaFilter -> SingletonsList Inline -> Lua (SingletonsList Inline)
forall a.
(Data a, Peekable a, Pushable a) =>
LuaFilter -> SingletonsList a -> Lua (SingletonsList a)
runOnSequence LuaFilter
lf
in if LuaFilter
lf LuaFilter -> [String] -> Bool
`hasOneOf` [String]
inlineElementNames
then (SingletonsList Inline -> Lua (SingletonsList Inline))
-> a -> Lua a
forall a b (m :: * -> *).
(Walkable a b, Monad m, Applicative m, Functor m) =>
(a -> m a) -> b -> m b
walkM SingletonsList Inline -> Lua (SingletonsList Inline)
f
else a -> Lua a
forall (m :: * -> *) a. Monad m => a -> m a
return
walkInlineLists :: Walkable (List Inline) a => LuaFilter -> a -> Lua a
walkInlineLists :: forall a. Walkable (List Inline) a => LuaFilter -> a -> Lua a
walkInlineLists LuaFilter
lf =
let f :: List Inline -> Lua (List Inline)
f :: List Inline -> Lua (List Inline)
f = String -> LuaFilter -> List Inline -> Lua (List Inline)
forall a.
(Data a, Peekable a, Pushable a) =>
String -> LuaFilter -> a -> Lua a
runOnValue String
listOfInlinesFilterName LuaFilter
lf
in if LuaFilter
lf LuaFilter -> String -> Bool
`contains` String
listOfInlinesFilterName
then (List Inline -> Lua (List Inline)) -> a -> Lua a
forall a b (m :: * -> *).
(Walkable a b, Monad m, Applicative m, Functor m) =>
(a -> m a) -> b -> m b
walkM List Inline -> Lua (List Inline)
f
else a -> Lua a
forall (m :: * -> *) a. Monad m => a -> m a
return
walkBlocks :: Walkable (SingletonsList Block) a => LuaFilter -> a -> Lua a
walkBlocks :: forall a.
Walkable (SingletonsList Block) a =>
LuaFilter -> a -> Lua a
walkBlocks LuaFilter
lf =
let f :: SingletonsList Block -> Lua (SingletonsList Block)
f :: SingletonsList Block -> Lua (SingletonsList Block)
f = LuaFilter -> SingletonsList Block -> Lua (SingletonsList Block)
forall a.
(Data a, Peekable a, Pushable a) =>
LuaFilter -> SingletonsList a -> Lua (SingletonsList a)
runOnSequence LuaFilter
lf
in if LuaFilter
lf LuaFilter -> [String] -> Bool
`hasOneOf` [String]
blockElementNames
then (SingletonsList Block -> Lua (SingletonsList Block)) -> a -> Lua a
forall a b (m :: * -> *).
(Walkable a b, Monad m, Applicative m, Functor m) =>
(a -> m a) -> b -> m b
walkM SingletonsList Block -> Lua (SingletonsList Block)
f
else a -> Lua a
forall (m :: * -> *) a. Monad m => a -> m a
return
walkBlockLists :: Walkable (List Block) a => LuaFilter -> a -> Lua a
walkBlockLists :: forall a. Walkable (List Block) a => LuaFilter -> a -> Lua a
walkBlockLists LuaFilter
lf =
let f :: List Block -> Lua (List Block)
f :: List Block -> Lua (List Block)
f = String -> LuaFilter -> List Block -> Lua (List Block)
forall a.
(Data a, Peekable a, Pushable a) =>
String -> LuaFilter -> a -> Lua a
runOnValue String
listOfBlocksFilterName LuaFilter
lf
in if LuaFilter
lf LuaFilter -> String -> Bool
`contains` String
listOfBlocksFilterName
then (List Block -> Lua (List Block)) -> a -> Lua a
forall a b (m :: * -> *).
(Walkable a b, Monad m, Applicative m, Functor m) =>
(a -> m a) -> b -> m b
walkM List Block -> Lua (List Block)
f
else a -> Lua a
forall (m :: * -> *) a. Monad m => a -> m a
return
walkMeta :: LuaFilter -> Pandoc -> Lua Pandoc
walkMeta :: LuaFilter -> Pandoc -> Lua Pandoc
walkMeta LuaFilter
lf (Pandoc Meta
m [Block]
bs) = do
Meta
m' <- String -> LuaFilter -> Meta -> Lua Meta
forall a.
(Data a, Peekable a, Pushable a) =>
String -> LuaFilter -> a -> Lua a
runOnValue String
"Meta" LuaFilter
lf Meta
m
Pandoc -> Lua Pandoc
forall (m :: * -> *) a. Monad m => a -> m a
return (Pandoc -> Lua Pandoc) -> Pandoc -> Lua Pandoc
forall a b. (a -> b) -> a -> b
$ Meta -> [Block] -> Pandoc
Pandoc Meta
m' [Block]
bs
walkPandoc :: LuaFilter -> Pandoc -> Lua Pandoc
walkPandoc :: LuaFilter -> Pandoc -> Lua Pandoc
walkPandoc (LuaFilter Map String LuaFilterFunction
fnMap) =
case (Maybe LuaFilterFunction
-> Maybe LuaFilterFunction -> Maybe LuaFilterFunction)
-> Maybe LuaFilterFunction
-> [Maybe LuaFilterFunction]
-> Maybe LuaFilterFunction
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' Maybe LuaFilterFunction
-> Maybe LuaFilterFunction -> Maybe LuaFilterFunction
forall (m :: * -> *) a. MonadPlus m => m a -> m a -> m a
mplus Maybe LuaFilterFunction
forall a. Maybe a
Nothing ((String -> Maybe LuaFilterFunction)
-> [String] -> [Maybe LuaFilterFunction]
forall a b. (a -> b) -> [a] -> [b]
map (String -> Map String LuaFilterFunction -> Maybe LuaFilterFunction
forall k a. Ord k => k -> Map k a -> Maybe a
`Map.lookup` Map String LuaFilterFunction
fnMap) [String]
pandocFilterNames) of
Just LuaFilterFunction
fn -> \Pandoc
x -> LuaFilterFunction -> Pandoc -> Lua ()
forall a. Pushable a => LuaFilterFunction -> a -> Lua ()
runFilterFunction LuaFilterFunction
fn Pandoc
x Lua () -> Lua Pandoc -> Lua Pandoc
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> Pandoc -> Lua Pandoc
forall a. Peekable a => a -> Lua a
singleElement Pandoc
x
Maybe LuaFilterFunction
Nothing -> Pandoc -> Lua Pandoc
forall (m :: * -> *) a. Monad m => a -> m a
return
constructorsFor :: DataType -> [String]
constructorsFor :: DataType -> [String]
constructorsFor DataType
x = (Constr -> String) -> [Constr] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map Constr -> String
forall a. Show a => a -> String
show (DataType -> [Constr]
dataTypeConstrs DataType
x)
inlineElementNames :: [String]
inlineElementNames :: [String]
inlineElementNames = String
"Inline" String -> [String] -> [String]
forall a. a -> [a] -> [a]
: DataType -> [String]
constructorsFor (Inline -> DataType
forall a. Data a => a -> DataType
dataTypeOf (Text -> Inline
Str Text
forall a. Monoid a => a
mempty))
blockElementNames :: [String]
blockElementNames :: [String]
blockElementNames = String
"Block" String -> [String] -> [String]
forall a. a -> [a] -> [a]
: DataType -> [String]
constructorsFor (Block -> DataType
forall a. Data a => a -> DataType
dataTypeOf ([Inline] -> Block
Para []))
listOfInlinesFilterName :: String
listOfInlinesFilterName :: String
listOfInlinesFilterName = String
"Inlines"
listOfBlocksFilterName :: String
listOfBlocksFilterName :: String
listOfBlocksFilterName = String
"Blocks"
metaFilterName :: String
metaFilterName :: String
metaFilterName = String
"Meta"
pandocFilterNames :: [String]
pandocFilterNames :: [String]
pandocFilterNames = [String
"Pandoc", String
"Doc"]
singleElement :: Peekable a => a -> Lua a
singleElement :: forall a. Peekable a => a -> Lua a
singleElement a
x = do
Bool
elementUnchanged <- StackIndex -> Lua Bool
Lua.isnil (-StackIndex
1)
if Bool
elementUnchanged
then a
x a -> Lua () -> Lua a
forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ StackIndex -> Lua ()
Lua.pop StackIndex
1
else do
Either PandocError a
mbres <- StackIndex -> Lua (Either PandocError a)
forall a. Peekable a => StackIndex -> Lua (Either PandocError a)
peekEither (-StackIndex
1)
case Either PandocError a
mbres of
Right a
res -> a
res a -> Lua () -> Lua a
forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ StackIndex -> Lua ()
Lua.pop StackIndex
1
Left PandocError
err -> do
StackIndex -> Lua ()
Lua.pop StackIndex
1
String -> Lua a
forall a. String -> Lua a
Lua.throwMessage
(String
"Error while trying to get a filter's return " String -> String -> String
forall a. Semigroup a => a -> a -> a
<>
String
"value from Lua stack.\n" String -> String -> String
forall a. Semigroup a => a -> a -> a
<> PandocError -> String
forall a. Show a => a -> String
show PandocError
err)
peekEither :: Peekable a => StackIndex -> Lua (Either PandocError a)
peekEither :: forall a. Peekable a => StackIndex -> Lua (Either PandocError a)
peekEither = Lua a -> Lua (Either PandocError a)
forall (m :: * -> *) e a.
(MonadCatch m, Exception e) =>
m a -> m (Either e a)
try (Lua a -> Lua (Either PandocError a))
-> (StackIndex -> Lua a)
-> StackIndex
-> Lua (Either PandocError a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. StackIndex -> Lua a
forall a. Peekable a => StackIndex -> Lua a
Lua.peek