{-# LANGUAGE NoImplicitPrelude #-}
module Text.Pandoc.Lua.Init
( LuaException (..)
, LuaPackageParams (..)
, runPandocLua
, initLuaState
, luaPackageParams
, registerScriptPath
) where
import Prelude
import Control.Monad.Trans (MonadIO (..))
import Data.Data (Data, dataTypeConstrs, dataTypeOf, showConstr)
import Data.IORef (newIORef, readIORef)
import Data.Version (Version (versionBranch))
import Foreign.Lua (Lua)
import GHC.IO.Encoding (getForeignEncoding, setForeignEncoding, utf8)
import Paths_pandoc (version)
import Text.Pandoc.Class (PandocIO, getCommonState, getUserDataDir, getMediaBag,
setMediaBag)
import Text.Pandoc.Definition (pandocTypesVersion)
import Text.Pandoc.Lua.Packages (LuaPackageParams (..),
installPandocPackageSearcher)
import Text.Pandoc.Lua.Util (loadScriptFromDataDir)
import qualified Foreign.Lua as Lua
import qualified Foreign.Lua.Module.Text as Lua
import qualified Text.Pandoc.Definition as Pandoc
newtype LuaException = LuaException String deriving (Show)
runPandocLua :: Lua a -> PandocIO (Either LuaException a)
runPandocLua luaOp = do
luaPkgParams <- luaPackageParams
enc <- liftIO $ getForeignEncoding <* setForeignEncoding utf8
res <- liftIO $ Lua.runEither (initLuaState luaPkgParams *> luaOp)
liftIO $ setForeignEncoding enc
newMediaBag <- liftIO (readIORef (luaPkgMediaBag luaPkgParams))
setMediaBag newMediaBag
return $ case res of
Left (Lua.Exception msg) -> Left (LuaException msg)
Right x -> Right x
luaPackageParams :: PandocIO LuaPackageParams
luaPackageParams = do
commonState <- getCommonState
datadir <- getUserDataDir
mbRef <- liftIO . newIORef =<< getMediaBag
return LuaPackageParams
{ luaPkgCommonState = commonState
, luaPkgDataDir = datadir
, luaPkgMediaBag = mbRef
}
initLuaState :: LuaPackageParams -> Lua ()
initLuaState luaPkgParams = do
Lua.openlibs
Lua.preloadTextModule "text"
Lua.push (versionBranch version)
Lua.setglobal "PANDOC_VERSION"
Lua.push (versionBranch pandocTypesVersion)
Lua.setglobal "PANDOC_API_VERSION"
installPandocPackageSearcher luaPkgParams
loadScriptFromDataDir (luaPkgDataDir luaPkgParams) "init.lua"
putConstructorsInRegistry
registerScriptPath :: FilePath -> Lua ()
registerScriptPath fp = do
Lua.push fp
Lua.setglobal "PANDOC_SCRIPT_FILE"
putConstructorsInRegistry :: Lua ()
putConstructorsInRegistry = do
Lua.getglobal "pandoc"
constrsToReg $ Pandoc.Pandoc mempty mempty
constrsToReg $ Pandoc.Str mempty
constrsToReg $ Pandoc.Para mempty
constrsToReg $ Pandoc.Meta mempty
constrsToReg $ Pandoc.MetaList mempty
constrsToReg $ Pandoc.Citation mempty mempty mempty Pandoc.AuthorInText 0 0
putInReg "Attr"
Lua.pop 1
where
constrsToReg :: Data a => a -> Lua ()
constrsToReg = mapM_ (putInReg . showConstr) . dataTypeConstrs . dataTypeOf
putInReg :: String -> Lua ()
putInReg name = do
Lua.push ("pandoc." ++ name)
Lua.push name
Lua.rawget (Lua.nthFromTop 3)
Lua.rawset Lua.registryindex