{-# LANGUAGE FlexibleContexts     #-}
{-# LANGUAGE IncoherentInstances  #-}
{-# LANGUAGE OverloadedStrings    #-}
{-# LANGUAGE ScopedTypeVariables  #-}
{- |
Module      : Text.Pandoc.Lua.Filter
Copyright   : © 2012-2021 John MacFarlane,
              © 2017-2021 Albert Krewinkel
License     : GNU GPL, version 2 or above
Maintainer  : Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>
Stability   : alpha

Types and functions for running Lua filters.
-}
module Text.Pandoc.Lua.Filter ( LuaFilterFunction
                              , LuaFilter
                              , peekLuaFilter
                              , runFilterFile
                              , walkInlines
                              , walkInlineLists
                              , walkBlocks
                              , walkBlockLists
                              , module Text.Pandoc.Lua.Walk
                              ) where
import Control.Applicative ((<|>))
import Control.Monad (mplus, (>=>), (<$!>))
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.String (IsString (fromString))
import HsLua as Lua
import Text.Pandoc.Definition
import Text.Pandoc.Error (PandocError)
import Text.Pandoc.Lua.Marshaling ()
import Text.Pandoc.Lua.Marshaling.AST
import Text.Pandoc.Lua.Marshaling.List (List (..), peekList')
import Text.Pandoc.Lua.Walk (SingletonsList (..))
import Text.Pandoc.Walk (Walkable (walkM))

import qualified Data.Map.Strict as Map
import qualified Text.Pandoc.Lua.Util as LuaUtil

-- | Transform document using the filter defined in the given file.
runFilterFile :: FilePath -> Pandoc -> LuaE PandocError Pandoc
runFilterFile :: FilePath -> Pandoc -> LuaE PandocError Pandoc
runFilterFile FilePath
filterPath Pandoc
doc = do
  StackIndex
oldtop <- LuaE PandocError StackIndex
forall e. LuaE e StackIndex
Lua.gettop
  Status
stat <- FilePath -> LuaE PandocError Status
forall e. LuaError e => FilePath -> LuaE e Status
LuaUtil.dofileWithTraceback FilePath
filterPath
  if Status
stat Status -> Status -> Bool
forall a. Eq a => a -> a -> Bool
/= Status
Lua.OK
    then LuaE PandocError Pandoc
forall e a. LuaError e => LuaE e a
Lua.throwErrorAsException
    else do
      StackIndex
newtop <- LuaE PandocError StackIndex
forall e. LuaE e StackIndex
Lua.gettop
      -- Use the returned filters, or the implicitly defined global
      -- filter if nothing was returned.
      [LuaFilter]
luaFilters <- if StackIndex
newtop StackIndex -> StackIndex -> StackIndex
forall a. Num a => a -> a -> a
- StackIndex
oldtop StackIndex -> StackIndex -> Bool
forall a. Ord a => a -> a -> Bool
>= StackIndex
1
                    then StackIndex -> LuaE PandocError [LuaFilter]
forall a e. (Peekable a, PeekError e) => StackIndex -> LuaE e a
Lua.peek StackIndex
Lua.top
                    else LuaE PandocError ()
forall e. LuaE e ()
Lua.pushglobaltable LuaE PandocError ()
-> LuaE PandocError [LuaFilter] -> LuaE PandocError [LuaFilter]
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> (LuaFilter -> [LuaFilter])
-> LuaE PandocError LuaFilter -> LuaE PandocError [LuaFilter]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (LuaFilter -> [LuaFilter] -> [LuaFilter]
forall a. a -> [a] -> [a]
:[]) LuaE PandocError LuaFilter
forall e a. (PeekError e, Peekable a) => LuaE e a
Lua.popValue
      [LuaFilter] -> Pandoc -> LuaE PandocError Pandoc
runAll [LuaFilter]
luaFilters Pandoc
doc

runAll :: [LuaFilter] -> Pandoc -> LuaE PandocError Pandoc
runAll :: [LuaFilter] -> Pandoc -> LuaE PandocError Pandoc
runAll = (LuaFilter
 -> (Pandoc -> LuaE PandocError Pandoc)
 -> Pandoc
 -> LuaE PandocError Pandoc)
-> (Pandoc -> LuaE PandocError Pandoc)
-> [LuaFilter]
-> Pandoc
-> LuaE PandocError Pandoc
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr ((Pandoc -> LuaE PandocError Pandoc)
-> (Pandoc -> LuaE PandocError Pandoc)
-> Pandoc
-> LuaE PandocError Pandoc
forall (m :: * -> *) a b c.
Monad m =>
(a -> m b) -> (b -> m c) -> a -> m c
(>=>) ((Pandoc -> LuaE PandocError Pandoc)
 -> (Pandoc -> LuaE PandocError Pandoc)
 -> Pandoc
 -> LuaE PandocError Pandoc)
-> (LuaFilter -> Pandoc -> LuaE PandocError Pandoc)
-> LuaFilter
-> (Pandoc -> LuaE PandocError Pandoc)
-> Pandoc
-> LuaE PandocError Pandoc
forall b c a. (b -> c) -> (a -> b) -> a -> c
. LuaFilter -> Pandoc -> LuaE PandocError Pandoc
walkMWithLuaFilter) Pandoc -> LuaE PandocError Pandoc
forall (m :: * -> *) a. Monad m => a -> m a
return

-- | Filter function stored in the registry
newtype LuaFilterFunction = LuaFilterFunction Lua.Reference

-- | Collection of filter functions (at most one function per element
-- constructor)
newtype LuaFilter = LuaFilter (Map Name LuaFilterFunction)

instance Peekable LuaFilter where
  peek :: StackIndex -> LuaE e LuaFilter
peek = Peek e LuaFilter -> LuaE e LuaFilter
forall e a. LuaError e => Peek e a -> LuaE e a
Lua.forcePeek (Peek e LuaFilter -> LuaE e LuaFilter)
-> (StackIndex -> Peek e LuaFilter)
-> StackIndex
-> LuaE e LuaFilter
forall b c a. (b -> c) -> (a -> b) -> a -> c
. StackIndex -> Peek e LuaFilter
forall e. LuaError e => Peeker e LuaFilter
peekLuaFilter

-- | Retrieves a LuaFilter object from the stack.
peekLuaFilter :: LuaError e => Peeker e LuaFilter
peekLuaFilter :: Peeker e LuaFilter
peekLuaFilter StackIndex
idx = do
  let constrs :: [Name]
constrs = Name
listOfInlinesFilterName
              Name -> [Name] -> [Name]
forall a. a -> [a] -> [a]
: Name
listOfBlocksFilterName
              Name -> [Name] -> [Name]
forall a. a -> [a] -> [a]
: Name
metaFilterName
              Name -> [Name] -> [Name]
forall a. a -> [a] -> [a]
: [Name]
pandocFilterNames
              [Name] -> [Name] -> [Name]
forall a. [a] -> [a] -> [a]
++ [Name]
blockElementNames
              [Name] -> [Name] -> [Name]
forall a. [a] -> [a] -> [a]
++ [Name]
inlineElementNames
  let go :: Name
-> Map Name LuaFilterFunction
-> Peek e (Map Name LuaFilterFunction)
go Name
constr Map Name LuaFilterFunction
acc = LuaE e (Map Name LuaFilterFunction)
-> Peek e (Map Name LuaFilterFunction)
forall e a. LuaE e a -> Peek e a
Lua.liftLua (LuaE e (Map Name LuaFilterFunction)
 -> Peek e (Map Name LuaFilterFunction))
-> LuaE e (Map Name LuaFilterFunction)
-> Peek e (Map Name LuaFilterFunction)
forall a b. (a -> b) -> a -> b
$ do
        StackIndex -> Name -> LuaE e Type
forall e. LuaError e => StackIndex -> Name -> LuaE e Type
Lua.getfield StackIndex
idx Name
constr
        Maybe LuaFilterFunction
filterFn <- LuaE e (Maybe LuaFilterFunction)
forall e. LuaError e => LuaE e (Maybe LuaFilterFunction)
registerFilterFunction
        Map Name LuaFilterFunction -> LuaE e (Map Name LuaFilterFunction)
forall (m :: * -> *) a. Monad m => a -> m a
return (Map Name LuaFilterFunction -> LuaE e (Map Name LuaFilterFunction))
-> Map Name LuaFilterFunction
-> LuaE e (Map Name LuaFilterFunction)
forall a b. (a -> b) -> a -> b
$ case Maybe LuaFilterFunction
filterFn of
          Maybe LuaFilterFunction
Nothing -> Map Name LuaFilterFunction
acc
          Just LuaFilterFunction
fn -> Name
-> LuaFilterFunction
-> Map Name LuaFilterFunction
-> Map Name LuaFilterFunction
forall k a. Ord k => k -> a -> Map k a -> Map k a
Map.insert Name
constr LuaFilterFunction
fn Map Name LuaFilterFunction
acc
  Map Name LuaFilterFunction -> LuaFilter
LuaFilter (Map Name LuaFilterFunction -> LuaFilter)
-> Peek e (Map Name LuaFilterFunction) -> Peek e LuaFilter
forall (m :: * -> *) a b. Monad m => (a -> b) -> m a -> m b
<$!> (Name
 -> Map Name LuaFilterFunction
 -> Peek e (Map Name LuaFilterFunction))
-> Map Name LuaFilterFunction
-> [Name]
-> Peek e (Map Name LuaFilterFunction)
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> b -> m b) -> b -> t a -> m b
foldrM Name
-> Map Name LuaFilterFunction
-> Peek e (Map Name LuaFilterFunction)
forall e.
LuaError e =>
Name
-> Map Name LuaFilterFunction
-> Peek e (Map Name LuaFilterFunction)
go Map Name LuaFilterFunction
forall k a. Map k a
Map.empty [Name]
constrs

-- | Register the function at the top of the stack as a filter function in the
-- registry.
registerFilterFunction :: LuaError e => LuaE e (Maybe LuaFilterFunction)
registerFilterFunction :: LuaE e (Maybe LuaFilterFunction)
registerFilterFunction = do
  Bool
isFn <- StackIndex -> LuaE e Bool
forall e. StackIndex -> LuaE e Bool
Lua.isfunction StackIndex
Lua.top
  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)
-> LuaE e Reference -> LuaE e (Maybe LuaFilterFunction)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> StackIndex -> LuaE e Reference
forall e. StackIndex -> LuaE e Reference
Lua.ref StackIndex
Lua.registryindex
    else Maybe LuaFilterFunction
forall a. Maybe a
Nothing Maybe LuaFilterFunction
-> LuaE e () -> LuaE e (Maybe LuaFilterFunction)
forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ Int -> LuaE e ()
forall e. Int -> LuaE e ()
Lua.pop Int
1

-- | Retrieve filter function from registry and push it to the top of the stack.
pushFilterFunction :: LuaFilterFunction -> LuaE PandocError ()
pushFilterFunction :: LuaFilterFunction -> LuaE PandocError ()
pushFilterFunction (LuaFilterFunction Reference
fnRef) =
  StackIndex -> Reference -> LuaE PandocError ()
forall e. LuaError e => StackIndex -> Reference -> LuaE e ()
Lua.getref StackIndex
Lua.registryindex Reference
fnRef

-- | Fetch either a list of elements from the stack. If there is a single
-- element instead of a list, fetch that element as a singleton list. If the top
-- of the stack is nil, return the default element that was passed to this
-- function. If none of these apply, raise an error.
elementOrList :: Peeker PandocError a -> a -> LuaE PandocError [a]
elementOrList :: Peeker PandocError a -> a -> LuaE PandocError [a]
elementOrList Peeker PandocError a
p a
x = do
  Bool
elementUnchanged <- StackIndex -> LuaE PandocError Bool
forall e. StackIndex -> LuaE e Bool
Lua.isnil StackIndex
top
  if Bool
elementUnchanged
    then [a
x] [a] -> LuaE PandocError () -> LuaE PandocError [a]
forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ Int -> LuaE PandocError ()
forall e. Int -> LuaE e ()
pop Int
1
    else Peek PandocError [a] -> LuaE PandocError [a]
forall e a. LuaError e => Peek e a -> LuaE e a
forcePeek (Peek PandocError [a] -> LuaE PandocError [a])
-> (Peek PandocError [a] -> Peek PandocError [a])
-> Peek PandocError [a]
-> LuaE PandocError [a]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Peek PandocError [a] -> LuaE PandocError () -> Peek PandocError [a]
forall e a b. Peek e a -> LuaE e b -> Peek e a
`lastly` Int -> LuaE PandocError ()
forall e. Int -> LuaE e ()
pop Int
1) (Peek PandocError [a] -> LuaE PandocError [a])
-> Peek PandocError [a] -> LuaE PandocError [a]
forall a b. (a -> b) -> a -> b
$ (((a -> [a] -> [a]
forall a. a -> [a] -> [a]
:[]) (a -> [a]) -> Peek PandocError a -> Peek PandocError [a]
forall (m :: * -> *) a b. Monad m => (a -> b) -> m a -> m b
<$!> Peeker PandocError a
p StackIndex
top) Peek PandocError [a]
-> Peek PandocError [a] -> Peek PandocError [a]
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Peeker PandocError a -> Peeker PandocError [a]
forall a e. LuaError e => Peeker e a -> Peeker e [a]
peekList Peeker PandocError a
p StackIndex
top)

-- | Fetches a single element; returns the fallback if the value is @nil@.
singleElement :: forall a e. (LuaError e) => Peeker e a -> a -> LuaE e a
singleElement :: Peeker e a -> a -> LuaE e a
singleElement Peeker e a
p a
x = do
  Bool
elementUnchanged <- StackIndex -> LuaE e Bool
forall e. StackIndex -> LuaE e Bool
Lua.isnil StackIndex
top
  if Bool
elementUnchanged
    then a
x a -> LuaE e () -> LuaE e a
forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ Int -> LuaE e ()
forall e. Int -> LuaE e ()
Lua.pop Int
1
    else Peek e a -> LuaE e a
forall e a. LuaError e => Peek e a -> LuaE e a
forcePeek (Peek e a -> LuaE e a) -> Peek e a -> LuaE e a
forall a b. (a -> b) -> a -> b
$ Peeker e a
p StackIndex
top Peek e a -> LuaE e () -> Peek e a
forall e a b. Peek e a -> LuaE e b -> Peek e a
`lastly` Int -> LuaE e ()
forall e. Int -> LuaE e ()
pop Int
1

-- | Pop and return a value from the stack; if the value at the top of
-- the stack is @nil@, return the fallback element.
popOption :: Peeker PandocError a -> a -> LuaE PandocError a
popOption :: Peeker PandocError a -> a -> LuaE PandocError a
popOption Peeker PandocError a
peeker a
fallback = Peek PandocError a -> LuaE PandocError a
forall e a. LuaError e => Peek e a -> LuaE e a
forcePeek (Peek PandocError a -> LuaE PandocError a)
-> (Peek PandocError a -> Peek PandocError a)
-> Peek PandocError a
-> LuaE PandocError a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Peek PandocError a -> LuaE PandocError () -> Peek PandocError a
forall e a b. Peek e a -> LuaE e b -> Peek e a
`lastly` Int -> LuaE PandocError ()
forall e. Int -> LuaE e ()
pop Int
1) (Peek PandocError a -> LuaE PandocError a)
-> Peek PandocError a -> LuaE PandocError a
forall a b. (a -> b) -> a -> b
$
  (a
fallback a -> Peek PandocError () -> Peek PandocError a
forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ Peeker PandocError ()
forall e. Peeker e ()
peekNil StackIndex
top) Peek PandocError a -> Peek PandocError a -> Peek PandocError a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Peeker PandocError a
peeker StackIndex
top

-- | Apply filter on a sequence of AST elements. Both lists and single
-- value are accepted as filter function return values.
runOnSequence :: forall a. (Data a, Pushable a)
              => Peeker PandocError a -> LuaFilter -> SingletonsList a
              -> LuaE PandocError (SingletonsList a)
runOnSequence :: Peeker PandocError a
-> LuaFilter
-> SingletonsList a
-> LuaE PandocError (SingletonsList a)
runOnSequence Peeker PandocError a
peeker (LuaFilter Map Name LuaFilterFunction
fnMap) (SingletonsList [a]
xs) =
  [a] -> SingletonsList a
forall a. [a] -> SingletonsList a
SingletonsList ([a] -> SingletonsList a)
-> LuaE PandocError [a] -> LuaE PandocError (SingletonsList a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (a -> LuaE PandocError [a]) -> [a] -> LuaE PandocError [a]
forall (m :: * -> *) a. Monad m => (a -> m [a]) -> [a] -> m [a]
mconcatMapM a -> LuaE PandocError [a]
tryFilter [a]
xs
 where
  tryFilter :: a -> LuaE PandocError [a]
  tryFilter :: a -> LuaE PandocError [a]
tryFilter a
x =
    let filterFnName :: Name
filterFnName = FilePath -> Name
forall a. IsString a => FilePath -> a
fromString (FilePath -> Name) -> FilePath -> Name
forall a b. (a -> b) -> a -> b
$ Constr -> FilePath
showConstr (a -> Constr
forall a. Data a => a -> Constr
toConstr a
x)
        catchAllName :: Name
catchAllName = FilePath -> Name
forall a. IsString a => FilePath -> a
fromString (FilePath -> Name) -> (FilePath -> FilePath) -> FilePath -> Name
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath -> FilePath
tyconUQname (FilePath -> Name) -> FilePath -> Name
forall a b. (a -> b) -> a -> b
$ DataType -> FilePath
dataTypeName (a -> DataType
forall a. Data a => a -> DataType
dataTypeOf a
x)
    in case Name -> Map Name LuaFilterFunction -> Maybe LuaFilterFunction
forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup Name
filterFnName Map Name LuaFilterFunction
fnMap Maybe LuaFilterFunction
-> Maybe LuaFilterFunction -> Maybe LuaFilterFunction
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Name -> Map Name LuaFilterFunction -> Maybe LuaFilterFunction
forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup Name
catchAllName Map Name LuaFilterFunction
fnMap of
         Just LuaFilterFunction
fn -> LuaFilterFunction -> a -> LuaE PandocError ()
forall a.
Pushable a =>
LuaFilterFunction -> a -> LuaE PandocError ()
runFilterFunction LuaFilterFunction
fn a
x LuaE PandocError () -> LuaE PandocError [a] -> LuaE PandocError [a]
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> Peeker PandocError a -> a -> LuaE PandocError [a]
forall a. Peeker PandocError a -> a -> LuaE PandocError [a]
elementOrList Peeker PandocError a
peeker a
x
         Maybe LuaFilterFunction
Nothing -> [a] -> LuaE PandocError [a]
forall (m :: * -> *) a. Monad m => a -> m a
return [a
x]

-- | Try filtering the given value without type error corrections on
-- the return value.
runOnValue :: (Data a, Pushable a)
           => Name -> Peeker PandocError a
           -> LuaFilter -> a
           -> LuaE PandocError a
runOnValue :: Name
-> Peeker PandocError a -> LuaFilter -> a -> LuaE PandocError a
runOnValue Name
filterFnName Peeker PandocError a
peeker (LuaFilter Map Name LuaFilterFunction
fnMap) a
x =
  case Name -> Map Name LuaFilterFunction -> Maybe LuaFilterFunction
forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup Name
filterFnName Map Name LuaFilterFunction
fnMap of
    Just LuaFilterFunction
fn -> LuaFilterFunction -> a -> LuaE PandocError ()
forall a.
Pushable a =>
LuaFilterFunction -> a -> LuaE PandocError ()
runFilterFunction LuaFilterFunction
fn a
x LuaE PandocError () -> LuaE PandocError a -> LuaE PandocError a
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> Peeker PandocError a -> a -> LuaE PandocError a
forall a. Peeker PandocError a -> a -> LuaE PandocError a
popOption Peeker PandocError a
peeker a
x
    Maybe LuaFilterFunction
Nothing -> a -> LuaE PandocError a
forall (m :: * -> *) a. Monad m => a -> m a
return a
x

-- | Push a value to the stack via a Lua filter function. The filter
-- function is called with the given element as argument and is expected
-- to return an element. Alternatively, the function can return nothing
-- or nil, in which case the element is left unchanged.
runFilterFunction :: Pushable a
                  => LuaFilterFunction -> a -> LuaE PandocError ()
runFilterFunction :: LuaFilterFunction -> a -> LuaE PandocError ()
runFilterFunction LuaFilterFunction
lf a
x = do
  LuaFilterFunction -> LuaE PandocError ()
pushFilterFunction LuaFilterFunction
lf
  a -> LuaE PandocError ()
forall a e. (Pushable a, LuaError e) => a -> LuaE e ()
Lua.push a
x
  NumArgs -> NumResults -> LuaE PandocError ()
forall e. LuaError e => NumArgs -> NumResults -> LuaE e ()
LuaUtil.callWithTraceback NumArgs
1 NumResults
1

walkMWithLuaFilter :: LuaFilter -> Pandoc -> LuaE PandocError Pandoc
walkMWithLuaFilter :: LuaFilter -> Pandoc -> LuaE PandocError Pandoc
walkMWithLuaFilter LuaFilter
f =
      LuaFilter -> Pandoc -> LuaE PandocError Pandoc
forall a.
Walkable (SingletonsList Inline) a =>
LuaFilter -> a -> LuaE PandocError a
walkInlines LuaFilter
f
  (Pandoc -> LuaE PandocError Pandoc)
-> (Pandoc -> LuaE PandocError Pandoc)
-> Pandoc
-> LuaE PandocError Pandoc
forall (m :: * -> *) a b c.
Monad m =>
(a -> m b) -> (b -> m c) -> a -> m c
>=> LuaFilter -> Pandoc -> LuaE PandocError Pandoc
forall a.
Walkable (List Inline) a =>
LuaFilter -> a -> LuaE PandocError a
walkInlineLists LuaFilter
f
  (Pandoc -> LuaE PandocError Pandoc)
-> (Pandoc -> LuaE PandocError Pandoc)
-> Pandoc
-> LuaE PandocError Pandoc
forall (m :: * -> *) a b c.
Monad m =>
(a -> m b) -> (b -> m c) -> a -> m c
>=> LuaFilter -> Pandoc -> LuaE PandocError Pandoc
forall a.
Walkable (SingletonsList Block) a =>
LuaFilter -> a -> LuaE PandocError a
walkBlocks LuaFilter
f
  (Pandoc -> LuaE PandocError Pandoc)
-> (Pandoc -> LuaE PandocError Pandoc)
-> Pandoc
-> LuaE PandocError Pandoc
forall (m :: * -> *) a b c.
Monad m =>
(a -> m b) -> (b -> m c) -> a -> m c
>=> LuaFilter -> Pandoc -> LuaE PandocError Pandoc
forall a.
Walkable (List Block) a =>
LuaFilter -> a -> LuaE PandocError a
walkBlockLists LuaFilter
f
  (Pandoc -> LuaE PandocError Pandoc)
-> (Pandoc -> LuaE PandocError Pandoc)
-> Pandoc
-> LuaE PandocError Pandoc
forall (m :: * -> *) a b c.
Monad m =>
(a -> m b) -> (b -> m c) -> a -> m c
>=> LuaFilter -> Pandoc -> LuaE PandocError Pandoc
walkMeta LuaFilter
f
  (Pandoc -> LuaE PandocError Pandoc)
-> (Pandoc -> LuaE PandocError Pandoc)
-> Pandoc
-> LuaE PandocError Pandoc
forall (m :: * -> *) a b c.
Monad m =>
(a -> m b) -> (b -> m c) -> a -> m c
>=> LuaFilter -> Pandoc -> LuaE PandocError 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 -> [Name] -> Bool
hasOneOf :: LuaFilter -> [Name] -> Bool
hasOneOf (LuaFilter Map Name LuaFilterFunction
fnMap) = (Name -> Bool) -> [Name] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any (Name -> Map Name LuaFilterFunction -> Bool
forall k a. Ord k => k -> Map k a -> Bool
`Map.member` Map Name LuaFilterFunction
fnMap)

contains :: LuaFilter -> Name -> Bool
contains :: LuaFilter -> Name -> Bool
contains (LuaFilter Map Name LuaFilterFunction
fnMap) = (Name -> Map Name LuaFilterFunction -> Bool
forall k a. Ord k => k -> Map k a -> Bool
`Map.member` Map Name LuaFilterFunction
fnMap)

walkInlines :: Walkable (SingletonsList Inline) a
            => LuaFilter -> a -> LuaE PandocError a
walkInlines :: LuaFilter -> a -> LuaE PandocError a
walkInlines LuaFilter
lf =
  let f :: SingletonsList Inline -> LuaE PandocError (SingletonsList Inline)
      f :: SingletonsList Inline -> LuaE PandocError (SingletonsList Inline)
f = Peeker PandocError Inline
-> LuaFilter
-> SingletonsList Inline
-> LuaE PandocError (SingletonsList Inline)
forall a.
(Data a, Pushable a) =>
Peeker PandocError a
-> LuaFilter
-> SingletonsList a
-> LuaE PandocError (SingletonsList a)
runOnSequence Peeker PandocError Inline
forall e. LuaError e => Peeker e Inline
peekInline LuaFilter
lf
  in if LuaFilter
lf LuaFilter -> [Name] -> Bool
`hasOneOf` [Name]
inlineElementNames
     then (SingletonsList Inline -> LuaE PandocError (SingletonsList Inline))
-> a -> LuaE PandocError a
forall a b (m :: * -> *).
(Walkable a b, Monad m, Applicative m, Functor m) =>
(a -> m a) -> b -> m b
walkM SingletonsList Inline -> LuaE PandocError (SingletonsList Inline)
f
     else a -> LuaE PandocError a
forall (m :: * -> *) a. Monad m => a -> m a
return

walkInlineLists :: Walkable (List Inline) a
                => LuaFilter -> a -> LuaE PandocError a
walkInlineLists :: LuaFilter -> a -> LuaE PandocError a
walkInlineLists LuaFilter
lf =
  let f :: List Inline -> LuaE PandocError (List Inline)
      f :: List Inline -> LuaE PandocError (List Inline)
f = Name
-> Peeker PandocError (List Inline)
-> LuaFilter
-> List Inline
-> LuaE PandocError (List Inline)
forall a.
(Data a, Pushable a) =>
Name
-> Peeker PandocError a -> LuaFilter -> a -> LuaE PandocError a
runOnValue Name
listOfInlinesFilterName (Peeker PandocError Inline -> Peeker PandocError (List Inline)
forall e a. LuaError e => Peeker e a -> Peeker e (List a)
peekList' Peeker PandocError Inline
forall e. LuaError e => Peeker e Inline
peekInline) LuaFilter
lf
  in if LuaFilter
lf LuaFilter -> Name -> Bool
`contains` Name
listOfInlinesFilterName
     then (List Inline -> LuaE PandocError (List Inline))
-> a -> LuaE PandocError a
forall a b (m :: * -> *).
(Walkable a b, Monad m, Applicative m, Functor m) =>
(a -> m a) -> b -> m b
walkM List Inline -> LuaE PandocError (List Inline)
f
     else a -> LuaE PandocError a
forall (m :: * -> *) a. Monad m => a -> m a
return

walkBlocks :: Walkable (SingletonsList Block) a
           => LuaFilter -> a -> LuaE PandocError a
walkBlocks :: LuaFilter -> a -> LuaE PandocError a
walkBlocks LuaFilter
lf =
  let f :: SingletonsList Block -> LuaE PandocError (SingletonsList Block)
      f :: SingletonsList Block -> LuaE PandocError (SingletonsList Block)
f = Peeker PandocError Block
-> LuaFilter
-> SingletonsList Block
-> LuaE PandocError (SingletonsList Block)
forall a.
(Data a, Pushable a) =>
Peeker PandocError a
-> LuaFilter
-> SingletonsList a
-> LuaE PandocError (SingletonsList a)
runOnSequence Peeker PandocError Block
forall e. LuaError e => Peeker e Block
peekBlock LuaFilter
lf
  in if LuaFilter
lf LuaFilter -> [Name] -> Bool
`hasOneOf` [Name]
blockElementNames
     then (SingletonsList Block -> LuaE PandocError (SingletonsList Block))
-> a -> LuaE PandocError a
forall a b (m :: * -> *).
(Walkable a b, Monad m, Applicative m, Functor m) =>
(a -> m a) -> b -> m b
walkM SingletonsList Block -> LuaE PandocError (SingletonsList Block)
f
     else a -> LuaE PandocError a
forall (m :: * -> *) a. Monad m => a -> m a
return

walkBlockLists :: Walkable (List Block) a
               => LuaFilter -> a -> LuaE PandocError a
walkBlockLists :: LuaFilter -> a -> LuaE PandocError a
walkBlockLists LuaFilter
lf =
  let f :: List Block -> LuaE PandocError (List Block)
      f :: List Block -> LuaE PandocError (List Block)
f = Name
-> Peeker PandocError (List Block)
-> LuaFilter
-> List Block
-> LuaE PandocError (List Block)
forall a.
(Data a, Pushable a) =>
Name
-> Peeker PandocError a -> LuaFilter -> a -> LuaE PandocError a
runOnValue Name
listOfBlocksFilterName (Peeker PandocError Block -> Peeker PandocError (List Block)
forall e a. LuaError e => Peeker e a -> Peeker e (List a)
peekList' Peeker PandocError Block
forall e. LuaError e => Peeker e Block
peekBlock) LuaFilter
lf
  in if LuaFilter
lf LuaFilter -> Name -> Bool
`contains` Name
listOfBlocksFilterName
     then (List Block -> LuaE PandocError (List Block))
-> a -> LuaE PandocError a
forall a b (m :: * -> *).
(Walkable a b, Monad m, Applicative m, Functor m) =>
(a -> m a) -> b -> m b
walkM List Block -> LuaE PandocError (List Block)
f
     else a -> LuaE PandocError a
forall (m :: * -> *) a. Monad m => a -> m a
return

walkMeta :: LuaFilter -> Pandoc -> LuaE PandocError Pandoc
walkMeta :: LuaFilter -> Pandoc -> LuaE PandocError Pandoc
walkMeta LuaFilter
lf (Pandoc Meta
m [Block]
bs) = do
  Meta
m' <- Name
-> Peeker PandocError Meta
-> LuaFilter
-> Meta
-> LuaE PandocError Meta
forall a.
(Data a, Pushable a) =>
Name
-> Peeker PandocError a -> LuaFilter -> a -> LuaE PandocError a
runOnValue Name
"Meta" Peeker PandocError Meta
forall e. LuaError e => Peeker e Meta
peekMeta LuaFilter
lf Meta
m
  Pandoc -> LuaE PandocError Pandoc
forall (m :: * -> *) a. Monad m => a -> m a
return (Pandoc -> LuaE PandocError Pandoc)
-> Pandoc -> LuaE PandocError Pandoc
forall a b. (a -> b) -> a -> b
$ Meta -> [Block] -> Pandoc
Pandoc Meta
m' [Block]
bs

walkPandoc :: LuaFilter -> Pandoc -> LuaE PandocError Pandoc
walkPandoc :: LuaFilter -> Pandoc -> LuaE PandocError Pandoc
walkPandoc (LuaFilter Map Name 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 ((Name -> Maybe LuaFilterFunction)
-> [Name] -> [Maybe LuaFilterFunction]
forall a b. (a -> b) -> [a] -> [b]
map (Name -> Map Name LuaFilterFunction -> Maybe LuaFilterFunction
forall k a. Ord k => k -> Map k a -> Maybe a
`Map.lookup` Map Name LuaFilterFunction
fnMap) [Name]
pandocFilterNames) of
    Just LuaFilterFunction
fn -> \Pandoc
x -> LuaFilterFunction -> Pandoc -> LuaE PandocError ()
forall a.
Pushable a =>
LuaFilterFunction -> a -> LuaE PandocError ()
runFilterFunction LuaFilterFunction
fn Pandoc
x LuaE PandocError ()
-> LuaE PandocError Pandoc -> LuaE PandocError Pandoc
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> Peeker PandocError Pandoc -> Pandoc -> LuaE PandocError Pandoc
forall a e. LuaError e => Peeker e a -> a -> LuaE e a
singleElement Peeker PandocError Pandoc
forall e. LuaError e => Peeker e Pandoc
peekPandoc Pandoc
x
    Maybe LuaFilterFunction
Nothing -> Pandoc -> LuaE PandocError Pandoc
forall (m :: * -> *) a. Monad m => a -> m a
return

constructorsFor :: DataType -> [Name]
constructorsFor :: DataType -> [Name]
constructorsFor DataType
x = (Constr -> Name) -> [Constr] -> [Name]
forall a b. (a -> b) -> [a] -> [b]
map (FilePath -> Name
forall a. IsString a => FilePath -> a
fromString (FilePath -> Name) -> (Constr -> FilePath) -> Constr -> Name
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Constr -> FilePath
forall a. Show a => a -> FilePath
show) (DataType -> [Constr]
dataTypeConstrs DataType
x)

inlineElementNames :: [Name]
inlineElementNames :: [Name]
inlineElementNames = Name
"Inline" Name -> [Name] -> [Name]
forall a. a -> [a] -> [a]
: DataType -> [Name]
constructorsFor (Inline -> DataType
forall a. Data a => a -> DataType
dataTypeOf (Text -> Inline
Str Text
forall a. Monoid a => a
mempty))

blockElementNames :: [Name]
blockElementNames :: [Name]
blockElementNames = Name
"Block" Name -> [Name] -> [Name]
forall a. a -> [a] -> [a]
: DataType -> [Name]
constructorsFor (Block -> DataType
forall a. Data a => a -> DataType
dataTypeOf ([Inline] -> Block
Para []))

listOfInlinesFilterName :: Name
listOfInlinesFilterName :: Name
listOfInlinesFilterName = Name
"Inlines"

listOfBlocksFilterName :: Name
listOfBlocksFilterName :: Name
listOfBlocksFilterName = Name
"Blocks"

metaFilterName :: Name
metaFilterName :: Name
metaFilterName = Name
"Meta"

pandocFilterNames :: [Name]
pandocFilterNames :: [Name]
pandocFilterNames = [Name
"Pandoc", Name
"Doc"]