lib: refactor low-level text file reading
This commit is contained in:
		
							parent
							
								
									631f0fc1e2
								
							
						
					
					
						commit
						81e964502b
					
				| @ -156,7 +156,7 @@ readJournalFile mformat mrulesfile assrt prefixedfile = do | |||||||
|     (mprefixformat, f) = splitReaderPrefix prefixedfile |     (mprefixformat, f) = splitReaderPrefix prefixedfile | ||||||
|     mfmt = mformat <|> mprefixformat |     mfmt = mformat <|> mprefixformat | ||||||
|   requireJournalFileExists f |   requireJournalFileExists f | ||||||
|   readFileOrStdinAnyLineEnding f >>= readJournal mfmt mrulesfile assrt (Just f) |   readFileOrStdinPortably f >>= readJournal mfmt mrulesfile assrt (Just f) | ||||||
| 
 | 
 | ||||||
| -- | If a filepath is prefixed by one of the reader names and a colon, | -- | If a filepath is prefixed by one of the reader names and a colon, | ||||||
| -- split that off. Eg "csv:-" -> (Just "csv", "-"). | -- split that off. Eg "csv:-" -> (Just "csv", "-"). | ||||||
| @ -276,7 +276,7 @@ readJournalFileWithOpts iopts prefixedfile = do | |||||||
|     (mfmt, f) = splitReaderPrefix prefixedfile |     (mfmt, f) = splitReaderPrefix prefixedfile | ||||||
|     iopts' = iopts{mformat_=firstJust [mfmt, mformat_ iopts]} |     iopts' = iopts{mformat_=firstJust [mfmt, mformat_ iopts]} | ||||||
|   requireJournalFileExists f |   requireJournalFileExists f | ||||||
|   t <- readFileOrStdinAnyLineEnding f |   t <- readFileOrStdinPortably f | ||||||
|   ej <- readJournalWithOpts iopts' (Just f) t |   ej <- readJournalWithOpts iopts' (Just f) t | ||||||
|   case ej of |   case ej of | ||||||
|     Left e  -> return $ Left e |     Left e  -> return $ Left e | ||||||
| @ -324,7 +324,7 @@ latestDatesFileFor f = dir </> ".latest" <.> fname | |||||||
|     (dir, fname) = splitFileName f |     (dir, fname) = splitFileName f | ||||||
| 
 | 
 | ||||||
| readFileStrictly :: FilePath -> IO Text | readFileStrictly :: FilePath -> IO Text | ||||||
| readFileStrictly f = readFile' f >>= \t -> C.evaluate (T.length t) >> return t | readFileStrictly f = readFilePortably f >>= \t -> C.evaluate (T.length t) >> return t | ||||||
| 
 | 
 | ||||||
| -- | Given zero or more latest dates (all the same, representing the | -- | Given zero or more latest dates (all the same, representing the | ||||||
| -- latest previously seen transaction date, and how many transactions | -- latest previously seen transaction date, and how many transactions | ||||||
|  | |||||||
| @ -104,7 +104,7 @@ readJournalFromCsv mrulesfile csvfile csvdata = | |||||||
|     if rulesfileexists |     if rulesfileexists | ||||||
|     then do |     then do | ||||||
|       dbg1IO "using conversion rules file" rulesfile |       dbg1IO "using conversion rules file" rulesfile | ||||||
|       liftIO $ (readFile' rulesfile >>= expandIncludes (takeDirectory rulesfile)) |       liftIO $ (readFilePortably rulesfile >>= expandIncludes (takeDirectory rulesfile)) | ||||||
|     else return $ defaultRulesText rulesfile |     else return $ defaultRulesText rulesfile | ||||||
|   rules <- liftIO (runExceptT $ parseAndValidateCsvRules rulesfile rulestext) >>= either throwerr return  |   rules <- liftIO (runExceptT $ parseAndValidateCsvRules rulesfile rulestext) >>= either throwerr return  | ||||||
|   dbg2IO "rules" rules |   dbg2IO "rules" rules | ||||||
| @ -365,7 +365,7 @@ instance ShowErrorComponent String where | |||||||
| -- and runs some extra validation checks. | -- and runs some extra validation checks. | ||||||
| parseRulesFile :: FilePath -> ExceptT String IO CsvRules | parseRulesFile :: FilePath -> ExceptT String IO CsvRules | ||||||
| parseRulesFile f =  | parseRulesFile f =  | ||||||
|   liftIO (readFile' f >>= expandIncludes (takeDirectory f)) >>= parseAndValidateCsvRules f |   liftIO (readFilePortably f >>= expandIncludes (takeDirectory f)) >>= parseAndValidateCsvRules f | ||||||
| 
 | 
 | ||||||
| -- | Inline all files referenced by include directives in this hledger CSV rules text, recursively. | -- | Inline all files referenced by include directives in this hledger CSV rules text, 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. | ||||||
|  | |||||||
| @ -188,7 +188,7 @@ includedirectivep = do | |||||||
|     liftIO $ runExceptT $ do |     liftIO $ runExceptT $ do | ||||||
|       let curdir = takeDirectory (sourceName parentpos) |       let curdir = takeDirectory (sourceName parentpos) | ||||||
|       filepath <- expandPath curdir filename `orRethrowIOError` (show parentpos ++ " locating " ++ filename) |       filepath <- expandPath curdir filename `orRethrowIOError` (show parentpos ++ " locating " ++ filename) | ||||||
|       txt      <- readFileAnyLineEnding filepath `orRethrowIOError` (show parentpos ++ " reading " ++ filepath) |       txt      <- readFilePortably filepath `orRethrowIOError` (show parentpos ++ " reading " ++ filepath) | ||||||
|       (ej1::Either (ParseError Char MPErr) ParsedJournal) <- |       (ej1::Either (ParseError Char MPErr) ParsedJournal) <- | ||||||
|         runParserT |         runParserT | ||||||
|            (evalStateT |            (evalStateT | ||||||
|  | |||||||
| @ -150,30 +150,23 @@ firstJust ms = case dropWhile (==Nothing) ms of | |||||||
|     [] -> Nothing |     [] -> Nothing | ||||||
|     (md:_) -> md |     (md:_) -> md | ||||||
| 
 | 
 | ||||||
| -- | Read a file in universal newline mode, handling any of the usual line ending conventions. | -- | Read text from a file, handling any of the usual line ending conventions. | ||||||
| readFile' :: FilePath -> IO Text | readFilePortably :: FilePath -> IO Text | ||||||
| readFile' name =  do | readFilePortably f =  openFile f ReadMode >>= readHandlePortably | ||||||
|   h <- openFile name ReadMode |  | ||||||
|   hSetNewlineMode h universalNewlineMode |  | ||||||
|   T.hGetContents h |  | ||||||
| 
 | 
 | ||||||
| -- | Read a file in universal newline mode, handling any of the usual line ending conventions. | -- | Read text from a file, or from standard input if the path is "-",  | ||||||
| readFileAnyLineEnding :: FilePath -> IO Text | -- handling any of the usual line ending conventions. | ||||||
| readFileAnyLineEnding path =  do | readFileOrStdinPortably :: String -> IO Text | ||||||
|   h <- openFile path ReadMode | readFileOrStdinPortably f = openFileOrStdin f ReadMode >>= readHandlePortably | ||||||
|   hSetNewlineMode h universalNewlineMode |  | ||||||
|   T.hGetContents h |  | ||||||
| 
 |  | ||||||
| -- | Read the given file, or standard input if the path is "-", using |  | ||||||
| -- universal newline mode. |  | ||||||
| readFileOrStdinAnyLineEnding :: String -> IO Text |  | ||||||
| readFileOrStdinAnyLineEnding f = do |  | ||||||
|   h <- fileHandle f |  | ||||||
|   hSetNewlineMode h universalNewlineMode |  | ||||||
|   T.hGetContents h |  | ||||||
|   where |   where | ||||||
|     fileHandle "-" = return stdin |     openFileOrStdin :: String -> IOMode -> IO Handle | ||||||
|     fileHandle f = openFile f ReadMode |     openFileOrStdin "-" _ = return stdin | ||||||
|  |     openFileOrStdin f m   = openFile f m | ||||||
|  | 
 | ||||||
|  | readHandlePortably :: Handle -> IO Text | ||||||
|  | readHandlePortably h = do | ||||||
|  |   hSetNewlineMode h universalNewlineMode | ||||||
|  |   T.hGetContents h | ||||||
| 
 | 
 | ||||||
| -- | Total version of maximum, for integral types, giving 0 for an empty list. | -- | Total version of maximum, for integral types, giving 0 for an empty list. | ||||||
| maximum' :: Integral a => [a] -> a | maximum' :: Integral a => [a] -> a | ||||||
|  | |||||||
| @ -249,7 +249,7 @@ openBrowserOn u = trybrowsers browsers u | |||||||
| -- indicating whether we did anything. | -- indicating whether we did anything. | ||||||
| writeFileWithBackupIfChanged :: FilePath -> T.Text -> IO Bool | writeFileWithBackupIfChanged :: FilePath -> T.Text -> IO Bool | ||||||
| writeFileWithBackupIfChanged f t = do | writeFileWithBackupIfChanged f t = do | ||||||
|   s <- readFile' f |   s <- readFilePortably f | ||||||
|   if t == s then return False |   if t == s then return False | ||||||
|             else backUpFile f >> T.writeFile f t >> return True |             else backUpFile f >> T.writeFile f t >> return True | ||||||
| 
 | 
 | ||||||
| @ -259,7 +259,7 @@ writeFileWithBackup :: FilePath -> String -> IO () | |||||||
| writeFileWithBackup f t = backUpFile f >> writeFile f t | writeFileWithBackup f t = backUpFile f >> writeFile f t | ||||||
| 
 | 
 | ||||||
| readFileStrictly :: FilePath -> IO T.Text | readFileStrictly :: FilePath -> IO T.Text | ||||||
| readFileStrictly f = readFile' f >>= \s -> C.evaluate (T.length s) >> return s | readFileStrictly f = readFilePortably f >>= \s -> C.evaluate (T.length s) >> return s | ||||||
| 
 | 
 | ||||||
| -- | Back up this file with a (incrementing) numbered suffix, or give an error. | -- | Back up this file with a (incrementing) numbered suffix, or give an error. | ||||||
| backUpFile :: FilePath -> IO () | backUpFile :: FilePath -> IO () | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user