{-# LANGUAGE FlexibleContexts #-}
module Text.Pandoc.Lua.Filter ( LuaFilterFunction
, LuaFilter
, runFilterFile
, walkInlines
, walkInlineLists
, walkBlocks
, walkBlockLists
, 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 :: FilePath -> Pandoc -> Lua Pandoc
runFilterFile FilePath
filterPath Pandoc
doc = do
StackIndex
top <- Lua StackIndex
Lua.gettop
Status
stat <- FilePath -> Lua Status
LuaUtil.dofileWithTraceback FilePath
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 :: [FilePath]
constrs = FilePath
listOfInlinesFilterName
FilePath -> [FilePath] -> [FilePath]
forall a. a -> [a] -> [a]
: FilePath
listOfBlocksFilterName
FilePath -> [FilePath] -> [FilePath]
forall a. a -> [a] -> [a]
: FilePath
metaFilterName
FilePath -> [FilePath] -> [FilePath]
forall a. a -> [a] -> [a]
: [FilePath]
pandocFilterNames
[FilePath] -> [FilePath] -> [FilePath]
forall a. [a] -> [a] -> [a]
++ [FilePath]
blockElementNames
[FilePath] -> [FilePath] -> [FilePath]
forall a. [a] -> [a] -> [a]
++ [FilePath]
inlineElementNames
let go :: FilePath
-> Map FilePath LuaFilterFunction
-> Lua (Map FilePath LuaFilterFunction)
go FilePath
constr Map FilePath LuaFilterFunction
acc = do
StackIndex -> FilePath -> Lua ()
Lua.getfield StackIndex
idx FilePath
constr
Maybe LuaFilterFunction
filterFn <- Lua (Maybe LuaFilterFunction)
registerFilterFunction
Map FilePath LuaFilterFunction
-> Lua (Map FilePath LuaFilterFunction)
forall (m :: * -> *) a. Monad m => a -> m a
return (Map FilePath LuaFilterFunction
-> Lua (Map FilePath LuaFilterFunction))
-> Map FilePath LuaFilterFunction
-> Lua (Map FilePath LuaFilterFunction)
forall a b. (a -> b) -> a -> b
$ case Maybe LuaFilterFunction
filterFn of
Maybe LuaFilterFunction
Nothing -> Map FilePath LuaFilterFunction
acc
Just LuaFilterFunction
fn -> FilePath
-> LuaFilterFunction
-> Map FilePath LuaFilterFunction
-> Map FilePath LuaFilterFunction
forall k a. Ord k => k -> a -> Map k a -> Map k a
Map.insert FilePath
constr LuaFilterFunction
fn Map FilePath LuaFilterFunction
acc
Map FilePath LuaFilterFunction -> LuaFilter
LuaFilter (Map FilePath LuaFilterFunction -> LuaFilter)
-> Lua (Map FilePath LuaFilterFunction) -> Lua LuaFilter
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (FilePath
-> Map FilePath LuaFilterFunction
-> Lua (Map FilePath LuaFilterFunction))
-> Map FilePath LuaFilterFunction
-> [FilePath]
-> Lua (Map FilePath LuaFilterFunction)
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> b -> m b) -> b -> t a -> m b
foldrM FilePath
-> Map FilePath LuaFilterFunction
-> Lua (Map FilePath LuaFilterFunction)
go Map FilePath LuaFilterFunction
forall k a. Map k a
Map.empty [FilePath]
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 :: 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 :: 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 :: LuaFilter -> SingletonsList a -> Lua (SingletonsList a)
runOnSequence (LuaFilter Map FilePath 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 :: a -> Lua [a]
tryFilter a
x =
let filterFnName :: FilePath
filterFnName = Constr -> FilePath
showConstr (a -> Constr
forall a. Data a => a -> Constr
toConstr a
x)
catchAllName :: FilePath
catchAllName = FilePath -> FilePath
tyconUQname (FilePath -> FilePath) -> FilePath -> FilePath
forall a b. (a -> b) -> a -> b
$ DataType -> FilePath
dataTypeName (a -> DataType
forall a. Data a => a -> DataType
dataTypeOf a
x)
in case FilePath
-> Map FilePath LuaFilterFunction -> Maybe LuaFilterFunction
forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup FilePath
filterFnName Map FilePath LuaFilterFunction
fnMap Maybe LuaFilterFunction
-> Maybe LuaFilterFunction -> Maybe LuaFilterFunction
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> FilePath
-> Map FilePath LuaFilterFunction -> Maybe LuaFilterFunction
forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup FilePath
catchAllName Map FilePath 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 :: FilePath -> LuaFilter -> a -> Lua a
runOnValue FilePath
filterFnName (LuaFilter Map FilePath LuaFilterFunction
fnMap) a
x =
case FilePath
-> Map FilePath LuaFilterFunction -> Maybe LuaFilterFunction
forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup FilePath
filterFnName Map FilePath 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 :: 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 :: (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 -> [FilePath] -> Bool
hasOneOf (LuaFilter Map FilePath LuaFilterFunction
fnMap) = (FilePath -> Bool) -> [FilePath] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any (FilePath -> Map FilePath LuaFilterFunction -> Bool
forall k a. Ord k => k -> Map k a -> Bool
`Map.member` Map FilePath LuaFilterFunction
fnMap)
contains :: LuaFilter -> String -> Bool
contains :: LuaFilter -> FilePath -> Bool
contains (LuaFilter Map FilePath LuaFilterFunction
fnMap) = (FilePath -> Map FilePath LuaFilterFunction -> Bool
forall k a. Ord k => k -> Map k a -> Bool
`Map.member` Map FilePath LuaFilterFunction
fnMap)
walkInlines :: Walkable (SingletonsList Inline) a => LuaFilter -> a -> Lua a
walkInlines :: 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 -> [FilePath] -> Bool
`hasOneOf` [FilePath]
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 :: LuaFilter -> a -> Lua a
walkInlineLists LuaFilter
lf =
let f :: List Inline -> Lua (List Inline)
f :: List Inline -> Lua (List Inline)
f = FilePath -> LuaFilter -> List Inline -> Lua (List Inline)
forall a.
(Data a, Peekable a, Pushable a) =>
FilePath -> LuaFilter -> a -> Lua a
runOnValue FilePath
listOfInlinesFilterName LuaFilter
lf
in if LuaFilter
lf LuaFilter -> FilePath -> Bool
`contains` FilePath
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 :: 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 -> [FilePath] -> Bool
`hasOneOf` [FilePath]
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 :: LuaFilter -> a -> Lua a
walkBlockLists LuaFilter
lf =
let f :: List Block -> Lua (List Block)
f :: List Block -> Lua (List Block)
f = FilePath -> LuaFilter -> List Block -> Lua (List Block)
forall a.
(Data a, Peekable a, Pushable a) =>
FilePath -> LuaFilter -> a -> Lua a
runOnValue FilePath
listOfBlocksFilterName LuaFilter
lf
in if LuaFilter
lf LuaFilter -> FilePath -> Bool
`contains` FilePath
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' <- FilePath -> LuaFilter -> Meta -> Lua Meta
forall a.
(Data a, Peekable a, Pushable a) =>
FilePath -> LuaFilter -> a -> Lua a
runOnValue FilePath
"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 FilePath 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 ((FilePath -> Maybe LuaFilterFunction)
-> [FilePath] -> [Maybe LuaFilterFunction]
forall a b. (a -> b) -> [a] -> [b]
map (FilePath
-> Map FilePath LuaFilterFunction -> Maybe LuaFilterFunction
forall k a. Ord k => k -> Map k a -> Maybe a
`Map.lookup` Map FilePath LuaFilterFunction
fnMap) [FilePath]
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 -> [FilePath]
constructorsFor DataType
x = (Constr -> FilePath) -> [Constr] -> [FilePath]
forall a b. (a -> b) -> [a] -> [b]
map Constr -> FilePath
forall a. Show a => a -> FilePath
show (DataType -> [Constr]
dataTypeConstrs DataType
x)
inlineElementNames :: [String]
inlineElementNames :: [FilePath]
inlineElementNames = FilePath
"Inline" FilePath -> [FilePath] -> [FilePath]
forall a. a -> [a] -> [a]
: DataType -> [FilePath]
constructorsFor (Inline -> DataType
forall a. Data a => a -> DataType
dataTypeOf (Text -> Inline
Str Text
forall a. Monoid a => a
mempty))
blockElementNames :: [String]
blockElementNames :: [FilePath]
blockElementNames = FilePath
"Block" FilePath -> [FilePath] -> [FilePath]
forall a. a -> [a] -> [a]
: DataType -> [FilePath]
constructorsFor (Block -> DataType
forall a. Data a => a -> DataType
dataTypeOf ([Inline] -> Block
Para []))
listOfInlinesFilterName :: String
listOfInlinesFilterName :: FilePath
listOfInlinesFilterName = FilePath
"Inlines"
listOfBlocksFilterName :: String
listOfBlocksFilterName :: FilePath
listOfBlocksFilterName = FilePath
"Blocks"
metaFilterName :: String
metaFilterName :: FilePath
metaFilterName = FilePath
"Meta"
pandocFilterNames :: [String]
pandocFilterNames :: [FilePath]
pandocFilterNames = [FilePath
"Pandoc", FilePath
"Doc"]
singleElement :: Peekable a => a -> Lua a
singleElement :: 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
FilePath -> Lua a
forall a. FilePath -> Lua a
Lua.throwMessage
(FilePath
"Error while trying to get a filter's return " FilePath -> FilePath -> FilePath
forall a. Semigroup a => a -> a -> a
<>
FilePath
"value from Lua stack.\n" FilePath -> FilePath -> FilePath
forall a. Semigroup a => a -> a -> a
<> PandocError -> FilePath
forall a. Show a => a -> FilePath
show PandocError
err)
peekEither :: Peekable a => StackIndex -> Lua (Either PandocError a)
peekEither :: 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