summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlbert Krewinkel <albert@zeitkraut.de>2022-12-04 23:16:01 +0100
committerJohn MacFarlane <jgm@berkeley.edu>2022-12-05 08:52:37 -0800
commita03b77fbd35a0547f51429cd24388728aadd2008 (patch)
tree52d64efed811804febc2b6352e80887e9ded6792
parenta4ac1ebb954b0eaf0eac0805b8340b1609ef5d8f (diff)
Lua: support `-D` CLI option for custom writers [API change]
A new error `PandocNoTemplateError` (code 87) is thrown if a template is required but cannot be found.
-rw-r--r--pandoc-lua-engine/src/Text/Pandoc/Lua/Writer.hs24
-rw-r--r--pandoc-lua-engine/test/Tests/Lua/Writer.hs10
-rw-r--r--pandoc-lua-engine/test/writer-template.lua2
-rw-r--r--pandoc-lua-engine/test/writer-template.out.txt3
-rw-r--r--src/Text/Pandoc/App/CommandLineOptions.hs20
-rw-r--r--src/Text/Pandoc/App/OutputSettings.hs15
-rw-r--r--src/Text/Pandoc/Error.hs3
-rw-r--r--src/Text/Pandoc/Scripting.hs3
8 files changed, 43 insertions, 37 deletions
diff --git a/pandoc-lua-engine/src/Text/Pandoc/Lua/Writer.hs b/pandoc-lua-engine/src/Text/Pandoc/Lua/Writer.hs
index c5e3e2469..91573c87b 100644
--- a/pandoc-lua-engine/src/Text/Pandoc/Lua/Writer.hs
+++ b/pandoc-lua-engine/src/Text/Pandoc/Lua/Writer.hs
@@ -31,15 +31,13 @@ import Text.Pandoc.Format (ExtensionsConfig (..))
import Text.Pandoc.Lua.Global (Global (..), setGlobals)
import Text.Pandoc.Lua.Init (runLuaWith)
import Text.Pandoc.Lua.Marshal.Format (peekExtensionsConfig)
-import Text.Pandoc.Lua.Marshal.Template (peekTemplate)
import Text.Pandoc.Lua.Marshal.WriterOptions (pushWriterOptions)
-import Text.Pandoc.Templates (Template)
import Text.Pandoc.Writers (Writer (..))
import qualified Text.Pandoc.Lua.Writer.Classic as Classic
-- | Convert Pandoc to custom markup.
writeCustom :: (PandocMonad m, MonadIO m)
- => FilePath -> m (Writer m, ExtensionsConfig, m (Template Text))
+ => FilePath -> m (Writer m, ExtensionsConfig, Maybe Text)
writeCustom luaFile = do
luaState <- liftIO newGCManagedState
luaFile' <- fromMaybe luaFile <$> findFileWithDataFallback "writers" luaFile
@@ -66,19 +64,15 @@ writeCustom luaFile = do
TypeNil -> ExtensionsConfig mempty mempty <$ pop 1
_ -> forcePeek $ peekExtensionsConfig top `lastly` pop 1
- -- Store template function in registry
- let templateField = "Pandoc Writer Template"
- rawgetglobal "Template" *> setfield registryindex templateField
+ mtemplate <- rawgetglobal "Template" >>= \case
+ TypeNil -> pure Nothing
+ TypeFunction -> Just <$> do
+ callTrace 0 1
+ forcePeek $ peekText top `lastly` pop 1
+ _ -> Just <$> do
+ forcePeek $ peekText top `lastly` pop 1
- let getTemplate = liftIO $ withGCManagedState @PandocError luaState $ do
- getfield registryindex templateField >>= \case
- TypeNil -> failLua $ "No default template for writer; " <>
- "the global variable Template is undefined."
- _ -> do
- callTrace 0 1
- forcePeek $ peekTemplate top `lastly` pop 1
-
- let addProperties = (, extsConf, getTemplate)
+ let addProperties = (, extsConf, mtemplate)
rawgetglobal "Writer" >>= \case
TypeNil -> rawgetglobal "ByteStringWriter" >>= \case
diff --git a/pandoc-lua-engine/test/Tests/Lua/Writer.hs b/pandoc-lua-engine/test/Tests/Lua/Writer.hs
index c9a0d478c..97d772bc5 100644
--- a/pandoc-lua-engine/test/Tests/Lua/Writer.hs
+++ b/pandoc-lua-engine/test/Tests/Lua/Writer.hs
@@ -11,6 +11,7 @@ Tests for custom Lua writers.
module Tests.Lua.Writer (tests) where
import Data.Default (Default (def))
+import Data.Maybe (fromMaybe)
import Text.Pandoc.Class (runIOorExplode, readFileStrict)
import Text.Pandoc.Extensions (Extension (..))
import Text.Pandoc.Format (ExtensionsDiff (..), FlavoredFormat (..),
@@ -59,13 +60,8 @@ tests =
, goldenVsString "template"
"writer-template.out.txt"
(runIOorExplode $ do
- txt <- writeCustom "writer-template.lua" >>= \case
- (TextWriter f, _, mt) -> do
- template <- mt
- let opts = def{ writerTemplate = Just template }
- f opts (B.doc (B.plain (B.str "body goes here")))
- _ -> error "Expected a text writer"
- pure $ BL.fromStrict (UTF8.fromText txt))
+ (_, _, template) <- writeCustom "writer-template.lua"
+ pure . BL.fromStrict . UTF8.fromText $ fromMaybe "" template)
, testCase "preset extensions" $ do
let ediff = ExtensionsDiff{extsToEnable = [], extsToDisable = []}
diff --git a/pandoc-lua-engine/test/writer-template.lua b/pandoc-lua-engine/test/writer-template.lua
index c90f7c1ef..8908c0ebb 100644
--- a/pandoc-lua-engine/test/writer-template.lua
+++ b/pandoc-lua-engine/test/writer-template.lua
@@ -3,5 +3,5 @@ function Writer (doc, opts)
end
function Template ()
- return pandoc.template.compile '<!-- start -->\n$body$\n<!-- stop -->\n'
+ return '<!-- start -->\n$body$\n<!-- stop -->\n'
end
diff --git a/pandoc-lua-engine/test/writer-template.out.txt b/pandoc-lua-engine/test/writer-template.out.txt
index 1fb343c28..18e531cff 100644
--- a/pandoc-lua-engine/test/writer-template.out.txt
+++ b/pandoc-lua-engine/test/writer-template.out.txt
@@ -1,4 +1,3 @@
<!-- start -->
-body goes here
-
+$body$
<!-- stop -->
diff --git a/src/Text/Pandoc/App/CommandLineOptions.hs b/src/Text/Pandoc/App/CommandLineOptions.hs
index 78f548fb3..a65fe5a04 100644
--- a/src/Text/Pandoc/App/CommandLineOptions.hs
+++ b/src/Text/Pandoc/App/CommandLineOptions.hs
@@ -51,6 +51,7 @@ import Text.Pandoc.App.Opt (Opt (..), LineEnding (..), IpynbOutput (..),
fullDefaultsPath, OptInfo(..))
import Text.Pandoc.Filter (Filter (..))
import Text.Pandoc.Highlighting (highlightingStyles, lookupHighlightingStyle)
+import Text.Pandoc.Scripting (ScriptingEngine (..))
import Text.Pandoc.Shared (safeStrRead)
import Text.Printf
import qualified Control.Exception as E
@@ -60,7 +61,6 @@ import qualified Data.ByteString.Lazy as B
import qualified Data.Map as M
import qualified Data.Text as T
import qualified Text.Pandoc.UTF8 as UTF8
-import Text.Pandoc.Scripting (ScriptingEngine(..))
parseOptions :: [OptDescr (Opt -> ExceptT OptInfo IO Opt)]
-> Opt -> IO (Either OptInfo Opt)
@@ -105,7 +105,7 @@ parseOptionsFromArgs options' defaults prg rawArgs = do
-- | React to an 'OptInfo' by printing the requested information
-- and exiting or (if there was a parsing error) raising an error.
handleOptInfo :: ScriptingEngine -> OptInfo -> IO ()
-handleOptInfo _engine info = E.handle (handleError . Left) $ do
+handleOptInfo engine info = E.handle (handleError . Left) $ do
case info of
BashCompletion -> do
datafiles <- getDataFileNames
@@ -152,9 +152,19 @@ handleOptInfo _engine info = E.handle (handleError . Left) $ do
mapM_ (UTF8.hPutStrLn stdout . fst) highlightingStyles
PrintDefaultTemplate mbout fmt -> do
let write = maybe (UTF8.hPutStr stdout) (UTF8.writeFile) mbout
- templ <- runIO $ do
- setUserDataDir Nothing
- getDefaultTemplate fmt
+
+ templ <- runIO $
+ case splitExtension (T.unpack fmt) of
+ (_, "") -> do
+ -- built-in format
+ setUserDataDir Nothing
+ getDefaultTemplate fmt
+ _ -> do
+ -- format looks like a filepath => custom writer
+ (_, _, mt) <- engineWriteCustom engine (T.unpack fmt)
+ case mt of
+ Just t -> pure t
+ Nothing -> E.throw $ PandocNoTemplateError fmt
case templ of
Right t
| T.null t -> -- e.g. for docx, odt, json:
diff --git a/src/Text/Pandoc/App/OutputSettings.hs b/src/Text/Pandoc/App/OutputSettings.hs
index 8b5d450cf..c3f0ade8b 100644
--- a/src/Text/Pandoc/App/OutputSettings.hs
+++ b/src/Text/Pandoc/App/OutputSettings.hs
@@ -107,6 +107,9 @@ optToOutputSettings scriptingEngine opts = do
Format.parseFlavoredFormat writerName
let standalone = optStandalone opts || not (isTextFormat format) || pdfOutput
+ let templateOrThrow = \case
+ Left e -> throwError $ PandocTemplateError (T.pack e)
+ Right t -> pure t
let processCustomTemplate getDefault =
case optTemplate opts of
_ | not standalone -> return Nothing
@@ -118,16 +121,18 @@ optToOutputSettings scriptingEngine opts = do
_ -> tp
getTemplate tp'
>>= runWithPartials . compileTemplate tp'
- >>= (\case
- Left e -> throwError $ PandocTemplateError (T.pack e)
- Right t -> return $ Just t)
+ >>= fmap Just . templateOrThrow
(writer, writerExts, mtemplate) <-
if "lua" `T.isSuffixOf` format
then do
- (w, extsConf, mt) <- engineWriteCustom scriptingEngine (T.unpack format)
+ let path = T.unpack format
+ (w, extsConf, mt) <- engineWriteCustom scriptingEngine path
wexts <- Format.applyExtensionsDiff extsConf flvrd
- templ <- processCustomTemplate mt
+ templ <- processCustomTemplate $ case mt of
+ Nothing -> throwError $ PandocNoTemplateError format
+ Just t -> (runWithDefaultPartials $ compileTemplate path t) >>=
+ templateOrThrow
return (w, wexts, templ)
else do
tmpl <- processCustomTemplate (compileDefaultTemplate format)
diff --git a/src/Text/Pandoc/Error.hs b/src/Text/Pandoc/Error.hs
index 434b37240..915fa04cb 100644
--- a/src/Text/Pandoc/Error.hs
+++ b/src/Text/Pandoc/Error.hs
@@ -52,6 +52,7 @@ data PandocError = PandocIOError Text IOError
| PandocCouldNotFindMetadataFileError Text
| PandocResourceNotFound Text
| PandocTemplateError Text
+ | PandocNoTemplateError Text
| PandocAppError Text
| PandocEpubSubdirectoryError Text
| PandocMacroLoop Text
@@ -100,6 +101,7 @@ renderError e =
PandocResourceNotFound fn ->
"File " <> fn <> " not found in resource path"
PandocTemplateError s -> "Error compiling template " <> s
+ PandocNoTemplateError fp -> "No template defined in " <> fp
PandocAppError s -> s
PandocEpubSubdirectoryError s ->
"EPUB subdirectory name '" <> s <> "' contains illegal characters"
@@ -174,6 +176,7 @@ handleError (Left e) =
PandocSyntaxMapError{} -> 67
PandocFilterError{} -> 83
PandocLuaError{} -> 84
+ PandocNoTemplateError{} -> 87
PandocNoScriptingEngine -> 89
PandocMacroLoop{} -> 91
PandocUTF8DecodingError{} -> 92
diff --git a/src/Text/Pandoc/Scripting.hs b/src/Text/Pandoc/Scripting.hs
index 29027dd6d..1942014cb 100644
--- a/src/Text/Pandoc/Scripting.hs
+++ b/src/Text/Pandoc/Scripting.hs
@@ -23,7 +23,6 @@ import Text.Pandoc.Definition (Pandoc)
import Text.Pandoc.Error (PandocError (PandocNoScriptingEngine))
import Text.Pandoc.Filter.Environment (Environment)
import Text.Pandoc.Format (ExtensionsConfig)
-import Text.Pandoc.Templates (Template)
import Text.Pandoc.Readers (Reader)
import Text.Pandoc.Writers (Writer)
@@ -42,7 +41,7 @@ data ScriptingEngine = ScriptingEngine
, engineWriteCustom :: forall m. (PandocMonad m, MonadIO m)
=> FilePath
- -> m (Writer m, ExtensionsConfig, m (Template Text))
+ -> m (Writer m, ExtensionsConfig, Maybe Text)
-- ^ Invoke the given script file to convert to any custom format.
}