From b3cee8bdb03abf85eb480506291feb16a00b2445 Mon Sep 17 00:00:00 2001 From: Albert Krewinkel Date: Wed, 8 Jun 2022 22:31:06 +0200 Subject: [PATCH] Lua: Simplify module loading code. Modules are now loaded directly; the special pandoc Lua package searcher is no longer necessary and has been removed. --- pandoc.cabal | 1 - src/Text/Pandoc/Lua/Init.hs | 61 +++++++++++++++------------ src/Text/Pandoc/Lua/Packages.hs | 75 --------------------------------- 3 files changed, 34 insertions(+), 103 deletions(-) delete mode 100644 src/Text/Pandoc/Lua/Packages.hs diff --git a/pandoc.cabal b/pandoc.cabal index 94fb8e7a2..83a3a7def 100644 --- a/pandoc.cabal +++ b/pandoc.cabal @@ -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, diff --git a/src/Text/Pandoc/Lua/Init.hs b/src/Text/Pandoc/Lua/Init.hs index 1df3fa959..44769bdba 100644 --- a/src/Text/Pandoc/Lua/Init.hs +++ b/src/Text/Pandoc/Lua/Init.hs @@ -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 diff --git a/src/Text/Pandoc/Lua/Packages.hs b/src/Text/Pandoc/Lua/Packages.hs deleted file mode 100644 index 1a9cb23bb..000000000 --- a/src/Text/Pandoc/Lua/Packages.hs +++ /dev/null @@ -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 - 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)