    {-# LANGUAGE OverloadedStrings    #-}
    {-# LANGUAGE ImpredicativeTypes   #-}
    {-# LANGUAGE ScopedTypeVariables  #-}
    {- |
    Module      : Text.Pandoc.Scripting
    Copyright   : © 2022-2024 Albert Krewinkel
    License     : GPL-2.0-or-later
    Maintainer  : Albert Krewinkel <albert+pandoc@tarleb.com>

    Central data structure for scripting engines.
    -}
    module Text.Pandoc.Scripting
      ( ScriptingEngine (..)
      , CustomComponents(..)
      , noEngine
      )
    where

    import Control.Monad.Except (throwError)
    import Control.Monad.IO.Class (MonadIO)
    import Data.Text (Text)
    import Text.Pandoc.Class.PandocMonad (PandocMonad)
    import Text.Pandoc.Definition (Pandoc)
    import Text.Pandoc.Error (PandocError (PandocNoScriptingEngine))
    import Text.Pandoc.Filter.Environment (Environment)
    import Text.Pandoc.Format (ExtensionsConfig)
    import Text.Pandoc.Readers (Reader)
    import Text.Pandoc.Writers (Writer)

    -- | A component of a custom reader/writer: a custom reader,
    -- a custom writer, a template for a custom writer, or a specification
    -- of the extensions used by a script and their default values.
    -- Note that a single script can contain all of these.
    data CustomComponents m =
      CustomComponents
      { forall (m :: * -> *). CustomComponents m -> Maybe (Reader m)
    customReader :: Maybe (Reader m)
      , forall (m :: * -> *). CustomComponents m -> Maybe (Writer m)
    customWriter :: Maybe (Writer m)
      , forall (m :: * -> *). CustomComponents m -> Maybe Text
    customTemplate :: Maybe Text
      , forall (m :: * -> *). CustomComponents m -> Maybe ExtensionsConfig
    customExtensions :: Maybe ExtensionsConfig
      }

    -- | Structure to define a scripting engine.
    data ScriptingEngine = ScriptingEngine
      { ScriptingEngine -> Text
    engineName :: Text   -- ^ Name of the engine.

      , ScriptingEngine
    -> forall (m :: * -> *).
       (PandocMonad m, MonadIO m) =>
       Environment -> [String] -> String -> Pandoc -> m Pandoc
    engineApplyFilter :: forall m. (PandocMonad m, MonadIO m)
                          => Environment -> [String] -> FilePath
                          -> Pandoc -> m Pandoc
        -- ^ Use the scripting engine to run a filter.

      , ScriptingEngine
    -> forall (m :: * -> *).
       (PandocMonad m, MonadIO m) =>
       String -> m (CustomComponents m)
    engineLoadCustom :: forall m. (PandocMonad m, MonadIO m)
                         => FilePath -> m (CustomComponents m)
        -- ^ Function to load a custom reader/writer from a script.
      }

    noEngine :: ScriptingEngine
    noEngine :: ScriptingEngine
    noEngine = ScriptingEngine
      { engineName :: Text
    engineName = Text
    "none"
      , engineApplyFilter :: forall (m :: * -> *).
    (PandocMonad m, MonadIO m) =>
    Environment -> [String] -> String -> Pandoc -> m Pandoc
    engineApplyFilter = \Environment
    _env [String]
    _args String
    _fp Pandoc
    _doc ->
          PandocError -> m Pandoc
    forall a. PandocError -> m a
    forall e (m :: * -> *) a. MonadError e m => e -> m a
    throwError PandocError
    PandocNoScriptingEngine
      , engineLoadCustom :: forall (m :: * -> *).
    (PandocMonad m, MonadIO m) =>
    String -> m (CustomComponents m)
    engineLoadCustom = \String
    _fp ->
          PandocError -> m (CustomComponents m)
    forall a. PandocError -> m a
    forall e (m :: * -> *) a. MonadError e m => e -> m a
    throwError PandocError
    PandocNoScriptingEngine
      }