{-# LANGUAGE LambdaCase #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE RankNTypes #-} {- | Module : Text.Pandoc.Lua.Run Copyright : Copyright © 2017-2024 Albert Krewinkel License : GPL-2.0-or-later Maintainer : Albert Krewinkel Run code in the Lua interpreter. -} module Text.Pandoc.Lua.Run ( runLua , runLuaNoEnv , runLuaWith ) where import Control.Monad.Catch (try) import Control.Monad.Trans (MonadIO (..)) import HsLua as Lua hiding (try) import Text.Pandoc.Class (PandocMonad (..)) import Text.Pandoc.Error (PandocError) import Text.Pandoc.Lua.Global (Global (..), setGlobals) import Text.Pandoc.Lua.Init (initLua) import Text.Pandoc.Lua.PandocLua (PandocLua (..), liftPandocLua) -- | Run the Lua interpreter, using pandoc's default way of environment -- initialization. runLua :: (PandocMonad m, MonadIO m) => LuaE PandocError a -> m (Either PandocError a) runLua action = do runPandocLuaWith Lua.run . try $ do initLua liftPandocLua action runLuaWith :: (PandocMonad m, MonadIO m) => GCManagedState -> LuaE PandocError a -> m (Either PandocError a) runLuaWith luaState action = do runPandocLuaWith (withGCManagedState luaState) . try $ do initLua liftPandocLua action -- | Like 'runLua', but ignores all environment variables like @LUA_PATH@. runLuaNoEnv :: (PandocMonad m, MonadIO m) => LuaE PandocError a -> m (Either PandocError a) runLuaNoEnv action = do runPandocLuaWith Lua.run . try $ do liftPandocLua $ do -- This is undocumented, but works -- the code is adapted from the -- `lua.c` sources for the default interpreter. Lua.pushboolean True Lua.setfield Lua.registryindex "LUA_NOENV" initLua liftPandocLua action -- | Evaluate a @'PandocLua'@ computation, running all contained Lua -- operations. runPandocLuaWith :: (PandocMonad m, MonadIO m) => (forall b. LuaE PandocError b -> IO b) -> PandocLua a -> m a runPandocLuaWith runner pLua = do origState <- getCommonState let globals = defaultGlobals (result, newState) <- liftIO . runner . unPandocLua $ do putCommonState origState liftPandocLua $ setGlobals globals r <- pLua c <- getCommonState return (r, c) putCommonState newState return result -- | Global variables which should always be set. defaultGlobals :: [Global] defaultGlobals = [ PANDOC_API_VERSION , PANDOC_STATE , PANDOC_VERSION ]