diff --git a/gleam.toml b/gleam.toml index 2cf7cd1..bd61c5f 100644 --- a/gleam.toml +++ b/gleam.toml @@ -1,13 +1,17 @@ name = "gsv" version = "0.1.0" -description = "A Gleam project" +description = "A simple csv parser written in gleam " # Fill out these fields if you intend to generate HTML documentation or publish # your project to the Hex package manager. # -# licences = ["Apache-2.0"] -# repository = { type = "github", user = "username", repo = "project" } -# links = [{ title = "Website", href = "https://gleam.run" }] +licences = ["Apache-2.0"] +repository = { type = "github", user = "bcpeinhardt", repo = "gsv" } + +internal_modules = [ + "gsv/internal", + "gsv/internal/*", +] [dependencies] gleam_stdlib = "~> 0.28" diff --git a/src/gsv.gleam b/src/gsv.gleam index 2437988..2d43032 100644 --- a/src/gsv.gleam +++ b/src/gsv.gleam @@ -3,12 +3,17 @@ import internal/token import gleam/list import gleam/string +/// Parses a csv string to a list of lists of strings. +/// Automatically handles Windows and Unix line endings. pub fn to_lists(input: String) -> Result(List(List(String)), Nil) { input |> token.scan |> ast.parse } +/// Option for using "\n = LF = Unix" or "\r\n = CRLF = Windows" +/// line endings. Use with the `from_lists` function when +/// writing to a csv string. pub type LineEnding { Windows Unix @@ -21,6 +26,11 @@ fn le_to_string(le: LineEnding) -> String { } } +/// Takes a list of lists of strings and writes it to a csv string. +/// Will automatically escape strings that contain double quotes or +/// line endings with double quotes (in csv, double quotes get escaped by doing +/// a double doublequote) +/// The string `he"llo\n` becomes `"he""llo\n"` pub fn from_lists( input: List(List(String)), separator separator: String, @@ -34,12 +44,12 @@ pub fn from_lists( // Double quotes need to be escaped with an extra doublequote let entry = string.replace(entry, "\"", "\"\"") - // If the string contains a , \n \r or " it needs to be escaped by wrapping in double quotes + // If the string contains a , \n \r\n or " it needs to be escaped by wrapping in double quotes case - string.contains(entry, separator) || string.contains( + string.contains(entry, separator) || string.contains(entry, "\n") || string.contains( entry, - le_to_string(line_ending), - ) || string.contains(entry, "\"") + "\"", + ) { True -> "\"" <> entry <> "\"" False -> entry