@@ -32,16 +32,18 @@ import Data.Char (isLower, toLower)
3232import Data.Maybe (fromMaybe)
3333import GHC.Generics hiding (Meta)
3434import Text.Pandoc.Filter (Filter (..))
35−import Text.Pandoc.Logging (Verbosity (WARNING))
35+import Text.Pandoc.Logging (Verbosity (WARNING), LogMessage(..))
3636import Text.Pandoc.Options (TopLevelDivision (TopLevelDefault),
3737 TrackChanges (AcceptChanges),
3838 WrapOption (WrapAuto), HTMLMathMethod (PlainMath),
3939 ReferenceLocation (EndOfDocument),
4040 ObfuscationMethod (NoObfuscation),
4141 CiteMethod (Citeproc))
42−import Text.Pandoc.Class (readFileLazy, fileExists, setVerbosity, PandocMonad)
42+import Text.Pandoc.Class (readFileLazy, fileExists, setVerbosity, report,
43+ PandocMonad(lookupEnv), getUserDataDir)
4344import Text.Pandoc.Error (PandocError (PandocParseError, PandocSomeError))
44−import Text.Pandoc.Shared (camelCaseStrToHyphenated, defaultUserDataDirs, findM, ordNub)
45+import Text.Pandoc.Shared (camelCaseStrToHyphenated, defaultUserDataDir,
46+ findM, ordNub)
4547import qualified Text.Pandoc.Parsing as P
4648import Text.Pandoc.Readers.Metadata (yamlMap)
4749import Text.Pandoc.Class.PandocPure
@@ -176,17 +178,120 @@ instance (PandocMonad m, MonadIO m)
176178 dataDir <- case M.lookup "data-dir" opts of
177179 Nothing -> return Nothing
178180 Just v -> Just . unpack <$> parseYAML v
179− f <- parseOptions $ M.toList m
181+ f <- parseOptions (M.toList m)
180182 case M.lookup "defaults" opts of
181183 Just v -> do
182184 g <- parseDefaults v dataDir
183− return $ g >=> f
184− Nothing -> return f
185+ return $ g >=> f >=> resolveVarsInOpt
186+ Nothing -> return $ f >=> resolveVarsInOpt
185187 where
186188 toText (Scalar _ (SStr s)) = s
187189 toText _ = ""
188190 parseYAML n = failAtNode n "Expected a mapping"
189191
192+resolveVarsInOpt :: (PandocMonad m, MonadIO m) => Opt -> m Opt
193+resolveVarsInOpt
194+ opt@Opt
195+ { optTemplate = oTemplate
196+ , optMetadataFiles = oMetadataFiles
197+ , optOutputFile = oOutputFile
198+ , optInputFiles = oInputFiles
199+ , optSyntaxDefinitions = oSyntaxDefinitions
200+ , optAbbreviations = oAbbreviations
201+ , optReferenceDoc = oReferenceDoc
202+ , optEpubMetadata = oEpubMetadata
203+ , optEpubFonts = oEpubFonts
204+ , optEpubCoverImage = oEpubCoverImage
205+ , optLogFile = oLogFile
206+ , optFilters = oFilters
207+ , optDataDir = oDataDir
208+ , optExtractMedia = oExtractMedia
209+ , optCss = oCss
210+ , optIncludeBeforeBody = oIncludeBeforeBody
211+ , optIncludeAfterBody = oIncludeAfterBody
212+ , optIncludeInHeader = oIncludeInHeader
213+ , optResourcePath = oResourcePath
214+ , optCSL = oCSL
215+ , optBibliography = oBibliography
216+ , optCitationAbbreviations = oCitationAbbreviations
217+ }
218+ = do
219+ oTemplate' <- mapM resolveVars oTemplate
220+ oMetadataFiles' <- mapM resolveVars oMetadataFiles
221+ oOutputFile' <- mapM resolveVars oOutputFile
222+ oInputFiles' <- mapM (mapM resolveVars) oInputFiles
223+ oSyntaxDefinitions' <- mapM resolveVars oSyntaxDefinitions
224+ oAbbreviations' <- mapM resolveVars oAbbreviations
225+ oReferenceDoc' <- mapM resolveVars oReferenceDoc
226+ oEpubMetadata' <- mapM resolveVars oEpubMetadata
227+ oEpubFonts' <- mapM resolveVars oEpubFonts
228+ oEpubCoverImage' <- mapM resolveVars oEpubCoverImage
229+ oLogFile' <- mapM resolveVars oLogFile
230+ oFilters' <- mapM resolveVarsInFilter oFilters
231+ oDataDir' <- mapM resolveVars oDataDir
232+ oExtractMedia' <- mapM resolveVars oExtractMedia
233+ oCss' <- mapM resolveVars oCss
234+ oIncludeBeforeBody' <- mapM resolveVars oIncludeBeforeBody
235+ oIncludeAfterBody' <- mapM resolveVars oIncludeAfterBody
236+ oIncludeInHeader' <- mapM resolveVars oIncludeInHeader
237+ oResourcePath' <- mapM resolveVars oResourcePath
238+ oCSL' <- mapM resolveVars oCSL
239+ oBibliography' <- mapM resolveVars oBibliography
240+ oCitationAbbreviations' <- mapM resolveVars oCitationAbbreviations
241+ return opt{ optTemplate = oTemplate'
242+ , optMetadataFiles = oMetadataFiles'
243+ , optOutputFile = oOutputFile'
244+ , optInputFiles = oInputFiles'
245+ , optSyntaxDefinitions = oSyntaxDefinitions'
246+ , optAbbreviations = oAbbreviations'
247+ , optReferenceDoc = oReferenceDoc'
248+ , optEpubMetadata = oEpubMetadata'
249+ , optEpubFonts = oEpubFonts'
250+ , optEpubCoverImage = oEpubCoverImage'
251+ , optLogFile = oLogFile'
252+ , optFilters = oFilters'
253+ , optDataDir = oDataDir'
254+ , optExtractMedia = oExtractMedia'
255+ , optCss = oCss'
256+ , optIncludeBeforeBody = oIncludeBeforeBody'
257+ , optIncludeAfterBody = oIncludeAfterBody'
258+ , optIncludeInHeader = oIncludeInHeader'
259+ , optResourcePath = oResourcePath'
260+ , optCSL = oCSL'
261+ , optBibliography = oBibliography'
262+ , optCitationAbbreviations = oCitationAbbreviations'
263+ }
264+
265+ where
266+ resolveVars [] = return []
267+ resolveVars ('$':'{':xs) =
268+ let (ys, zs) = break (=='}') xs
269+ in if null zs
270+ then return $ '$':'{':xs
271+ else do
272+ val <- lookupEnv' ys
273+ (val ++) <$> resolveVars (drop 1 zs)
274+ resolveVars (c:cs) = (c:) <$> resolveVars cs
275+ lookupEnv' "USERDATA" = do
276+ mbodatadir <- mapM resolveVars oDataDir
277+ mbdatadir <- getUserDataDir
278+ defdatadir <- liftIO defaultUserDataDir
279+ return $ fromMaybe defdatadir (mbodatadir <|> mbdatadir)
280+ lookupEnv' v = do
281+ mbval <- fmap T.unpack <$> lookupEnv (T.pack v)
282+ case mbval of
283+ Nothing -> do
284+ report $ EnvironmentVariableUndefined (T.pack v)
285+ return mempty
286+ Just x -> return x
287+ resolveVarsInFilter (JSONFilter fp) =
288+ JSONFilter <$> resolveVars fp
289+ resolveVarsInFilter (LuaFilter fp) =
290+ LuaFilter <$> resolveVars fp
291+ resolveVarsInFilter CiteprocFilter = return CiteprocFilter
292+
293+
294+
190295parseDefaults :: (PandocMonad m, MonadIO m)
191296 => Node Pos
192297 -> Maybe FilePath