diff --git a/docs/src/data/sample.dcf b/docs/src/data/sample.dcf new file mode 100644 index 000000000..4a27c036a --- /dev/null +++ b/docs/src/data/sample.dcf @@ -0,0 +1,9 @@ +Package: foo +Version: 1.0 +Depends: libc6 (>= 2.0), libfoo (>= 1.2) +Description: A test package. + +Package: bar +Version: 2.0 +Recommends: foo +Description: Another package. diff --git a/docs/src/features.md b/docs/src/features.md index 4cca80a80..048ec2a04 100644 --- a/docs/src/features.md +++ b/docs/src/features.md @@ -17,7 +17,7 @@ Quick links: # Features Miller is like awk, sed, cut, join, and sort for **name-indexed data, such as -CSV, TSV, JSON, JSON Lines, and YAML**. You get to work with your data using named +CSV, TSV, JSON, JSON Lines, YAML, and DCF**. You get to work with your data using named fields, without needing to count positional column indices. This is something the Unix toolkit always could have done, and arguably always @@ -25,7 +25,7 @@ should have done. It operates on key-value-pair data while the familiar Unix tools operate on integer-indexed fields: if the natural data structure for the latter is the array, then Miller's natural data structure is the insertion-ordered hash map. This encompasses a **variety of data formats**, -including but not limited to the familiar CSV, TSV, JSON, JSON Lines, and YAML. +including but not limited to the familiar CSV, TSV, JSON, JSON Lines, YAML, and DCF. (Miller can handle **positionally-indexed data** as a special case.) * Miller is **multi-purpose**: it's useful for **data cleaning**, **data reduction**, **statistical reporting**, **devops**, **system administration**, **log-file processing**, **format conversion**, and **database-query post-processing**. diff --git a/docs/src/features.md.in b/docs/src/features.md.in index b3d674f67..1ab62ed6f 100644 --- a/docs/src/features.md.in +++ b/docs/src/features.md.in @@ -1,7 +1,7 @@ # Features Miller is like awk, sed, cut, join, and sort for **name-indexed data, such as -CSV, TSV, JSON, JSON Lines, and YAML**. You get to work with your data using named +CSV, TSV, JSON, JSON Lines, YAML, and DCF**. You get to work with your data using named fields, without needing to count positional column indices. This is something the Unix toolkit always could have done, and arguably always @@ -9,7 +9,7 @@ should have done. It operates on key-value-pair data while the familiar Unix tools operate on integer-indexed fields: if the natural data structure for the latter is the array, then Miller's natural data structure is the insertion-ordered hash map. This encompasses a **variety of data formats**, -including but not limited to the familiar CSV, TSV, JSON, JSON Lines, and YAML. +including but not limited to the familiar CSV, TSV, JSON, JSON Lines, YAML, and DCF. (Miller can handle **positionally-indexed data** as a special case.) * Miller is **multi-purpose**: it's useful for **data cleaning**, **data reduction**, **statistical reporting**, **devops**, **system administration**, **log-file processing**, **format conversion**, and **database-query post-processing**. diff --git a/docs/src/file-formats.md b/docs/src/file-formats.md index c43cd27f7..519704f8f 100644 --- a/docs/src/file-formats.md +++ b/docs/src/file-formats.md @@ -17,7 +17,7 @@ Quick links: # File formats Miller handles name-indexed data using several formats: some you probably know -by name, such as CSV, TSV, JSON, JSON Lines, and YAML -- and other formats you're likely already +by name, such as CSV, TSV, JSON, JSON Lines, YAML, and DCF -- and other formats you're likely already seeing and using in your structured data. Additionally, Miller gives you the option to include comments within your data. @@ -108,6 +108,17 @@ NIDX: implicitly numerically indexed (Unix-toolkit style) | the quick brown | Record 1: "1":"the", "2":"quick", "3":"brown" | fox jumped | Record 2: "1":"fox", "2":"jumped" +---------------------+ + +DCF: Debian control file format ++------------+ +| apple: 1 | +| bat: 2 | +| cog: 3 | +| | +| dish: 7 | +| egg: 8 | +| 3: flint | ++------------+ ## CSV/TSV/ASV/USV/etc. @@ -720,6 +731,43 @@ the dawn's light +## DCF (Debian control file) + +
+cat data/sample.dcf
+
+
+Package: foo
+Version: 1.0
+Depends: libc6 (>= 2.0), libfoo (>= 1.2)
+Description: A test package.
+
+Package: bar
+Version: 2.0
+Recommends: foo
+Description: Another package.
+
+ +
+mlr -i dcf -o json cat data/sample.dcf
+
+
+[
+{
+  "Package": "foo",
+  "Version": "1.0",
+  "Depends": ["libc6 (>= 2.0)", "libfoo (>= 1.2)"],
+  "Description": "A test package."
+},
+{
+  "Package": "bar",
+  "Version": "2.0",
+  "Recommends": ["foo"],
+  "Description": "Another package."
+}
+]
+
+ ## Data-conversion keystroke-savers While you can do format conversion using `mlr --icsv --ojson cat myfile.csv`, there are also keystroke-savers for this purpose, such as `mlr --c2j cat myfile.csv`. For a complete list: @@ -731,7 +779,7 @@ While you can do format conversion using `mlr --icsv --ojson cat myfile.csv`, th FORMAT-CONVERSION KEYSTROKE-SAVER FLAGS As keystroke-savers for format-conversion you may use the following. The letters c, t, j, l, d, n, x, p, m, and y refer to formats CSV, TSV, JSON, JSON Lines, -DKVP, NIDX, XTAB, PPRINT, markdown, and YAML, respectively. +DKVP, NIDX, XTAB, PPRINT, markdown, and YAML, respectively. DCF is also supported (use --dcf for DCF in and out). | In\out | CSV | TSV | JSON | JSONL | DKVP | NIDX | XTAB | PPRINT | Markdown | YAML | +----------+----------+----------+----------+-------+-------+-------+-------+--------+----------+--------+ diff --git a/docs/src/file-formats.md.in b/docs/src/file-formats.md.in index 0ac5223eb..ac4c247e3 100644 --- a/docs/src/file-formats.md.in +++ b/docs/src/file-formats.md.in @@ -1,7 +1,7 @@ # File formats Miller handles name-indexed data using several formats: some you probably know -by name, such as CSV, TSV, JSON, JSON Lines, and YAML -- and other formats you're likely already +by name, such as CSV, TSV, JSON, JSON Lines, YAML, and DCF -- and other formats you're likely already seeing and using in your structured data. Additionally, Miller gives you the option to include comments within your data. @@ -362,6 +362,16 @@ GENMD-RUN-COMMAND mlr --nidx --fs ' ' --repifs cut -f 2,3 data/mydata.txt GENMD-EOF +## DCF (Debian control file) + +GENMD-RUN-COMMAND +cat data/sample.dcf +GENMD-EOF + +GENMD-RUN-COMMAND +mlr -i dcf -o json cat data/sample.dcf +GENMD-EOF + ## Data-conversion keystroke-savers While you can do format conversion using `mlr --icsv --ojson cat myfile.csv`, there are also keystroke-savers for this purpose, such as `mlr --c2j cat myfile.csv`. For a complete list: diff --git a/docs/src/glossary.md b/docs/src/glossary.md index b9e5a5e22..ffdc83b0b 100644 --- a/docs/src/glossary.md +++ b/docs/src/glossary.md @@ -468,7 +468,7 @@ trying to define a [local variable](#local-variable) `if = 3` will result in a p A subsequence of a text file in between line-ending symbols such as the special linefeed character. Tools in the [Unix toolkit](#unix-toolkit) generally operate on lines; Miller is designed to do that (using the [NIDX format flags](file-formats.md#nidx-index-numbered-toolkit-style)), as well -as non-line-oriented formats such as [CSV, TSV, JSON, YAML, and others](file-formats.md). +as non-line-oriented formats such as [CSV, TSV, JSON, YAML, DCF, and others](file-formats.md). ## local variable diff --git a/docs/src/glossary.md.in b/docs/src/glossary.md.in index e47dc611b..0bee3b9e0 100644 --- a/docs/src/glossary.md.in +++ b/docs/src/glossary.md.in @@ -452,7 +452,7 @@ trying to define a [local variable](#local-variable) `if = 3` will result in a p A subsequence of a text file in between line-ending symbols such as the special linefeed character. Tools in the [Unix toolkit](#unix-toolkit) generally operate on lines; Miller is designed to do that (using the [NIDX format flags](file-formats.md#nidx-index-numbered-toolkit-style)), as well -as non-line-oriented formats such as [CSV, TSV, JSON, YAML, and others](file-formats.md). +as non-line-oriented formats such as [CSV, TSV, JSON, YAML, DCF, and others](file-formats.md). ## local variable diff --git a/docs/src/index.md b/docs/src/index.md index e7d72c341..a14fddfca 100644 --- a/docs/src/index.md +++ b/docs/src/index.md @@ -16,7 +16,7 @@ Quick links: # Introduction -**Miller is a command-line tool for querying, shaping, and reformatting data files in various formats, including CSV, TSV, JSON, JSON Lines, and YAML.** +**Miller is a command-line tool for querying, shaping, and reformatting data files in various formats, including CSV, TSV, JSON, JSON Lines, YAML, and DCF.** **The big picture:** Even well into the 21st century, our world is full of text-formatted data such as CSV. Google _CSV memes_, for example. We need tooling to _thrive in this world_, nimbly manipulating data which is in CSVs. And we need tooling to _move beyond CSV_, to be able to pull data out and into other storage and processing systems. Miller is designed for both of these goals. @@ -39,7 +39,7 @@ pretty-print your data horizontally or vertically to make it easier to read. mlr --json head -n 1 myfile.json -The `sort`, `head`, etc., are called *verbs*. They're analogs of familiar command-line tools like `sort`, `head`, and so on -- but they're aware of name-indexed, multi-line file formats like CSV, TSV, JSON, and YAML. In addition, though, using Miller's `put` verb, you can use programming-language statements for expressions like +The `sort`, `head`, etc., are called *verbs*. They're analogs of familiar command-line tools like `sort`, `head`, and so on -- but they're aware of name-indexed, multi-line file formats like CSV, TSV, JSON, YAML, and DCF. In addition, though, using Miller's `put` verb, you can use programming-language statements for expressions like
 mlr --csv put '$rate = $units / $seconds' input.csv
diff --git a/docs/src/index.md.in b/docs/src/index.md.in
index 6ade85f28..e4426d4ac 100644
--- a/docs/src/index.md.in
+++ b/docs/src/index.md.in
@@ -1,6 +1,6 @@
 # Introduction
 
-**Miller is a command-line tool for querying, shaping, and reformatting data files in various formats, including CSV, TSV, JSON, JSON Lines, and YAML.**
+**Miller is a command-line tool for querying, shaping, and reformatting data files in various formats, including CSV, TSV, JSON, JSON Lines, YAML, and DCF.**
 
 **The big picture:** Even well into the 21st century, our world is full of text-formatted data such as CSV. Google _CSV memes_, for example. We need tooling to _thrive in this world_, nimbly manipulating data which is in CSVs. And we need tooling to _move beyond CSV_, to be able to pull data out and into other storage and processing systems. Miller is designed for both of these goals.
 
@@ -23,7 +23,7 @@ GENMD-SHOW-COMMAND
 mlr --json head -n 1 myfile.json
 GENMD-EOF
 
-The `sort`, `head`, etc., are called *verbs*. They're analogs of familiar command-line tools like `sort`, `head`, and so on -- but they're aware of name-indexed, multi-line file formats like CSV, TSV, JSON, and YAML. In addition, though, using Miller's `put` verb, you can use programming-language statements for expressions like
+The `sort`, `head`, etc., are called *verbs*. They're analogs of familiar command-line tools like `sort`, `head`, and so on -- but they're aware of name-indexed, multi-line file formats like CSV, TSV, JSON, YAML, and DCF. In addition, though, using Miller's `put` verb, you can use programming-language statements for expressions like
 
 GENMD-SHOW-COMMAND
 mlr --csv put '$rate = $units / $seconds' input.csv
diff --git a/docs/src/manpage.md b/docs/src/manpage.md
index b3f893c2d..9f1e17d85 100644
--- a/docs/src/manpage.md
+++ b/docs/src/manpage.md
@@ -141,6 +141,17 @@ This is simply a copy of what you should see on running `man mlr` at a command p
        | fox jumped          | Record 2: "1":"fox", "2":"jumped"
        +---------------------+
 
+       DCF: Debian control file format
+       +------------+
+       | apple: 1   |
+       | bat: 2     |
+       | cog: 3     |
+       |            |
+       | dish: 7    |
+       | egg: 8     |
+       | 3: flint   |
+       +------------+
+
 1mHELP OPTIONS0m
        Type 'mlr help {topic}' for any of the following:
        Essentials:
@@ -393,6 +404,8 @@ This is simply a copy of what you should see on running `man mlr` at a command p
        --asv or --asvlite       Use ASV format for input and output data.
        --csv or -c or --c2c     Use CSV format for input and output data.
        --csvlite                Use CSV-lite format for input and output data.
+       --dcf                    Use Debian control file (DCF) format for input and
+                                output data.
        --dkvp or --d2d          Use DKVP format for input and output data.
        --gen-field-name         Specify field name for --igen. Defaults to "i".
        --gen-start              Specify start value for --igen. Defaults to 1.
@@ -401,6 +414,7 @@ This is simply a copy of what you should see on running `man mlr` at a command p
        --iasv or --iasvlite     Use ASV format for input data.
        --icsv                   Use CSV format for input data.
        --icsvlite               Use CSV-lite format for input data.
+       --idcf                   Use Debian control file (DCF) format for input data.
        --idkvp                  Use DKVP format for input data.
        --igen                   Ignore input files and instead generate sequential
                                 numeric input using --gen-field-name, --gen-start,
@@ -424,6 +438,7 @@ This is simply a copy of what you should see on running `man mlr` at a command p
        --oasv or --oasvlite     Use ASV format for output data.
        --ocsv                   Use CSV format for output data.
        --ocsvlite               Use CSV-lite format for output data.
+       --odcf                   Use Debian control file (DCF) format for output data.
        --odkvp                  Use DKVP format for output data.
        --ojson                  Use JSON format for output data.
        --ojsonl                 Use JSON Lines format for output data.
@@ -470,7 +485,7 @@ This is simply a copy of what you should see on running `man mlr` at a command p
 1mFORMAT-CONVERSION KEYSTROKE-SAVER FLAGS0m
        As keystroke-savers for format-conversion you may use the following.
        The letters c, t, j, l, d, n, x, p, m, and y refer to formats CSV, TSV, JSON, JSON Lines,
-       DKVP, NIDX, XTAB, PPRINT, markdown, and YAML, respectively.
+       DKVP, NIDX, XTAB, PPRINT, markdown, and YAML, respectively. DCF is also supported (use --dcf for DCF in and out).
 
        | In\out   | CSV      | TSV      | JSON     | JSONL | DKVP  | NIDX  | XTAB  | PPRINT | Markdown | YAML   |
        +----------+----------+----------+----------+-------+-------+-------+-------+--------+----------+--------+
@@ -837,6 +852,7 @@ This is simply a copy of what you should see on running `man mlr` at a command p
                Format   FS     PS     RS
                csv      ","    N/A    "\n"
                csvlite  ","    N/A    "\n"
+               dcf      N/A    N/A    N/A
                dkvp     ","    "="    "\n"
                gen      ","    N/A    "\n"
                json     N/A    N/A    N/A
@@ -3787,5 +3803,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-02-15                         4mMILLER24m(1)
+                                  2026-02-16                         4mMILLER24m(1)
 
diff --git a/docs/src/manpage.txt b/docs/src/manpage.txt index 31faedd7d..91004e078 100644 --- a/docs/src/manpage.txt +++ b/docs/src/manpage.txt @@ -120,6 +120,17 @@ | fox jumped | Record 2: "1":"fox", "2":"jumped" +---------------------+ + DCF: Debian control file format + +------------+ + | apple: 1 | + | bat: 2 | + | cog: 3 | + | | + | dish: 7 | + | egg: 8 | + | 3: flint | + +------------+ + 1mHELP OPTIONS0m Type 'mlr help {topic}' for any of the following: Essentials: @@ -372,6 +383,8 @@ --asv or --asvlite Use ASV format for input and output data. --csv or -c or --c2c Use CSV format for input and output data. --csvlite Use CSV-lite format for input and output data. + --dcf Use Debian control file (DCF) format for input and + output data. --dkvp or --d2d Use DKVP format for input and output data. --gen-field-name Specify field name for --igen. Defaults to "i". --gen-start Specify start value for --igen. Defaults to 1. @@ -380,6 +393,7 @@ --iasv or --iasvlite Use ASV format for input data. --icsv Use CSV format for input data. --icsvlite Use CSV-lite format for input data. + --idcf Use Debian control file (DCF) format for input data. --idkvp Use DKVP format for input data. --igen Ignore input files and instead generate sequential numeric input using --gen-field-name, --gen-start, @@ -403,6 +417,7 @@ --oasv or --oasvlite Use ASV format for output data. --ocsv Use CSV format for output data. --ocsvlite Use CSV-lite format for output data. + --odcf Use Debian control file (DCF) format for output data. --odkvp Use DKVP format for output data. --ojson Use JSON format for output data. --ojsonl Use JSON Lines format for output data. @@ -449,7 +464,7 @@ 1mFORMAT-CONVERSION KEYSTROKE-SAVER FLAGS0m As keystroke-savers for format-conversion you may use the following. The letters c, t, j, l, d, n, x, p, m, and y refer to formats CSV, TSV, JSON, JSON Lines, - DKVP, NIDX, XTAB, PPRINT, markdown, and YAML, respectively. + DKVP, NIDX, XTAB, PPRINT, markdown, and YAML, respectively. DCF is also supported (use --dcf for DCF in and out). | In\out | CSV | TSV | JSON | JSONL | DKVP | NIDX | XTAB | PPRINT | Markdown | YAML | +----------+----------+----------+----------+-------+-------+-------+-------+--------+----------+--------+ @@ -816,6 +831,7 @@ Format FS PS RS csv "," N/A "\n" csvlite "," N/A "\n" + dcf N/A N/A N/A dkvp "," "=" "\n" gen "," N/A "\n" json N/A N/A N/A @@ -3766,4 +3782,4 @@ MIME Type for Comma-Separated Values (CSV) Files, the Miller docsite https://miller.readthedocs.io - 2026-02-15 4mMILLER24m(1) + 2026-02-16 4mMILLER24m(1) diff --git a/docs/src/mk-flag-info.rb b/docs/src/mk-flag-info.rb index cbe109817..a464b3799 100755 --- a/docs/src/mk-flag-info.rb +++ b/docs/src/mk-flag-info.rb @@ -16,7 +16,7 @@ for section_name in section_names # The markdown in this section looks a lot better when hand-crafted (thanks Nikos!). puts <= recordsPerBatch { + readerChannel <- recordsAndContexts + recordsAndContexts = make([]*types.RecordAndContext, 0, recordsPerBatch) + } + } + +flush: + if len(recordsAndContexts) > 0 { + readerChannel <- recordsAndContexts + } +} + +// splitCommaList splits a DCF comma-separated value and returns Miller Mlrval +// array elements (trimmed, skipping empty). +func splitCommaList(s string) []*mlrval.Mlrval { + parts := strings.Split(s, ",") + out := make([]*mlrval.Mlrval, 0, len(parts)) + for _, p := range parts { + p = strings.TrimSpace(p) + if p == "" { + continue + } + out = append(out, mlrval.FromString(p)) + } + return out +} + +// dcfParagraphToRecord converts a control paragraph to a Miller record. List +// fields (Depends, Build-Depends, etc.) become arrays; all other fields stay +// strings. Uses para.Order to preserve field order. Returns nil on error (caller +// must have sent on errorChannel). +func dcfParagraphToRecord(para *control.Paragraph, dedupeFieldNames bool) *mlrval.Mlrmap { + rec := mlrval.NewMlrmapAsRecord() + + // Preserve order from the DCF file when present. + keys := para.Order + if len(keys) == 0 { + for k := range para.Values { + keys = append(keys, k) + } + } + + for _, k := range keys { + v, ok := para.Values[k] + if !ok { + continue + } + + var mv *mlrval.Mlrval + if dcfListFieldNames[k] { + mv = mlrval.FromArray(splitCommaList(v)) + } else { + mv = mlrval.FromString(v) + } + + if _, err := rec.PutReferenceMaybeDedupe(k, mv, dedupeFieldNames); err != nil { + return nil + } + } + + return rec +} diff --git a/pkg/input/record_reader_factory.go b/pkg/input/record_reader_factory.go index cbcdea25f..a150d257a 100644 --- a/pkg/input/record_reader_factory.go +++ b/pkg/input/record_reader_factory.go @@ -30,6 +30,8 @@ func Create(readerOptions *cli.TReaderOptions, recordsPerBatch int64) (IRecordRe return NewRecordReaderTSV(readerOptions, recordsPerBatch) case "xtab": return NewRecordReaderXTAB(readerOptions, recordsPerBatch) + case "dcf": + return NewRecordReaderDCF(readerOptions, recordsPerBatch) case "gen": return NewPseudoReaderGen(readerOptions, recordsPerBatch) default: diff --git a/pkg/lib/file_readers.go b/pkg/lib/file_readers.go index d370d616f..dc169d84b 100644 --- a/pkg/lib/file_readers.go +++ b/pkg/lib/file_readers.go @@ -2,7 +2,7 @@ // Wrapper for os.Open which maps string filename to *os.File, which in turn // implements io.ReadCloser, and optional in turn wrapping that in a // gzip/zlib/bunzip2 reader. Shared across record-readers for all the various -// input-file formats (CSV, JSON, XTAB, DKVP, NIDX, PPRINT) which Miller +// input-file formats (CSV, JSON, XTAB, DKVP, NIDX, PPRINT, DCF) which Miller // supports. // // There are two ways of handling compressed data in the Miller Go port: diff --git a/pkg/output/record_writer_dcf.go b/pkg/output/record_writer_dcf.go new file mode 100644 index 000000000..174245a3e --- /dev/null +++ b/pkg/output/record_writer_dcf.go @@ -0,0 +1,85 @@ +package output + +import ( + "bufio" + "strings" + + "github.com/johnkerl/miller/v6/pkg/cli" + "github.com/johnkerl/miller/v6/pkg/colorizer" + "github.com/johnkerl/miller/v6/pkg/mlrval" + "github.com/johnkerl/miller/v6/pkg/types" +) + +type RecordWriterDCF struct { + writerOptions *cli.TWriterOptions +} + +func NewRecordWriterDCF(writerOptions *cli.TWriterOptions) (*RecordWriterDCF, error) { + return &RecordWriterDCF{ + writerOptions: writerOptions, + }, nil +} + +func (writer *RecordWriterDCF) Write( + outrec *mlrval.Mlrmap, + _ *types.Context, + bufferedOutputStream *bufio.Writer, + outputIsStdout bool, +) error { + if outrec == nil { + return nil + } + if outrec.IsEmpty() { + bufferedOutputStream.WriteString("\n") + return nil + } + + for pe := outrec.Head; pe != nil; pe = pe.Next { + valueStr := dcfValueString(pe.Value) + keyStr := colorizer.MaybeColorizeKey(pe.Key, outputIsStdout) + valueStr = colorizer.MaybeColorizeValue(valueStr, outputIsStdout) + writeDCFField(bufferedOutputStream, keyStr, valueStr) + } + bufferedOutputStream.WriteString("\n") + return nil +} + +// dcfValueString returns the string form of a field value for DCF output. +// Arrays are joined with ", " to match list fields (Depends, etc.). +func dcfValueString(mv *mlrval.Mlrval) string { + if mv == nil { + return "" + } + if mv.IsArray() { + arr := mv.GetArray() + if arr == nil || len(arr) == 0 { + return "" + } + parts := make([]string, 0, len(arr)) + for _, el := range arr { + if el != nil { + parts = append(parts, el.String()) + } + } + return strings.Join(parts, ", ") + } + return mv.String() +} + +// writeDCFField writes one "Key: value" line, folding on newlines per DCF: +// continuation lines start with a single space. +func writeDCFField(b *bufio.Writer, key, value string) { + lines := strings.Split(value, "\n") + for i, line := range lines { + if i == 0 { + b.WriteString(key) + b.WriteString(": ") + b.WriteString(line) + b.WriteString("\n") + } else { + b.WriteString(" ") + b.WriteString(line) + b.WriteString("\n") + } + } +} diff --git a/pkg/output/record_writer_factory.go b/pkg/output/record_writer_factory.go index c7bb9ad02..5f6457655 100644 --- a/pkg/output/record_writer_factory.go +++ b/pkg/output/record_writer_factory.go @@ -20,6 +20,8 @@ func Create(writerOptions *cli.TWriterOptions) (IRecordWriter, error) { return NewRecordWriterJSONLines(writerOptions) case "yaml": return NewRecordWriterYAML(writerOptions) + case "dcf": + return NewRecordWriterDCF(writerOptions) case "md": return NewRecordWriterMarkdown(writerOptions) case "markdown": diff --git a/pkg/terminals/help/entry.go b/pkg/terminals/help/entry.go index 9d08e9f9c..49e5a9cd7 100644 --- a/pkg/terminals/help/entry.go +++ b/pkg/terminals/help/entry.go @@ -447,6 +447,17 @@ NIDX: implicitly numerically indexed (Unix-toolkit style) | the quick brown | Record 1: "1":"the", "2":"quick", "3":"brown" | fox jumped | Record 2: "1":"fox", "2":"jumped" +---------------------+ + +DCF: Debian control file format ++------------+ +| apple: 1 | +| bat: 2 | +| cog: 3 | +| | +| dish: 7 | +| egg: 8 | +| 3: flint | ++------------+ `) } diff --git a/test/cases/io-dcf/0001/cmd b/test/cases/io-dcf/0001/cmd new file mode 100644 index 000000000..dfd92306d --- /dev/null +++ b/test/cases/io-dcf/0001/cmd @@ -0,0 +1 @@ +mlr --itsv --rs lf --odcf cat test/input/simple.tsv diff --git a/test/cases/io-dcf/0001/experr b/test/cases/io-dcf/0001/experr new file mode 100644 index 000000000..e69de29bb diff --git a/test/cases/io-dcf/0001/expout b/test/cases/io-dcf/0001/expout new file mode 100644 index 000000000..88e43f4a0 --- /dev/null +++ b/test/cases/io-dcf/0001/expout @@ -0,0 +1,30 @@ +a: pan +b: pan +i: 1 +x: 2 +y: 0.98994500 + +a: eks +b: pan +i: 2 +x: 1 +y: 0.77515900 + +a: wye +b: wye +i: 3 +x: 1 +y: 0.76164200 + +a: eks +b: wye +i: 4 +x: 5 +y: 0.32293400 + +a: wye +b: pan +i: 5 +x: 5 +y: 0.44828300 + diff --git a/test/cases/io-dcf/0002/cmd b/test/cases/io-dcf/0002/cmd new file mode 100644 index 000000000..20918268f --- /dev/null +++ b/test/cases/io-dcf/0002/cmd @@ -0,0 +1 @@ +mlr --icsv --odcf cat ${CASEDIR}/input diff --git a/test/cases/io-dcf/0002/experr b/test/cases/io-dcf/0002/experr new file mode 100644 index 000000000..e69de29bb diff --git a/test/cases/io-dcf/0002/expout b/test/cases/io-dcf/0002/expout new file mode 100644 index 000000000..563f5558c --- /dev/null +++ b/test/cases/io-dcf/0002/expout @@ -0,0 +1,4 @@ +a: 1 +b: 2|3 +c: 4 + diff --git a/test/cases/io-dcf/0002/input b/test/cases/io-dcf/0002/input new file mode 100644 index 000000000..d3fb76193 --- /dev/null +++ b/test/cases/io-dcf/0002/input @@ -0,0 +1,2 @@ +a,b,c +1,2|3,4 diff --git a/test/cases/io-dcf/0003/cmd b/test/cases/io-dcf/0003/cmd new file mode 100644 index 000000000..e2a7adf04 --- /dev/null +++ b/test/cases/io-dcf/0003/cmd @@ -0,0 +1 @@ +mlr --idcf --odcf cat test/input/test.dcf diff --git a/test/cases/io-dcf/0003/experr b/test/cases/io-dcf/0003/experr new file mode 100644 index 000000000..e69de29bb diff --git a/test/cases/io-dcf/0003/expout b/test/cases/io-dcf/0003/expout new file mode 100644 index 000000000..5bfa59e96 --- /dev/null +++ b/test/cases/io-dcf/0003/expout @@ -0,0 +1,10 @@ +Package: foo +Version: 1.0 +Depends: libc6 (>= 2.0), libfoo (>= 1.2) +Description: A test package. + +Package: bar +Version: 2.0 +Recommends: foo +Description: Another package. + diff --git a/test/cases/io-dcf/dcf-input/cmd b/test/cases/io-dcf/dcf-input/cmd new file mode 100644 index 000000000..f9774999e --- /dev/null +++ b/test/cases/io-dcf/dcf-input/cmd @@ -0,0 +1 @@ +mlr --idcf --ojson cat test/input/test.dcf diff --git a/test/cases/io-dcf/dcf-input/experr b/test/cases/io-dcf/dcf-input/experr new file mode 100644 index 000000000..e69de29bb diff --git a/test/cases/io-dcf/dcf-input/expout b/test/cases/io-dcf/dcf-input/expout new file mode 100644 index 000000000..f8f299fdf --- /dev/null +++ b/test/cases/io-dcf/dcf-input/expout @@ -0,0 +1,14 @@ +[ +{ + "Package": "foo", + "Version": "1.0", + "Depends": ["libc6 (>= 2.0)", "libfoo (>= 1.2)"], + "Description": "A test package." +}, +{ + "Package": "bar", + "Version": "2.0", + "Recommends": ["foo"], + "Description": "Another package." +} +] diff --git a/test/input/test.dcf b/test/input/test.dcf new file mode 100644 index 000000000..4a27c036a --- /dev/null +++ b/test/input/test.dcf @@ -0,0 +1,9 @@ +Package: foo +Version: 1.0 +Depends: libc6 (>= 2.0), libfoo (>= 1.2) +Description: A test package. + +Package: bar +Version: 2.0 +Recommends: foo +Description: Another package.