From ac08b072dc3676d1560893434f6dbeb1464976f2 Mon Sep 17 00:00:00 2001 From: John Kerl Date: Sun, 5 Jul 2026 20:35:32 -0400 Subject: [PATCH] Honor `--ors crlf` for CSV output (#1810) (#2150) * Honor --ors CRLF for CSV output (#1810) The full-CSV record writer validated ORS as newline or carriage-return/newline, but never propagated the choice to the forked Go CSV writer's UseCRLF field, so `--ors '\r\n'` (or `--ors crlf`) silently produced LF line endings. Set UseCRLF from the writer options so CRLF output is honored. Default behavior (LF) is unchanged, and other ORS values are still rejected. The CSV-lite and TSV writers already honored CRLF ORS. Also: fix a copy-paste "for CSV" in the TSV writer's ORS-validation message, add unit tests asserting byte-exact line endings (the regtest harness normalizes CR/LF, so this can't be asserted in test/cases), add CLI-level regression cases, and update the separators documentation. This substantially addresses #1722 as well: RFC-4180-style CRLF output can now be requested on any platform. Co-Authored-By: Claude Fable 5 * Fix errcheck lint: check Flush() error in CSV writer test --------- Co-authored-by: Claude Fable 5 --- docs/src/manpage.md | 5 +- docs/src/manpage.txt | 5 +- docs/src/reference-main-flag-list.md | 3 + docs/src/reference-main-separators.md | 8 +- docs/src/reference-main-separators.md.in | 8 +- man/manpage.txt | 5 +- man/mlr.1 | 7 +- pkg/cli/option_parse.go | 3 + pkg/output/record_writer_csv.go | 5 +- pkg/output/record_writer_csv_test.go | 99 +++++++++++++++++++++ pkg/output/record_writer_tsv.go | 2 +- test/cases/io-csv-ors-crlf/0001/cmd | 1 + test/cases/io-csv-ors-crlf/0001/experr | 0 test/cases/io-csv-ors-crlf/0001/expout | 11 +++ test/cases/io-csv-ors-crlf/0002/cmd | 1 + test/cases/io-csv-ors-crlf/0002/experr | 0 test/cases/io-csv-ors-crlf/0002/expout | 11 +++ test/cases/io-csv-ors-crlf/0003/cmd | 1 + test/cases/io-csv-ors-crlf/0003/experr | 0 test/cases/io-csv-ors-crlf/0003/expout | 11 +++ test/cases/io-csv-ors-crlf/0004/cmd | 1 + test/cases/io-csv-ors-crlf/0004/experr | 0 test/cases/io-csv-ors-crlf/0004/expout | 11 +++ test/cases/io-csv-ors-crlf/0005/cmd | 1 + test/cases/io-csv-ors-crlf/0005/experr | 1 + test/cases/io-csv-ors-crlf/0005/expout | 0 test/cases/io-csv-ors-crlf/0005/should-fail | 0 27 files changed, 185 insertions(+), 15 deletions(-) create mode 100644 pkg/output/record_writer_csv_test.go create mode 100644 test/cases/io-csv-ors-crlf/0001/cmd create mode 100644 test/cases/io-csv-ors-crlf/0001/experr create mode 100644 test/cases/io-csv-ors-crlf/0001/expout create mode 100644 test/cases/io-csv-ors-crlf/0002/cmd create mode 100644 test/cases/io-csv-ors-crlf/0002/experr create mode 100644 test/cases/io-csv-ors-crlf/0002/expout create mode 100644 test/cases/io-csv-ors-crlf/0003/cmd create mode 100644 test/cases/io-csv-ors-crlf/0003/experr create mode 100644 test/cases/io-csv-ors-crlf/0003/expout create mode 100644 test/cases/io-csv-ors-crlf/0004/cmd create mode 100644 test/cases/io-csv-ors-crlf/0004/experr create mode 100644 test/cases/io-csv-ors-crlf/0004/expout create mode 100644 test/cases/io-csv-ors-crlf/0005/cmd create mode 100644 test/cases/io-csv-ors-crlf/0005/experr create mode 100644 test/cases/io-csv-ors-crlf/0005/expout create mode 100644 test/cases/io-csv-ors-crlf/0005/should-fail diff --git a/docs/src/manpage.md b/docs/src/manpage.md index 6da1b95f8..d05ef2c42 100644 --- a/docs/src/manpage.md +++ b/docs/src/manpage.md @@ -840,6 +840,9 @@ This is simply a copy of what you should see on running `man mlr` at a command p * Default line endings (`--irs` and `--ors`) are newline which is interpreted to accept carriage-return/newline files (e.g. on Windows) for input, and to produce platform-appropriate line endings on output. + * For CSV, CSV-lite, TSV, and TSV-lite output, ORS may be either newline (the + default) or carriage-return/newline: e.g. `--ors crlf` or `--ors '\r\n'` + for RFC-4180-style line endings on any platform. Notes about all other separators: @@ -4045,5 +4048,5 @@ This is simply a copy of what you should see on running `man mlr` at a command p MIME Type for Comma-Separated Values (CSV) Files, the Miller docsite https://miller.readthedocs.io - 2026-07-05 4mMILLER24m(1) + 2026-07-06 4mMILLER24m(1) diff --git a/docs/src/manpage.txt b/docs/src/manpage.txt index e4fe84bc4..068e64a1f 100644 --- a/docs/src/manpage.txt +++ b/docs/src/manpage.txt @@ -819,6 +819,9 @@ * Default line endings (`--irs` and `--ors`) are newline which is interpreted to accept carriage-return/newline files (e.g. on Windows) for input, and to produce platform-appropriate line endings on output. + * For CSV, CSV-lite, TSV, and TSV-lite output, ORS may be either newline (the + default) or carriage-return/newline: e.g. `--ors crlf` or `--ors '\r\n'` + for RFC-4180-style line endings on any platform. Notes about all other separators: @@ -4024,4 +4027,4 @@ MIME Type for Comma-Separated Values (CSV) Files, the Miller docsite https://miller.readthedocs.io - 2026-07-05 4mMILLER24m(1) + 2026-07-06 4mMILLER24m(1) diff --git a/docs/src/reference-main-flag-list.md b/docs/src/reference-main-flag-list.md index b5b4b6502..5147d6af1 100644 --- a/docs/src/reference-main-flag-list.md +++ b/docs/src/reference-main-flag-list.md @@ -451,6 +451,9 @@ Notes about line endings: * Default line endings (`--irs` and `--ors`) are newline which is interpreted to accept carriage-return/newline files (e.g. on Windows) for input, and to produce platform-appropriate line endings on output. +* For CSV, CSV-lite, TSV, and TSV-lite output, ORS may be either newline (the + default) or carriage-return/newline: e.g. `--ors crlf` or `--ors '\r\n'` + for RFC-4180-style line endings on any platform. Notes about all other separators: diff --git a/docs/src/reference-main-separators.md b/docs/src/reference-main-separators.md index 4f37b75a2..d4d1ba9db 100644 --- a/docs/src/reference-main-separators.md +++ b/docs/src/reference-main-separators.md @@ -261,8 +261,8 @@ a:4;b:5;c:6;d:>>>,|||;<<< Notes: -* CSV IRS and ORS must be newline, and CSV IFS must be a single character. (CSV-lite does not have these restrictions.) -* TSV IRS and ORS must be newline, and TSV IFS must be a tab. (TSV-lite does not have these restrictions.) +* CSV IRS must be newline -- CR/LF line endings are accepted on input. CSV ORS must be either newline (the default) or carriage-return/newline -- e.g. `--ors crlf` or `--ors '\r\n'` for RFC-4180-style line endings on any platform. CSV IFS must be a single character. (CSV-lite does not have these restrictions.) +* TSV IRS must be newline -- CR/LF line endings are accepted on input. TSV ORS must be either newline (the default) or carriage-return/newline. TSV IFS must be a tab. (TSV-lite does not have these restrictions.) * See the [CSV section](file-formats.md#csvtsvasvusvetc) for information about ASV and USV. * JSON and YAML: ignore separator flags from the command line. * Headerless CSV overlaps quite a bit with NIDX format using comma for IFS. See also the page on [CSV with and without headers](csv-with-and-without-headers.md). @@ -270,8 +270,8 @@ Notes: | | **RS** | **FS** | **PS** | |------------|---------|---------|----------| -| [**CSV**](file-formats.md#csvtsvasvusvetc) | Always `\n`; not alterable * | Default `,`; must be single-character | None | -| [**TSV**](file-formats.md#csvtsvasvusvetc) | Always `\n`; not alterable * | Default `\t`; must be single-character | None | +| [**CSV**](file-formats.md#csvtsvasvusvetc) | Default `\n`; may be set to `\r\n` * | Default `,`; must be single-character | None | +| [**TSV**](file-formats.md#csvtsvasvusvetc) | Default `\n`; may be set to `\r\n` * | Default `\t`; must be single-character | None | | [**CSV-lite**](file-formats.md#csvtsvasvusvetc) | Default `\n` * | Default `,` | None | | [**TSV-lite**](file-formats.md#csvtsvasvusvetc) | Default `\n` * | Default `\t` | None | | [**JSON**](file-formats.md#json) | N/A; records are between `{` and `}` | Always `,`; not alterable | Always `:`; not alterable | diff --git a/docs/src/reference-main-separators.md.in b/docs/src/reference-main-separators.md.in index 2fd128abf..f358b3655 100644 --- a/docs/src/reference-main-separators.md.in +++ b/docs/src/reference-main-separators.md.in @@ -151,8 +151,8 @@ GENMD-EOF Notes: -* CSV IRS and ORS must be newline, and CSV IFS must be a single character. (CSV-lite does not have these restrictions.) -* TSV IRS and ORS must be newline, and TSV IFS must be a tab. (TSV-lite does not have these restrictions.) +* CSV IRS must be newline -- CR/LF line endings are accepted on input. CSV ORS must be either newline (the default) or carriage-return/newline -- e.g. `--ors crlf` or `--ors '\r\n'` for RFC-4180-style line endings on any platform. CSV IFS must be a single character. (CSV-lite does not have these restrictions.) +* TSV IRS must be newline -- CR/LF line endings are accepted on input. TSV ORS must be either newline (the default) or carriage-return/newline. TSV IFS must be a tab. (TSV-lite does not have these restrictions.) * See the [CSV section](file-formats.md#csvtsvasvusvetc) for information about ASV and USV. * JSON and YAML: ignore separator flags from the command line. * Headerless CSV overlaps quite a bit with NIDX format using comma for IFS. See also the page on [CSV with and without headers](csv-with-and-without-headers.md). @@ -160,8 +160,8 @@ Notes: | | **RS** | **FS** | **PS** | |------------|---------|---------|----------| -| [**CSV**](file-formats.md#csvtsvasvusvetc) | Always `\n`; not alterable * | Default `,`; must be single-character | None | -| [**TSV**](file-formats.md#csvtsvasvusvetc) | Always `\n`; not alterable * | Default `\t`; must be single-character | None | +| [**CSV**](file-formats.md#csvtsvasvusvetc) | Default `\n`; may be set to `\r\n` * | Default `,`; must be single-character | None | +| [**TSV**](file-formats.md#csvtsvasvusvetc) | Default `\n`; may be set to `\r\n` * | Default `\t`; must be single-character | None | | [**CSV-lite**](file-formats.md#csvtsvasvusvetc) | Default `\n` * | Default `,` | None | | [**TSV-lite**](file-formats.md#csvtsvasvusvetc) | Default `\n` * | Default `\t` | None | | [**JSON**](file-formats.md#json) | N/A; records are between `{` and `}` | Always `,`; not alterable | Always `:`; not alterable | diff --git a/man/manpage.txt b/man/manpage.txt index e4fe84bc4..068e64a1f 100644 --- a/man/manpage.txt +++ b/man/manpage.txt @@ -819,6 +819,9 @@ * Default line endings (`--irs` and `--ors`) are newline which is interpreted to accept carriage-return/newline files (e.g. on Windows) for input, and to produce platform-appropriate line endings on output. + * For CSV, CSV-lite, TSV, and TSV-lite output, ORS may be either newline (the + default) or carriage-return/newline: e.g. `--ors crlf` or `--ors '\r\n'` + for RFC-4180-style line endings on any platform. Notes about all other separators: @@ -4024,4 +4027,4 @@ MIME Type for Comma-Separated Values (CSV) Files, the Miller docsite https://miller.readthedocs.io - 2026-07-05 4mMILLER24m(1) + 2026-07-06 4mMILLER24m(1) diff --git a/man/mlr.1 b/man/mlr.1 index 995e6825b..6744ca31b 100644 --- a/man/mlr.1 +++ b/man/mlr.1 @@ -2,12 +2,12 @@ .\" Title: mlr .\" Author: [see the "AUTHOR" section] .\" Generator: ./mkman.rb -.\" Date: 2026-07-05 +.\" Date: 2026-07-06 .\" Manual: \ \& .\" Source: \ \& .\" Language: English .\" -.TH "MILLER" "1" "2026-07-05" "\ \&" "\ \&" +.TH "MILLER" "1" "2026-07-06" "\ \&" "\ \&" .\" ----------------------------------------------------------------- .\" * Portability definitions .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -987,6 +987,9 @@ Notes about line endings: * Default line endings (`--irs` and `--ors`) are newline which is interpreted to accept carriage-return/newline files (e.g. on Windows) for input, and to produce platform-appropriate line endings on output. +* For CSV, CSV-lite, TSV, and TSV-lite output, ORS may be either newline (the + default) or carriage-return/newline: e.g. `--ors crlf` or `--ors '\er\en'` + for RFC-4180-style line endings on any platform. Notes about all other separators: diff --git a/pkg/cli/option_parse.go b/pkg/cli/option_parse.go index 06c13c010..f5c27841c 100644 --- a/pkg/cli/option_parse.go +++ b/pkg/cli/option_parse.go @@ -158,6 +158,9 @@ Notes about line endings: * Default line endings (` + "`--irs`" + ` and ` + "`--ors`" + `) are newline which is interpreted to accept carriage-return/newline files (e.g. on Windows) for input, and to produce platform-appropriate line endings on output. +* For CSV, CSV-lite, TSV, and TSV-lite output, ORS may be either newline (the + default) or carriage-return/newline: e.g. ` + "`--ors crlf`" + ` or ` + "`--ors '\\r\\n'`" + ` + for RFC-4180-style line endings on any platform. Notes about all other separators: diff --git a/pkg/output/record_writer_csv.go b/pkg/output/record_writer_csv.go index bb96bc706..3f0b075c2 100644 --- a/pkg/output/record_writer_csv.go +++ b/pkg/output/record_writer_csv.go @@ -32,7 +32,7 @@ func NewRecordWriterCSV(writerOptions *cli.TWriterOptions) (*RecordWriterCSV, er return nil, fmt.Errorf("for CSV, OFS can only be a single character") } if writerOptions.ORS != "\n" && writerOptions.ORS != "\r\n" { - return nil, fmt.Errorf("for CSV, ORS cannot be altered") + return nil, fmt.Errorf("for CSV, ORS must be newline or carriage-return/newline") } writer := &RecordWriterCSV{ writerOptions: writerOptions, @@ -59,6 +59,9 @@ func (writer *RecordWriterCSV) Write( if writer.csvWriter == nil { writer.csvWriter = csv.NewWriter(bufferedOutputStream) writer.csvWriter.Comma = rune(writer.writerOptions.OFS[0]) // xxx temp -- needs length-1 OFS + // Issues #1810 and #1722: honor `--ors '\r\n'` (or `--ors crlf`) for + // CSV output. The default remains "\n". + writer.csvWriter.UseCRLF = writer.writerOptions.ORS == "\r\n" } if writer.firstRecordKeys == nil { diff --git a/pkg/output/record_writer_csv_test.go b/pkg/output/record_writer_csv_test.go new file mode 100644 index 000000000..7e313bdb6 --- /dev/null +++ b/pkg/output/record_writer_csv_test.go @@ -0,0 +1,99 @@ +// Tests for https://github.com/johnkerl/miller/issues/1810 and +// https://github.com/johnkerl/miller/issues/1722: `--ors '\r\n'` (or `--ors +// crlf`) should be honored for CSV/CSV-lite/TSV output. These are unit tests +// rather than regression-test cases since the regression-test harness +// normalizes CR/LF to LF before comparing outputs, and so cannot assert +// byte-exact line endings. + +package output + +import ( + "bufio" + "bytes" + "testing" + + "github.com/johnkerl/miller/v6/pkg/cli" + "github.com/johnkerl/miller/v6/pkg/mlrval" +) + +func makeTestRecord() *mlrval.Mlrmap { + record := mlrval.NewMlrmap() + record.PutReference("a", mlrval.FromString("1")) + record.PutReference("b", mlrval.FromString("2")) + return record +} + +// runWriter drives a record-writer with a single a=1,b=2 record and returns +// the output bytes. +func runWriter(t *testing.T, writer IRecordWriter) string { + t.Helper() + var buffer bytes.Buffer + bufferedOutputStream := bufio.NewWriter(&buffer) + err := writer.Write(makeTestRecord(), nil, bufferedOutputStream, false) + if err != nil { + t.Fatal(err) + } + err = writer.Write(nil, nil, bufferedOutputStream, false) // end of stream + if err != nil { + t.Fatal(err) + } + if err := bufferedOutputStream.Flush(); err != nil { + t.Fatal(err) + } + return buffer.String() +} + +func TestCSVWriterLFDefault(t *testing.T) { + writer, err := NewRecordWriterCSV(&cli.TWriterOptions{OFS: ",", ORS: "\n"}) + if err != nil { + t.Fatal(err) + } + output := runWriter(t, writer) + expected := "a,b\n1,2\n" + if output != expected { + t.Fatalf("expected %q, got %q", expected, output) + } +} + +func TestCSVWriterCRLF(t *testing.T) { + writer, err := NewRecordWriterCSV(&cli.TWriterOptions{OFS: ",", ORS: "\r\n"}) + if err != nil { + t.Fatal(err) + } + output := runWriter(t, writer) + expected := "a,b\r\n1,2\r\n" + if output != expected { + t.Fatalf("expected %q, got %q", expected, output) + } +} + +func TestCSVWriterRejectsOtherORS(t *testing.T) { + _, err := NewRecordWriterCSV(&cli.TWriterOptions{OFS: ",", ORS: ";"}) + if err == nil { + t.Fatal("expected error for ORS \";\" but got none") + } +} + +func TestCSVLiteWriterCRLF(t *testing.T) { + writer, err := NewRecordWriterCSVLite(&cli.TWriterOptions{OFS: ",", ORS: "\r\n"}) + if err != nil { + t.Fatal(err) + } + output := runWriter(t, writer) + expected := "a,b\r\n1,2\r\n" + if output != expected { + t.Fatalf("expected %q, got %q", expected, output) + } +} + +func TestTSVWriterCRLF(t *testing.T) { + writer, err := NewRecordWriterTSV(&cli.TWriterOptions{OFS: "\t", ORS: "\r\n"}) + if err != nil { + t.Fatal(err) + } + output := runWriter(t, writer) + expected := "a\tb\r\n1\t2\r\n" + if output != expected { + t.Fatalf("expected %q, got %q", expected, output) + } +} diff --git a/pkg/output/record_writer_tsv.go b/pkg/output/record_writer_tsv.go index 3ea66b90a..5582a6d9e 100644 --- a/pkg/output/record_writer_tsv.go +++ b/pkg/output/record_writer_tsv.go @@ -24,7 +24,7 @@ func NewRecordWriterTSV(writerOptions *cli.TWriterOptions) (*RecordWriterTSV, er return nil, fmt.Errorf("for TSV, OFS cannot be altered") } if writerOptions.ORS != "\n" && writerOptions.ORS != "\r\n" { - return nil, fmt.Errorf("for CSV, ORS cannot be altered") + return nil, fmt.Errorf("for TSV, ORS must be newline or carriage-return/newline") } return &RecordWriterTSV{ writerOptions: writerOptions, diff --git a/test/cases/io-csv-ors-crlf/0001/cmd b/test/cases/io-csv-ors-crlf/0001/cmd new file mode 100644 index 000000000..5993e01b1 --- /dev/null +++ b/test/cases/io-csv-ors-crlf/0001/cmd @@ -0,0 +1 @@ +mlr --icsv --ocsv --ors crlf cat test/input/line-term-lf.csv diff --git a/test/cases/io-csv-ors-crlf/0001/experr b/test/cases/io-csv-ors-crlf/0001/experr new file mode 100644 index 000000000..e69de29bb diff --git a/test/cases/io-csv-ors-crlf/0001/expout b/test/cases/io-csv-ors-crlf/0001/expout new file mode 100644 index 000000000..37eac50e4 --- /dev/null +++ b/test/cases/io-csv-ors-crlf/0001/expout @@ -0,0 +1,11 @@ +a,b,i,x,y +pan,pan,1,0.34679014,0.72680286 +eks,pan,2,0.75867996,0.52215111 +wye,wye,3,0.20460331,0.33831853 +eks,wye,4,0.38139939,0.13418874 +wye,pan,5,0.57328892,0.86362447 +zee,pan,6,0.52712616,0.49322129 +eks,zee,7,0.61178406,0.18788492 +zee,wye,8,0.59855401,0.97618139 +hat,wye,9,0.03144188,0.74955076 +pan,wye,10,0.50262601,0.95261836 diff --git a/test/cases/io-csv-ors-crlf/0002/cmd b/test/cases/io-csv-ors-crlf/0002/cmd new file mode 100644 index 000000000..a53581049 --- /dev/null +++ b/test/cases/io-csv-ors-crlf/0002/cmd @@ -0,0 +1 @@ +mlr --icsv --ocsv --ors crlf cat test/input/line-term-crlf.csv diff --git a/test/cases/io-csv-ors-crlf/0002/experr b/test/cases/io-csv-ors-crlf/0002/experr new file mode 100644 index 000000000..e69de29bb diff --git a/test/cases/io-csv-ors-crlf/0002/expout b/test/cases/io-csv-ors-crlf/0002/expout new file mode 100644 index 000000000..37eac50e4 --- /dev/null +++ b/test/cases/io-csv-ors-crlf/0002/expout @@ -0,0 +1,11 @@ +a,b,i,x,y +pan,pan,1,0.34679014,0.72680286 +eks,pan,2,0.75867996,0.52215111 +wye,wye,3,0.20460331,0.33831853 +eks,wye,4,0.38139939,0.13418874 +wye,pan,5,0.57328892,0.86362447 +zee,pan,6,0.52712616,0.49322129 +eks,zee,7,0.61178406,0.18788492 +zee,wye,8,0.59855401,0.97618139 +hat,wye,9,0.03144188,0.74955076 +pan,wye,10,0.50262601,0.95261836 diff --git a/test/cases/io-csv-ors-crlf/0003/cmd b/test/cases/io-csv-ors-crlf/0003/cmd new file mode 100644 index 000000000..26297f1cc --- /dev/null +++ b/test/cases/io-csv-ors-crlf/0003/cmd @@ -0,0 +1 @@ +mlr --icsv --ocsv --ors lf cat test/input/line-term-crlf.csv diff --git a/test/cases/io-csv-ors-crlf/0003/experr b/test/cases/io-csv-ors-crlf/0003/experr new file mode 100644 index 000000000..e69de29bb diff --git a/test/cases/io-csv-ors-crlf/0003/expout b/test/cases/io-csv-ors-crlf/0003/expout new file mode 100644 index 000000000..37eac50e4 --- /dev/null +++ b/test/cases/io-csv-ors-crlf/0003/expout @@ -0,0 +1,11 @@ +a,b,i,x,y +pan,pan,1,0.34679014,0.72680286 +eks,pan,2,0.75867996,0.52215111 +wye,wye,3,0.20460331,0.33831853 +eks,wye,4,0.38139939,0.13418874 +wye,pan,5,0.57328892,0.86362447 +zee,pan,6,0.52712616,0.49322129 +eks,zee,7,0.61178406,0.18788492 +zee,wye,8,0.59855401,0.97618139 +hat,wye,9,0.03144188,0.74955076 +pan,wye,10,0.50262601,0.95261836 diff --git a/test/cases/io-csv-ors-crlf/0004/cmd b/test/cases/io-csv-ors-crlf/0004/cmd new file mode 100644 index 000000000..c347399d3 --- /dev/null +++ b/test/cases/io-csv-ors-crlf/0004/cmd @@ -0,0 +1 @@ +mlr --icsv --otsv --ors crlf cat test/input/line-term-lf.csv diff --git a/test/cases/io-csv-ors-crlf/0004/experr b/test/cases/io-csv-ors-crlf/0004/experr new file mode 100644 index 000000000..e69de29bb diff --git a/test/cases/io-csv-ors-crlf/0004/expout b/test/cases/io-csv-ors-crlf/0004/expout new file mode 100644 index 000000000..03ac8f384 --- /dev/null +++ b/test/cases/io-csv-ors-crlf/0004/expout @@ -0,0 +1,11 @@ +a b i x y +pan pan 1 0.34679014 0.72680286 +eks pan 2 0.75867996 0.52215111 +wye wye 3 0.20460331 0.33831853 +eks wye 4 0.38139939 0.13418874 +wye pan 5 0.57328892 0.86362447 +zee pan 6 0.52712616 0.49322129 +eks zee 7 0.61178406 0.18788492 +zee wye 8 0.59855401 0.97618139 +hat wye 9 0.03144188 0.74955076 +pan wye 10 0.50262601 0.95261836 diff --git a/test/cases/io-csv-ors-crlf/0005/cmd b/test/cases/io-csv-ors-crlf/0005/cmd new file mode 100644 index 000000000..04914ef75 --- /dev/null +++ b/test/cases/io-csv-ors-crlf/0005/cmd @@ -0,0 +1 @@ +mlr --icsv --ocsv --ors semicolon cat test/input/line-term-lf.csv diff --git a/test/cases/io-csv-ors-crlf/0005/experr b/test/cases/io-csv-ors-crlf/0005/experr new file mode 100644 index 000000000..1e7caec8c --- /dev/null +++ b/test/cases/io-csv-ors-crlf/0005/experr @@ -0,0 +1 @@ +mlr: for CSV, ORS must be newline or carriage-return/newline diff --git a/test/cases/io-csv-ors-crlf/0005/expout b/test/cases/io-csv-ors-crlf/0005/expout new file mode 100644 index 000000000..e69de29bb diff --git a/test/cases/io-csv-ors-crlf/0005/should-fail b/test/cases/io-csv-ors-crlf/0005/should-fail new file mode 100644 index 000000000..e69de29bb