T.P.Scripting: add CustomComponents, and change...

...the ScriptingEngine fields.  Instead of separate fields for
custom readers and writers, we now have a single function
that loads any number of "components" from a script: these
may be custom readers, custom writers, templates for writers,
or extension configs.  (Note: it's possible to have a custom
reader and a custom writer for a format together in the same file.)

This is primarily motivated by the need for a smoother check
for custom templates and extensions for `-D` and `--list-extensions`,
but it also seems more elegant.

This is a partial implementation of #8417.
This commit is contained in:
John MacFarlane
2022-12-05 22:50:38 +01:00
committed by Albert Krewinkel
parent a031b800db
commit 5db482fefb
5 changed files with 41 additions and 26 deletions
+1 -2
View File
@@ -86,8 +86,7 @@ library
, Text.Pandoc.Lua.Module.Utils
, Text.Pandoc.Lua.Orphans
, Text.Pandoc.Lua.PandocLua
, Text.Pandoc.Lua.Reader
, Text.Pandoc.Lua.Writer
, Text.Pandoc.Lua.Custom
, Text.Pandoc.Lua.Writer.Classic
, Text.Pandoc.Lua.Writer.Scaffolding
+2 -4
View File
@@ -30,8 +30,7 @@ import Text.Pandoc.Error (PandocError)
import Text.Pandoc.Lua.Filter (applyFilter)
import Text.Pandoc.Lua.Global (Global (..), setGlobals)
import Text.Pandoc.Lua.Init (runLua, runLuaNoEnv)
import Text.Pandoc.Lua.Reader (readCustom)
import Text.Pandoc.Lua.Writer (writeCustom)
import Text.Pandoc.Lua.Custom (loadCustom)
import Text.Pandoc.Lua.Orphans ()
import Text.Pandoc.Scripting (ScriptingEngine (..))
import qualified Text.Pandoc.UTF8 as UTF8
@@ -46,6 +45,5 @@ getEngine = do
pure $ ScriptingEngine
{ engineName = maybe "Lua (unknown version)" UTF8.toText versionName
, engineApplyFilter = applyFilter
, engineReadCustom = readCustom
, engineWriteCustom = writeCustom
, engineLoadCustom = loadCustom
}
+8 -3
View File
@@ -60,7 +60,7 @@ import Text.Pandoc.Filter (Filter (JSONFilter, LuaFilter), Environment (..),
applyFilters)
import qualified Text.Pandoc.Format as Format
import Text.Pandoc.PDF (makePDF)
import Text.Pandoc.Scripting (ScriptingEngine (..))
import Text.Pandoc.Scripting (ScriptingEngine (..), CustomComponents(..))
import Text.Pandoc.SelfContained (makeSelfContained)
import Text.Pandoc.Shared (eastAsianLineBreakFilter,
headerShift, filterIpynbOutput, tshow)
@@ -168,8 +168,13 @@ convertWithOpts' scriptingEngine istty datadir opts = do
if ".lua" `T.isSuffixOf` readerName
then do
let scriptPath = T.unpack readerNameBase
(r, extsConf) <- engineReadCustom scriptingEngine scriptPath
rexts <- Format.applyExtensionsDiff extsConf flvrd
components <- engineLoadCustom scriptingEngine scriptPath
r <- case customReader components of
Nothing -> throwError $ PandocAppError $
readerName <> " does not contain a custom reader"
Just r -> return r
let extsConf = fromMaybe mempty (customExtensions components)
rexts <- Format.applyExtensionsDiff extsConf flvrd
return (r, rexts)
else if optSandbox opts
then case runPure (getReader flvrd) of
+13 -6
View File
@@ -41,7 +41,8 @@ import Text.Pandoc.App.Opt (Opt (..))
import Text.Pandoc.App.CommandLineOptions (engines, setVariable)
import qualified Text.Pandoc.Format as Format
import Text.Pandoc.Highlighting (lookupHighlightingStyle)
import Text.Pandoc.Scripting (ScriptingEngine (engineWriteCustom))
import Text.Pandoc.Scripting (ScriptingEngine (engineLoadCustom),
CustomComponents(..))
import qualified Text.Pandoc.UTF8 as UTF8
readUtf8File :: PandocMonad m => FilePath -> m T.Text
@@ -127,12 +128,18 @@ optToOutputSettings scriptingEngine opts = do
if "lua" `T.isSuffixOf` format
then do
let path = T.unpack format
(w, extsConf, mt) <- engineWriteCustom scriptingEngine path
components <- engineLoadCustom scriptingEngine path
w <- case customWriter components of
Nothing -> throwError $ PandocAppError $
format <> " does not contain a custom writer"
Just w -> return w
let extsConf = fromMaybe mempty $ customExtensions components
wexts <- Format.applyExtensionsDiff extsConf flvrd
templ <- processCustomTemplate $ case mt of
Nothing -> throwError $ PandocNoTemplateError format
Just t -> (runWithDefaultPartials $ compileTemplate path t) >>=
templateOrThrow
templ <- processCustomTemplate $
case customTemplate components of
Nothing -> throwError $ PandocNoTemplateError format
Just t -> (runWithDefaultPartials $ compileTemplate path t) >>=
templateOrThrow
return (w, wexts, templ)
else do
tmpl <- processCustomTemplate (compileDefaultTemplate format)
+17 -11
View File
@@ -11,6 +11,7 @@ Central data structure for scripting engines.
-}
module Text.Pandoc.Scripting
( ScriptingEngine (..)
, CustomComponents(..)
, noEngine
)
where
@@ -26,6 +27,18 @@ import Text.Pandoc.Format (ExtensionsConfig)
import Text.Pandoc.Readers (Reader)
import Text.Pandoc.Writers (Writer)
-- | A component of a custom reader/writer: a custom reader,
-- a custom writer, a template for a custom writer, or a specification
-- of the extensions used by a script and their default values.
-- Note that a single script can contain all of these.
data CustomComponents m =
CustomComponents
{ customReader :: Maybe (Reader m)
, customWriter :: Maybe (Writer m)
, customTemplate :: Maybe Text
, customExtensions :: Maybe ExtensionsConfig
}
-- | Structure to define a scripting engine.
data ScriptingEngine = ScriptingEngine
{ engineName :: Text -- ^ Name of the engine.
@@ -35,14 +48,9 @@ data ScriptingEngine = ScriptingEngine
-> Pandoc -> m Pandoc
-- ^ Use the scripting engine to run a filter.
, engineReadCustom :: forall m. (PandocMonad m, MonadIO m)
=> FilePath -> m (Reader m, ExtensionsConfig)
-- ^ Function to parse input into a 'Pandoc' document.
, engineWriteCustom :: forall m. (PandocMonad m, MonadIO m)
=> FilePath
-> m (Writer m, ExtensionsConfig, Maybe Text)
-- ^ Invoke the given script file to convert to any custom format.
, engineLoadCustom :: forall m. (PandocMonad m, MonadIO m)
=> FilePath -> m (CustomComponents m)
-- ^ Function to load a custom reader/writer from a script.
}
noEngine :: ScriptingEngine
@@ -50,8 +58,6 @@ noEngine = ScriptingEngine
{ engineName = "none"
, engineApplyFilter = \_env _args _fp _doc ->
throwError PandocNoScriptingEngine
, engineReadCustom = \_fp ->
throwError PandocNoScriptingEngine
, engineWriteCustom = \_fp ->
, engineLoadCustom = \_fp ->
throwError PandocNoScriptingEngine
}