summaryrefslogtreecommitdiff
path: root/src/Text/Pandoc/Lua/Init.hs
diff options
context:
space:
mode:
Diffstat (limited to 'src/Text/Pandoc/Lua/Init.hs')
-rw-r--r--src/Text/Pandoc/Lua/Init.hs117
1 files changed, 117 insertions, 0 deletions
diff --git a/src/Text/Pandoc/Lua/Init.hs b/src/Text/Pandoc/Lua/Init.hs
new file mode 100644
index 000000000..8fa228837
--- /dev/null
+++ b/src/Text/Pandoc/Lua/Init.hs
@@ -0,0 +1,117 @@
+{-
+Copyright © 2017-2018 Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+-}
+{- |
+ Module : Text.Pandoc.Lua
+ Copyright : Copyright © 2017-2018 Albert Krewinkel
+ License : GNU GPL, version 2 or above
+
+ Maintainer : Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>
+ Stability : alpha
+
+Functions to initialize the Lua interpreter.
+-}
+module Text.Pandoc.Lua.Init
+ ( LuaException (..)
+ , LuaPackageParams (..)
+ , runPandocLua
+ , initLuaState
+ , luaPackageParams
+ , registerScriptPath
+ ) where
+
+import Control.Monad.Trans (MonadIO (..))
+import Data.Data (Data, dataTypeConstrs, dataTypeOf, showConstr)
+import Data.IORef (newIORef, readIORef)
+import Data.Version (Version (versionBranch))
+import Foreign.Lua (Lua, LuaException (..))
+import GHC.IO.Encoding (getForeignEncoding, setForeignEncoding, utf8)
+import Paths_pandoc (version)
+import Text.Pandoc.Class (PandocIO, getCommonState, getUserDataDir, getMediaBag,
+ setMediaBag)
+import Text.Pandoc.Definition (pandocTypesVersion)
+import Text.Pandoc.Lua.Packages (LuaPackageParams (..),
+ installPandocPackageSearcher)
+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
+
+-- | Run the lua interpreter, using pandoc's default way of environment
+-- initalization.
+runPandocLua :: Lua a -> PandocIO (Either LuaException a)
+runPandocLua luaOp = do
+ luaPkgParams <- luaPackageParams
+ enc <- liftIO $ getForeignEncoding <* setForeignEncoding utf8
+ res <- liftIO $ Lua.runLuaEither (initLuaState luaPkgParams *> luaOp)
+ liftIO $ setForeignEncoding enc
+ newMediaBag <- liftIO (readIORef (luaPkgMediaBag luaPkgParams))
+ setMediaBag newMediaBag
+ return res
+
+-- | Generate parameters required to setup pandoc's lua environment.
+luaPackageParams :: PandocIO LuaPackageParams
+luaPackageParams = do
+ commonState <- getCommonState
+ datadir <- getUserDataDir
+ mbRef <- liftIO . newIORef =<< getMediaBag
+ return LuaPackageParams
+ { luaPkgCommonState = commonState
+ , luaPkgDataDir = datadir
+ , luaPkgMediaBag = mbRef
+ }
+
+-- Initialize the lua state with all required values
+initLuaState :: LuaPackageParams -> Lua ()
+initLuaState luaPkgParams = do
+ Lua.openlibs
+ Lua.preloadTextModule "text"
+ Lua.push (versionBranch version)
+ Lua.setglobal "PANDOC_VERSION"
+ Lua.push (versionBranch pandocTypesVersion)
+ Lua.setglobal "PANDOC_API_VERSION"
+ installPandocPackageSearcher luaPkgParams
+ loadScriptFromDataDir (luaPkgDataDir luaPkgParams) "init.lua"
+ putConstructorsInRegistry
+
+registerScriptPath :: FilePath -> Lua ()
+registerScriptPath fp = do
+ Lua.push fp
+ Lua.setglobal "PANDOC_SCRIPT_FILE"
+
+putConstructorsInRegistry :: Lua ()
+putConstructorsInRegistry = do
+ Lua.getglobal "pandoc"
+ constrsToReg $ Pandoc.Pandoc mempty mempty
+ constrsToReg $ Pandoc.Str mempty
+ constrsToReg $ Pandoc.Para mempty
+ constrsToReg $ Pandoc.Meta mempty
+ constrsToReg $ Pandoc.MetaList mempty
+ constrsToReg $ Pandoc.Citation mempty mempty mempty Pandoc.AuthorInText 0 0
+ putInReg "Attr" -- used for Attr type alias
+ Lua.pop 1
+ where
+ constrsToReg :: Data a => a -> Lua ()
+ constrsToReg = mapM_ (putInReg . showConstr) . dataTypeConstrs . dataTypeOf
+
+ putInReg :: String -> Lua ()
+ putInReg name = do
+ Lua.push ("pandoc." ++ name) -- name in registry
+ Lua.push name -- in pandoc module
+ Lua.rawget (Lua.nthFromTop 3)
+ Lua.rawset Lua.registryindex