Skip to content

Commit

Permalink
Lua: add function pandoc.utils.run_lua_filter
Browse files Browse the repository at this point in the history
  • Loading branch information
tarleb committed May 24, 2024
1 parent d01f2ac commit 63cb191
Show file tree
Hide file tree
Showing 5 changed files with 94 additions and 61 deletions.
1 change: 1 addition & 0 deletions pandoc-lua-engine/pandoc-lua-engine.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ library
hs-source-dirs: src
exposed-modules: Text.Pandoc.Lua
other-modules: Text.Pandoc.Lua.Custom
, Text.Pandoc.Lua.Engine
, Text.Pandoc.Lua.Filter
, Text.Pandoc.Lua.Global
, Text.Pandoc.Lua.Init
Expand Down
20 changes: 1 addition & 19 deletions pandoc-lua-engine/src/Text/Pandoc/Lua.hs
Original file line number Diff line number Diff line change
Expand Up @@ -23,26 +23,8 @@ module Text.Pandoc.Lua
, getEngine
) where

import Control.Monad.IO.Class (MonadIO (liftIO))
import HsLua.Core (getglobal, openlibs, run, top, tostring)
import Text.Pandoc.Error (PandocError)
import Text.Pandoc.Lua.Filter (applyFilter)
import Text.Pandoc.Lua.Engine (getEngine, applyFilter)
import Text.Pandoc.Lua.Global (Global (..), setGlobals)
import Text.Pandoc.Lua.Init (runLua, runLuaNoEnv)
import Text.Pandoc.Lua.Custom (loadCustom)
import Text.Pandoc.Lua.Orphans ()
import Text.Pandoc.Scripting (ScriptingEngine (..))
import qualified Text.Pandoc.UTF8 as UTF8

-- | Constructs the Lua scripting engine.
getEngine :: MonadIO m => m ScriptingEngine
getEngine = do
versionName <- liftIO . run @PandocError $ do
openlibs
getglobal "_VERSION"
tostring top
pure $ ScriptingEngine
{ engineName = maybe "Lua (unknown version)" UTF8.toText versionName
, engineApplyFilter = applyFilter
, engineLoadCustom = loadCustom
}
73 changes: 73 additions & 0 deletions pandoc-lua-engine/src/Text/Pandoc/Lua/Engine.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TypeApplications #-}
{- |
Module : Text.Pandoc.Lua.Engine
Copyright : Copyright © 2017-2024 Albert Krewinkel
License : GPL-2.0-or-later
Maintainer : Albert Krewinkel <tarleb+pandoc@zeitkraut.de>
Running pandoc Lua filters.
-}
module Text.Pandoc.Lua.Engine
( getEngine
, applyFilter
) where

import Control.Exception (throw)
import Control.Monad ((>=>))
import Control.Monad.IO.Class (MonadIO (liftIO))
import HsLua.Core (getglobal, openlibs, run, top, tostring)
import Text.Pandoc.Class (PandocMonad)
import Text.Pandoc.Definition (Pandoc)
import Text.Pandoc.Filter (Environment (..))
import Text.Pandoc.Error (PandocError (PandocFilterError, PandocLuaError))
import Text.Pandoc.Lua.Filter (runFilterFile)
import Text.Pandoc.Lua.Global (Global (..), setGlobals)
import Text.Pandoc.Lua.Init (runLua)
import Text.Pandoc.Lua.Custom (loadCustom)
import Text.Pandoc.Lua.Orphans ()
import Text.Pandoc.Scripting (ScriptingEngine (..))
import qualified Text.Pandoc.UTF8 as UTF8
import qualified Data.Text as T

-- | Constructs the Lua scripting engine.
getEngine :: MonadIO m => m ScriptingEngine
getEngine = do
versionName <- liftIO . run @PandocError $ do
openlibs
getglobal "_VERSION"
tostring top
pure $ ScriptingEngine
{ engineName = maybe "Lua (unknown version)" UTF8.toText versionName
, engineApplyFilter = applyFilter
, engineLoadCustom = loadCustom
}

-- | Run the Lua filter in @filterPath@ for a transformation to the
-- target format (first element in args). Pandoc uses Lua init files to
-- setup the Lua interpreter.
applyFilter :: (PandocMonad m, MonadIO m)
=> Environment
-> [String]
-> FilePath
-> Pandoc
-> m Pandoc
applyFilter fenv args fp doc = do
let globals = [ FORMAT $ case args of
x:_ -> T.pack x
_ -> ""
, PANDOC_READER_OPTIONS (envReaderOptions fenv)
, PANDOC_WRITER_OPTIONS (envWriterOptions fenv)
, PANDOC_SCRIPT_FILE fp
]
runLua >=> forceResult fp $ do
setGlobals globals
runFilterFile fp doc

forceResult :: (PandocMonad m, MonadIO m)
=> FilePath -> Either PandocError Pandoc -> m Pandoc
forceResult fp eitherResult = case eitherResult of
Right x -> return x
Left err -> throw . PandocFilterError (T.pack fp) $ case err of
PandocLuaError msg -> msg
_ -> T.pack $ show err
47 changes: 5 additions & 42 deletions pandoc-lua-engine/src/Text/Pandoc/Lua/Filter.hs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE IncoherentInstances #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ScopedTypeVariables #-}
{- |
Module : Text.Pandoc.Lua.Filter
Expand All @@ -13,29 +12,22 @@ Stability : alpha
Types and functions for running Lua filters.
-}
module Text.Pandoc.Lua.Filter
( applyFilter
( runFilterFile
) where
import Control.Monad ((>=>), (<$!>))
import HsLua as Lua
import Text.Pandoc.Definition
import Text.Pandoc.Filter (Environment (..))
import HsLua
import Text.Pandoc.Definition (Pandoc)
import Text.Pandoc.Error (PandocError)
import Text.Pandoc.Lua.Marshal.AST
import Text.Pandoc.Lua.Marshal.Filter
import Text.Pandoc.Lua.Global (Global (..), setGlobals)
import Text.Pandoc.Lua.Init (runLua)
import Text.Pandoc.Lua.PandocLua ()
import Control.Exception (throw)
import qualified Data.Text as T
import Text.Pandoc.Class (PandocMonad)
import Control.Monad.Trans (MonadIO)
import Text.Pandoc.Error (PandocError (PandocFilterError, PandocLuaError))

-- | Transform document using the filter defined in the given file.
runFilterFile :: FilePath -> Pandoc -> LuaE PandocError Pandoc
runFilterFile filterPath doc = do
oldtop <- gettop
stat <- dofileTrace (Just filterPath)
if stat /= Lua.OK
if stat /= OK
then throwErrorAsException
else do
newtop <- gettop
Expand All @@ -50,32 +42,3 @@ runFilterFile filterPath doc = do

runAll :: [Filter] -> Pandoc -> LuaE PandocError Pandoc
runAll = foldr ((>=>) . applyFully) return

-- | Run the Lua filter in @filterPath@ for a transformation to the
-- target format (first element in args). Pandoc uses Lua init files to
-- setup the Lua interpreter.
applyFilter :: (PandocMonad m, MonadIO m)
=> Environment
-> [String]
-> FilePath
-> Pandoc
-> m Pandoc
applyFilter fenv args fp doc = do
let globals = [ FORMAT $ case args of
x:_ -> T.pack x
_ -> ""
, PANDOC_READER_OPTIONS (envReaderOptions fenv)
, PANDOC_WRITER_OPTIONS (envWriterOptions fenv)
, PANDOC_SCRIPT_FILE fp
]
runLua >=> forceResult fp $ do
setGlobals globals
runFilterFile fp doc

forceResult :: (PandocMonad m, MonadIO m)
=> FilePath -> Either PandocError Pandoc -> m Pandoc
forceResult fp eitherResult = case eitherResult of
Right x -> return x
Left err -> throw . PandocFilterError (T.pack fp) $ case err of
PandocLuaError msg -> msg
_ -> T.pack $ show err
14 changes: 14 additions & 0 deletions pandoc-lua-engine/src/Text/Pandoc/Lua/Module/Utils.hs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import Text.Pandoc.Citeproc (getReferences, processCitations)
import Text.Pandoc.Definition
import Text.Pandoc.Error (PandocError)
import Text.Pandoc.Filter (applyJSONFilter)
import Text.Pandoc.Lua.Filter (runFilterFile)
import Text.Pandoc.Lua.Marshal.AST
import Text.Pandoc.Lua.Marshal.Reference
import Text.Pandoc.Lua.PandocLua (PandocLua (unPandocLua))
Expand Down Expand Up @@ -60,6 +61,7 @@ documentedModule = Module
, from_simple_table `since` v[2,11]
, make_sections `since` v[2,8]
, references `since` v[2,17]
, run_lua_filter `since` v[3,2,1]
, run_json_filter `since` v[2,1,1]
, normalize_date `since` v[2,0,6]
, sha1 `since` v[2,0,6]
Expand Down Expand Up @@ -246,6 +248,18 @@ references = defun "references"
, " end"
]

-- | Run a filter from a file.
run_lua_filter :: DocumentedFunction PandocError
run_lua_filter = defun "run_filter_filter"
### (flip runFilterFile)
<#> parameter peekPandoc "Pandoc" "doc" "the Pandoc document to filter"
<#> parameter peekString "string" "filter" "filepath of the filter to run"
=#> functionResult pushPandoc "Pandoc" "filtered document"
#? ( "Filter the given doc by passing it through a Lua filter." <>
"\n\nThe filter will be run in the current Lua process."
)

-- | Process the document with a JSON filter.
run_json_filter :: DocumentedFunction PandocError
run_json_filter = defun "run_json_filter"
### (\doc filterPath margs -> do
Expand Down

0 comments on commit 63cb191

Please sign in to comment.