Lua filters: use script to initialize the interpreter

The file `init.lua` is used to initialize the Lua interpreter which is
used in Lua filters. This gives users the option to require libraries
which they want to use in all of their filters, and to extend default
modules.
This commit is contained in:
Albert Krewinkel 2017-12-06 20:45:38 +01:00
parent d5b1c7b767
commit 4066a385ac
No known key found for this signature in database
GPG key ID: 388DC0B21F631124
5 changed files with 46 additions and 14 deletions

6
data/init.lua Normal file
View file

@ -0,0 +1,6 @@
-- This Lua script is run every time the Lua interpreter is started when running
-- a Lua filter. It can be customized to load additional modules or to alter the
-- default modules.
pandoc = require 'pandoc'
pandoc.mediabag = require 'pandoc.mediabag'

View file

@ -3,7 +3,7 @@ title: Pandoc Lua Filters
author: author:
- Albert Krewinkel - Albert Krewinkel
- John MacFarlane - John MacFarlane
date: 'November 20, 2017' date: 'December 6, 2017'
--- ---
# Introduction # Introduction
@ -176,6 +176,34 @@ Some pandoc functions have been made available in lua:
which stores binary content such as images that may be which stores binary content such as images that may be
included in the final document. included in the final document.
# Lua interpreter initialization
The way the Lua interpreter is set-up can be controlled by
placing a file `init.lua` in pandoc's data directory. The
default init file loads the `pandoc` and `pandoc.mediabag`
modules:
``` lua
pandoc = require 'pandoc'
pandoc.mediabag = require 'pandoc.mediabag'
```
A common use-case would be to add code to load additional
modules or to alter default modules. E.g., the following snippet
adds all unicode-aware functions defined in the [`text`
module](#module-text) to the default `string` module, prefixed
with the string `uc_`.
```lua
for name, fn in pairs(require 'text') do
string['uc_' .. name] = fn
end
```
This makes it possible to apply these functions on strings using
colon syntax (`mystring:uc_upper()`).
# Examples # Examples
## Macro substitution. ## Macro substitution.

View file

@ -108,6 +108,8 @@ data-files:
data/abbreviations data/abbreviations
-- sample lua custom writer -- sample lua custom writer
data/sample.lua data/sample.lua
-- lua init script
data/init.lua
-- pandoc lua module -- pandoc lua module
data/pandoc.lua data/pandoc.lua
-- lua List module -- lua List module

View file

@ -48,10 +48,11 @@ import Foreign.Lua (FromLuaStack (peek), Lua, LuaException (..),
Status (OK), ToLuaStack (push)) Status (OK), ToLuaStack (push))
import Text.Pandoc.Class (PandocIO, getCommonState, getMediaBag, setMediaBag) import Text.Pandoc.Class (PandocIO, getCommonState, getMediaBag, setMediaBag)
import Text.Pandoc.Definition import Text.Pandoc.Definition
import Text.Pandoc.Lua.Filter (LuaFilter, walkMWithLuaFilter)
import Text.Pandoc.Lua.Packages (LuaPackageParams (..), import Text.Pandoc.Lua.Packages (LuaPackageParams (..),
installPandocPackageSearcher) installPandocPackageSearcher)
import Text.Pandoc.Lua.PandocModule (pushMediaBagModule, pushPandocModule) import Text.Pandoc.Lua.PandocModule (pushPandocModule) -- TODO: remove
import Text.Pandoc.Lua.Filter (LuaFilter, walkMWithLuaFilter) import Text.Pandoc.Lua.Util (loadScriptFromDataDir)
import qualified Foreign.Lua as Lua import qualified Foreign.Lua as Lua
import qualified Foreign.Lua.Module.Text as Lua import qualified Foreign.Lua.Module.Text as Lua
@ -101,17 +102,11 @@ luaPackageParams datadir = do
-- Initialize the lua state with all required values -- Initialize the lua state with all required values
initLuaState :: LuaPackageParams -> Lua () initLuaState :: LuaPackageParams -> Lua ()
initLuaState luaPkgParams@(LuaPackageParams commonState datadir mbRef) = do initLuaState luaPkgParams = do
Lua.openlibs Lua.openlibs
Lua.preloadTextModule "text" Lua.preloadTextModule "text"
installPandocPackageSearcher luaPkgParams installPandocPackageSearcher luaPkgParams
pushPandocModule datadir loadScriptFromDataDir (luaPkgDataDir luaPkgParams) "init.lua"
-- add MediaBag module
push "mediabag"
pushMediaBagModule commonState mbRef
Lua.rawset (-3)
Lua.setglobal "pandoc"
return ()
pushGlobalFilter :: Lua () pushGlobalFilter :: Lua ()
pushGlobalFilter = do pushGlobalFilter = do

View file

@ -60,7 +60,7 @@ import qualified Text.Pandoc.MediaBag as MB
-- | Push the "pandoc" on the lua stack. Requires the `list` module to be -- | Push the "pandoc" on the lua stack. Requires the `list` module to be
-- loaded. -- loaded.
pushPandocModule :: Maybe FilePath -> Lua () pushPandocModule :: Maybe FilePath -> Lua NumResults
pushPandocModule datadir = do pushPandocModule datadir = do
loadScriptFromDataDir datadir "pandoc.lua" loadScriptFromDataDir datadir "pandoc.lua"
addFunction "_pipe" pipeFn addFunction "_pipe" pipeFn
@ -68,6 +68,7 @@ pushPandocModule datadir = do
addFunction "sha1" sha1HashFn addFunction "sha1" sha1HashFn
addFunction "walk_block" walkBlock addFunction "walk_block" walkBlock
addFunction "walk_inline" walkInline addFunction "walk_inline" walkInline
return 1
walkElement :: (ToLuaStack a, Walkable [Inline] a, Walkable [Block] a) walkElement :: (ToLuaStack a, Walkable [Inline] a, Walkable [Block] a)
=> a -> LuaFilter -> Lua NumResults => a -> LuaFilter -> Lua NumResults
@ -99,14 +100,14 @@ readDoc formatSpec content = do
-- --
-- MediaBag submodule -- MediaBag submodule
-- --
pushMediaBagModule :: CommonState -> IORef MB.MediaBag -> Lua () pushMediaBagModule :: CommonState -> IORef MB.MediaBag -> Lua NumResults
pushMediaBagModule commonState mediaBagRef = do pushMediaBagModule commonState mediaBagRef = do
Lua.newtable Lua.newtable
addFunction "insert" (insertMediaFn mediaBagRef) addFunction "insert" (insertMediaFn mediaBagRef)
addFunction "lookup" (lookupMediaFn mediaBagRef) addFunction "lookup" (lookupMediaFn mediaBagRef)
addFunction "list" (mediaDirectoryFn mediaBagRef) addFunction "list" (mediaDirectoryFn mediaBagRef)
addFunction "fetch" (fetch commonState mediaBagRef) addFunction "fetch" (fetch commonState mediaBagRef)
return () return 1
addFunction :: ToHaskellFunction a => String -> a -> Lua () addFunction :: ToHaskellFunction a => String -> a -> Lua ()
addFunction name fn = do addFunction name fn = do