csv: fix multiple includes in one rules file
This commit is contained in:
parent
6614aab5d7
commit
e94f04311d
@ -1,9 +1,9 @@
|
|||||||
{-# LANGUAGE CPP #-}
|
|
||||||
{-|
|
{-|
|
||||||
|
|
||||||
A reader for CSV data, using an extra rules file to help interpret the data.
|
A reader for CSV data, using an extra rules file to help interpret the data.
|
||||||
|
|
||||||
-}
|
-}
|
||||||
|
{-# LANGUAGE CPP #-}
|
||||||
{-# LANGUAGE FlexibleContexts #-}
|
{-# LANGUAGE FlexibleContexts #-}
|
||||||
{-# LANGUAGE ScopedTypeVariables #-}
|
{-# LANGUAGE ScopedTypeVariables #-}
|
||||||
{-# LANGUAGE TypeFamilies #-}
|
{-# LANGUAGE TypeFamilies #-}
|
||||||
@ -41,6 +41,7 @@ import Data.Ord
|
|||||||
import qualified Data.Set as S
|
import qualified Data.Set as S
|
||||||
import Data.Text (Text)
|
import Data.Text (Text)
|
||||||
import qualified Data.Text as T
|
import qualified Data.Text as T
|
||||||
|
import qualified Data.Text.IO as T
|
||||||
import Data.Time.Calendar (Day)
|
import Data.Time.Calendar (Day)
|
||||||
#if MIN_VERSION_time(1,5,0)
|
#if MIN_VERSION_time(1,5,0)
|
||||||
import Data.Time.Format (parseTimeM, defaultTimeLocale)
|
import Data.Time.Format (parseTimeM, defaultTimeLocale)
|
||||||
@ -367,22 +368,18 @@ parseRulesFile :: FilePath -> ExceptT String IO CsvRules
|
|||||||
parseRulesFile f =
|
parseRulesFile f =
|
||||||
liftIO (readFile' f >>= expandIncludes (takeDirectory f)) >>= parseAndValidateCsvRules f
|
liftIO (readFile' f >>= expandIncludes (takeDirectory f)) >>= parseAndValidateCsvRules f
|
||||||
|
|
||||||
-- | Look for hledger rules file-style include directives in this text,
|
-- | Inline all files referenced by include directives in this hledger CSV rules text, recursively.
|
||||||
-- and interpolate the included files, recursively.
|
-- Included file paths may be relative to the directory of the provided file path.
|
||||||
-- Included file paths may be relative to the directory of the
|
|
||||||
-- provided file path.
|
|
||||||
-- This is a cheap hack to avoid rewriting the CSV rules parser.
|
-- This is a cheap hack to avoid rewriting the CSV rules parser.
|
||||||
expandIncludes :: FilePath -> T.Text -> IO T.Text
|
expandIncludes dir content = mapM (expandLine dir) (T.lines content) >>= return . T.unlines
|
||||||
expandIncludes basedir content = do
|
where
|
||||||
let (ls,rest) = break (T.isPrefixOf "include") $ T.lines content
|
expandLine dir line =
|
||||||
case rest of
|
case line of
|
||||||
[] -> return $ T.unlines ls
|
(T.stripPrefix "include " -> Just f) -> expandIncludes dir' =<< T.readFile f'
|
||||||
((T.stripPrefix "include" -> Just f):ls') -> do
|
where
|
||||||
let f' = basedir </> dropWhile isSpace (T.unpack f)
|
f' = dir </> dropWhile isSpace (T.unpack f)
|
||||||
basedir' = takeDirectory f'
|
dir' = takeDirectory f'
|
||||||
included <- readFile' f' >>= expandIncludes basedir'
|
_ -> return line
|
||||||
return $ T.unlines [T.unlines ls, included, T.unlines ls']
|
|
||||||
ls' -> return $ T.unlines $ ls ++ ls' -- should never get here
|
|
||||||
|
|
||||||
-- | An error-throwing action that parses this text as CSV conversion rules
|
-- | An error-throwing action that parses this text as CSV conversion rules
|
||||||
-- and runs some extra validation checks. The file path is for error messages.
|
-- and runs some extra validation checks. The file path is for error messages.
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user