git.iko.soy/typeable/pandoc
on master help sign in
Lua filters: report traceback when an error occurs

A proper Lua traceback is added if either loading of a file or execution of a filter function fails. This should be of help to authors of Lua filters who need to debug their code.

commit9abdbb2783d246c736f05119390e81084f9ab07c authorAlbert Krewinkel <albert@zeitkraut.de> dateMon 1 Oct 2018, 16:10 (8 years ago) parent1ffe47b
9 files changed+49−16
pandoc.cabal+1−1 src/Text/Pandoc/Lua.hs+2−1 src/Text/Pandoc/Lua/Filter.hs+4−5 src/Text/Pandoc/Lua/Util.hs+36−2 src/Text/Pandoc/Writers/Custom.hs+2−2 stack.lts10.yaml+1−2 stack.lts11.yaml+1−1 stack.lts9.yaml+1−1 stack.yaml+1−1
pandoc.cabal+1−1
@@ -372,7 +372,7 @@ library
372372 blaze-html >= 0.9 && < 0.10,
373373 blaze-markup >= 0.8 && < 0.9,
374374 vector >= 0.10 && < 0.13,
375− hslua >= 1.0 && < 1.1,
375+ hslua >= 1.0.1 && < 1.1,
376376 hslua-module-text >= 0.2 && < 0.3,
377377 binary >= 0.5 && < 0.10,
378378 SHA >= 1.6 && < 1.7,
src/Text/Pandoc/Lua.hs+2−1
@@ -39,6 +39,7 @@ import Text.Pandoc.Class (PandocIO)
3939import Text.Pandoc.Definition (Pandoc)
4040import Text.Pandoc.Lua.Filter (LuaFilter, walkMWithLuaFilter)
4141import Text.Pandoc.Lua.Init (LuaException (..), runPandocLua, registerScriptPath)
42+import Text.Pandoc.Lua.Util (dofileWithTraceback)
4243import Text.Pandoc.Options (ReaderOptions)
4344
4445import qualified Foreign.Lua as Lua
@@ -58,7 +59,7 @@ runLuaFilter' ropts filterPath format pd = do
5859 registerReaderOptions
5960 registerScriptPath filterPath
6061 top <- Lua.gettop
61− stat <- Lua.dofile filterPath
62+ stat <- dofileWithTraceback filterPath
6263 if stat /= Lua.OK
6364 then Lua.throwTopMessage
6465 else do
src/Text/Pandoc/Lua/Filter.hs+4−5
@@ -52,6 +52,7 @@ import Text.Pandoc.Walk (walkM, Walkable)
5252
5353import qualified Data.Map.Strict as Map
5454import qualified Foreign.Lua as Lua
55+import qualified Text.Pandoc.Lua.Util as LuaUtil
5556
5657-- | Filter function stored in the registry
5758newtype LuaFilterFunction = LuaFilterFunction Lua.Reference
@@ -118,11 +119,9 @@ tryFilter (LuaFilter fnMap) x =
118119-- element is left unchanged.
119120runFilterFunction :: Pushable a => LuaFilterFunction -> a -> Lua ()
120121runFilterFunction lf x = do
121− let errorPrefix = "Error while running filter function:\n"
122− Lua.withExceptionMessage (errorPrefix <>) $ do
123− pushFilterFunction lf
124− Lua.push x
125− Lua.call 1 1
122+ pushFilterFunction lf
123+ Lua.push x
124+ LuaUtil.callWithTraceback 1 1
126125
127126walkMWithLuaFilter :: LuaFilter -> Pandoc -> Lua Pandoc
128127walkMWithLuaFilter f =
src/Text/Pandoc/Lua/Util.hs+36−2
@@ -40,12 +40,14 @@ module Text.Pandoc.Lua.Util
4040 , loadScriptFromDataDir
4141 , defineHowTo
4242 , throwTopMessageAsError'
43+ , callWithTraceback
44+ , dofileWithTraceback
4345 ) where
4446
4547import Prelude
4648import Control.Monad (unless, when)
47−import Foreign.Lua ( Lua, NumArgs, Peekable, Pushable, StackIndex
48− , ToHaskellFunction )
49+import Foreign.Lua ( Lua, NumArgs, NumResults, Peekable, Pushable, StackIndex
50+ , Status, ToHaskellFunction )
4951import Text.Pandoc.Class (readDataFile, runIOorExplode, setUserDataDir)
5052
5153import qualified Foreign.Lua as Lua
@@ -137,3 +139,35 @@ throwTopMessageAsError' modifier = do
137139-- | Mark the context of a Lua computation for better error reporting.
138140defineHowTo :: String -> Lua a -> Lua a
139141defineHowTo ctx = Lua.withExceptionMessage (("Could not " <> ctx <> ": ") <>)
142+
143+-- | Like @'Lua.pcall'@, but uses a predefined error handler which adds a
144+-- traceback on error.
145+pcallWithTraceback :: NumArgs -> NumResults -> Lua Status
146+pcallWithTraceback nargs nresults = do
147+ let traceback' :: Lua NumResults
148+ traceback' = do
149+ l <- Lua.state
150+ msg <- Lua.tostring' (Lua.nthFromBottom 1)
151+ Lua.traceback l (Just (UTF8.toString msg)) 2
152+ return 1
153+ tracebackIdx <- Lua.absindex (Lua.nthFromTop (Lua.fromNumArgs nargs + 1))
154+ Lua.pushHaskellFunction traceback'
155+ Lua.insert tracebackIdx
156+ result <- Lua.pcall nargs nresults (Just tracebackIdx)
157+ Lua.remove tracebackIdx
158+ return result
159+
160+-- | Like @'Lua.call'@, but adds a traceback to the error message (if any).
161+callWithTraceback :: NumArgs -> NumResults -> Lua ()
162+callWithTraceback nargs nresults = do
163+ result <- pcallWithTraceback nargs nresults
164+ when (result /= Lua.OK) Lua.throwTopMessage
165+
166+-- | Run the given string as a Lua program, while also adding a traceback to the
167+-- error message if an error occurs.
168+dofileWithTraceback :: FilePath -> Lua Status
169+dofileWithTraceback fp = do
170+ loadRes <- Lua.loadfile fp
171+ case loadRes of
172+ Lua.OK -> pcallWithTraceback 0 Lua.multret
173+ _ -> return loadRes
src/Text/Pandoc/Writers/Custom.hs+2−2
@@ -47,7 +47,7 @@ import Text.Pandoc.Error
4747import Text.Pandoc.Lua.Init (LuaException (LuaException), runPandocLua,
4848 registerScriptPath)
4949import Text.Pandoc.Lua.StackInstances ()
50−import Text.Pandoc.Lua.Util (addField)
50+import Text.Pandoc.Lua.Util (addField, dofileWithTraceback)
5151import Text.Pandoc.Options
5252import Text.Pandoc.Templates
5353import qualified Text.Pandoc.UTF8 as UTF8
@@ -111,7 +111,7 @@ writeCustom :: FilePath -> WriterOptions -> Pandoc -> PandocIO Text
111111writeCustom luaFile opts doc@(Pandoc meta _) = do
112112 res <- runPandocLua $ do
113113 registerScriptPath luaFile
114− stat <- Lua.dofile luaFile
114+ stat <- dofileWithTraceback luaFile
115115 -- check for error in lua script (later we'll change the return type
116116 -- to handle this more gracefully):
117117 when (stat /= Lua.OK) $
stack.lts10.yaml+1−2
@@ -19,13 +19,12 @@ extra-deps:
1919- test-framework-0.8.2.0
2020- pandoc-types-1.17.5.1
2121- cmark-gfm-0.1.3
22−- hslua-module-text-0.1.2.1
2322- texmath-0.11.1
2423- haddock-library-1.6.0
2524- HsYAML-0.1.1.1
2625- text-1.2.3.0
2726- hs-bibutils-6.6.0.0
28−- hslua-1.0.0
27+- hslua-1.0.1
2928- hslua-module-text-0.2.0
3029ghc-options:
3130 "$locals": -fhide-source-paths -XNoImplicitPrelude
stack.lts11.yaml+1−1
@@ -20,7 +20,7 @@ extra-deps:
2020- HsYAML-0.1.1.1
2121- hs-bibutils-6.6.0.0
2222- yaml-0.9.0
23−- hslua-1.0.0
23+- hslua-1.0.1
2424- hslua-module-text-0.2.0
2525ghc-options:
2626 "$locals": -fhide-source-paths -XNoImplicitPrelude
stack.lts9.yaml+1−1
@@ -12,7 +12,7 @@ packages:
1212- '.'
1313extra-deps:
1414- pandoc-citeproc-0.14.4
15−- hslua-1.0.0
15+- hslua-1.0.1
1616- hslua-module-text-0.2.0
1717- ansi-terminal-0.8.0.2
1818- cmark-gfm-0.1.3
stack.yaml+1−1
@@ -24,7 +24,7 @@ extra-deps:
2424- HsYAML-0.1.1.1
2525- texmath-0.11.1
2626- yaml-0.9.0
27−- hslua-1.0.0
27+- hslua-1.0.1
2828- hslua-module-text-0.2.0
2929ghc-options:
3030 "$locals": -fhide-source-paths -XNoImplicitPrelude