aboutsummaryrefslogtreecommitdiff
path: root/src/Text/Pandoc/Lua
diff options
context:
space:
mode:
authorAlbert Krewinkel <albert+github@zeitkraut.de>2019-02-09 22:56:49 +0100
committerJohn MacFarlane <jgm@berkeley.edu>2019-02-09 13:56:49 -0800
commit75c791b4fea141417fa088b9f5b9861ef57f4790 (patch)
tree70f9eb34cdcad28da29284336b7a916611700842 /src/Text/Pandoc/Lua
parent66ed198fff937cdd98d530f3ef3d1a46cbe79360 (diff)
downloadpandoc-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.hs33
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