std.csv
CSV (RFC 4180), read and written as Go’s encoding/csv reads and
writes it with its settings left as they are: a record a line, ended
by a line feed or a carriage return and a line feed, its fields
between commas. A field may be quoted with ", a "" in it one ";
quoted, it may hold commas and line breaks (one written as a carriage
return and a line feed read as a line feed, as Go reads it). Reading
skips an empty line, and every record must have as many fields as the
first. Import it by a name, import std.csv as CSV.
import std.csv as CSV
-- | >>> names-- | Right ["Ada", "Grace"]names : Either CSV.ParseError (List String)names = case CSV.parse "name,born\nAda,1815\nGrace,1906\n" of Right (_ :: rows) -> Right (List.concatMap (List.take 1) rows) Right Nil -> Right Nil Left e -> Left eParseError
type ParseError = { line : Int, column : Int, message : String }Where the text is not CSV: its line and its column there (from 1, the column counted in bytes), and what is wrong, in Go’s words.
parse
parse : String -> Either ParseError (List (List String))The records of a text, each a list of its fields. A line break at the end makes no record, nor does an empty text, nor an empty line.
>>> parse "a,b,c\n1,2,3\n"Right [["a", "b", "c"], ["1", "2", "3"]]>>> parse "x,,\r\n\r\n,y,\"\"\r\nlast,one,here"Right [["x", "", ""], ["", "y", ""], ["last", "one", "here"]]>>> parse ""Right [](a quoted field: its commas, line breaks and doubled quotes; a carriage return and a line feed in it read as a line feed)
>>> parse "\"a, b\",\"say \"\"hi\"\"\"\n\"two\nlines\",\"cr\r\nlf\"\n"Right [["a, b", "say \"hi\""], ["two\nlines", "cr\nlf"]](where it is not CSV: a quote in a field not quoted, text after a closing quote, a quote not closed, a record of another width)
>>> parse "a,b\nc,d\"e\n"Left { line = 2, column = 4, message = "bare \" in non-quoted-field" }>>> parse "\"a\"b,c"Left { line = 1, column = 4, message = "extraneous or missing \" in quoted-field" }>>> parse "a\n\"b\nc"Left { line = 3, column = 2, message = "extraneous or missing \" in quoted-field" }>>> parse "a,b\nc\n"Left { line = 2, column = 1, message = "wrong number of fields" }render
render : List (List String) -> StringThe text of records, as Go’s csv.Writer writes it: each record
ended by a line feed, its fields between commas; a field quoted
where it has a comma, a quote or a line break in it, or starts with
a space, each " in it doubled.
>>> render [["a", "b c", "d,e"], ["say \"hi\"", " x", "two\nlines"]]"a,b c,\"d,e\"\n\"say \"\"hi\"\"\",\" x\",\"two\nlines\"\n">>> render []""(what it writes, parse reads back)
>>> parse (render [["", "\"", "a,b"], [" x", "", "two\nlines"]])Right [["", "\"", "a,b"], [" x", "", "two\nlines"]]