Lua: Simplify module loading code.

Modules are now loaded directly; the special pandoc Lua package searcher
is no longer necessary and has been removed.
This commit is contained in:
Albert Krewinkel 2022-06-08 22:31:06 +02:00
parent 665d5b0fbd
commit b3cee8bdb0
No known key found for this signature in database
GPG key ID: 388DC0B21F631124
3 changed files with 34 additions and 103 deletions

View file

@ -753,7 +753,6 @@ library
Text.Pandoc.Lua.Module.Types,
Text.Pandoc.Lua.Module.Utils,
Text.Pandoc.Lua.Orphans,
Text.Pandoc.Lua.Packages,
Text.Pandoc.Lua.PandocLua,
Text.Pandoc.Lua.Writer.Classic,
Text.Pandoc.XML.Light,

View file

@ -22,11 +22,20 @@ import HsLua as Lua hiding (status, try)
import GHC.IO.Encoding (getForeignEncoding, setForeignEncoding, utf8)
import Text.Pandoc.Class.PandocMonad (PandocMonad, readDataFile)
import Text.Pandoc.Error (PandocError (PandocLuaError))
import Text.Pandoc.Lua.Packages (installPandocPackageSearcher)
import Text.Pandoc.Lua.Marshal.List (pushListModule)
import Text.Pandoc.Lua.PandocLua (PandocLua, liftPandocLua, runPandocLua)
import qualified Data.ByteString as B
import qualified Data.Text as T
import qualified Lua.LPeg as LPeg
import qualified Text.Pandoc.Lua.Module.Pandoc as ModulePandoc
import qualified HsLua.Module.DocLayout as Module.Layout
import qualified HsLua.Module.Path as Module.Path
import qualified HsLua.Module.Text as Module.Text
import qualified Text.Pandoc.Lua.Module.Pandoc as Module.Pandoc
import qualified Text.Pandoc.Lua.Module.MediaBag as Pandoc.MediaBag
import qualified Text.Pandoc.Lua.Module.System as Pandoc.System
import qualified Text.Pandoc.Lua.Module.Template as Pandoc.Template
import qualified Text.Pandoc.Lua.Module.Types as Pandoc.Types
import qualified Text.Pandoc.Lua.Module.Utils as Pandoc.Utils
-- | Run the lua interpreter, using pandoc's default way of environment
-- initialization.
@ -42,47 +51,45 @@ runLua luaOp = do
-- | Modules that are loaded at startup and assigned to fields in the
-- pandoc module.
loadedModules :: [(Name, Name)]
--
-- Note that @pandoc.List@ is not included here for technical reasons;
-- it must be handled separately.
loadedModules :: [Module PandocError]
loadedModules =
[ ("pandoc.List", "List")
, ("pandoc.layout", "layout")
, ("pandoc.mediabag", "mediabag")
, ("pandoc.path", "path")
, ("pandoc.system", "system")
, ("pandoc.template", "template")
, ("pandoc.types", "types")
, ("pandoc.utils", "utils")
, ("text", "text")
[ Pandoc.MediaBag.documentedModule
, Pandoc.System.documentedModule
, Pandoc.Template.documentedModule
, Pandoc.Types.documentedModule
, Pandoc.Utils.documentedModule
, Module.Layout.documentedModule { moduleName = "pandoc.layout" }
, Module.Path.documentedModule { moduleName = "pandoc.path" }
, Module.Text.documentedModule
]
-- | Initialize the lua state with all required values
initLuaState :: PandocLua ()
initLuaState = do
liftPandocLua Lua.openlibs
installPandocPackageSearcher
initPandocModule
installLpegSearcher
setGlobalModules
loadInitScript "init.lua"
where
initPandocModule :: PandocLua ()
initPandocModule = do
initPandocModule = liftPandocLua $ do
-- Push module table
ModulePandoc.pushModule
-- register as loaded module
liftPandocLua $ do
Lua.getfield Lua.registryindex Lua.loaded
Lua.pushvalue (Lua.nth 2)
Lua.setfield (Lua.nth 2) "pandoc"
Lua.pop 1 -- remove LOADED table
registerModule Module.Pandoc.documentedModule
-- load modules and add them to the `pandoc` module table.
liftPandocLua $ forM_ loadedModules $ \(pkgname, fieldname) -> do
Lua.getglobal "require"
Lua.pushName pkgname
Lua.call 1 1
Lua.setfield (nth 2) fieldname
forM_ loadedModules $ \mdl -> do
registerModule mdl
let isNotAsciiDot = (/= 46)
let fieldname = B.takeWhileEnd isNotAsciiDot (fromName $ moduleName mdl)
Lua.setfield (nth 2) (Name fieldname)
-- pandoc.List is low-level and must be opened differently.
requirehs "pandoc.List" (const pushListModule)
setfield (nth 2) "List"
-- assign module to global variable
liftPandocLua $ Lua.setglobal "pandoc"
Lua.setglobal "pandoc"
loadInitScript :: FilePath -> PandocLua ()
loadInitScript scriptFile = do

View file

@ -1,75 +0,0 @@
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TypeApplications #-}
{- |
Module : Text.Pandoc.Lua.Packages
Copyright : Copyright © 2017-2022 Albert Krewinkel
License : GNU GPL, version 2 or above
Maintainer : Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>
Stability : alpha
Pandoc module for Lua.
-}
module Text.Pandoc.Lua.Packages
( installPandocPackageSearcher
) where
import Control.Monad (forM_)
import Data.String (fromString)
import Text.Pandoc.Error (PandocError)
import Text.Pandoc.Lua.Marshal.List (pushListModule)
import Text.Pandoc.Lua.PandocLua (PandocLua, liftPandocLua)
import qualified HsLua as Lua
import qualified HsLua.Module.DocLayout as DocLayout
import qualified HsLua.Module.Path as Path
import qualified HsLua.Module.Text as Text
import qualified Text.Pandoc.Lua.Module.Pandoc as Pandoc
import qualified Text.Pandoc.Lua.Module.MediaBag as MediaBag
import qualified Text.Pandoc.Lua.Module.System as System
import qualified Text.Pandoc.Lua.Module.Template as Template
import qualified Text.Pandoc.Lua.Module.Types as Types
import qualified Text.Pandoc.Lua.Module.Utils as Utils
-- | Insert pandoc's package loader as the first loader, making it the default.
installPandocPackageSearcher :: PandocLua ()
installPandocPackageSearcher = liftPandocLua $ do
Lua.getglobal' "package.searchers"
shiftArray
Lua.pushHaskellFunction $ Lua.toHaskellFunction pandocPackageSearcher
Lua.rawseti (Lua.nth 2) 1
Lua.pop 1 -- remove 'package.searchers' from stack
where
shiftArray = forM_ [4, 3, 2, 1] $ \i -> do
Lua.rawgeti (-1) i
Lua.rawseti (-2) (i + 1)
-- | Load a pandoc module.
pandocPackageSearcher :: String -> PandocLua Lua.NumResults
pandocPackageSearcher pkgName =
case pkgName of
"pandoc" -> pushModuleLoader Pandoc.documentedModule
"pandoc.layout" -> pushModuleLoader DocLayout.documentedModule
"pandoc.mediabag" -> pushModuleLoader MediaBag.documentedModule
"pandoc.path" -> pushModuleLoader Path.documentedModule
"pandoc.system" -> pushModuleLoader System.documentedModule
"pandoc.template" -> pushModuleLoader Template.documentedModule
"pandoc.types" -> pushModuleLoader Types.documentedModule
"pandoc.utils" -> pushModuleLoader Utils.documentedModule
"text" -> pushModuleLoader Text.documentedModule
"pandoc.List" -> pushWrappedHsFun . Lua.toHaskellFunction @PandocError $
(Lua.NumResults 1 <$ pushListModule @PandocError)
_ -> reportPandocSearcherFailure
where
pushModuleLoader mdl = liftPandocLua $ do
let mdl' = mdl { Lua.moduleName = fromString pkgName }
Lua.pushHaskellFunction $
Lua.NumResults 1 <$ Lua.pushModule mdl'
return (Lua.NumResults 1)
pushWrappedHsFun f = liftPandocLua $ do
Lua.pushHaskellFunction f
return 1
reportPandocSearcherFailure = liftPandocLua $ do
Lua.push ("\n\t" <> pkgName <> " is not one of pandoc's default packages")
return (Lua.NumResults 1)