diff --git a/hledger-lib/Hledger/Read.hs b/hledger-lib/Hledger/Read.hs index 7b597a3c1..75f21561b 100644 --- a/hledger-lib/Hledger/Read.hs +++ b/hledger-lib/Hledger/Read.hs @@ -156,7 +156,7 @@ readJournalFile mformat mrulesfile assrt prefixedfile = do (mprefixformat, f) = splitReaderPrefix prefixedfile mfmt = mformat <|> mprefixformat 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, -- split that off. Eg "csv:-" -> (Just "csv", "-"). @@ -276,7 +276,7 @@ readJournalFileWithOpts iopts prefixedfile = do (mfmt, f) = splitReaderPrefix prefixedfile iopts' = iopts{mformat_=firstJust [mfmt, mformat_ iopts]} requireJournalFileExists f - t <- readFileOrStdinAnyLineEnding f + t <- readFileOrStdinPortably f ej <- readJournalWithOpts iopts' (Just f) t case ej of Left e -> return $ Left e @@ -324,7 +324,7 @@ latestDatesFileFor f = dir ".latest" <.> fname (dir, fname) = splitFileName f 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 -- latest previously seen transaction date, and how many transactions diff --git a/hledger-lib/Hledger/Read/CsvReader.hs b/hledger-lib/Hledger/Read/CsvReader.hs index 33a7e0b98..5bec0fd86 100644 --- a/hledger-lib/Hledger/Read/CsvReader.hs +++ b/hledger-lib/Hledger/Read/CsvReader.hs @@ -104,7 +104,7 @@ readJournalFromCsv mrulesfile csvfile csvdata = if rulesfileexists then do dbg1IO "using conversion rules file" rulesfile - liftIO $ (readFile' rulesfile >>= expandIncludes (takeDirectory rulesfile)) + liftIO $ (readFilePortably rulesfile >>= expandIncludes (takeDirectory rulesfile)) else return $ defaultRulesText rulesfile rules <- liftIO (runExceptT $ parseAndValidateCsvRules rulesfile rulestext) >>= either throwerr return dbg2IO "rules" rules @@ -365,7 +365,7 @@ instance ShowErrorComponent String where -- and runs some extra validation checks. parseRulesFile :: FilePath -> ExceptT String IO CsvRules 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. -- Included file paths may be relative to the directory of the provided file path. diff --git a/hledger-lib/Hledger/Read/JournalReader.hs b/hledger-lib/Hledger/Read/JournalReader.hs index a66d57b09..963c53d66 100644 --- a/hledger-lib/Hledger/Read/JournalReader.hs +++ b/hledger-lib/Hledger/Read/JournalReader.hs @@ -188,7 +188,7 @@ includedirectivep = do liftIO $ runExceptT $ do let curdir = takeDirectory (sourceName parentpos) 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) <- runParserT (evalStateT diff --git a/hledger-lib/Hledger/Utils.hs b/hledger-lib/Hledger/Utils.hs index 41fb05c39..89092064a 100644 --- a/hledger-lib/Hledger/Utils.hs +++ b/hledger-lib/Hledger/Utils.hs @@ -150,30 +150,23 @@ firstJust ms = case dropWhile (==Nothing) ms of [] -> Nothing (md:_) -> md --- | Read a file in universal newline mode, handling any of the usual line ending conventions. -readFile' :: FilePath -> IO Text -readFile' name = do - h <- openFile name ReadMode - hSetNewlineMode h universalNewlineMode - T.hGetContents h +-- | Read text from a file, handling any of the usual line ending conventions. +readFilePortably :: FilePath -> IO Text +readFilePortably f = openFile f ReadMode >>= readHandlePortably --- | Read a file in universal newline mode, handling any of the usual line ending conventions. -readFileAnyLineEnding :: FilePath -> IO Text -readFileAnyLineEnding path = do - h <- openFile path ReadMode - 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 +-- | Read text from a file, or from standard input if the path is "-", +-- handling any of the usual line ending conventions. +readFileOrStdinPortably :: String -> IO Text +readFileOrStdinPortably f = openFileOrStdin f ReadMode >>= readHandlePortably where - fileHandle "-" = return stdin - fileHandle f = openFile f ReadMode + openFileOrStdin :: String -> IOMode -> IO Handle + 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. maximum' :: Integral a => [a] -> a diff --git a/hledger/Hledger/Cli/Utils.hs b/hledger/Hledger/Cli/Utils.hs index 4c1bb615d..8f272e50f 100644 --- a/hledger/Hledger/Cli/Utils.hs +++ b/hledger/Hledger/Cli/Utils.hs @@ -249,7 +249,7 @@ openBrowserOn u = trybrowsers browsers u -- indicating whether we did anything. writeFileWithBackupIfChanged :: FilePath -> T.Text -> IO Bool writeFileWithBackupIfChanged f t = do - s <- readFile' f + s <- readFilePortably f if t == s then return False 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 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. backUpFile :: FilePath -> IO ()