    {-# LANGUAGE LambdaCase #-}
    {-# LANGUAGE OverloadedStrings #-}
    {- |
    Module      : Text.Pandoc.Lua.Filter
    Copyright   : © 2012-2024 John MacFarlane,
                  © 2017-2024 Albert Krewinkel
    License     : GPL-2.0-or-later
    Maintainer  : Albert Krewinkel <albert+pandoc@tarleb.com>

    Types and functions for running Lua filters.
    -}
    module Text.Pandoc.Lua.Filter
      ( runFilterFile
      , runFilterFile'
      ) where
    import Control.Monad ((>=>), (<$!>))
    import HsLua as Lua
    import Text.Pandoc.Definition (Pandoc)
    import Text.Pandoc.Error (PandocError)
    import Text.Pandoc.Lua.Marshal.AST
    import Text.Pandoc.Lua.Marshal.Filter
    import Text.Pandoc.Lua.PandocLua ()

    -- | Transform document using the filter defined in the given file.
    -- Runs the filter in the global environment.
    runFilterFile :: FilePath -> Pandoc -> LuaE PandocError Pandoc
    runFilterFile :: FilePath -> Pandoc -> LuaE PandocError Pandoc
    runFilterFile FilePath
    filterPath Pandoc
    doc = do
      LuaE PandocError ()
    forall e. LuaE e ()
    Lua.pushglobaltable
      StackIndex -> FilePath -> Pandoc -> LuaE PandocError Pandoc
    runFilterFile' StackIndex
    Lua.top FilePath
    filterPath Pandoc
    doc LuaE PandocError Pandoc
    -> LuaE PandocError () -> LuaE PandocError Pandoc
    forall a b.
    LuaE PandocError a -> LuaE PandocError b -> LuaE PandocError a
    forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
    <* Int -> LuaE PandocError ()
    forall e. Int -> LuaE e ()
    Lua.pop Int
    1

    -- | Like 'runFilterFile', but uses the table at the given index as the
    -- environment in which the filter is run.
    runFilterFile' :: StackIndex -> FilePath -> Pandoc
                   -> LuaE PandocError Pandoc
    runFilterFile' :: StackIndex -> FilePath -> Pandoc -> LuaE PandocError Pandoc
    runFilterFile' StackIndex
    envIdx FilePath
    filterPath Pandoc
    doc = do
      oldtop <- LuaE PandocError StackIndex
    forall e. LuaE e StackIndex
    gettop
      stat <- dofileTrace' envIdx (Just filterPath)
      if stat /= OK
        then throwErrorAsException
        else do
          newtop <- gettop
          -- Use the returned filters, or the implicitly defined global
          -- filter if nothing was returned.
          luaFilters <- forcePeek $
            if newtop - oldtop >= 1
            then liftLua (rawlen top) >>= \case
              -- explicitly returned filter, either a single one or a list
              Int
    0 -> (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
    <$!> Peeker PandocError Filter
    forall e. LuaError e => Peeker e Filter
    peekFilter StackIndex
    top  -- single filter
              Int
    _ -> 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    -- list of explicit filters
            else (:[]) <$!> peekFilter envIdx -- get the implicit filter in _ENV
          settop oldtop
          runAll luaFilters doc

    -- | Apply Lua filters to a document
    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

    -- | Like 'HsLua.Core.Trace.dofileTrace', but uses a local environment.
    dofileTrace' :: LuaError e
                 => StackIndex     -- ^ stack index of the environment table
                 -> Maybe FilePath -- ^ file to load (or @Nothing@ for stdin)
                 -> LuaE e Status
    dofileTrace' :: forall e.
    LuaError e =>
    StackIndex -> Maybe FilePath -> LuaE e Status
    dofileTrace' StackIndex
    envIdx Maybe FilePath
    fp = do
      absEnv <- StackIndex -> LuaE e StackIndex
    forall e. StackIndex -> LuaE e StackIndex
    Lua.absindex StackIndex
    envIdx
      loadfile fp >>= \case
        Status
    OK -> do
          StackIndex -> LuaE e ()
    forall e. StackIndex -> LuaE e ()
    Lua.pushvalue StackIndex
    absEnv
          Just (Name "_ENV") <- StackIndex -> Int -> LuaE e (Maybe Name)
    forall e. StackIndex -> Int -> LuaE e (Maybe Name)
    Lua.setupvalue (CInt -> StackIndex
    Lua.nth CInt
    2) Int
    1
          pcallTrace 0 multret
        Status
    s  -> Status -> LuaE e Status
    forall a. a -> LuaE e a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure Status
    s