csv reader: add the include directive, useful for factoring out common rules used with multiple CSV files

This commit is contained in:
Simon Michael 2013-08-03 20:47:43 -07:00
parent 308916185c
commit eff1d3f1a5
2 changed files with 20 additions and 3 deletions

View File

@ -549,8 +549,12 @@ The following kinds of rule can appear in any order:
%-m/%-d/%Y
%Y-%h-%d
**include** *RULESFILE*
: Include another rules file at this point. Useful for common rules shared across multiple CSV files.
Typically you'll keep one rules file for each account which you
download as CSV. For an example, see [How to read CSV files](CSV.html).
download as CSV. For an example, see [How to read CSV
files](CSV.html).
Other notes:

View File

@ -22,7 +22,7 @@ import Control.Exception hiding (try)
import Control.Monad
import Control.Monad.Error
-- import Test.HUnit
import Data.Char (toLower, isDigit)
import Data.Char (toLower, isDigit, isSpace)
import Data.List
import Data.Maybe
import Data.Ord
@ -319,7 +319,7 @@ getDirective directivename = lookup directivename . rdirectives
parseRulesFile :: FilePath -> IO (Either ParseError CsvRules)
parseRulesFile f = do
s <- readFile' f
s <- readFile' f >>= expandIncludes
let rules = parseCsvRules f s
return $ case rules of
Left e -> Left e
@ -329,6 +329,19 @@ parseRulesFile f = do
where
toParseError s = newErrorMessage (Message s) (initialPos "")
-- | Pre-parse csv rules to interpolate included files, recursively.
-- This is a cheap hack to avoid rewriting the existing parser.
expandIncludes :: String -> IO String
expandIncludes s = do
let (ls,rest) = break (isPrefixOf "include") $ lines s
case rest of
[] -> return $ unlines ls
(('i':'n':'c':'l':'u':'d':'e':f):ls') -> do
let f' = dropWhile isSpace f
included <- readFile f' >>= expandIncludes
return $ unlines [unlines ls, included, unlines ls']
ls' -> return $ unlines $ ls ++ ls' -- should never get here
parseCsvRules :: FilePath -> String -> Either ParseError CsvRules
-- parseCsvRules rulesfile s = runParser csvrulesfile nullrules{baseAccount=takeBaseName rulesfile} rulesfile s
parseCsvRules rulesfile s =