@@ -15,6 +15,9 @@ You should have received a copy of the GNU General Public License
1515along with this program; if not, write to the Free Software
1616Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
1717-}
18+{-# LANGUAGE FlexibleContexts #-}
19+{-# LANGUAGE FlexibleInstances #-}
20+{-# LANGUAGE MultiParamTypeClasses #-}
1821{-# LANGUAGE OverloadedStrings #-}
1922{- |
2023 Module : Text.Pandoc.Lua
@@ -130,29 +133,35 @@ execInlineLuaFilter :: LuaState
130133 -> HashMap Text (LuaFilterFunction Inline)
131134 -> Inline -> IO Inline
132135execInlineLuaFilter lua fnMap x = do
133− let filterOrId constr = case HashMap.lookup constr fnMap of
134− Nothing -> return x
135− Just fn -> runLuaFilterFunction lua fn x
136+ let runFn :: PushViaFilterFunction Inline a => LuaFilterFunction Inline -> a
137+ runFn fn = runLuaFilterFunction lua fn
138+ let tryFilter :: Text -> (LuaFilterFunction Inline -> IO Inline) -> IO Inline
139+ tryFilter fnName callFilterFn =
140+ case HashMap.lookup fnName fnMap of
141+ Nothing -> return x
142+ Just fn -> callFilterFn fn
136143 case x of
137− Cite _ _ -> filterOrId "Cite"
138− Code _ _ -> filterOrId "Code"
139− Emph _ -> filterOrId "Emph"
140− Image _ _ _ -> filterOrId "Image"
141− LineBreak -> filterOrId "LineBreak"
142− Link _ _ _ -> filterOrId "Link"
143− Math _ _ -> filterOrId "Math"
144− Note _ -> filterOrId "Note"
145− Quoted _ _ -> filterOrId "Quoted"
146− RawInline _ _ -> filterOrId "RawInline"
147− SmallCaps _ -> filterOrId "SmallCaps"
148− SoftBreak -> filterOrId "SoftBreak"
149− Space -> filterOrId "Space"
150− Span _ _ -> filterOrId "Span"
151− Str _ -> filterOrId "Str"
152− Strikeout _ -> filterOrId "Strikeout"
153− Strong _ -> filterOrId "Strong"
154− Subscript _ -> filterOrId "Subscript"
155− Superscript _ -> filterOrId "Superscript"
144+ LineBreak -> tryFilter "LineBreak" runFn
145+ SoftBreak -> tryFilter "SoftBreak" runFn
146+ Space -> tryFilter "Space" runFn
147+ Cite cs lst -> tryFilter "Cite" $ \fn -> runFn fn lst cs
148+ Code attr str -> tryFilter "Code" $ \fn -> runFn fn str attr
149+ Emph lst -> tryFilter "Emph" $ \fn -> runFn fn lst
150+ Math mt lst -> tryFilter "Math" $ \fn -> runFn fn lst mt
151+ Note blks -> tryFilter "Note" $ \fn -> runFn fn blks
152+ Quoted qt lst -> tryFilter "Quoted" $ \fn -> runFn fn qt lst
153+ RawInline f str -> tryFilter "RawInline" $ \fn -> runFn fn f str
154+ SmallCaps lst -> tryFilter "SmallCaps" $ \fn -> runFn fn lst
155+ Span attr lst -> tryFilter "Span" $ \fn -> runFn fn lst attr
156+ Str str -> tryFilter "Str" $ \fn -> runFn fn str
157+ Strikeout lst -> tryFilter "Strikeout" $ \fn -> runFn fn lst
158+ Strong lst -> tryFilter "Strong" $ \fn -> runFn fn lst
159+ Subscript lst -> tryFilter "Subscript" $ \fn -> runFn fn lst
160+ Superscript lst -> tryFilter "Superscript" $ \fn -> runFn fn lst
161+ Link attr txt (src, tit) -> tryFilter "Link" $
162+ \fn -> runFn fn txt src tit attr
163+ Image attr alt (src, tit) -> tryFilter "Image" $
164+ \fn -> runFn fn alt src tit attr
156165
157166instance StackValue LuaFilter where
158167 valuetype _ = Lua.TTABLE
@@ -164,17 +173,33 @@ instance StackValue LuaFilter where
164173 docFnMap <- Lua.peek lua i
165174 return $ LuaFilter lua <$> inlineFnMap <*> blockFnMap <*> docFnMap
166175
167−runLuaFilterFunction :: (StackValue a)
168− => LuaState -> LuaFilterFunction a -> a -> IO a
169−runLuaFilterFunction lua lf inline = do
170− pushFilterFunction lua lf
171− Lua.push lua inline
172− Lua.call lua 1 1
173− mbres <- Lua.peek lua (-1)
174− case mbres of
175− Nothing -> error $ "Error while trying to get a filter's return "
176− ++ "value from lua stack."
177− Just res -> res <$ Lua.pop lua 1
176+-- | Helper class for pushing a single value to the stack via a lua function.
177+-- See @pushViaCall@.
178+class PushViaFilterFunction a b where
179+ pushViaFilterFunction' :: LuaState -> LuaFilterFunction a -> IO () -> Int -> b
180+
181+instance (StackValue a) => PushViaFilterFunction a (IO a) where
182+ pushViaFilterFunction' lua lf pushArgs num = do
183+ pushFilterFunction lua lf
184+ pushArgs
185+ Lua.call lua num 1
186+ mbres <- Lua.peek lua (-1)
187+ case mbres of
188+ Nothing -> error $ "Error while trying to get a filter's return "
189+ ++ "value from lua stack."
190+ Just res -> res <$ Lua.pop lua 1
191+
192+instance (PushViaFilterFunction a c, StackValue b) =>
193+ PushViaFilterFunction a (b -> c) where
194+ pushViaFilterFunction' lua lf pushArgs num x =
195+ pushViaFilterFunction' lua lf (pushArgs *> push lua x) (num + 1)
196+
197+-- | Push an value to the stack via a lua filter function. The function is
198+-- called with all arguments that are passed to this function and is expected to
199+-- return a single value.
200+runLuaFilterFunction :: (StackValue a, PushViaFilterFunction a b)
201+ => LuaState -> LuaFilterFunction a -> b
202+runLuaFilterFunction lua lf = pushViaFilterFunction' lua lf (return ()) 0
178203
179204-- | Push the filter function to the top of the stack.
180205pushFilterFunction :: Lua.LuaState -> LuaFilterFunction a -> IO ()