@@ -39,6 +39,7 @@ module Data.FileEmbed
39 , injectFileWith
39 , injectFileWith
40 -- * Relative path manipulation
40 -- * Relative path manipulation
41 , makeRelativeToProject
41 , makeRelativeToProject
42+ , makeRelativeToLocationPredicate
42 -- * Internal
43 -- * Internal
43 , stringToBs
44 , stringToBs
@@ -408,7 +409,19 @@ available, you can use the non-@With@ variants.
409-- @since 0.0.10
410-- @since 0.0.10
410makeRelativeToProject :: FilePath -> Q FilePath
411makeRelativeToProject :: FilePath -> Q FilePath
411−makeRelativeToProject rel = do
412+makeRelativeToProject = makeRelativeToLocationPredicate $ (==) ".cabal" . takeExtension
414+-- | Take a predicate to infer the project root and a relative file path, the given file path is then attached to the inferred project root
416+-- This function looks at the source location of the Haskell file calling it,
417+-- finds the first parent directory with a file matching the given predicate, and uses that as the
418+-- root directory for fixing the relative path.
420+-- @$(makeRelativeToLocationPredicate ((==) ".cabal" . takeExtension) "data/foo.txt" >>= embedFile)@
423+makeRelativeToLocationPredicate :: (FilePath -> Bool) -> FilePath -> Q FilePath
424+makeRelativeToLocationPredicate isTargetFile rel = do
412 loc <- qLocation
425 loc <- qLocation
413 runIO $ do
426 runIO $ do
414 srcFP <- canonicalizePath $ loc_filename loc
427 srcFP <- canonicalizePath $ loc_filename loc
@@ -423,8 +436,6 @@ makeRelativeToProject rel = do
423 then return Nothing
436 then return Nothing
425 contents <- getDirectoryContents dir
438 contents <- getDirectoryContents dir
426− if any isCabalFile contents
439+ if any isTargetFile contents
427 then return (Just dir)
440 then return (Just dir)
428 else findProjectDir dir
441 else findProjectDir dir
430− isCabalFile fp = takeExtension fp == ".cabal"