Skip to content

Releases: BrianHicks/elm-csv

4.0.0 – Optional fields

31 Mar 15:36
4.0.0
aa5ebe5
Compare
Choose a tag to compare

Thanks to @gampleman's hard work, elm-csv now has:

  • Optional fields and columns with optionalField and optionalColumn
  • Dynamic decoding with availableFields
  • Improved error handling (specifically with less repetition when the same error occurs on multiple rows.)

Full Diff: 3.0.3...4.0.0

3.0.0 – Encoding and better errors

02 Feb 14:38
Compare
Choose a tag to compare

Csv.Encode

You can now encode CSVs using this package:

import Csv.Encode as Encode

Encode.encode
    { encoder =
        Encode.withFieldNames
            (\(r, g, b) ->
               [ ( "red", r )
               , ( "green", g )
               , ( "blue", b )
               ]
            )
    , fieldSeparator = ','
    }
    [ ( "FF", "FF", "FF" )
    , ( "00", "00", "00" )
    ]
--> "red,green,blue\r\nFF,FF,FF\r\n00,00,00"

Fields will be properly quoted and escaped. In addition, withFieldNames will always produce aligned CSVs, even in cases where the provided function does not provide all the fields every time.

Better Error Messages

Error messages are greatly improved.

  1. Row numbers are never negative.
  2. Errors now specify which column they came frome.
  3. You now get all the problems in a decoding run in a single error, instead of having to re-run to discover further problems.
  4. Message strings and constructors are streamlined and clarified.

These changes are why this release is numbered 3.0.0 instead of 2.1.0—the internal custom types representing errors changed. However, unless you were doing your own message-to-string encoding, this release is unlikely to have broken your code. (decodeCsv produces the error that errorToString takes, just like before. If you were using that, you can upgrade safely!)

End-of-line Quotes Bug Fix

There was a bug (#15) where quoted fields at the end of a line would combine adjacent lines into one. This release fixes that!

2.0.1 – Trailing newlines

27 Jan 12:03
Compare
Choose a tag to compare

The 2.0.0 parser would add wrongly add an extra row with a single blank field if the file had a trailing newline. This is now fixed. Thank you to @jpagex for reporting this in #8.

2.0.0 – API improvements and faster parser

26 Jan 15:40
Compare
Choose a tag to compare

This upgrade makes a few tweaks to the API to make creating decoders easier.

API Changes

Pipeline renaming

pipeline is now into, and required is now pipeline. This makes pipeline code nicer:

decoder : Decoder Pet
decoder =
    Decode.into Pet
        |> Decode.pipeline (Decode.field "id" Decode.int)
        |> Decode.pipeline (Decode.field "name" Decode.string)
        |> Decode.pipeline (Decode.field "species" Decode.string)
        |> Decode.pipeline (Decode.field "weight" (Decode.blank Decode.float))

fromResult

fromResult now just takes a Result String a instead of a function that produces a Result String a. This is to make scenarios like this possible:

Decode.string
    |> Decode.map String.toLower
    |> Decode.andThen (Decode.fromResult << Hex.fromString)

This was previously impossible—the design of fromResult made it so that you could not do any pre-processing to your strings before your conversion function got them. You have to do a little more work now, but in exchange you get a lot more flexibility.

API Additions

To make up for breaking your code, I also added fromMaybe : String -> Result String a. It does the same thing as fromResult (fails when it doesn't get a value) but asks you to provide an error message for the failure since Nothing has no info for us to use.

Faster Parser

This release switches to a hand-rolled parser, which is faster than the one released in 1.0.0. It's 25 times faster for "normal" CSVs—that is, those delimited with , or ;. If you use other characters to delimit your fields, it's a little slower but still something like 24 times faster than the 1.0.0 parser. Thank you to @w0rm for advice on squeezing every last bit of performance out of the code.

As a consequence of the upgrade, this package no longer depends on elm/parser. If you added it to your transitive dependencies when you installed this package, you can remove it on upgrade.

Look out for some blog posts from @BrianHicks soon on how he achieved this speedup!

Upgrade Instructions

  • Replace Decode.pipeline with Decode.into, and then Decode.required with Decode.pipeline. If you do it in that order, it should be safe to run a global find/replace on your code!
  • Lift any instances of fromResult: where you previously would have had fromResult Hex.fromString you now will have string |> andThen (fromResult << Hex.fromString).
  • If you were case-matching on any problems in Csv.Parser, you'll have to read the code to figure out what's wrong. Fortunately, it should actually be giving more descriptive error messages now—previously they were just Parser.DeadEnds, now they have meaning specific to CSVs!