diff --git a/hledger-lib/Hledger/Read/Common.hs b/hledger-lib/Hledger/Read/Common.hs index 6a206a0c4..893c47cdb 100644 --- a/hledger-lib/Hledger/Read/Common.hs +++ b/hledger-lib/Hledger/Read/Common.hs @@ -262,7 +262,7 @@ rawOptsToInputOpts day usecoloronstdout postingaccttags rawopts = handleReadFnToTextReadFn :: (InputOpts -> FilePath -> Text -> ExceptT String IO Journal) -> InputOpts -> FilePath -> Handle -> ExceptT String IO Journal handleReadFnToTextReadFn p iopts fp = - p iopts fp <=< lift . readHandlePortably + p iopts fp <=< lift . hGetContentsPortably Nothing -- | Get the date span from --forecast's PERIODEXPR argument, if any. -- This will fail with a usage error if the period expression cannot be parsed, diff --git a/hledger-lib/Hledger/Read/CsvReader.hs b/hledger-lib/Hledger/Read/CsvReader.hs index fa0783b02..ecb47a992 100644 --- a/hledger-lib/Hledger/Read/CsvReader.hs +++ b/hledger-lib/Hledger/Read/CsvReader.hs @@ -63,7 +63,7 @@ parse :: SepFormat -> InputOpts -> FilePath -> Handle -> ExceptT String IO Journ parse sep iopts f h = do rules <- readRules $ getRulesFile f (mrules_file_ iopts) mencoding <- rulesEncoding rules - csvtext <- lift $ readHandlePortably' mencoding h + csvtext <- lift $ hGetContentsPortably mencoding h readJournalFromCsv rules f csvtext (Just sep) -- apply any command line account aliases. Can fail with a bad replacement pattern. >>= liftEither . journalApplyAliases (aliasesFromOpts iopts) diff --git a/hledger-lib/Hledger/Read/RulesReader.hs b/hledger-lib/Hledger/Read/RulesReader.hs index 179f8df07..c42776914 100644 --- a/hledger-lib/Hledger/Read/RulesReader.hs +++ b/hledger-lib/Hledger/Read/RulesReader.hs @@ -235,7 +235,7 @@ parse iopts rulesfile h = do (_, Just f, mc) -> do -- trace "file found" $ mencoding <- rulesEncoding rules liftIO $ do - raw <- openFileOrStdin f >>= readHandlePortably' mencoding + raw <- openFileOrStdin f >>= hGetContentsPortably mencoding maybe (return raw) (\c -> runCommandAsFilter rulesfile (dbg0Msg ("running: "++c) c) raw) mc -- no file pattern, but a data generating command diff --git a/hledger-lib/Hledger/Utils/IO.hs b/hledger-lib/Hledger/Utils/IO.hs index e5982053b..ff010e93f 100644 --- a/hledger-lib/Hledger/Utils/IO.hs +++ b/hledger-lib/Hledger/Utils/IO.hs @@ -46,8 +46,7 @@ module Hledger.Utils.IO ( readFileOrStdinPortably', readFileStrictly, readFilePortably, - readHandlePortably, - readHandlePortably', + hGetContentsPortably, -- hereFileRelative, inputToHandle, @@ -435,7 +434,7 @@ readFileStrictly f = readFilePortably f >>= \t -> evaluate (T.length t) >> retur -- using the system locale's text encoding, -- ignoring any utf8 BOM prefix (as seen in paypal's 2018 CSV, eg) if that encoding is utf8. readFilePortably :: FilePath -> IO T.Text -readFilePortably f = openFile f ReadMode >>= readHandlePortably +readFilePortably f = openFile f ReadMode >>= hGetContentsPortably Nothing -- | Like readFilePortably, but read from standard input if the path is "-". readFileOrStdinPortably :: String -> IO T.Text @@ -443,7 +442,7 @@ readFileOrStdinPortably = readFileOrStdinPortably' Nothing -- | Like readFileOrStdinPortably, but take an optional converter. readFileOrStdinPortably' :: Maybe DynEncoding -> String -> IO T.Text -readFileOrStdinPortably' c f = openFileOrStdin f >>= readHandlePortably' c +readFileOrStdinPortably' c f = openFileOrStdin f >>= hGetContentsPortably c -- | Open a file for reading, using the standard System.IO.openFile. -- This opens the handle in text mode, using the initial system locale's text encoding. @@ -451,22 +450,18 @@ openFileOrStdin :: String -> IO Handle openFileOrStdin "-" = return stdin openFileOrStdin f' = openFile f' ReadMode --- readHandlePortably' with no text encoding specified. -readHandlePortably :: Handle -> IO T.Text -readHandlePortably = readHandlePortably' Nothing - --- | Read text from a handle with a specified encoding, using the encoding package. --- Or if no encoding is specified, it uses the handle's current encoding, --- after first changing it to UTF-8BOM if it was UTF-8, to allow a Byte Order Mark at the start. +-- | Read text from a handle, perhaps using a specified encoding from the encoding package. +-- Or if no encoding is specified, using the handle's current encoding, +-- changing it to UTF-8BOM if it was UTF-8, to ignore any Byte Order Mark at the start. -- Also it converts Windows line endings to newlines. -- If decoding fails, this throws an IOException (or possibly a UnicodeException or something else from the encoding package). -readHandlePortably' :: Maybe DynEncoding -> Handle -> IO T.Text -readHandlePortably' Nothing h = do +hGetContentsPortably :: Maybe DynEncoding -> Handle -> IO T.Text +hGetContentsPortably Nothing h = do hSetNewlineMode h universalNewlineMode menc <- hGetEncoding h when (fmap show menc == Just "UTF-8") $ hSetEncoding h utf8_bom T.hGetContents h -readHandlePortably' (Just e) h = +hGetContentsPortably (Just e) h = -- convert newlines manually, because Enc.hGetContents uses bytestring's hGetContents T.replace "\r\n" "\n" . T.pack <$> let ?enc = e in Enc.hGetContents h