{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE IncoherentInstances #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ScopedTypeVariables #-}
module Text.Pandoc.Lua.Filter
( applyFilter
) where
import Control.Monad ((>=>), (<$!>))
import HsLua as Lua
import Text.Pandoc.Definition
import Text.Pandoc.Filter (Environment (..))
import Text.Pandoc.Lua.Marshal.AST
import Text.Pandoc.Lua.Marshal.Filter
import Text.Pandoc.Lua.Global (Global (..), setGlobals)
import Text.Pandoc.Lua.Init (runLua)
import Text.Pandoc.Lua.PandocLua ()
import Control.Exception (throw)
import qualified Data.Text as T
import Text.Pandoc.Class (PandocMonad)
import Control.Monad.Trans (MonadIO)
import Text.Pandoc.Error (PandocError (PandocFilterError, PandocLuaError))
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
gettop
Status
stat <- Maybe FilePath -> LuaE PandocError Status
forall e. Maybe FilePath -> LuaE e Status
dofileTrace (FilePath -> Maybe FilePath
forall a. a -> Maybe a
Just 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
throwErrorAsException
else do
StackIndex
newtop <- LuaE PandocError StackIndex
forall e. LuaE e StackIndex
gettop
[Filter]
luaFilters <- Peek PandocError [Filter] -> LuaE PandocError [Filter]
forall e a. LuaError e => Peek e a -> LuaE e a
forcePeek (Peek PandocError [Filter] -> LuaE PandocError [Filter])
-> Peek PandocError [Filter] -> LuaE PandocError [Filter]
forall a b. (a -> b) -> a -> b
$
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 Peeker PandocError Filter -> Peeker PandocError [Filter]
forall a e. LuaError e => Peeker e a -> Peeker e [a]
peekList Peeker PandocError Filter
forall e. LuaError e => Peeker e Filter
peekFilter StackIndex
top
else (Filter -> [Filter] -> [Filter]
forall a. a -> [a] -> [a]
:[]) (Filter -> [Filter])
-> Peek PandocError Filter -> Peek PandocError [Filter]
forall (m :: * -> *) a b. Monad m => (a -> b) -> m a -> m b
<$!> (LuaE PandocError () -> Peek PandocError ()
forall e a. LuaE e a -> Peek e a
liftLua LuaE PandocError ()
forall e. LuaE e ()
pushglobaltable Peek PandocError ()
-> Peek PandocError Filter -> Peek PandocError Filter
forall a b.
Peek PandocError a -> Peek PandocError b -> Peek PandocError b
forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> Peeker PandocError Filter
forall e. LuaError e => Peeker e Filter
peekFilter StackIndex
top)
StackIndex -> LuaE PandocError ()
forall e. StackIndex -> LuaE e ()
settop StackIndex
oldtop
[Filter] -> Pandoc -> LuaE PandocError Pandoc
runAll [Filter]
luaFilters Pandoc
doc
runAll :: [Filter] -> Pandoc -> LuaE PandocError Pandoc
runAll :: [Filter] -> Pandoc -> LuaE PandocError Pandoc
runAll = (Filter
-> (Pandoc -> LuaE PandocError Pandoc)
-> Pandoc
-> LuaE PandocError Pandoc)
-> (Pandoc -> LuaE PandocError Pandoc)
-> [Filter]
-> Pandoc
-> LuaE PandocError Pandoc
forall a b. (a -> b -> b) -> b -> [a] -> b
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)
-> (Filter -> Pandoc -> LuaE PandocError Pandoc)
-> Filter
-> (Pandoc -> LuaE PandocError Pandoc)
-> Pandoc
-> LuaE PandocError Pandoc
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Filter -> Pandoc -> LuaE PandocError Pandoc
forall e. LuaError e => Filter -> Pandoc -> LuaE e Pandoc
applyFully) Pandoc -> LuaE PandocError Pandoc
forall a. a -> LuaE PandocError a
forall (m :: * -> *) a. Monad m => a -> m a
return
applyFilter :: (PandocMonad m, MonadIO m)
=> Environment
-> [String]
-> FilePath
-> Pandoc
-> m Pandoc
applyFilter :: forall (m :: * -> *).
(PandocMonad m, MonadIO m) =>
Environment -> [FilePath] -> FilePath -> Pandoc -> m Pandoc
applyFilter Environment
fenv [FilePath]
args FilePath
fp Pandoc
doc = do
let globals :: [Global]
globals = [ Text -> Global
FORMAT (Text -> Global) -> Text -> Global
forall a b. (a -> b) -> a -> b
$ case [FilePath]
args of
FilePath
x:[FilePath]
_ -> FilePath -> Text
T.pack FilePath
x
[FilePath]
_ -> Text
""
, ReaderOptions -> Global
PANDOC_READER_OPTIONS (Environment -> ReaderOptions
envReaderOptions Environment
fenv)
, WriterOptions -> Global
PANDOC_WRITER_OPTIONS (Environment -> WriterOptions
envWriterOptions Environment
fenv)
, FilePath -> Global
PANDOC_SCRIPT_FILE FilePath
fp
]
LuaE PandocError Pandoc -> m (Either PandocError Pandoc)
forall (m :: * -> *) a.
(PandocMonad m, MonadIO m) =>
LuaE PandocError a -> m (Either PandocError a)
runLua (LuaE PandocError Pandoc -> m (Either PandocError Pandoc))
-> (Either PandocError Pandoc -> m Pandoc)
-> LuaE PandocError Pandoc
-> m Pandoc
forall (m :: * -> *) a b c.
Monad m =>
(a -> m b) -> (b -> m c) -> a -> m c
>=> FilePath -> Either PandocError Pandoc -> m Pandoc
forall (m :: * -> *).
(PandocMonad m, MonadIO m) =>
FilePath -> Either PandocError Pandoc -> m Pandoc
forceResult FilePath
fp (LuaE PandocError Pandoc -> m Pandoc)
-> LuaE PandocError Pandoc -> m Pandoc
forall a b. (a -> b) -> a -> b
$ do
[Global] -> LuaE PandocError ()
setGlobals [Global]
globals
FilePath -> Pandoc -> LuaE PandocError Pandoc
runFilterFile FilePath
fp Pandoc
doc
forceResult :: (PandocMonad m, MonadIO m)
=> FilePath -> Either PandocError Pandoc -> m Pandoc
forceResult :: forall (m :: * -> *).
(PandocMonad m, MonadIO m) =>
FilePath -> Either PandocError Pandoc -> m Pandoc
forceResult FilePath
fp Either PandocError Pandoc
eitherResult = case Either PandocError Pandoc
eitherResult of
Right Pandoc
x -> Pandoc -> m Pandoc
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return Pandoc
x
Left PandocError
err -> PandocError -> m Pandoc
forall a e. Exception e => e -> a
throw (PandocError -> m Pandoc)
-> (Text -> PandocError) -> Text -> m Pandoc
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Text -> PandocError
PandocFilterError (FilePath -> Text
T.pack FilePath
fp) (Text -> m Pandoc) -> Text -> m Pandoc
forall a b. (a -> b) -> a -> b
$ case PandocError
err of
PandocLuaError Text
msg -> Text
msg
PandocError
_ -> FilePath -> Text
T.pack (FilePath -> Text) -> FilePath -> Text
forall a b. (a -> b) -> a -> b
$ PandocError -> FilePath
forall a. Show a => a -> FilePath
show PandocError
err