From 75c791b4fea141417fa088b9f5b9861ef57f4790 Mon Sep 17 00:00:00 2001 From: Albert Krewinkel Date: Sat, 9 Feb 2019 22:56:49 +0100 Subject: Lua filters: load module `pandoc` before calling `init.lua` (#5287) The file `init.lua` in pandoc's data directory is run as part of pandoc's Lua initialization process. Previously, the `pandoc` module was loaded in `init.lua`, and the structure for marshaling was set-up after. This allowed simple patching of element marshaling, but made using `init.lua` more difficult: - it encouraged mixing essential initialization with user-defined customization; - upstream changes to init.lua had to be merged manually; - accidentally breaking marshaling by removing required modules was possible; Instead, all required modules are now loaded before calling `init.lua`. The file can be used entirely for user customization. Patching marshaling functions, while discouraged, is still possible via the `debug` module. --- src/Text/Pandoc/Lua/Init.hs | 33 +++++++++++++++++++++++++++------ 1 file changed, 27 insertions(+), 6 deletions(-) (limited to 'src/Text/Pandoc/Lua') diff --git a/src/Text/Pandoc/Lua/Init.hs b/src/Text/Pandoc/Lua/Init.hs index c3096f611..f05076b20 100644 --- a/src/Text/Pandoc/Lua/Init.hs +++ b/src/Text/Pandoc/Lua/Init.hs @@ -49,6 +49,7 @@ 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 +import qualified Text.Pandoc.Lua.Module.Pandoc as ModulePandoc -- | Lua error message newtype LuaException = LuaException String deriving (Show) @@ -95,16 +96,37 @@ luaPackageParams = do -- | Initialize the lua state with all required values initLuaState :: LuaPackageParams -> Lua () -initLuaState luaPkgParams = do +initLuaState pkgParams = do Lua.openlibs Lua.preloadTextModule "text" - installPandocPackageSearcher luaPkgParams - loadScriptFromDataDir (luaPkgDataDir luaPkgParams) "init.lua" - putConstructorsInRegistry + installPandocPackageSearcher pkgParams + initPandocModule + loadScriptFromDataDir (luaPkgDataDir pkgParams) "init.lua" + where + initPandocModule :: Lua () + initPandocModule = do + -- Push module table + ModulePandoc.pushModule (luaPkgDataDir pkgParams) + -- register as loaded module + Lua.pushvalue Lua.stackTop + Lua.getfield Lua.registryindex Lua.loadedTableRegistryField + Lua.setfield (Lua.nthFromTop 2) "pandoc" + Lua.pop 1 + -- copy constructors into registry + putConstructorsInRegistry + -- assign module to global variable + Lua.setglobal "pandoc" +-- | AST elements are marshaled via normal constructor functions in the +-- @pandoc@ module. However, accessing Lua globals from Haskell is +-- expensive (due to error handling). Accessing the Lua registry is much +-- cheaper, which is why the constructor functions are copied into the +-- Lua registry and called from there. +-- +-- This function expects the @pandoc@ module to be at the top of the +-- stack. putConstructorsInRegistry :: Lua () putConstructorsInRegistry = do - Lua.getglobal "pandoc" constrsToReg $ Pandoc.Pandoc mempty mempty constrsToReg $ Pandoc.Str mempty constrsToReg $ Pandoc.Para mempty @@ -113,7 +135,6 @@ putConstructorsInRegistry = do constrsToReg $ Pandoc.Citation mempty mempty mempty Pandoc.AuthorInText 0 0 putInReg "Attr" -- used for Attr type alias putInReg "ListAttributes" -- used for ListAttributes type alias - Lua.pop 1 where constrsToReg :: Data a => a -> Lua () constrsToReg = mapM_ (putInReg . showConstr) . dataTypeConstrs . dataTypeOf -- cgit v1.2.3