-- | Functions for constructing CSV files as a 'Doc'.
module Utils.Drasil.CSV where

import Text.PrettyPrint (Doc, text, vcat)
import Data.List (intercalate)

-- | Creates a CSV file as a 'Doc' from a 'String' matrix.
makeCSV :: [[String]] -> Doc
makeCSV :: [[String]] -> Doc
makeCSV [[String]]
rows = [Doc] -> Doc
vcat ([Doc] -> Doc) -> [Doc] -> Doc
forall a b. (a -> b) -> a -> b
$ ([String] -> Doc) -> [[String]] -> [Doc]
forall a b. (a -> b) -> [a] -> [b]
map (String -> Doc
text (String -> Doc) -> ([String] -> String) -> [String] -> Doc
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [String] -> String
formatRow) [[String]]
rows
  where
    -- | Seperates each row item with a comma.
    formatRow :: [String] -> String
    formatRow :: [String] -> String
formatRow = String -> [String] -> String
forall a. [a] -> [[a]] -> [a]
intercalate String
"," ([String] -> String)
-> ([String] -> [String]) -> [String] -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (String -> String) -> [String] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map String -> String
escape

    -- | Adds quotations around the item if it contains ',', '"', \n', or ' '.
    escape :: String -> String
    escape :: String -> String
escape String
s
      | (Char -> Bool) -> String -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any (Char -> String -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` String
",\"\n ") String
s = String
"\"" String -> String -> String
forall a. [a] -> [a] -> [a]
++ (Char -> String) -> String -> String
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap Char -> String
escapeChar String
s String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
"\""
      | Bool
otherwise = String
s

    -- | Escapes double quotes.
    escapeChar :: Char -> String
    escapeChar :: Char -> String
escapeChar Char
'"' = String
"\"\""
    escapeChar Char
c   = [Char
c]