git.iko.soy/typeable/pandoc
on master help sign in
Text.Pandoc.Lua: move globals handling to separate module
7f70aaaAlbert Krewinkel
pandoc.cabal+1
@@ -541,6 +541,7 @@ library
541 Text.Pandoc.Writers.Powerpoint.Presentation,
541 Text.Pandoc.Writers.Powerpoint.Presentation,
542 Text.Pandoc.Writers.Powerpoint.Output,
542 Text.Pandoc.Writers.Powerpoint.Output,
543 Text.Pandoc.Lua.Filter,
543 Text.Pandoc.Lua.Filter,
544+ Text.Pandoc.Lua.Global,
544 Text.Pandoc.Lua.Init,
545 Text.Pandoc.Lua.Init,
545 Text.Pandoc.Lua.Module.MediaBag,
546 Text.Pandoc.Lua.Module.MediaBag,
546 Text.Pandoc.Lua.Module.Pandoc,
547 Text.Pandoc.Lua.Module.Pandoc,
src/Text/Pandoc/Lua.hs+10−18
@@ -37,8 +37,9 @@ import Control.Monad ((>=>))
37import Foreign.Lua (Lua)
37import Foreign.Lua (Lua)
38import Text.Pandoc.Class (PandocIO)
38import Text.Pandoc.Class (PandocIO)
39import Text.Pandoc.Definition (Pandoc)
39import Text.Pandoc.Definition (Pandoc)
40+import Text.Pandoc.Lua.Global (Global (..), setGlobals)
40import Text.Pandoc.Lua.Filter (LuaFilter, walkMWithLuaFilter)
41import Text.Pandoc.Lua.Filter (LuaFilter, walkMWithLuaFilter)
41−import Text.Pandoc.Lua.Init (LuaException (..), runPandocLua, registerScriptPath)
42+import Text.Pandoc.Lua.Init (LuaException (..), runPandocLua)
42import Text.Pandoc.Lua.Util (dofileWithTraceback)
43import Text.Pandoc.Lua.Util (dofileWithTraceback)
43import Text.Pandoc.Options (ReaderOptions)
44import Text.Pandoc.Options (ReaderOptions)
44
45
@@ -49,15 +50,8 @@ import qualified Foreign.Lua as Lua
49-- interpreter.
50-- interpreter.
50runLuaFilter :: ReaderOptions -> FilePath -> String
51runLuaFilter :: ReaderOptions -> FilePath -> String
51 -> Pandoc -> PandocIO (Either LuaException Pandoc)
52 -> Pandoc -> PandocIO (Either LuaException Pandoc)
52−runLuaFilter ropts filterPath format doc =
53+runLuaFilter ropts filterPath format doc = runPandocLua $ do
53− runPandocLua (runLuaFilter' ropts filterPath format doc)
54+ setGlobals globals
54−
55−runLuaFilter' :: ReaderOptions -> FilePath -> String
56− -> Pandoc -> Lua Pandoc
57−runLuaFilter' ropts filterPath format pd = do
58− registerFormat
59− registerReaderOptions
60− registerScriptPath filterPath
61 top <- Lua.gettop
55 top <- Lua.gettop
62 stat <- dofileWithTraceback filterPath
56 stat <- dofileWithTraceback filterPath
63 if stat /= Lua.OK
57 if stat /= Lua.OK
@@ -69,15 +63,13 @@ runLuaFilter' ropts filterPath format pd = do
69 luaFilters <- if newtop - top >= 1
63 luaFilters <- if newtop - top >= 1
70 then Lua.peek Lua.stackTop
64 then Lua.peek Lua.stackTop
71 else Lua.pushglobaltable *> fmap (:[]) Lua.popValue
65 else Lua.pushglobaltable *> fmap (:[]) Lua.popValue
72− runAll luaFilters pd
66+ runAll luaFilters doc
73− where
74− registerFormat = do
75− Lua.push format
76− Lua.setglobal "FORMAT"
77
67
78− registerReaderOptions = do
68+ where
79− Lua.push ropts
69+ globals = [ FORMAT format
80− Lua.setglobal "PANDOC_READER_OPTIONS"
70+ , PANDOC_READER_OPTIONS ropts
71+ , PANDOC_SCRIPT_FILE filterPath
72+ ]
81
73
82runAll :: [LuaFilter] -> Pandoc -> Lua Pandoc
74runAll :: [LuaFilter] -> Pandoc -> Lua Pandoc
83runAll = foldr ((>=>) . walkMWithLuaFilter) return
75runAll = 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
32 , runPandocLua
32 , runPandocLua
33 , initLuaState
33 , initLuaState
34 , luaPackageParams
34 , luaPackageParams
35− , registerScriptPath
36 ) where
35 ) where
37
36
38import Prelude
37import Prelude
39import Control.Monad.Trans (MonadIO (..))
38import Control.Monad.Trans (MonadIO (..))
40import Data.Data (Data, dataTypeConstrs, dataTypeOf, showConstr)
39import Data.Data (Data, dataTypeConstrs, dataTypeOf, showConstr)
41import Data.IORef (newIORef, readIORef)
40import Data.IORef (newIORef, readIORef)
42−import Data.Version (Version (versionBranch))
43import Foreign.Lua (Lua)
41import Foreign.Lua (Lua)
44import GHC.IO.Encoding (getForeignEncoding, setForeignEncoding, utf8)
42import GHC.IO.Encoding (getForeignEncoding, setForeignEncoding, utf8)
45−import Paths_pandoc (version)
46−import Text.Pandoc.Class (CommonState, PandocIO, getCommonState,
43+import Text.Pandoc.Class (PandocIO, getCommonState, getUserDataDir,
47− getUserDataDir, getMediaBag, setMediaBag)
44+ getMediaBag, setMediaBag)
48−import Text.Pandoc.Definition (pandocTypesVersion)
45+import Text.Pandoc.Lua.Global (Global (..), setGlobals)
49import Text.Pandoc.Lua.Packages (LuaPackageParams (..),
46import Text.Pandoc.Lua.Packages (LuaPackageParams (..),
50 installPandocPackageSearcher)
47 installPandocPackageSearcher)
51import Text.Pandoc.Lua.Util (loadScriptFromDataDir)
48import Text.Pandoc.Lua.Util (loadScriptFromDataDir)
@@ -61,11 +58,12 @@ newtype LuaException = LuaException String deriving (Show)
61-- initialization.
58-- initialization.
62runPandocLua :: Lua a -> PandocIO (Either LuaException a)
59runPandocLua :: Lua a -> PandocIO (Either LuaException a)
63runPandocLua luaOp = do
60runPandocLua luaOp = do
64− commonState <- getCommonState
65 luaPkgParams <- luaPackageParams
61 luaPkgParams <- luaPackageParams
62+ globals <- defaultGlobals
66 enc <- liftIO $ getForeignEncoding <* setForeignEncoding utf8
63 enc <- liftIO $ getForeignEncoding <* setForeignEncoding utf8
67 res <- liftIO . Lua.runEither $ do
64 res <- liftIO . Lua.runEither $ do
65+ setGlobals globals
68− initLuaState commonState luaPkgParams
66+ initLuaState luaPkgParams
69 luaOp
67 luaOp
70 liftIO $ setForeignEncoding enc
68 liftIO $ setForeignEncoding enc
71 newMediaBag <- liftIO (readIORef (luaPkgMediaBag luaPkgParams))
69 newMediaBag <- liftIO (readIORef (luaPkgMediaBag luaPkgParams))
@@ -74,6 +72,16 @@ runPandocLua luaOp = do
74 Left (Lua.Exception msg) -> Left (LuaException msg)
72 Left (Lua.Exception msg) -> Left (LuaException msg)
75 Right x -> Right x
73 Right x -> Right x
76
74
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+
77-- | Generate parameters required to setup pandoc's lua environment.
85-- | Generate parameters required to setup pandoc's lua environment.
78luaPackageParams :: PandocIO LuaPackageParams
86luaPackageParams :: PandocIO LuaPackageParams
79luaPackageParams = do
87luaPackageParams = do
@@ -87,25 +95,14 @@ luaPackageParams = do
87 }
95 }
88
96
89-- Initialize the lua state with all required values
97-- Initialize the lua state with all required values
90−initLuaState :: CommonState -> LuaPackageParams -> Lua ()
98+initLuaState :: LuaPackageParams -> Lua ()
91−initLuaState commonState luaPkgParams = do
99+initLuaState luaPkgParams = do
92 Lua.openlibs
100 Lua.openlibs
93 Lua.preloadTextModule "text"
101 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"
100 installPandocPackageSearcher luaPkgParams
102 installPandocPackageSearcher luaPkgParams
101 loadScriptFromDataDir (luaPkgDataDir luaPkgParams) "init.lua"
103 loadScriptFromDataDir (luaPkgDataDir luaPkgParams) "init.lua"
102 putConstructorsInRegistry
104 putConstructorsInRegistry
103
105
104−registerScriptPath :: FilePath -> Lua ()
105−registerScriptPath fp = do
106− Lua.push fp
107− Lua.setglobal "PANDOC_SCRIPT_FILE"
108−
109putConstructorsInRegistry :: Lua ()
106putConstructorsInRegistry :: Lua ()
110putConstructorsInRegistry = do
107putConstructorsInRegistry = do
111 Lua.getglobal "pandoc"
108 Lua.getglobal "pandoc"
src/Text/Pandoc/Writers/Custom.hs+8−30
@@ -1,4 +1,3 @@
1−{-# LANGUAGE DeriveDataTypeable #-}
2{-# LANGUAGE FlexibleInstances #-}
1{-# LANGUAGE FlexibleInstances #-}
3{-# LANGUAGE NoImplicitPrelude #-}
2{-# LANGUAGE NoImplicitPrelude #-}
4{- Copyright (C) 2012-2018 John MacFarlane <jgm@berkeley.edu>
3{- Copyright (C) 2012-2018 John MacFarlane <jgm@berkeley.edu>
@@ -36,21 +35,18 @@ import Control.Arrow ((***))
36import Control.Exception
35import Control.Exception
37import Control.Monad (when)
36import Control.Monad (when)
38import Data.Char (toLower)
37import Data.Char (toLower)
39−import Data.Data (Data)
40import Data.List (intersperse)
38import Data.List (intersperse)
41import qualified Data.Map as M
39import qualified Data.Map as M
42import Data.Text (Text, pack)
40import Data.Text (Text, pack)
43import Data.Typeable
41import Data.Typeable
44−import Foreign.Lua (Lua, Peekable, Pushable)
42+import Foreign.Lua (Lua, Pushable)
45−import Foreign.Lua.Userdata ( ensureUserdataMetatable, pushAnyWithMetatable
46− , metatableName)
47import Text.Pandoc.Class (PandocIO)
43import Text.Pandoc.Class (PandocIO)
48import Text.Pandoc.Definition
44import Text.Pandoc.Definition
49import Text.Pandoc.Error
45import Text.Pandoc.Error
46+import Text.Pandoc.Lua.Global (Global (..), setGlobals)
50−import Text.Pandoc.Lua.Init (LuaException (LuaException), runPandocLua,
47+import Text.Pandoc.Lua.Init (LuaException (LuaException), runPandocLua)
51− registerScriptPath)
52import Text.Pandoc.Lua.StackInstances ()
48import Text.Pandoc.Lua.StackInstances ()
53−import Text.Pandoc.Lua.Util (addField, addFunction, dofileWithTraceback)
49+import Text.Pandoc.Lua.Util (addField, dofileWithTraceback)
54import Text.Pandoc.Options
50import Text.Pandoc.Options
55import Text.Pandoc.Templates
51import Text.Pandoc.Templates
56import qualified Text.Pandoc.UTF8 as UTF8
52import qualified Text.Pandoc.UTF8 as UTF8
@@ -109,32 +105,14 @@ data PandocLuaException = PandocLuaException String
109
105
110instance Exception PandocLuaException
106instance Exception PandocLuaException
111
107
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−
132-- | Convert Pandoc to custom markup.
108-- | Convert Pandoc to custom markup.
133writeCustom :: FilePath -> WriterOptions -> Pandoc -> PandocIO Text
109writeCustom :: FilePath -> WriterOptions -> Pandoc -> PandocIO Text
134writeCustom luaFile opts doc@(Pandoc meta _) = do
110writeCustom luaFile opts doc@(Pandoc meta _) = do
111+ let globals = [ PANDOC_DOCUMENT doc
112+ , PANDOC_SCRIPT_FILE luaFile
113+ ]
135 res <- runPandocLua $ do
114 res <- runPandocLua $ do
136− Lua.push (LazyPandoc doc) *> Lua.setglobal "PANDOC_DOCUMENT"
115+ setGlobals globals
137− registerScriptPath luaFile
138 stat <- dofileWithTraceback luaFile
116 stat <- dofileWithTraceback luaFile
139 -- check for error in lua script (later we'll change the return type
117 -- check for error in lua script (later we'll change the return type
140 -- to handle this more gracefully):
118 -- to handle this more gracefully):