From 70d4c0c638bcbef92d5c4ad3589dea74869eb4ba Mon Sep 17 00:00:00 2001 From: Simon Michael Date: Thu, 11 May 2023 15:35:05 -1000 Subject: [PATCH] ;dev: csv: refactor, clarify --- hledger-lib/Hledger/Read/CsvReader.hs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/hledger-lib/Hledger/Read/CsvReader.hs b/hledger-lib/Hledger/Read/CsvReader.hs index fac2bc6bb..d1d7204a6 100644 --- a/hledger-lib/Hledger/Read/CsvReader.hs +++ b/hledger-lib/Hledger/Read/CsvReader.hs @@ -791,13 +791,14 @@ parseSeparator = specials . T.toLower specials "tab" = Just '\t' specials xs = fst <$> T.uncons xs -parseCsv :: Char -> FilePath -> Text -> ExceptT String IO CSV +-- Parse text into CSV records, using Cassava and the configured field separator. +parseCsv :: Char -> FilePath -> Text -> ExceptT String IO [CsvRecord] parseCsv separator filePath csvdata = ExceptT $ case filePath of "-" -> parseCassava separator "(stdin)" <$> T.getContents _ -> return $ if T.null csvdata then Right mempty else parseCassava separator filePath csvdata -parseCassava :: Char -> FilePath -> Text -> Either String CSV +parseCassava :: Char -> FilePath -> Text -> Either String [CsvRecord] parseCassava separator path content = either (Left . errorBundlePretty) (Right . parseResultToCsv) <$> CassavaMegaparsec.decodeWith (decodeOptions separator) Cassava.NoHeader path $ @@ -808,19 +809,19 @@ decodeOptions separator = Cassava.defaultDecodeOptions { Cassava.decDelimiter = fromIntegral (ord separator) } -parseResultToCsv :: (Foldable t, Functor t) => t (t B.ByteString) -> CSV +parseResultToCsv :: (Foldable t, Functor t) => t (t B.ByteString) -> [CsvRecord] parseResultToCsv = toListList . unpackFields where toListList = toList . fmap toList unpackFields = (fmap . fmap) T.decodeUtf8 -printCSV :: CSV -> TL.Text +printCSV :: [CsvRecord] -> TL.Text printCSV = TB.toLazyText . unlinesB . map printRecord where printRecord = foldMap TB.fromText . intersperse "," . map printField printField = wrap "\"" "\"" . T.replace "\"" "\"\"" -- | Return the cleaned up and validated CSV data (can be empty), or an error. -validateCsv :: CsvRules -> CSV -> Either String [CsvRecord] +validateCsv :: CsvRules -> [CsvRecord] -> Either String [CsvRecord] validateCsv rules = validate . applyConditionalSkips . filternulls where filternulls = filter (/=[""])