Allow ${.} in defaults files paths...

to refer to the directory where the default file is.
This will make it possible to create moveable
"packages" of resources in a directory.

Closes #5871.
This commit is contained in:
John MacFarlane 2021-03-05 11:56:41 -08:00
parent 6dd7520cc4
commit df00cf05cb
2 changed files with 24 additions and 2 deletions

View file

@ -1684,6 +1684,19 @@ user data directory that is current when the defaults file is
parsed, regardless of the setting of the environment
variable `USERDATA`.
`${.}` will resolve to the directory containing the default
file itself. This allows you to refer to resources contained
in that directory:
``` yaml
epub-cover-image: ${.}/cover.jpg
epub-metadata: ${.}/meta.xml
resource-path:
- . # the working directory from which pandoc is run
- ${.}/images # the images subdirectory of the directory
# containing this defaults file
```
This environment variable interpolation syntax *only* works in
fields that expect file paths.

View file

@ -27,7 +27,8 @@ module Text.Pandoc.App.Opt (
) where
import Control.Monad.Except (MonadIO, liftIO, throwError, (>=>), foldM)
import Control.Monad.State.Strict (StateT, modify, gets)
import System.FilePath ( addExtension, (</>), takeExtension )
import System.FilePath ( addExtension, (</>), takeExtension, takeDirectory )
import System.Directory ( canonicalizePath )
import Data.Char (isLower, toLower)
import Data.Maybe (fromMaybe)
import GHC.Generics hiding (Meta)
@ -189,7 +190,8 @@ instance (PandocMonad m, MonadIO m)
toText _ = ""
parseYAML n = failAtNode n "Expected a mapping"
resolveVarsInOpt :: (PandocMonad m, MonadIO m) => Opt -> m Opt
resolveVarsInOpt :: forall m. (PandocMonad m, MonadIO m)
=> Opt -> StateT DefaultsState m Opt
resolveVarsInOpt
opt@Opt
{ optTemplate = oTemplate
@ -263,6 +265,7 @@ resolveVarsInOpt
}
where
resolveVars :: FilePath -> StateT DefaultsState m FilePath
resolveVars [] = return []
resolveVars ('$':'{':xs) =
let (ys, zs) = break (=='}') xs
@ -272,6 +275,12 @@ resolveVarsInOpt
val <- lookupEnv' ys
(val ++) <$> resolveVars (drop 1 zs)
resolveVars (c:cs) = (c:) <$> resolveVars cs
lookupEnv' :: String -> StateT DefaultsState m String
lookupEnv' "." = do
mbCurDefaults <- gets curDefaults
maybe (return "")
(fmap takeDirectory . liftIO . canonicalizePath)
mbCurDefaults
lookupEnv' "USERDATA" = do
mbodatadir <- mapM resolveVars oDataDir
mbdatadir <- getUserDataDir