dev:Hledger.Utils.IO: readHandlePortably, readHandlePortably' -> hGetContentsPortably

This commit is contained in:
Simon Michael 2025-09-26 00:53:15 -10:00
parent 9351c70f74
commit 5db4ee7420
4 changed files with 12 additions and 17 deletions

View File

@ -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 :: (InputOpts -> FilePath -> Text -> ExceptT String IO Journal) -> InputOpts -> FilePath -> Handle -> ExceptT String IO Journal
handleReadFnToTextReadFn p iopts fp = 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. -- | 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, -- This will fail with a usage error if the period expression cannot be parsed,

View File

@ -63,7 +63,7 @@ parse :: SepFormat -> InputOpts -> FilePath -> Handle -> ExceptT String IO Journ
parse sep iopts f h = do parse sep iopts f h = do
rules <- readRules $ getRulesFile f (mrules_file_ iopts) rules <- readRules $ getRulesFile f (mrules_file_ iopts)
mencoding <- rulesEncoding rules mencoding <- rulesEncoding rules
csvtext <- lift $ readHandlePortably' mencoding h csvtext <- lift $ hGetContentsPortably mencoding h
readJournalFromCsv rules f csvtext (Just sep) readJournalFromCsv rules f csvtext (Just sep)
-- apply any command line account aliases. Can fail with a bad replacement pattern. -- apply any command line account aliases. Can fail with a bad replacement pattern.
>>= liftEither . journalApplyAliases (aliasesFromOpts iopts) >>= liftEither . journalApplyAliases (aliasesFromOpts iopts)

View File

@ -235,7 +235,7 @@ parse iopts rulesfile h = do
(_, Just f, mc) -> do -- trace "file found" $ (_, Just f, mc) -> do -- trace "file found" $
mencoding <- rulesEncoding rules mencoding <- rulesEncoding rules
liftIO $ do liftIO $ do
raw <- openFileOrStdin f >>= readHandlePortably' mencoding raw <- openFileOrStdin f >>= hGetContentsPortably mencoding
maybe (return raw) (\c -> runCommandAsFilter rulesfile (dbg0Msg ("running: "++c) c) raw) mc maybe (return raw) (\c -> runCommandAsFilter rulesfile (dbg0Msg ("running: "++c) c) raw) mc
-- no file pattern, but a data generating command -- no file pattern, but a data generating command

View File

@ -46,8 +46,7 @@ module Hledger.Utils.IO (
readFileOrStdinPortably', readFileOrStdinPortably',
readFileStrictly, readFileStrictly,
readFilePortably, readFilePortably,
readHandlePortably, hGetContentsPortably,
readHandlePortably',
-- hereFileRelative, -- hereFileRelative,
inputToHandle, inputToHandle,
@ -435,7 +434,7 @@ readFileStrictly f = readFilePortably f >>= \t -> evaluate (T.length t) >> retur
-- using the system locale's text encoding, -- 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. -- ignoring any utf8 BOM prefix (as seen in paypal's 2018 CSV, eg) if that encoding is utf8.
readFilePortably :: FilePath -> IO T.Text 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 "-". -- | Like readFilePortably, but read from standard input if the path is "-".
readFileOrStdinPortably :: String -> IO T.Text readFileOrStdinPortably :: String -> IO T.Text
@ -443,7 +442,7 @@ readFileOrStdinPortably = readFileOrStdinPortably' Nothing
-- | Like readFileOrStdinPortably, but take an optional converter. -- | Like readFileOrStdinPortably, but take an optional converter.
readFileOrStdinPortably' :: Maybe DynEncoding -> String -> IO T.Text 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. -- | 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. -- 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 "-" = return stdin
openFileOrStdin f' = openFile f' ReadMode openFileOrStdin f' = openFile f' ReadMode
-- readHandlePortably' with no text encoding specified. -- | Read text from a handle, perhaps using a specified encoding from the encoding package.
readHandlePortably :: Handle -> IO T.Text -- Or if no encoding is specified, using the handle's current encoding,
readHandlePortably = readHandlePortably' Nothing -- changing it to UTF-8BOM if it was UTF-8, to ignore any Byte Order Mark at the start.
-- | 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.
-- Also it converts Windows line endings to newlines. -- 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). -- 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 hGetContentsPortably :: Maybe DynEncoding -> Handle -> IO T.Text
readHandlePortably' Nothing h = do hGetContentsPortably Nothing h = do
hSetNewlineMode h universalNewlineMode hSetNewlineMode h universalNewlineMode
menc <- hGetEncoding h menc <- hGetEncoding h
when (fmap show menc == Just "UTF-8") $ hSetEncoding h utf8_bom when (fmap show menc == Just "UTF-8") $ hSetEncoding h utf8_bom
T.hGetContents h T.hGetContents h
readHandlePortably' (Just e) h = hGetContentsPortably (Just e) h =
-- convert newlines manually, because Enc.hGetContents uses bytestring's hGetContents -- convert newlines manually, because Enc.hGetContents uses bytestring's hGetContents
T.replace "\r\n" "\n" . T.pack <$> let ?enc = e in Enc.hGetContents h T.replace "\r\n" "\n" . T.pack <$> let ?enc = e in Enc.hGetContents h