git.iko.soy/typeable/pandoc
on master help sign in
Text.Pandoc.Lua: move globals handling to separate module
commit7f70aaa5fa5f69f5f72ff7ee67a1306425052113 authorAlbert Krewinkel <albert@zeitkraut.de> dateFri 26 Oct 2018, 22:15 (8 years ago) parentdc572e8
5 files changed+145−69
pandoc.cabal+1 src/Text/Pandoc/Lua.hs+10−18 src/Text/Pandoc/Lua/Global.hs+108 src/Text/Pandoc/Lua/Init.hs+18−21 src/Text/Pandoc/Writers/Custom.hs+8−30
pandoc.cabal+1
@@ -541,6 +541,7 @@ library
541541 Text.Pandoc.Writers.Powerpoint.Presentation,
542542 Text.Pandoc.Writers.Powerpoint.Output,
543543 Text.Pandoc.Lua.Filter,
544+ Text.Pandoc.Lua.Global,
544545 Text.Pandoc.Lua.Init,
545546 Text.Pandoc.Lua.Module.MediaBag,
546547 Text.Pandoc.Lua.Module.Pandoc,
src/Text/Pandoc/Lua.hs+10−18
@@ -37,8 +37,9 @@ import Control.Monad ((>=>))
3737import Foreign.Lua (Lua)
3838import Text.Pandoc.Class (PandocIO)
3939import Text.Pandoc.Definition (Pandoc)
40+import Text.Pandoc.Lua.Global (Global (..), setGlobals)
4041import Text.Pandoc.Lua.Filter (LuaFilter, walkMWithLuaFilter)
41−import Text.Pandoc.Lua.Init (LuaException (..), runPandocLua, registerScriptPath)
42+import Text.Pandoc.Lua.Init (LuaException (..), runPandocLua)
4243import Text.Pandoc.Lua.Util (dofileWithTraceback)
4344import Text.Pandoc.Options (ReaderOptions)
4445
@@ -49,15 +50,8 @@ import qualified Foreign.Lua as Lua
4950-- interpreter.
5051runLuaFilter :: ReaderOptions -> FilePath -> String
5152 -> Pandoc -> PandocIO (Either LuaException Pandoc)
52−runLuaFilter ropts filterPath format doc =
53− runPandocLua (runLuaFilter' ropts filterPath format doc)
54−
55−runLuaFilter' :: ReaderOptions -> FilePath -> String
56− -> Pandoc -> Lua Pandoc
57−runLuaFilter' ropts filterPath format pd = do
58− registerFormat
59− registerReaderOptions
60− registerScriptPath filterPath
53+runLuaFilter ropts filterPath format doc = runPandocLua $ do
54+ setGlobals globals
6155 top <- Lua.gettop
6256 stat <- dofileWithTraceback filterPath
6357 if stat /= Lua.OK
@@ -69,15 +63,13 @@ runLuaFilter' ropts filterPath format pd = do
6963 luaFilters <- if newtop - top >= 1
7064 then Lua.peek Lua.stackTop
7165 else Lua.pushglobaltable *> fmap (:[]) Lua.popValue
72− runAll luaFilters pd
73− where
74− registerFormat = do
75− Lua.push format
76− Lua.setglobal "FORMAT"
66+ runAll luaFilters doc
7767
78− registerReaderOptions = do
79− Lua.push ropts
80− Lua.setglobal "PANDOC_READER_OPTIONS"
68+ where
69+ globals = [ FORMAT format
70+ , PANDOC_READER_OPTIONS ropts
71+ , PANDOC_SCRIPT_FILE filterPath
72+ ]
8173
8274runAll :: [LuaFilter] -> Pandoc -> Lua Pandoc
8375runAll = foldr ((>=>) . walkMWithLuaFilter) return
src/Text/Pandoc/Lua/Global.hsnew file+108
@@ -0,0 +1,108 @@
1+{-# LANGUAGE DeriveDataTypeable #-}
2+{-# LANGUAGE NoImplicitPrelude #-}
3+{-
4+Copyright © 2017-2018 Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>
5+
6+This program is free software; you can redistribute it and/or modify
7+it under the terms of the GNU General Public License as published by
8+the Free Software Foundation; either version 2 of the License, or
9+(at your option) any later version.
10+
11+This program is distributed in the hope that it will be useful,
12+but WITHOUT ANY WARRANTY; without even the implied warranty of
13+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14+GNU General Public License for more details.
15+
16+You should have received a copy of the GNU General Public License
17+along with this program; if not, write to the Free Software
18+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19+-}
20+{- |
21+ Module : Text.Pandoc.Lua
22+ Copyright : Copyright © 2017-2018 Albert Krewinkel
23+ License : GNU GPL, version 2 or above
24+
25+ Maintainer : Albert Krewinkel <tarleb+pandoc@moltkeplatz.de>
26+ Stability : alpha
27+
28+Pandoc's Lua globals.
29+-}
30+module Text.Pandoc.Lua.Global
31+ ( Global (..)
32+ , setGlobals
33+ ) where
34+
35+import Prelude
36+import Data.Data (Data)
37+import Data.Version (Version (versionBranch))
38+import Foreign.Lua (Lua, Peekable, Pushable)
39+import Foreign.Lua.Userdata ( ensureUserdataMetatable, pushAnyWithMetatable
40+ , metatableName)
41+import Paths_pandoc (version)
42+import Text.Pandoc.Class (CommonState)
43+import Text.Pandoc.Definition (Pandoc (Pandoc), pandocTypesVersion)
44+import Text.Pandoc.Lua.StackInstances ()
45+import Text.Pandoc.Lua.Util (addFunction)
46+import Text.Pandoc.Options (ReaderOptions)
47+
48+import qualified Foreign.Lua as Lua
49+
50+-- | Permissible global Lua variables.
51+data Global =
52+ FORMAT String
53+ | PANDOC_API_VERSION
54+ | PANDOC_DOCUMENT Pandoc
55+ | PANDOC_READER_OPTIONS ReaderOptions
56+ | PANDOC_SCRIPT_FILE FilePath
57+ | PANDOC_STATE CommonState
58+ | PANDOC_VERSION
59+ -- Cannot derive instance of Data because of CommonState
60+
61+-- | Set all given globals.
62+setGlobals :: [Global] -> Lua ()
63+setGlobals = mapM_ setGlobal
64+
65+setGlobal :: Global -> Lua ()
66+setGlobal global = case global of
67+ -- This could be simplified if Global was an instance of Data.
68+ FORMAT format -> do
69+ Lua.push format
70+ Lua.setglobal "FORMAT"
71+ PANDOC_API_VERSION -> do
72+ Lua.push (versionBranch pandocTypesVersion)
73+ Lua.setglobal "PANDOC_API_VERSION"
74+ PANDOC_DOCUMENT doc -> do
75+ Lua.push (LazyPandoc doc)
76+ Lua.setglobal "PANDOC_DOCUMENT"
77+ PANDOC_READER_OPTIONS ropts -> do
78+ Lua.push ropts
79+ Lua.setglobal "PANDOC_READER_OPTIONS"
80+ PANDOC_SCRIPT_FILE filePath -> do
81+ Lua.push filePath
82+ Lua.setglobal "PANDOC_SCRIPT_FILE"
83+ PANDOC_STATE commonState -> do
84+ Lua.push commonState
85+ Lua.setglobal "PANDOC_STATE"
86+ PANDOC_VERSION -> do
87+ Lua.push (versionBranch version)
88+ Lua.setglobal "PANDOC_VERSION"
89+
90+-- | Readonly and lazy pandoc objects.
91+newtype LazyPandoc = LazyPandoc Pandoc
92+ deriving (Data)
93+
94+instance Pushable LazyPandoc where
95+ push lazyDoc = pushAnyWithMetatable pushPandocMetatable lazyDoc
96+ where
97+ pushPandocMetatable = ensureUserdataMetatable (metatableName lazyDoc) $
98+ addFunction "__index" indexLazyPandoc
99+
100+instance Peekable LazyPandoc where
101+ peek = Lua.peekAny
102+
103+indexLazyPandoc :: LazyPandoc -> String -> Lua Lua.NumResults
104+indexLazyPandoc (LazyPandoc (Pandoc meta blks)) field = 1 <$
105+ case field of
106+ "blocks" -> Lua.push blks
107+ "meta" -> Lua.push meta
108+ _ -> Lua.pushnil
src/Text/Pandoc/Lua/Init.hs+18−21
@@ -32,20 +32,17 @@ module Text.Pandoc.Lua.Init
3232 , runPandocLua
3333 , initLuaState
3434 , luaPackageParams
35− , registerScriptPath
3635 ) where
3736
3837import Prelude
3938import Control.Monad.Trans (MonadIO (..))
4039import Data.Data (Data, dataTypeConstrs, dataTypeOf, showConstr)
4140import Data.IORef (newIORef, readIORef)
42−import Data.Version (Version (versionBranch))
4341import Foreign.Lua (Lua)
4442import GHC.IO.Encoding (getForeignEncoding, setForeignEncoding, utf8)
45−import Paths_pandoc (version)
46−import Text.Pandoc.Class (CommonState, PandocIO, getCommonState,
47− getUserDataDir, getMediaBag, setMediaBag)
48−import Text.Pandoc.Definition (pandocTypesVersion)
43+import Text.Pandoc.Class (PandocIO, getCommonState, getUserDataDir,
44+ getMediaBag, setMediaBag)
45+import Text.Pandoc.Lua.Global (Global (..), setGlobals)
4946import Text.Pandoc.Lua.Packages (LuaPackageParams (..),
5047 installPandocPackageSearcher)
5148import Text.Pandoc.Lua.Util (loadScriptFromDataDir)
@@ -61,11 +58,12 @@ newtype LuaException = LuaException String deriving (Show)
6158-- initialization.
6259runPandocLua :: Lua a -> PandocIO (Either LuaException a)
6360runPandocLua luaOp = do
64− commonState <- getCommonState
6561 luaPkgParams <- luaPackageParams
62+ globals <- defaultGlobals
6663 enc <- liftIO $ getForeignEncoding <* setForeignEncoding utf8
6764 res <- liftIO . Lua.runEither $ do
68− initLuaState commonState luaPkgParams
65+ setGlobals globals
66+ initLuaState luaPkgParams
6967 luaOp
7068 liftIO $ setForeignEncoding enc
7169 newMediaBag <- liftIO (readIORef (luaPkgMediaBag luaPkgParams))
@@ -74,6 +72,16 @@ runPandocLua luaOp = do
7472 Left (Lua.Exception msg) -> Left (LuaException msg)
7573 Right x -> Right x
7674
75+-- | Global variables which should always be set.
76+defaultGlobals :: PandocIO [Global]
77+defaultGlobals = do
78+ commonState <- getCommonState
79+ return
80+ [ PANDOC_API_VERSION
81+ , PANDOC_STATE commonState
82+ , PANDOC_VERSION
83+ ]
84+
7785-- | Generate parameters required to setup pandoc's lua environment.
7886luaPackageParams :: PandocIO LuaPackageParams
7987luaPackageParams = do
@@ -87,25 +95,14 @@ luaPackageParams = do
8795 }
8896
8997-- Initialize the lua state with all required values
90−initLuaState :: CommonState -> LuaPackageParams -> Lua ()
91−initLuaState commonState luaPkgParams = do
98+initLuaState :: LuaPackageParams -> Lua ()
99+initLuaState luaPkgParams = do
92100 Lua.openlibs
93101 Lua.preloadTextModule "text"
94− Lua.push (versionBranch version)
95− Lua.setglobal "PANDOC_VERSION"
96− Lua.push (versionBranch pandocTypesVersion)
97− Lua.setglobal "PANDOC_API_VERSION"
98− Lua.push commonState
99− Lua.setglobal "PANDOC_STATE"
100102 installPandocPackageSearcher luaPkgParams
101103 loadScriptFromDataDir (luaPkgDataDir luaPkgParams) "init.lua"
102104 putConstructorsInRegistry
103105
104−registerScriptPath :: FilePath -> Lua ()
105−registerScriptPath fp = do
106− Lua.push fp
107− Lua.setglobal "PANDOC_SCRIPT_FILE"
108−
109106putConstructorsInRegistry :: Lua ()
110107putConstructorsInRegistry = do
111108 Lua.getglobal "pandoc"
src/Text/Pandoc/Writers/Custom.hs+8−30
@@ -1,4 +1,3 @@
1−{-# LANGUAGE DeriveDataTypeable #-}
21{-# LANGUAGE FlexibleInstances #-}
32{-# LANGUAGE NoImplicitPrelude #-}
43{- Copyright (C) 2012-2018 John MacFarlane <jgm@berkeley.edu>
@@ -36,21 +35,18 @@ import Control.Arrow ((***))
3635import Control.Exception
3736import Control.Monad (when)
3837import Data.Char (toLower)
39−import Data.Data (Data)
4038import Data.List (intersperse)
4139import qualified Data.Map as M
4240import Data.Text (Text, pack)
4341import Data.Typeable
44−import Foreign.Lua (Lua, Peekable, Pushable)
45−import Foreign.Lua.Userdata ( ensureUserdataMetatable, pushAnyWithMetatable
46− , metatableName)
42+import Foreign.Lua (Lua, Pushable)
4743import Text.Pandoc.Class (PandocIO)
4844import Text.Pandoc.Definition
4945import Text.Pandoc.Error
50−import Text.Pandoc.Lua.Init (LuaException (LuaException), runPandocLua,
51− registerScriptPath)
46+import Text.Pandoc.Lua.Global (Global (..), setGlobals)
47+import Text.Pandoc.Lua.Init (LuaException (LuaException), runPandocLua)
5248import Text.Pandoc.Lua.StackInstances ()
53−import Text.Pandoc.Lua.Util (addField, addFunction, dofileWithTraceback)
49+import Text.Pandoc.Lua.Util (addField, dofileWithTraceback)
5450import Text.Pandoc.Options
5551import Text.Pandoc.Templates
5652import qualified Text.Pandoc.UTF8 as UTF8
@@ -109,32 +105,14 @@ data PandocLuaException = PandocLuaException String
109105
110106instance Exception PandocLuaException
111107
112−-- | Readonly and lazy pandoc objects.
113−newtype LazyPandoc = LazyPandoc Pandoc
114− deriving (Data)
115−
116−instance Pushable LazyPandoc where
117− push lazyDoc = pushAnyWithMetatable pushPandocMetatable lazyDoc
118− where
119− pushPandocMetatable = ensureUserdataMetatable (metatableName lazyDoc) $
120− addFunction "__index" indexLazyPandoc
121−
122−instance Peekable LazyPandoc where
123− peek = Lua.peekAny
124−
125−indexLazyPandoc :: LazyPandoc -> String -> Lua Lua.NumResults
126−indexLazyPandoc (LazyPandoc (Pandoc meta blks)) field = 1 <$
127− case field of
128− "blocks" -> Lua.push blks
129− "meta" -> Lua.push meta
130− _ -> Lua.pushnil
131−
132108-- | Convert Pandoc to custom markup.
133109writeCustom :: FilePath -> WriterOptions -> Pandoc -> PandocIO Text
134110writeCustom luaFile opts doc@(Pandoc meta _) = do
111+ let globals = [ PANDOC_DOCUMENT doc
112+ , PANDOC_SCRIPT_FILE luaFile
113+ ]
135114 res <- runPandocLua $ do
136− Lua.push (LazyPandoc doc) *> Lua.setglobal "PANDOC_DOCUMENT"
137− registerScriptPath luaFile
115+ setGlobals globals
138116 stat <- dofileWithTraceback luaFile
139117 -- check for error in lua script (later we'll change the return type
140118 -- to handle this more gracefully):