git.iko.soy/typeable/pandoc
on master help sign in
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.

commit75c791b4fea141417fa088b9f5b9861ef57f4790 authorAlbert Krewinkel <albert+github@zeitkraut.de> dateSat 9 Feb 2019, 22:56 (8 years ago) parent66ed198
3 files changed+37−22
data/init.lua−2 doc/lua-filters.md+10−14 src/Text/Pandoc/Lua/Init.hs+27−6
data/init.lua−2
@@ -1,5 +1,3 @@
11-- This Lua script is run every time the Lua interpreter is started when running
22-- a Lua filter. It can be customized to load additional modules or to alter the
33-- default modules.
4−
5−pandoc = require 'pandoc'
doc/lua-filters.md+10−14
@@ -219,21 +219,15 @@ Some pandoc functions have been made available in lua:
219219
220220# Lua interpreter initialization
221221
222−The way the Lua interpreter is set-up can be controlled by
223−placing a file `init.lua` in pandoc's data directory. The
224−default init file loads the `pandoc` and `pandoc.mediabag`
225−modules:
222+Initialization of pandoc's Lua interpreter can be controlled by
223+placing a file `init.lua` in pandoc's data directory. A common
224+use-case would be to load additional modules, or even to alter
225+default modules.
226226
227−``` {.lua}
228−pandoc = require 'pandoc'
229−pandoc.mediabag = require 'pandoc.mediabag'
230−```
231−
232−A common use-case would be to add code to load additional
233−modules or to alter default modules. E.g., the following snippet
234−adds all unicode-aware functions defined in the [`text`
235−module](#module-text) to the default `string` module, prefixed
236−with the string `uc_`.
227+The following snippet is an example of code that might be useful
228+when added to `init.lua`. The snippet adds all unicode-aware
229+functions defined in the [`text` module] to the default `string`
230+module, prefixed with the string `uc_`.
237231
238232``` {.lua}
239233for name, fn in pairs(require 'text') do
@@ -244,6 +238,8 @@ end
244238This makes it possible to apply these functions on strings using
245239colon syntax (`mystring:uc_upper()`).
246240
241+[`text` module]: #module-text
242+
247243# Examples
248244
249245The following filters are presented as examples.
src/Text/Pandoc/Lua/Init.hs+27−6
@@ -49,6 +49,7 @@ import Text.Pandoc.Lua.Util (loadScriptFromDataDir)
4949import qualified Foreign.Lua as Lua
5050import qualified Foreign.Lua.Module.Text as Lua
5151import qualified Text.Pandoc.Definition as Pandoc
52+import qualified Text.Pandoc.Lua.Module.Pandoc as ModulePandoc
5253
5354-- | Lua error message
5455newtype LuaException = LuaException String deriving (Show)
@@ -95,16 +96,37 @@ luaPackageParams = do
9596
9697-- | Initialize the lua state with all required values
9798initLuaState :: LuaPackageParams -> Lua ()
98−initLuaState luaPkgParams = do
99+initLuaState pkgParams = do
99100 Lua.openlibs
100101 Lua.preloadTextModule "text"
101− installPandocPackageSearcher luaPkgParams
102− loadScriptFromDataDir (luaPkgDataDir luaPkgParams) "init.lua"
103− putConstructorsInRegistry
102+ installPandocPackageSearcher pkgParams
103+ initPandocModule
104+ loadScriptFromDataDir (luaPkgDataDir pkgParams) "init.lua"
105+ where
106+ initPandocModule :: Lua ()
107+ initPandocModule = do
108+ -- Push module table
109+ ModulePandoc.pushModule (luaPkgDataDir pkgParams)
110+ -- register as loaded module
111+ Lua.pushvalue Lua.stackTop
112+ Lua.getfield Lua.registryindex Lua.loadedTableRegistryField
113+ Lua.setfield (Lua.nthFromTop 2) "pandoc"
114+ Lua.pop 1
115+ -- copy constructors into registry
116+ putConstructorsInRegistry
117+ -- assign module to global variable
118+ Lua.setglobal "pandoc"
104119
120+-- | AST elements are marshaled via normal constructor functions in the
121+-- @pandoc@ module. However, accessing Lua globals from Haskell is
122+-- expensive (due to error handling). Accessing the Lua registry is much
123+-- cheaper, which is why the constructor functions are copied into the
124+-- Lua registry and called from there.
125+--
126+-- This function expects the @pandoc@ module to be at the top of the
127+-- stack.
105128putConstructorsInRegistry :: Lua ()
106129putConstructorsInRegistry = do
107− Lua.getglobal "pandoc"
108130 constrsToReg $ Pandoc.Pandoc mempty mempty
109131 constrsToReg $ Pandoc.Str mempty
110132 constrsToReg $ Pandoc.Para mempty
@@ -113,7 +135,6 @@ putConstructorsInRegistry = do
113135 constrsToReg $ Pandoc.Citation mempty mempty mempty Pandoc.AuthorInText 0 0
114136 putInReg "Attr" -- used for Attr type alias
115137 putInReg "ListAttributes" -- used for ListAttributes type alias
116− Lua.pop 1
117138 where
118139 constrsToReg :: Data a => a -> Lua ()
119140 constrsToReg = mapM_ (putInReg . showConstr) . dataTypeConstrs . dataTypeOf