{-# LANGUAGE OverloadedStrings #-}
module Hledger.Write.Csv (
CSV, CsvRecord, CsvValue,
printCSV,
printTSV,
tests_CsvUtils,
)
where
import Prelude hiding (Applicative(..))
import Data.List (intersperse)
import Data.Text (Text)
import qualified Data.Text as T
import qualified Data.Text.Lazy as TL
import qualified Data.Text.Lazy.Builder as TB
import Hledger.Utils
type CSV = [CsvRecord]
type CsvRecord = [CsvValue]
type CsvValue = Text
printCSV :: CSV -> TL.Text
printCSV :: CSV -> Text
printCSV = Builder -> Text
TB.toLazyText (Builder -> Text) -> (CSV -> Builder) -> CSV -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Builder] -> Builder
unlinesB ([Builder] -> Builder) -> (CSV -> [Builder]) -> CSV -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (CsvRecord -> Builder) -> CSV -> [Builder]
forall a b. (a -> b) -> [a] -> [b]
map CsvRecord -> Builder
printRecord
where printRecord :: CsvRecord -> Builder
printRecord = (Text -> Builder) -> CsvRecord -> Builder
forall m a. Monoid m => (a -> m) -> [a] -> m
forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
foldMap Text -> Builder
TB.fromText (CsvRecord -> Builder)
-> (CsvRecord -> CsvRecord) -> CsvRecord -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> CsvRecord -> CsvRecord
forall a. a -> [a] -> [a]
intersperse Text
"," (CsvRecord -> CsvRecord)
-> (CsvRecord -> CsvRecord) -> CsvRecord -> CsvRecord
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Text -> Text) -> CsvRecord -> CsvRecord
forall a b. (a -> b) -> [a] -> [b]
map Text -> Text
printField
printField :: Text -> Text
printField = Text -> Text -> Text -> Text
wrap Text
"\"" Text
"\"" (Text -> Text) -> (Text -> Text) -> Text -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. HasCallStack => Text -> Text -> Text -> Text
Text -> Text -> Text -> Text
T.replace Text
"\"" Text
"\"\""
printTSV :: CSV -> TL.Text
printTSV :: CSV -> Text
printTSV = Builder -> Text
TB.toLazyText (Builder -> Text) -> (CSV -> Builder) -> CSV -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Builder] -> Builder
unlinesB ([Builder] -> Builder) -> (CSV -> [Builder]) -> CSV -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (CsvRecord -> Builder) -> CSV -> [Builder]
forall a b. (a -> b) -> [a] -> [b]
map CsvRecord -> Builder
printRecord
where printRecord :: CsvRecord -> Builder
printRecord = (Text -> Builder) -> CsvRecord -> Builder
forall m a. Monoid m => (a -> m) -> [a] -> m
forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
foldMap Text -> Builder
TB.fromText (CsvRecord -> Builder)
-> (CsvRecord -> CsvRecord) -> CsvRecord -> Builder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> CsvRecord -> CsvRecord
forall a. a -> [a] -> [a]
intersperse Text
"\t" (CsvRecord -> CsvRecord)
-> (CsvRecord -> CsvRecord) -> CsvRecord -> CsvRecord
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Text -> Text) -> CsvRecord -> CsvRecord
forall a b. (a -> b) -> [a] -> [b]
map Text -> Text
printField
printField :: Text -> Text
printField = (Char -> Char) -> Text -> Text
T.map Char -> Char
replaceWhitespace
replaceWhitespace :: Char -> Char
replaceWhitespace Char
c | Char
c Char -> [Char] -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [Char
'\t', Char
'\n', Char
'\r'] = Char
' '
replaceWhitespace Char
c = Char
c
tests_CsvUtils :: TestTree
tests_CsvUtils :: TestTree
tests_CsvUtils = [Char] -> [TestTree] -> TestTree
testGroup [Char]
"CsvUtils" [
]