diff options
author | Albert Krewinkel <albert+github@zeitkraut.de> | 2019-02-09 22:56:49 +0100 |
---|---|---|
committer | John MacFarlane <jgm@berkeley.edu> | 2019-02-09 13:56:49 -0800 |
commit | 75c791b4fea141417fa088b9f5b9861ef57f4790 (patch) | |
tree | 70f9eb34cdcad28da29284336b7a916611700842 /src/Text/Pandoc/Lua | |
parent | 66ed198fff937cdd98d530f3ef3d1a46cbe79360 (diff) | |
download | pandoc-75c791b4fea141417fa088b9f5b9861ef57f4790.tar.gz |
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.
Diffstat (limited to 'src/Text/Pandoc/Lua')
-rw-r--r-- | src/Text/Pandoc/Lua/Init.hs | 33 |
1 files changed, 27 insertions, 6 deletions
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 |