miller/pkg/cli/option_parse.go
John Kerl 71190d3d99
plans/exit.md: record final status; defer phase 5; convert stragglers (#2207)
Phase-5 wrap-up for plans/exit.md. The DSL-runtime cluster (pkg/dsl/cst:
hofs.go, udf.go, evaluable.go) is deferred rather than converted: 58
regression cases pin the current loud-failure behavior (exact stderr plus
exit 1), and the planned error-Mlrval mechanism would make HOF/UDF misuse
fail silently as bare '(error)' with exit 0 -- a debugging-UX regression.
The alternative (typed panic recovered at the Execute* boundaries) preserves
behavior but introduces panic/recover to a codebase that has none. The
decision belongs with the issue-440 strict-mode design, where the
fatal-vs-data error taxonomy gets decided anyway; plans/exit.md now records
the rationale, the phase-by-phase status (#2198, #2202, #2204, #2205), and
the final intentional keep-list.

Also converted here, since they're squarely in prior phases' patterns rather
than the deferred expression-depth cluster:

- RootNode.ProcessEndOfStream (a phase-3 leftover on the put/filter
  Transform path) returns an error instead of printing-and-exiting on
  end-of-stream close failures; first error returned, any others printed at
  the site.
- The three CompileMillerRegexOrDie calls in option_parse.go (inside
  error-returning parser closures since phase 2) use CompileMillerRegex and
  return the error; 'mlr --ifs-regex (' output and exit code are unchanged.

All 4779 regression cases pass; make lint 0 issues.

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-15 16:05:53 -04:00

4176 lines
138 KiB
Go

// Items which might better belong in miller/cli, but which are placed in a
// deeper package to avoid a package-dependency cycle between miller/cli and
// miller/transforming.
package cli
import (
"bufio"
"errors"
"fmt"
"io"
"os"
"strings"
"github.com/mattn/go-isatty"
"github.com/johnkerl/miller/v6/pkg/colorizer"
"github.com/johnkerl/miller/v6/pkg/lib"
"github.com/johnkerl/miller/v6/pkg/mlrval"
)
// FinalizeReaderOptions does a few things.
// - If a file format was specified but one or more separators were not, a
// default specific to that file format is applied.
// - Computing regexes for IPS and IFS, and unbackslashing IRS. This is
// because the '\n' at the command line which is Go "\\n" (a backslash and an
// n) needs to become the single newline character, and likewise for "\t", etc.
// - IFS/IPS can have escapes like "\x1f" which aren't valid regex literals
// so we unhex them. For example, from "\x1f" -- the four bytes '\', 'x', '1', 'f'
// -- to the single byte with hex code 0x1f.
func FinalizeReaderOptions(readerOptions *TReaderOptions) error {
readerOptions.IFS = lib.UnhexStringLiteral(readerOptions.IFS)
readerOptions.IPS = lib.UnhexStringLiteral(readerOptions.IPS)
if !readerOptions.ifsWasSpecified {
if fs, ok := defaultFSes[readerOptions.InputFileFormat]; ok {
readerOptions.IFS = fs
} else {
return fmt.Errorf("unrecognized input format %q", readerOptions.InputFileFormat)
}
}
if !readerOptions.ipsWasSpecified {
if ps, ok := defaultPSes[readerOptions.InputFileFormat]; ok {
readerOptions.IPS = ps
} else {
return fmt.Errorf("unrecognized input format %q", readerOptions.InputFileFormat)
}
}
if !readerOptions.irsWasSpecified {
if rs, ok := defaultRSes[readerOptions.InputFileFormat]; ok {
readerOptions.IRS = rs
} else {
return fmt.Errorf("unrecognized input format %q", readerOptions.InputFileFormat)
}
}
if !readerOptions.allowRepeatIFSWasSpecified {
// Special case for Miller 6 upgrade -- now that we have regexing for mixes of tabs
// and spaces, that should now be the default for NIDX. But *only* for NIDX format,
// and if IFS wasn't specified.
if readerOptions.InputFileFormat == "nidx" && !readerOptions.ifsWasSpecified {
regex, err := lib.CompileMillerRegex(WHITESPACE_REGEX)
if err != nil {
return err
}
readerOptions.IFSRegex = regex
} else {
if allowRepeatIFS, ok := defaultAllowRepeatIFSes[readerOptions.InputFileFormat]; ok {
readerOptions.AllowRepeatIFS = allowRepeatIFS
} else {
return fmt.Errorf("unrecognized input format %q", readerOptions.InputFileFormat)
}
}
}
readerOptions.IFS = lib.UnbackslashStringLiteral(readerOptions.IFS)
readerOptions.IPS = lib.UnbackslashStringLiteral(readerOptions.IPS)
readerOptions.IRS = lib.UnbackslashStringLiteral(readerOptions.IRS)
if readerOptions.IRS == "" {
return errors.New("empty IRS")
}
return nil
}
// FinalizeWriterOptions unbackslashes OPS, OFS, and ORS. This is because
// the '\n' at the command line which is Go "\\n" (a backslash and an
// n) needs to become the single newline character., and likewise for "\t", etc.
func FinalizeWriterOptions(writerOptions *TWriterOptions) error {
if !writerOptions.ofsWasSpecified {
writerOptions.OFS = defaultFSes[writerOptions.OutputFileFormat]
}
if !writerOptions.opsWasSpecified {
writerOptions.OPS = defaultPSes[writerOptions.OutputFileFormat]
}
if !writerOptions.orsWasSpecified {
writerOptions.ORS = defaultRSes[writerOptions.OutputFileFormat]
}
// If output is a terminal, fflush on every record. Otherwise, use default
// buffering (flush every some number of KB or on EOF). This is a
// significant performance improvement for large files, as we invoke
// syscall.write (with its invocation overhead) far less frequently.
if !writerOptions.flushOnEveryRecordWasSpecified {
writerOptions.FlushOnEveryRecord = isatty.IsTerminal(os.Stdout.Fd())
}
writerOptions.OFS = lib.UnbackslashStringLiteral(writerOptions.OFS)
writerOptions.OPS = lib.UnbackslashStringLiteral(writerOptions.OPS)
writerOptions.ORS = lib.UnbackslashStringLiteral(writerOptions.ORS)
return nil
}
var FLAG_TABLE = FlagTable{
sections: []*FlagSection{
&LegacyFlagSection,
&SeparatorFlagSection,
&FileFormatFlagSection,
&FormatConversionKeystrokeSaverFlagSection,
&CSVTSVOnlyFlagSection,
&JSONOnlyFlagSection,
&PPRINTOnlyFlagSection,
&MarkdownOnlyFlagSection,
&DKVPOnlyFlagSection,
&CompressedDataFlagSection,
&CommentsInDataFlagSection,
&OutputColorizationFlagSection,
&FlattenUnflattenFlagSection,
&ProfilingFlagSection,
&MiscFlagSection,
},
}
func init() {
FLAG_TABLE.Sort()
}
// SEPARATOR FLAGS
func SeparatorPrintInfo() {
fmt.Println(`See the Separators doc page for more about record separators, field
separators, and pair separators. Also see the File formats doc page, or
` + "`mlr help file-formats`" + `, for more about the file formats Miller supports.
In brief:
* For DKVP records like ` + "`x=1,y=2,z=3`" + `, the fields are separated by a comma,
the key-value pairs are separated by a comma, and each record is separated
from the next by a newline.
* Each file format has its own default separators.
* Most formats, such as CSV, don't support pair-separators: keys are on the CSV
header line and values are on each CSV data line; keys and values are not
placed next to one another.
* Some separators are not programmable: for example JSON uses a colon as a
pair separator but this is non-modifiable in the JSON spec.
* You can set separators differently between Miller's input and output --
hence ` + "`--ifs`" + ` and ` + "`--ofs`" + `, etc.
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:
* IPS/OPS are only used for DKVP and XTAB formats, since only in these formats
do key-value pairs appear juxtaposed.
* IRS/ORS are ignored for XTAB format. Nominally IFS and OFS are newlines;
XTAB records are separated by two or more consecutive IFS/OFS -- i.e.
a blank line. Everything above about ` + "`--irs/--ors/--rs auto`" + ` becomes ` + "`--ifs/--ofs/--fs`" + `
auto for XTAB format. (XTAB's default IFS/OFS are "auto".)
* OFS must be single-character for PPRINT format. This is because it is used
with repetition for alignment; multi-character separators would make
alignment impossible.
* OPS may be multi-character for XTAB format, in which case alignment is
disabled.
* FS/PS are ignored for markdown format; RS is used.
* All FS and PS options are ignored for JSON format, since they are not relevant
to the JSON format.
* You can specify separators in any of the following ways, shown by example:
- Type them out, quoting as necessary for shell escapes, e.g.
` + "`--fs '|' --ips :`" + `
- C-style escape sequences, e.g. ` + "`--rs '\\r\\n' --fs '\\t'`" + `.
- To avoid backslashing, you can use any of the following names:`)
fmt.Println()
// Go doesn't preserve insertion order in its arrays so here we are inlining a sort.
aliases := lib.GetArrayKeysSorted(SEPARATOR_NAMES_TO_VALUES)
for _, alias := range aliases {
// Really absurd level of indent needed to get fixed-with font in mkdocs here,
// I don't know why. Usually it only takes 4, not 10.
fmt.Printf(" %-10s = \"%s\"\n", alias, SEPARATOR_NAMES_TO_VALUES[alias])
}
fmt.Println()
fmt.Println(" - Similarly, you can use the following for `--ifs-regex` and `--ips-regex`:")
fmt.Println()
aliases = lib.GetArrayKeysSorted(SEPARATOR_REGEX_NAMES_TO_VALUES)
for _, alias := range aliases {
fmt.Printf(" %-10s = \"%s\"\n", alias, SEPARATOR_REGEX_NAMES_TO_VALUES[alias])
}
fmt.Println()
fmt.Println("* Default separators by format:")
fmt.Println()
formats := lib.GetArrayKeysSorted(defaultFSes)
// Really absurd level of indent needed to get fixed-with font in mkdocs here,
// I don't know why. Usually it only takes 4, not 8.
fmt.Printf(" %-8s %-6s %-6s %-s\n", "Format", "FS", "PS", "RS")
for _, format := range formats {
defaultFS := "\"" + strings.ReplaceAll(defaultFSes[format], "\n", "\\n") + "\""
defaultPS := "\"" + strings.ReplaceAll(defaultPSes[format], "\n", "\\n") + "\""
defaultRS := "\"" + strings.ReplaceAll(defaultRSes[format], "\n", "\\n") + "\""
if defaultFS == "\"N/A\"" {
defaultFS = "N/A"
}
if defaultPS == "\"N/A\"" {
defaultPS = "N/A"
}
if defaultRS == "\"N/A\"" {
defaultRS = "N/A"
}
fmt.Printf(" %-8s %-6s %-6s %-s\n", format, defaultFS, defaultPS, defaultRS)
}
}
func ListSeparatorAliasesForOnlineHelp() {
// Go doesn't preserve insertion order in its arrays so here we are inlining a sort.
aliases := lib.GetArrayKeysSorted(SEPARATOR_NAMES_TO_VALUES)
for _, alias := range aliases {
// Really absurd level of indent needed to get fixed-with font in mkdocs here,
// I don't know why. Usually it only takes 4, not 10.
fmt.Printf("%-10s = \"%s\"\n", alias, SEPARATOR_NAMES_TO_VALUES[alias])
}
}
func ListSeparatorRegexAliasesForOnlineHelp() {
// Go doesn't preserve insertion order in its arrays so here we are inlining a sort.
aliases := lib.GetArrayKeysSorted(SEPARATOR_REGEX_NAMES_TO_VALUES)
for _, alias := range aliases {
// Really absurd level of indent needed to get fixed-with font in mkdocs here,
// I don't know why. Usually it only takes 4, not 10.
fmt.Printf("%-10s = \"%s\"\n", alias, SEPARATOR_REGEX_NAMES_TO_VALUES[alias])
}
}
func init() { SeparatorFlagSection.Sort() }
var SeparatorFlagSection = FlagSection{
name: "Separator flags",
infoPrinter: SeparatorPrintInfo,
flags: []Flag{
{
name: "--ifs",
arg: "{string}",
help: "Specify FS for input.",
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
if err := CheckArgCount(args, *pargi, argc, 2); err != nil {
return err
}
// Backward compatibility with Miller <= 5. Auto-inference of
// LF vs CR/LF line endings is handled within Go libraries so
// we needn't do anything ourselves.
if args[*pargi+1] != "auto" {
options.ReaderOptions.IFS = SeparatorFromArg(args[*pargi+1])
options.ReaderOptions.ifsWasSpecified = true
}
*pargi += 2
return nil
},
},
{
name: "--ifs-regex",
arg: "{string}",
help: "Specify FS for input as a regular expression.",
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
if err := CheckArgCount(args, *pargi, argc, 2); err != nil {
return err
}
// Backward compatibility with Miller <= 5. Auto-inference of
// LF vs CR/LF line endings is handled within Go libraries so
// we needn't do anything ourselves.
if args[*pargi+1] != "auto" {
regex, err := lib.CompileMillerRegex(SeparatorRegexFromArg(args[*pargi+1]))
if err != nil {
return err
}
options.ReaderOptions.IFSRegex = regex
options.ReaderOptions.ifsWasSpecified = true
}
*pargi += 2
return nil
},
},
{
name: "--ips",
arg: "{string}",
help: "Specify PS for input.",
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
if err := CheckArgCount(args, *pargi, argc, 2); err != nil {
return err
}
options.ReaderOptions.IPS = SeparatorFromArg(args[*pargi+1])
options.ReaderOptions.ipsWasSpecified = true
*pargi += 2
return nil
},
},
{
name: "--ips-regex",
arg: "{string}",
help: "Specify PS for input as a regular expression.",
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
if err := CheckArgCount(args, *pargi, argc, 2); err != nil {
return err
}
regex, err := lib.CompileMillerRegex(SeparatorRegexFromArg(args[*pargi+1]))
if err != nil {
return err
}
options.ReaderOptions.IPSRegex = regex
options.ReaderOptions.ipsWasSpecified = true
*pargi += 2
return nil
},
},
{
name: "--irs",
arg: "{string}",
help: "Specify RS for input.",
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
if err := CheckArgCount(args, *pargi, argc, 2); err != nil {
return err
}
// Backward compatibility with Miller <= 5. Auto-inference of
// LF vs CR/LF line endings is handled within Go libraries so
// we needn't do anything ourselves.
if args[*pargi+1] != "auto" {
options.ReaderOptions.IRS = SeparatorFromArg(args[*pargi+1])
options.ReaderOptions.irsWasSpecified = true
}
*pargi += 2
return nil
},
},
{
name: "--repifs",
help: "Let IFS be repeated: e.g. for splitting on multiple spaces.",
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.AllowRepeatIFS = true
options.ReaderOptions.allowRepeatIFSWasSpecified = true
*pargi += 1
return nil
},
},
{
name: "--ors",
arg: "{string}",
help: "Specify RS for output.",
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
if err := CheckArgCount(args, *pargi, argc, 2); err != nil {
return err
}
// Backward compatibility with Miller <= 5. Auto-inference of
// LF vs CR/LF line endings is handled within Go libraries so
// we needn't do anything ourselves.
if args[*pargi+1] != "auto" {
options.WriterOptions.ORS = SeparatorFromArg(args[*pargi+1])
options.WriterOptions.orsWasSpecified = true
}
*pargi += 2
return nil
},
},
{
name: "--ofs",
arg: "{string}",
help: "Specify FS for output.",
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
if err := CheckArgCount(args, *pargi, argc, 2); err != nil {
return err
}
options.WriterOptions.OFS = SeparatorFromArg(args[*pargi+1])
options.WriterOptions.ofsWasSpecified = true
*pargi += 2
return nil
},
},
{
name: "--ops",
arg: "{string}",
help: "Specify PS for output.",
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
if err := CheckArgCount(args, *pargi, argc, 2); err != nil {
return err
}
options.WriterOptions.OPS = SeparatorFromArg(args[*pargi+1])
options.WriterOptions.opsWasSpecified = true
*pargi += 2
return nil
},
},
{
name: "--rs",
arg: "{string}",
help: "Specify RS for input and output.",
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
if err := CheckArgCount(args, *pargi, argc, 2); err != nil {
return err
}
// Backward compatibility with Miller <= 5. Auto-inference of
// LF vs CR/LF line endings is handled within Go libraries so
// we needn't do anything ourselves.
if args[*pargi+1] != "auto" {
options.ReaderOptions.IRS = SeparatorFromArg(args[*pargi+1])
options.WriterOptions.ORS = SeparatorFromArg(args[*pargi+1])
options.ReaderOptions.irsWasSpecified = true
options.WriterOptions.orsWasSpecified = true
}
*pargi += 2
return nil
},
},
{
name: "--fs",
arg: "{string}",
help: "Specify FS for input and output.",
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
if err := CheckArgCount(args, *pargi, argc, 2); err != nil {
return err
}
// Backward compatibility with Miller <= 5. Auto-inference of
// LF vs CR/LF line endings is handled within Go libraries so
// we needn't do anything ourselves.
if args[*pargi+1] != "auto" {
options.ReaderOptions.IFS = SeparatorFromArg(args[*pargi+1])
options.WriterOptions.OFS = SeparatorFromArg(args[*pargi+1])
options.ReaderOptions.ifsWasSpecified = true
options.WriterOptions.ofsWasSpecified = true
}
*pargi += 2
return nil
},
},
{
name: "--ps",
arg: "{string}",
help: "Specify PS for input and output.",
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
if err := CheckArgCount(args, *pargi, argc, 2); err != nil {
return err
}
options.ReaderOptions.IPS = SeparatorFromArg(args[*pargi+1])
options.WriterOptions.OPS = SeparatorFromArg(args[*pargi+1])
options.ReaderOptions.ipsWasSpecified = true
options.WriterOptions.opsWasSpecified = true
*pargi += 2
return nil
},
},
},
}
// JSON-ONLY FLAGS
func JSONOnlyPrintInfo() {
fmt.Println("These are flags which are applicable to JSON output format.")
}
func init() { JSONOnlyFlagSection.Sort() }
var JSONOnlyFlagSection = FlagSection{
name: "JSON-only flags",
infoPrinter: JSONOnlyPrintInfo,
flags: []Flag{
{
name: "--jvstack",
help: "Put one key-value pair per line for JSON output (multi-line output). This is the default for JSON output format.",
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.WriterOptions.JSONOutputMultiline = true
*pargi += 1
return nil
},
},
{
name: "--no-jvstack",
help: "Put objects/arrays all on one line for JSON output. This is the default for JSON Lines output format.",
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.WriterOptions.JSONOutputMultiline = false
*pargi += 1
return nil
},
},
{
name: "--jlistwrap",
altNames: []string{"--jl"},
help: "Wrap JSON output in outermost `[ ]`. This is the default for JSON output format.",
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.WriterOptions.WrapJSONOutputInOuterList = true
*pargi += 1
return nil
},
},
{
name: "--no-jlistwrap",
help: "Do not wrap JSON output in outermost `[ ]`. This is the default for JSON Lines output format.",
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.WriterOptions.WrapJSONOutputInOuterList = false
*pargi += 1
return nil
},
},
{
name: "--yarray",
altNames: []string{"--ya"},
help: "Wrap YAML output in a single top-level array document. This is the default for YAML output format.",
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.WriterOptions.WrapYAMLOutputInOuterList = true
*pargi += 1
return nil
},
},
{
name: "--no-yarray",
help: "Do not wrap YAML output in a single array document; emit one YAML document per record with `---` between.",
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.WriterOptions.WrapYAMLOutputInOuterList = false
*pargi += 1
return nil
},
},
{
name: "--jvquoteall",
help: "Force all JSON values -- recursively into lists and object -- to string.",
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.WriterOptions.JVQuoteAll = true
*pargi += 1
return nil
},
},
},
}
// PPRINT-ONLY FLAGS
func PPRINTOnlyPrintInfo() {
fmt.Println("These are flags which are applicable to PPRINT format.")
}
func init() { PPRINTOnlyFlagSection.Sort() }
var PPRINTOnlyFlagSection = FlagSection{
name: "PPRINT-only flags",
infoPrinter: PPRINTOnlyPrintInfo,
flags: []Flag{
{
name: "--right",
help: "Right-justifies all fields for PPRINT output.",
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.WriterOptions.RightAlignedPPRINTOutput = true
*pargi += 1
return nil
},
},
{
name: "--right-align-numeric",
help: "Right-justifies fields with numeric values for PPRINT output, leaving " +
"other fields left-justified. Headers are right-justified over columns " +
"whose values are all numeric, so that header and data share the same " +
"alignment. Also applies to markdown output, where numeric columns get " +
"right-alignment markers (`---:`) in the header-separator line.",
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.WriterOptions.RightAlignNumericOutput = true
*pargi += 1
return nil
},
},
{
name: "--barred",
altNames: []string{"--barred-output"},
help: "Prints a border around PPRINT output.",
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.WriterOptions.BarredPprintOutput = true
*pargi += 1
return nil
},
},
{
name: "--barred-unicode",
help: "Uses unicode printing chars for barred output",
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.WriterOptions.BarredPprintOutput = true
options.WriterOptions.BarredUseUnicode = true
*pargi += 1
return nil
},
},
{
name: "--barred-input",
help: "When used in conjunction with --pprint, accepts barred input.",
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.BarredPprintInput = true
options.ReaderOptions.IFS = "|"
*pargi += 1
return nil
},
},
{
name: "--fixed",
arg: "{string}",
help: "Fixed width specification. One of 'widths:<col1-width>,<col2-width>,...', left-align, left-align-multi-word, right-align, right-align-multi-word",
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.FixedWidthSpec = args[*pargi+1]
*pargi += 2
return nil
},
},
{
name: "--fw",
arg: "{string}",
help: "Shortcut for --fixed left-align-multi-word",
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.FixedWidthSpec = "left-align-multi-word"
*pargi += 1
return nil
},
},
},
}
// MARKDOWN-ONLY FLAGS
func MarkdownOnlyPrintInfo() {
fmt.Println("These are flags which are applicable to markdown-tabular format.")
}
func init() { MarkdownOnlyFlagSection.Sort() }
var MarkdownOnlyFlagSection = FlagSection{
name: "Markdown-only flags",
infoPrinter: MarkdownOnlyPrintInfo,
flags: []Flag{
{
name: "--omd-aligned",
altNames: []string{"--omarkdown-aligned"},
help: "For markdown-tabular output, left-justify cells and pad each " +
"column to a uniform width, making the raw markdown source easier " +
"to read and maintain. (The rendered table is unaffected.) Implies " +
"--omd, so you do not need to also pass --omd.",
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.WriterOptions.OutputFileFormat = "markdown"
options.WriterOptions.MarkdownAlignedOutput = true
*pargi += 1
return nil
},
},
{
name: "--md-aligned",
altNames: []string{"--markdown-aligned"},
help: "Use markdown-tabular format for input and output data, with " +
"left-justified and padded columns. Implies --md, so you do not " +
"need to also pass --md.",
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "markdown"
options.WriterOptions.OutputFileFormat = "markdown"
options.WriterOptions.MarkdownAlignedOutput = true
*pargi += 1
return nil
},
},
},
}
// DKVP-ONLY FLAGS
func DKVPOnlyPrintInfo() {
fmt.Println("These are flags which are applicable to DKVP format.")
}
func init() { DKVPOnlyFlagSection.Sort() }
var DKVPOnlyFlagSection = FlagSection{
name: "DKVP-only flags",
infoPrinter: DKVPOnlyPrintInfo,
flags: []Flag{
{
name: "--incr-key",
help: "Without this option, keyless DKVP fields are keyed by field number. For example: `a=10,b=20,30,d=40,50` is ingested as `$a=10,$b=20,$3=30,$d=40,$5=50`. With this option, they're keyed by a running counter of keyless fields. For example: `a=10,b=20,30,d=40,50` is ingested as `$a=10,$b=20,$1=30,$d=40,$2=50`.",
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.WriterOptions.BarredPprintOutput = true
*pargi += 1
return nil
},
},
},
}
// LEGACY FLAGS
func LegacyFlagInfoPrint() {
fmt.Println(`These are flags which don't do anything in the current Miller version.
They are accepted as no-op flags in order to keep old scripts from breaking.`)
}
func init() { LegacyFlagSection.Sort() }
var LegacyFlagSection = FlagSection{
name: "Legacy flags",
infoPrinter: LegacyFlagInfoPrint,
flags: []Flag{
{
name: "--mmap",
help: "Miller no longer uses memory-mapping to access data files.",
parser: NoOpParse1,
},
{
name: "--no-mmap",
help: "Miller no longer uses memory-mapping to access data files.",
parser: NoOpParse1,
},
{
name: "--jsonx",
help: "The `--jvstack` flag is now default true in Miller 6.",
parser: NoOpParse1,
},
{
name: "--ojsonx",
help: "The `--jvstack` flag is now default true in Miller 6.",
parser: NoOpParse1,
},
{
name: "--jknquoteint",
help: "Type information from JSON input files is now preserved throughout the processing stream.",
parser: NoOpParse1,
},
{
name: "--jquoteall",
help: "Type information from JSON input files is now preserved throughout the processing stream.",
parser: NoOpParse1,
},
{
name: "--json-fatal-arrays-on-input",
help: "Miller now supports arrays as of version 6.",
parser: NoOpParse1,
},
{
name: "--json-map-arrays-on-input",
help: "Miller now supports arrays as of version 6.",
parser: NoOpParse1,
},
{
name: "--json-skip-arrays-on-input",
help: "Miller now supports arrays as of version 6.",
parser: NoOpParse1,
},
{
name: "--vflatsep",
help: "Ignored as of version 6. This functionality is subsumed into JSON formatting.",
parser: NoOpParse1,
},
{
name: "--quote-none",
help: "Ignored as of version 6. Types are inferred/retained through the processing flow now.",
parser: NoOpParse1,
},
{
name: "--quote-minimal",
help: "Ignored as of version 6. Types are inferred/retained through the processing flow now.",
parser: NoOpParse1,
},
{
name: "--quote-numeric",
help: "Ignored as of version 6. Types are inferred/retained through the processing flow now.",
parser: NoOpParse1,
},
{
name: "--quote-original",
help: "Ignored as of version 6. Types are inferred/retained through the processing flow now.",
parser: NoOpParse1,
},
},
}
// FILE-FORMAT FLAGS
func FileFormatPrintInfo() {
fmt.Println(`See the File formats doc page, and or ` + "`mlr help file-formats`" + `, for more
about file formats Miller supports.
Examples: ` + "`--csv`" + ` for CSV-formatted input and output; ` + "`--icsv --opprint`" + ` for
CSV-formatted input and pretty-printed output.
Please use ` + "`--iformat1 --oformat2`" + ` rather than ` + "`--format1 --oformat2`" + `.
The latter sets up input and output flags for ` + "`format1`" + `, not all of which
are overridden in all cases by setting output format to ` + "`format2`" + `.`)
}
func init() { FileFormatFlagSection.Sort() }
var FileFormatFlagSection = FlagSection{
name: "File-format flags",
infoPrinter: FileFormatPrintInfo,
flags: []Flag{
{
name: "--icsv",
help: "Use CSV format for input data.",
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "csv"
*pargi += 1
return nil
},
},
{
name: "--icsvlite",
help: "Use CSV-lite format for input data.",
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "csvlite"
*pargi += 1
return nil
},
},
{
name: "--itsv",
help: "Use TSV format for input data.",
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "tsv"
*pargi += 1
return nil
},
},
{
name: "--itsvlite",
help: "Use TSV-lite format for input data.",
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "csvlite"
options.ReaderOptions.IFS = "\t"
options.ReaderOptions.ifsWasSpecified = true
*pargi += 1
return nil
},
},
{
name: "--iasv",
altNames: []string{"--iasvlite"},
help: "Use ASV format for input data.",
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "csvlite"
options.ReaderOptions.IFS = ASV_FS
options.ReaderOptions.IRS = ASV_RS
options.ReaderOptions.ifsWasSpecified = true
options.ReaderOptions.irsWasSpecified = true
*pargi += 1
return nil
},
},
{
name: "--iusv",
altNames: []string{"--iusvlite"},
help: "Use USV format for input data.",
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "csvlite"
options.ReaderOptions.IFS = USV_FS
options.ReaderOptions.IRS = USV_RS
options.ReaderOptions.ifsWasSpecified = true
options.ReaderOptions.irsWasSpecified = true
*pargi += 1
return nil
},
},
{
name: "--idkvp",
help: "Use DKVP format for input data.",
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "dkvp"
*pargi += 1
return nil
},
},
{
name: "--ijson",
help: "Use JSON format for input data.",
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "json"
*pargi += 1
return nil
},
},
{
name: "--ijsonl",
help: "Use JSON Lines format for input data.",
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "json"
*pargi += 1
return nil
},
},
{
name: "--iyaml",
help: "Use YAML format for input data.",
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "yaml"
*pargi += 1
return nil
},
},
{
name: "--idcf",
help: "Use Debian control file (DCF) format for input data.",
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "dcf"
*pargi += 1
return nil
},
},
{
name: "--irecutils",
help: "Use GNU recutils (.rec) format for input data.",
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "recutils"
*pargi += 1
return nil
},
},
{
name: "--inidx",
help: "Use NIDX format for input data.",
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "nidx"
*pargi += 1
return nil
},
},
{
name: "--ixtab",
help: "Use XTAB format for input data.",
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "xtab"
*pargi += 1
return nil
},
},
{
name: "--ipprint",
help: "Use PPRINT format for input data.",
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "pprint"
options.ReaderOptions.IFS = " "
options.ReaderOptions.ifsWasSpecified = true
*pargi += 1
return nil
},
},
{
name: "-i",
arg: "{format name}",
help: "Use format name for input data. For example: `-i csv` is the same as `--icsv`.",
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
if err := CheckArgCount(args, *pargi, argc, 2); err != nil {
return err
}
options.ReaderOptions.InputFileFormat = args[*pargi+1]
if options.ReaderOptions.InputFileFormat == "md" {
options.ReaderOptions.InputFileFormat = "markdown" // alias
}
*pargi += 2
return nil
},
},
{
name: "--igen",
help: `Ignore input files and instead generate sequential numeric input using --gen-field-name,
--gen-start, --gen-step, and --gen-stop values. See also the seqgen verb, which is more useful/intuitive.`,
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "gen"
*pargi += 1
return nil
},
},
{
name: "--gen-field-name",
help: `Specify field name for --igen. Defaults to "` + DEFAULT_GEN_FIELD_NAME + `".`,
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "gen"
if err := CheckArgCount(args, *pargi, argc, 2); err != nil {
return err
}
options.ReaderOptions.GeneratorOptions.FieldName = args[*pargi+1]
*pargi += 2
return nil
},
},
{
name: "--gen-start",
help: "Specify start value for --igen. Defaults to " + DEFAULT_GEN_START_AS_STRING + ".",
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "gen"
if err := CheckArgCount(args, *pargi, argc, 2); err != nil {
return err
}
options.ReaderOptions.GeneratorOptions.StartAsString = args[*pargi+1]
*pargi += 2
return nil
},
},
{
name: "--gen-step",
help: "Specify step value for --igen. Defaults to " + DEFAULT_GEN_STEP_AS_STRING + ".",
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "gen"
if err := CheckArgCount(args, *pargi, argc, 2); err != nil {
return err
}
options.ReaderOptions.GeneratorOptions.StepAsString = args[*pargi+1]
*pargi += 2
return nil
},
},
{
name: "--gen-stop",
help: "Specify stop value for --igen. Defaults to " + DEFAULT_GEN_STOP_AS_STRING + ".",
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "gen"
if err := CheckArgCount(args, *pargi, argc, 2); err != nil {
return err
}
options.ReaderOptions.GeneratorOptions.StopAsString = args[*pargi+1]
*pargi += 2
return nil
},
},
{
name: "-o",
arg: "{format name}",
help: "Use format name for output data. For example: `-o csv` is the same as `--ocsv`.",
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
if err := CheckArgCount(args, *pargi, argc, 2); err != nil {
return err
}
options.WriterOptions.OutputFileFormat = args[*pargi+1]
if options.WriterOptions.OutputFileFormat == "md" {
options.WriterOptions.OutputFileFormat = "markdown" // alias
}
*pargi += 2
return nil
},
},
{
name: "--ocsv",
help: "Use CSV format for output data.",
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.WriterOptions.OutputFileFormat = "csv"
*pargi += 1
return nil
},
},
{
name: "--ocsvlite",
help: "Use CSV-lite format for output data.",
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.WriterOptions.OutputFileFormat = "csvlite"
*pargi += 1
return nil
},
},
{
name: "--otsv",
help: "Use TSV format for output data.",
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.WriterOptions.OutputFileFormat = "tsv"
options.WriterOptions.OFS = "\t"
options.WriterOptions.ofsWasSpecified = true
*pargi += 1
return nil
},
},
{
name: "--otsvlite",
help: "Use TSV-lite format for output data.",
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.WriterOptions.OutputFileFormat = "csvlite"
options.WriterOptions.OFS = "\t"
options.WriterOptions.ofsWasSpecified = true
*pargi += 1
return nil
},
},
{
name: "--oasv",
altNames: []string{"--oasvlite"},
help: "Use ASV format for output data.",
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.WriterOptions.OutputFileFormat = "csvlite"
options.WriterOptions.OFS = ASV_FS
options.WriterOptions.ORS = ASV_RS
options.WriterOptions.ofsWasSpecified = true
options.WriterOptions.orsWasSpecified = true
*pargi += 1
return nil
},
},
{
name: "--ousv",
altNames: []string{"--ousvlite"},
help: "Use USV format for output data.",
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.WriterOptions.OutputFileFormat = "csvlite"
options.WriterOptions.OFS = USV_FS
options.WriterOptions.ORS = USV_RS
options.WriterOptions.ofsWasSpecified = true
options.WriterOptions.orsWasSpecified = true
*pargi += 1
return nil
},
},
{
name: "--imd",
altNames: []string{"--imarkdown"},
help: "Use markdown-tabular format for input data.",
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "markdown"
*pargi += 1
return nil
},
},
{
name: "--omd",
altNames: []string{"--omarkdown"},
help: "Use markdown-tabular format for output data.",
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.WriterOptions.OutputFileFormat = "markdown"
*pargi += 1
return nil
},
},
{
name: "--md",
altNames: []string{"--markdown"},
help: "Use markdown-tabular format for input and output data.",
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "markdown"
options.WriterOptions.OutputFileFormat = "markdown"
*pargi += 1
return nil
},
},
{
name: "--odkvp",
help: "Use DKVP format for output data.",
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.WriterOptions.OutputFileFormat = "dkvp"
*pargi += 1
return nil
},
},
{
name: "--ojson",
help: "Use JSON format for output data.",
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.WriterOptions.OutputFileFormat = "json"
options.WriterOptions.WrapJSONOutputInOuterList = true
options.WriterOptions.JSONOutputMultiline = true
*pargi += 1
return nil
},
},
{
name: "--ojsonl",
help: "Use JSON Lines format for output data.",
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.WriterOptions.OutputFileFormat = "jsonl"
*pargi += 1
return nil
},
},
{
name: "--oyaml",
help: "Use YAML format for output data.",
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.WriterOptions.OutputFileFormat = "yaml"
options.WriterOptions.WrapYAMLOutputInOuterList = true
*pargi += 1
return nil
},
},
{
name: "--odcf",
help: "Use Debian control file (DCF) format for output data.",
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.WriterOptions.OutputFileFormat = "dcf"
*pargi += 1
return nil
},
},
{
name: "--orecutils",
help: "Use GNU recutils (.rec) format for output data.",
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.WriterOptions.OutputFileFormat = "recutils"
*pargi += 1
return nil
},
},
{
name: "--onidx",
help: "Use NIDX format for output data.",
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.WriterOptions.OutputFileFormat = "nidx"
options.WriterOptions.OFS = " "
options.WriterOptions.ofsWasSpecified = true
*pargi += 1
return nil
},
},
{
name: "--oxtab",
help: "Use XTAB format for output data.",
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.WriterOptions.OutputFileFormat = "xtab"
*pargi += 1
return nil
},
},
{
name: "--opprint",
help: "Use PPRINT format for output data.",
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.WriterOptions.OutputFileFormat = "pprint"
*pargi += 1
return nil
},
},
{
name: "--io",
arg: "{format name}",
help: "Use format name for input and output data. For example: `--io csv` is the same as `--csv`.",
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
if err := CheckArgCount(args, *pargi, argc, 2); err != nil {
return err
}
if defaultFSes[args[*pargi+1]] == "" {
return FlagErrorf("mlr: unrecognized I/O format \"%s\".", args[*pargi+1])
}
options.ReaderOptions.InputFileFormat = args[*pargi+1]
options.WriterOptions.OutputFileFormat = args[*pargi+1]
*pargi += 2
return nil
},
},
{
name: "--csv",
help: "Use CSV format for input and output data.",
altNames: []string{"-c", "--c2c"},
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "csv"
options.WriterOptions.OutputFileFormat = "csv"
*pargi += 1
return nil
},
},
{
name: "--csvlite",
help: "Use CSV-lite format for input and output data.",
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "csvlite"
options.WriterOptions.OutputFileFormat = "csvlite"
*pargi += 1
return nil
},
},
{
name: "--tsv",
help: "Use TSV format for input and output data.",
altNames: []string{"-t", "--t2t"},
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "tsv"
options.WriterOptions.OutputFileFormat = "tsv"
*pargi += 1
return nil
},
},
{
name: "--tsvlite",
help: "Use TSV-lite format for input and output data.",
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "csvlite"
options.WriterOptions.OutputFileFormat = "csvlite"
options.ReaderOptions.IFS = "\t"
options.WriterOptions.OFS = "\t"
options.ReaderOptions.ifsWasSpecified = true
options.WriterOptions.ofsWasSpecified = true
*pargi += 1
return nil
},
},
{
name: "--asv",
altNames: []string{"--asvlite"},
help: "Use ASV format for input and output data.",
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "csvlite"
options.WriterOptions.OutputFileFormat = "csvlite"
options.ReaderOptions.IFS = ASV_FS
options.WriterOptions.OFS = ASV_FS
options.ReaderOptions.IRS = ASV_RS
options.WriterOptions.ORS = ASV_RS
options.ReaderOptions.ifsWasSpecified = true
options.ReaderOptions.ifsWasSpecified = true
options.ReaderOptions.irsWasSpecified = true
options.WriterOptions.ofsWasSpecified = true
options.WriterOptions.orsWasSpecified = true
*pargi += 1
return nil
},
},
{
name: "--usv",
altNames: []string{"--usvlite"},
help: "Use USV format for input and output data.",
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "csvlite"
options.WriterOptions.OutputFileFormat = "csvlite"
options.ReaderOptions.IFS = USV_FS
options.WriterOptions.OFS = USV_FS
options.ReaderOptions.IRS = USV_RS
options.WriterOptions.ORS = USV_RS
options.ReaderOptions.ifsWasSpecified = true
options.ReaderOptions.irsWasSpecified = true
options.WriterOptions.ofsWasSpecified = true
options.WriterOptions.orsWasSpecified = true
*pargi += 1
return nil
},
},
{
name: "--dkvp",
help: "Use DKVP format for input and output data.",
altNames: []string{"--d2d"},
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "dkvp"
options.WriterOptions.OutputFileFormat = "dkvp"
*pargi += 1
return nil
},
},
{
name: "--dkvpx",
help: "Use DKVPX format for input and output data.",
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "dkvpx"
options.WriterOptions.OutputFileFormat = "dkvpx"
*pargi += 1
return nil
},
},
{
name: "--json",
help: "Use JSON format for input and output data.",
altNames: []string{"-j", "--j2j"},
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "json"
options.WriterOptions.OutputFileFormat = "json"
options.WriterOptions.WrapJSONOutputInOuterList = true
options.WriterOptions.JSONOutputMultiline = true
*pargi += 1
return nil
},
},
{
name: "--jsonl",
help: "Use JSON Lines format for input and output data.",
altNames: []string{"--l2l"},
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "json"
options.WriterOptions.OutputFileFormat = "jsonl"
*pargi += 1
return nil
},
},
{
name: "--yaml",
help: "Use YAML format for input and output data.",
altNames: []string{"--y2y"},
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "yaml"
options.WriterOptions.OutputFileFormat = "yaml"
options.WriterOptions.WrapYAMLOutputInOuterList = true
*pargi += 1
return nil
},
},
{
name: "--dcf",
help: "Use Debian control file (DCF) format for input and output data.",
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "dcf"
options.WriterOptions.OutputFileFormat = "dcf"
*pargi += 1
return nil
},
},
{
name: "--recutils",
help: "Use GNU recutils (.rec) format for input and output data.",
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "recutils"
options.WriterOptions.OutputFileFormat = "recutils"
*pargi += 1
return nil
},
},
{
name: "--nidx",
help: "Use NIDX format for input and output data.",
altNames: []string{"--n2n"},
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "nidx"
options.WriterOptions.OutputFileFormat = "nidx"
*pargi += 1
return nil
},
},
{
name: "--xtab",
help: "Use XTAB format for input and output data.",
altNames: []string{"--x2x"},
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "xtab"
options.WriterOptions.OutputFileFormat = "xtab"
*pargi += 1
return nil
},
},
{
name: "--xvright",
help: "Right-justify values for XTAB format.",
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.WriterOptions.RightAlignedXTABOutput = true
*pargi += 1
return nil
},
},
{
name: "--pprint",
help: "Use PPRINT format for input and output data.",
altNames: []string{"--p2p"},
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "pprint"
options.ReaderOptions.IFS = " "
options.ReaderOptions.ifsWasSpecified = true
options.WriterOptions.OutputFileFormat = "pprint"
*pargi += 1
return nil
},
},
},
}
// FORMAT-CONVERSION KEYSTROKE-SAVER FLAGS
func FormatConversionKeystrokeSaverPrintInfo() {
fmt.Println(`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. DCF is also supported (use --dcf for DCF in and out).
GNU recutils is also supported (use --recutils for recutils in and out).
| In\out | CSV | TSV | JSON | JSONL | DKVP | NIDX | XTAB | PPRINT | Markdown | YAML |
+----------+----------+----------+----------+-------+-------+-------+-------+--------+----------+--------+
| CSV | --c2c,-c | --c2t | --c2j | --c2l | --c2d | --c2n | --c2x | --c2p | --c2m | --c2y |
| TSV | --t2c | --t2t,-t | --t2j | --t2l | --t2d | --t2n | --t2x | --t2p | --t2m | --t2y |
| JSON | --j2c | --j2t | --j2j,-j | --j2l | --j2d | --j2n | --j2x | --j2p | --j2m | --j2y |
| JSONL | --l2c | --l2t | --l2j | --l2l | --l2d | --l2n | --l2x | --l2p | --l2m | --l2y |
| DKVP | --d2c | --d2t | --d2j | --d2l | --d2d | --d2n | --d2x | --d2p | --d2m | --d2y |
| NIDX | --n2c | --n2t | --n2j | --n2l | --n2d | --n2n | --n2x | --n2p | --n2m | --n2y |
| XTAB | --x2c | --x2t | --x2j | --x2l | --x2d | --x2n | --x2x | --x2p | --x2m | --x2y |
| PPRINT | --p2c | --p2t | --p2j | --p2l | --p2d | --p2n | --p2x | -p2p | --p2m | --p2y |
| Markdown | --m2c | --m2t | --m2j | --m2l | --m2d | --m2n | --m2x | --m2p | | --m2y |
| YAML | --y2c | --y2t | --y2j | --y2l | --y2d | --y2n | --y2x | --y2p | --y2m | --y2y |`)
}
func init() { FormatConversionKeystrokeSaverFlagSection.Sort() }
var FormatConversionKeystrokeSaverFlagSection = FlagSection{
name: "Format-conversion keystroke-saver flags",
infoPrinter: FormatConversionKeystrokeSaverPrintInfo,
flags: []Flag{
{
name: "-p",
help: "Keystroke-saver for `--nidx --fs space --repifs`.",
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "nidx"
options.WriterOptions.OutputFileFormat = "nidx"
options.ReaderOptions.IFS = " "
options.WriterOptions.OFS = " "
options.ReaderOptions.ifsWasSpecified = true
options.WriterOptions.ofsWasSpecified = true
options.ReaderOptions.AllowRepeatIFS = true
options.ReaderOptions.allowRepeatIFSWasSpecified = true
*pargi += 1
return nil
},
},
{
name: "-T",
help: "Keystroke-saver for `--nidx --fs tab`.",
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "nidx"
options.WriterOptions.OutputFileFormat = "nidx"
options.ReaderOptions.IFS = "\t"
options.WriterOptions.OFS = "\t"
options.ReaderOptions.ifsWasSpecified = true
options.WriterOptions.ofsWasSpecified = true
*pargi += 1
return nil
},
},
{
name: "--c2t",
help: "Use CSV for input, TSV for output.",
// For format-conversion keystroke-savers, a matrix is plenty -- we don't
// need to print a tedious 60-line list.
suppressFlagEnumeration: true,
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "csv"
options.WriterOptions.OutputFileFormat = "tsv"
options.ReaderOptions.irsWasSpecified = true
*pargi += 1
return nil
},
},
{
name: "--c2d",
help: "Use CSV for input, DKVP for output.",
// For format-conversion keystroke-savers, a matrix is plenty -- we don't
// need to print a tedious 60-line list.
suppressFlagEnumeration: true,
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "csv"
options.WriterOptions.OutputFileFormat = "dkvp"
options.ReaderOptions.irsWasSpecified = true
*pargi += 1
return nil
},
},
{
name: "--c2n",
help: "Use CSV for input, NIDX for output.",
// For format-conversion keystroke-savers, a matrix is plenty -- we don't
// need to print a tedious 60-line list.
suppressFlagEnumeration: true,
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "csv"
options.WriterOptions.OutputFileFormat = "nidx"
options.WriterOptions.OFS = " "
options.ReaderOptions.irsWasSpecified = true
options.WriterOptions.ofsWasSpecified = true
*pargi += 1
return nil
},
},
{
name: "--c2j",
help: "Use CSV for input, JSON for output.",
// For format-conversion keystroke-savers, a matrix is plenty -- we don't
// need to print a tedious 60-line list.
suppressFlagEnumeration: true,
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "csv"
options.WriterOptions.OutputFileFormat = "json"
options.WriterOptions.WrapJSONOutputInOuterList = true
options.WriterOptions.JSONOutputMultiline = true
options.ReaderOptions.irsWasSpecified = true
*pargi += 1
return nil
},
},
{
name: "--c2l",
help: "Use CSV for input, JSON Lines for output.",
// For format-conversion keystroke-savers, a matrix is plenty -- we don't
// need to print a tedious 60-line list.
suppressFlagEnumeration: true,
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "csv"
options.WriterOptions.OutputFileFormat = "json"
options.WriterOptions.WrapJSONOutputInOuterList = false
options.WriterOptions.JSONOutputMultiline = false
options.ReaderOptions.irsWasSpecified = true
*pargi += 1
return nil
},
},
{
name: "--c2p",
help: "Use CSV for input, PPRINT for output.",
// For format-conversion keystroke-savers, a matrix is plenty -- we don't
// need to print a tedious 60-line list.
suppressFlagEnumeration: true,
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "csv"
options.WriterOptions.OutputFileFormat = "pprint"
options.ReaderOptions.irsWasSpecified = true
*pargi += 1
return nil
},
},
{
name: "--c2m",
help: "Use CSV for input, markdown-tabular for output.",
// For format-conversion keystroke-savers, a matrix is plenty -- we don't
// need to print a tedious 60-line list.
suppressFlagEnumeration: true,
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "csv"
options.WriterOptions.OutputFileFormat = "markdown"
*pargi += 1
return nil
},
},
{
name: "--c2y",
help: "Use CSV for input, YAML for output.",
suppressFlagEnumeration: true,
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "csv"
options.WriterOptions.OutputFileFormat = "yaml"
options.WriterOptions.WrapYAMLOutputInOuterList = true
options.ReaderOptions.irsWasSpecified = true
*pargi += 1
return nil
},
},
{
name: "--c2b",
help: "Use CSV for input, PPRINT with `--barred` for output.",
// For format-conversion keystroke-savers, a matrix is plenty -- we don't
// need to print a tedious 60-line list.
suppressFlagEnumeration: true,
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "csv"
options.WriterOptions.OutputFileFormat = "pprint"
options.WriterOptions.BarredPprintOutput = true
options.ReaderOptions.irsWasSpecified = true
*pargi += 1
return nil
},
},
{
name: "--c2x",
help: "Use CSV for input, XTAB for output.",
// For format-conversion keystroke-savers, a matrix is plenty -- we don't
// need to print a tedious 60-line list.
suppressFlagEnumeration: true,
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "csv"
options.WriterOptions.OutputFileFormat = "xtab"
options.ReaderOptions.irsWasSpecified = true
*pargi += 1
return nil
},
},
{
name: "--c2m",
help: "Use CSV for input, markdown-tabular for output.",
// For format-conversion keystroke-savers, a matrix is plenty -- we don't
// need to print a tedious 60-line list.
suppressFlagEnumeration: true,
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "csv"
options.WriterOptions.OutputFileFormat = "markdown"
options.ReaderOptions.irsWasSpecified = true
*pargi += 1
return nil
},
},
{
name: "--t2c",
help: "Use TSV for input, CSV for output.",
// For format-conversion keystroke-savers, a matrix is plenty -- we don't
// need to print a tedious 60-line list.
suppressFlagEnumeration: true,
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "tsv"
options.WriterOptions.OutputFileFormat = "csv"
*pargi += 1
return nil
},
},
{
name: "--t2d",
help: "Use TSV for input, DKVP for output.",
// For format-conversion keystroke-savers, a matrix is plenty -- we don't
// need to print a tedious 60-line list.
suppressFlagEnumeration: true,
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "tsv"
options.WriterOptions.OutputFileFormat = "dkvp"
*pargi += 1
return nil
},
},
{
name: "--t2n",
help: "Use TSV for input, NIDX for output.",
// For format-conversion keystroke-savers, a matrix is plenty -- we don't
// need to print a tedious 60-line list.
suppressFlagEnumeration: true,
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "tsv"
options.WriterOptions.OutputFileFormat = "nidx"
options.WriterOptions.OFS = " "
options.WriterOptions.ofsWasSpecified = true
options.ReaderOptions.CSVLazyQuotes = true
*pargi += 1
return nil
},
},
{
name: "--t2j",
help: "Use TSV for input, JSON for output.",
// For format-conversion keystroke-savers, a matrix is plenty -- we don't
// need to print a tedious 60-line list.
suppressFlagEnumeration: true,
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "tsv"
options.WriterOptions.OutputFileFormat = "json"
options.WriterOptions.WrapJSONOutputInOuterList = true
options.WriterOptions.JSONOutputMultiline = true
*pargi += 1
return nil
},
},
{
name: "--t2l",
help: "Use TSV for input, JSON Lines for output.",
// For format-conversion keystroke-savers, a matrix is plenty -- we don't
// need to print a tedious 60-line list.
suppressFlagEnumeration: true,
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "tsv"
options.WriterOptions.OutputFileFormat = "json"
options.WriterOptions.WrapJSONOutputInOuterList = false
options.WriterOptions.JSONOutputMultiline = false
*pargi += 1
return nil
},
},
{
name: "--t2p",
help: "Use TSV for input, PPRINT for output.",
// For format-conversion keystroke-savers, a matrix is plenty -- we don't
// need to print a tedious 60-line list.
suppressFlagEnumeration: true,
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "tsv"
options.WriterOptions.OutputFileFormat = "pprint"
*pargi += 1
return nil
},
},
{
name: "--t2m",
help: "Use TSV for input, markdown tabular for output.",
// For format-conversion keystroke-savers, a matrix is plenty -- we don't
// need to print a tedious 60-line list.
suppressFlagEnumeration: true,
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "tsv"
options.WriterOptions.OutputFileFormat = "markdown"
*pargi += 1
return nil
},
},
{
name: "--t2y",
help: "Use TSV for input, YAML for output.",
suppressFlagEnumeration: true,
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "tsv"
options.WriterOptions.OutputFileFormat = "yaml"
options.WriterOptions.WrapYAMLOutputInOuterList = true
*pargi += 1
return nil
},
},
{
name: "--t2b",
help: "Use TSV for input, PPRINT with `--barred` for output.",
// For format-conversion keystroke-savers, a matrix is plenty -- we don't
// need to print a tedious 60-line list.
suppressFlagEnumeration: true,
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "tsv"
options.WriterOptions.OutputFileFormat = "pprint"
options.WriterOptions.BarredPprintOutput = true
*pargi += 1
return nil
},
},
{
name: "--t2x",
help: "Use TSV for input, XTAB for output.",
// For format-conversion keystroke-savers, a matrix is plenty -- we don't
// need to print a tedious 60-line list.
suppressFlagEnumeration: true,
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "tsv"
options.WriterOptions.OutputFileFormat = "xtab"
*pargi += 1
return nil
},
},
{
name: "--t2m",
help: "Use TSV for input, markdown-tabular for output.",
// For format-conversion keystroke-savers, a matrix is plenty -- we don't
// need to print a tedious 60-line list.
suppressFlagEnumeration: true,
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "tsv"
options.WriterOptions.OutputFileFormat = "markdown"
*pargi += 1
return nil
},
},
{
name: "--d2c",
help: "Use DKVP for input, CSV for output.",
// For format-conversion keystroke-savers, a matrix is plenty -- we don't
// need to print a tedious 60-line list.
suppressFlagEnumeration: true,
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "dkvp"
options.WriterOptions.OutputFileFormat = "csv"
*pargi += 1
return nil
},
},
{
name: "--d2t",
help: "Use DKVP for input, TSV for output.",
// For format-conversion keystroke-savers, a matrix is plenty -- we don't
// need to print a tedious 60-line list.
suppressFlagEnumeration: true,
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "dkvp"
options.WriterOptions.OutputFileFormat = "tsv"
options.WriterOptions.OFS = "\t"
options.WriterOptions.ofsWasSpecified = true
options.WriterOptions.orsWasSpecified = true
*pargi += 1
return nil
},
},
{
name: "--d2n",
help: "Use DKVP for input, NIDX for output.",
// For format-conversion keystroke-savers, a matrix is plenty -- we don't
// need to print a tedious 60-line list.
suppressFlagEnumeration: true,
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "dkvp"
options.WriterOptions.OutputFileFormat = "nidx"
options.WriterOptions.OFS = " "
options.WriterOptions.ofsWasSpecified = true
*pargi += 1
return nil
},
},
{
name: "--d2j",
help: "Use DKVP for input, JSON for output.",
// For format-conversion keystroke-savers, a matrix is plenty -- we don't
// need to print a tedious 60-line list.
suppressFlagEnumeration: true,
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "dkvp"
options.WriterOptions.OutputFileFormat = "json"
options.WriterOptions.WrapJSONOutputInOuterList = true
options.WriterOptions.JSONOutputMultiline = true
*pargi += 1
return nil
},
},
{
name: "--d2l",
help: "Use DKVP for input, JSON Lines for output.",
// For format-conversion keystroke-savers, a matrix is plenty -- we don't
// need to print a tedious 60-line list.
suppressFlagEnumeration: true,
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "dkvp"
options.WriterOptions.OutputFileFormat = "json"
options.WriterOptions.WrapJSONOutputInOuterList = false
options.WriterOptions.JSONOutputMultiline = false
*pargi += 1
return nil
},
},
{
name: "--d2p",
help: "Use DKVP for input, PPRINT for output.",
// For format-conversion keystroke-savers, a matrix is plenty -- we don't
// need to print a tedious 60-line list.
suppressFlagEnumeration: true,
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "dkvp"
options.WriterOptions.OutputFileFormat = "pprint"
*pargi += 1
return nil
},
},
{
name: "--d2m",
help: "Use DKVP for input, markdown tabular for output.",
// For format-conversion keystroke-savers, a matrix is plenty -- we don't
// need to print a tedious 60-line list.
suppressFlagEnumeration: true,
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "dkvp"
options.WriterOptions.OutputFileFormat = "markdown"
*pargi += 1
return nil
},
},
{
name: "--d2y",
help: "Use DKVP for input, YAML for output.",
suppressFlagEnumeration: true,
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "dkvp"
options.WriterOptions.OutputFileFormat = "yaml"
options.WriterOptions.WrapYAMLOutputInOuterList = true
*pargi += 1
return nil
},
},
{
name: "--d2b",
help: "Use DKVP for input, PPRINT with `--barred` for output.",
// For format-conversion keystroke-savers, a matrix is plenty -- we don't
// need to print a tedious 60-line list.
suppressFlagEnumeration: true,
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "dkvp"
options.WriterOptions.OutputFileFormat = "pprint"
options.WriterOptions.BarredPprintOutput = true
*pargi += 1
return nil
},
},
{
name: "--d2x",
help: "Use DKVP for input, XTAB for output.",
// For format-conversion keystroke-savers, a matrix is plenty -- we don't
// need to print a tedious 60-line list.
suppressFlagEnumeration: true,
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "dkvp"
options.WriterOptions.OutputFileFormat = "xtab"
*pargi += 1
return nil
},
},
{
name: "--d2m",
help: "Use DKVP for input, markdown-tabular for output.",
// For format-conversion keystroke-savers, a matrix is plenty -- we don't
// need to print a tedious 60-line list.
suppressFlagEnumeration: true,
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "dkvp"
options.WriterOptions.OutputFileFormat = "markdown"
*pargi += 1
return nil
},
},
{
name: "--n2c",
help: "Use NIDX for input, CSV for output.",
// For format-conversion keystroke-savers, a matrix is plenty -- we don't
// need to print a tedious 60-line list.
suppressFlagEnumeration: true,
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "nidx"
options.WriterOptions.OutputFileFormat = "csv"
options.WriterOptions.orsWasSpecified = true
*pargi += 1
return nil
},
},
{
name: "--n2t",
help: "Use NIDX for input, TSV for output.",
// For format-conversion keystroke-savers, a matrix is plenty -- we don't
// need to print a tedious 60-line list.
suppressFlagEnumeration: true,
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "nidx"
options.WriterOptions.OutputFileFormat = "tsv"
*pargi += 1
return nil
},
},
{
name: "--n2d",
help: "Use NIDX for input, DKVP for output.",
// For format-conversion keystroke-savers, a matrix is plenty -- we don't
// need to print a tedious 60-line list.
suppressFlagEnumeration: true,
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "nidx"
options.WriterOptions.OutputFileFormat = "dkvp"
*pargi += 1
return nil
},
},
{
name: "--n2j",
help: "Use NIDX for input, JSON for output.",
// For format-conversion keystroke-savers, a matrix is plenty -- we don't
// need to print a tedious 60-line list.
suppressFlagEnumeration: true,
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "nidx"
options.WriterOptions.OutputFileFormat = "json"
options.WriterOptions.WrapJSONOutputInOuterList = true
options.WriterOptions.JSONOutputMultiline = true
*pargi += 1
return nil
},
},
{
name: "--n2l",
help: "Use NIDX for input, JSON Lines for output.",
// For format-conversion keystroke-savers, a matrix is plenty -- we don't
// need to print a tedious 60-line list.
suppressFlagEnumeration: true,
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "nidx"
options.WriterOptions.OutputFileFormat = "json"
options.WriterOptions.WrapJSONOutputInOuterList = false
options.WriterOptions.JSONOutputMultiline = false
*pargi += 1
return nil
},
},
{
name: "--n2p",
help: "Use NIDX for input, PPRINT for output.",
// For format-conversion keystroke-savers, a matrix is plenty -- we don't
// need to print a tedious 60-line list.
suppressFlagEnumeration: true,
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "nidx"
options.WriterOptions.OutputFileFormat = "pprint"
*pargi += 1
return nil
},
},
{
name: "--n2m",
help: "Use NIDX for input, markdown tabular for output.",
// For format-conversion keystroke-savers, a matrix is plenty -- we don't
// need to print a tedious 60-line list.
suppressFlagEnumeration: true,
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "nidx"
options.WriterOptions.OutputFileFormat = "markdown"
*pargi += 1
return nil
},
},
{
name: "--n2y",
help: "Use NIDX for input, YAML for output.",
suppressFlagEnumeration: true,
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "nidx"
options.WriterOptions.OutputFileFormat = "yaml"
options.WriterOptions.WrapYAMLOutputInOuterList = true
*pargi += 1
return nil
},
},
{
name: "--n2b",
help: "Use NIDX for input, PPRINT with `--barred` for output.",
// For format-conversion keystroke-savers, a matrix is plenty -- we don't
// need to print a tedious 60-line list.
suppressFlagEnumeration: true,
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "nidx"
options.WriterOptions.OutputFileFormat = "pprint"
options.WriterOptions.BarredPprintOutput = true
*pargi += 1
return nil
},
},
{
name: "--n2x",
help: "Use NIDX for input, XTAB for output.",
// For format-conversion keystroke-savers, a matrix is plenty -- we don't
// need to print a tedious 60-line list.
suppressFlagEnumeration: true,
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "nidx"
options.WriterOptions.OutputFileFormat = "xtab"
*pargi += 1
return nil
},
},
{
name: "--n2m",
help: "Use NIDX for input, markdown-tabular for output.",
// For format-conversion keystroke-savers, a matrix is plenty -- we don't
// need to print a tedious 60-line list.
suppressFlagEnumeration: true,
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "nidx"
options.WriterOptions.OutputFileFormat = "markdown"
*pargi += 1
return nil
},
},
{
name: "--j2c",
help: "Use JSON for input, CSV for output.",
// For format-conversion keystroke-savers, a matrix is plenty -- we don't
// need to print a tedious 60-line list.
suppressFlagEnumeration: true,
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "json"
options.WriterOptions.OutputFileFormat = "csv"
options.WriterOptions.orsWasSpecified = true
*pargi += 1
return nil
},
},
{
name: "--j2l",
help: "Use JSON for input, JSONL for output.",
// For format-conversion keystroke-savers, a matrix is plenty -- we don't
// need to print a tedious 60-line list.
suppressFlagEnumeration: true,
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "json"
options.WriterOptions.OutputFileFormat = "json"
options.WriterOptions.WrapJSONOutputInOuterList = false
options.WriterOptions.JSONOutputMultiline = false
*pargi += 1
return nil
},
},
{
name: "--j2t",
help: "Use JSON for input, TSV for output.",
// For format-conversion keystroke-savers, a matrix is plenty -- we don't
// need to print a tedious 60-line list.
suppressFlagEnumeration: true,
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "json"
options.WriterOptions.OutputFileFormat = "tsv"
*pargi += 1
return nil
},
},
{
name: "--j2d",
help: "Use JSON for input, DKVP for output.",
// For format-conversion keystroke-savers, a matrix is plenty -- we don't
// need to print a tedious 60-line list.
suppressFlagEnumeration: true,
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "json"
options.WriterOptions.OutputFileFormat = "dkvp"
*pargi += 1
return nil
},
},
{
name: "--j2n",
help: "Use JSON for input, NIDX for output.",
// For format-conversion keystroke-savers, a matrix is plenty -- we don't
// need to print a tedious 60-line list.
suppressFlagEnumeration: true,
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "json"
options.WriterOptions.OutputFileFormat = "nidx"
*pargi += 1
return nil
},
},
{
name: "--j2p",
help: "Use JSON for input, PPRINT for output.",
// For format-conversion keystroke-savers, a matrix is plenty -- we don't
// need to print a tedious 60-line list.
suppressFlagEnumeration: true,
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "json"
options.WriterOptions.OutputFileFormat = "pprint"
*pargi += 1
return nil
},
},
{
name: "--j2m",
help: "Use JSON for input, markdown-tabular for output.",
// For format-conversion keystroke-savers, a matrix is plenty -- we don't
// need to print a tedious 60-line list.
suppressFlagEnumeration: true,
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "json"
options.WriterOptions.OutputFileFormat = "markdown"
*pargi += 1
return nil
},
},
{
name: "--j2y",
help: "Use JSON for input, YAML for output.",
suppressFlagEnumeration: true,
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "json"
options.WriterOptions.OutputFileFormat = "yaml"
options.WriterOptions.WrapYAMLOutputInOuterList = true
*pargi += 1
return nil
},
},
{
name: "--j2b",
help: "Use JSON for input, PPRINT with --barred for output.",
// For format-conversion keystroke-savers, a matrix is plenty -- we don't
// need to print a tedious 60-line list.
suppressFlagEnumeration: true,
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "json"
options.WriterOptions.OutputFileFormat = "pprint"
options.WriterOptions.BarredPprintOutput = true
*pargi += 1
return nil
},
},
{
name: "--j2x",
help: "Use JSON for input, XTAB for output.",
// For format-conversion keystroke-savers, a matrix is plenty -- we don't
// need to print a tedious 60-line list.
suppressFlagEnumeration: true,
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "json"
options.WriterOptions.OutputFileFormat = "xtab"
*pargi += 1
return nil
},
},
{
name: "--j2m",
help: "Use JSON for input, markdown-tabular for output.",
// For format-conversion keystroke-savers, a matrix is plenty -- we don't
// need to print a tedious 60-line list.
suppressFlagEnumeration: true,
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "json"
options.WriterOptions.OutputFileFormat = "markdown"
*pargi += 1
return nil
},
},
{
name: "--l2c",
help: "Use JSON Lines for input, CSV for output.",
// For format-conversion keystroke-savers, a matrix is plenty -- we don't
// need to print a tedious 60-line list.
suppressFlagEnumeration: true,
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "json"
options.WriterOptions.OutputFileFormat = "csv"
options.WriterOptions.orsWasSpecified = true
*pargi += 1
return nil
},
},
{
name: "--l2t",
help: "Use JSON Lines for input, TSV for output.",
// For format-conversion keystroke-savers, a matrix is plenty -- we don't
// need to print a tedious 60-line list.
suppressFlagEnumeration: true,
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "json"
options.WriterOptions.OutputFileFormat = "tsv"
*pargi += 1
return nil
},
},
{
name: "--l2d",
help: "Use JSON Lines for input, DKVP for output.",
// For format-conversion keystroke-savers, a matrix is plenty -- we don't
// need to print a tedious 60-line list.
suppressFlagEnumeration: true,
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "json"
options.WriterOptions.OutputFileFormat = "dkvp"
*pargi += 1
return nil
},
},
{
name: "--l2j",
help: "Use JSONL for input, JSON for output.",
// For format-conversion keystroke-savers, a matrix is plenty -- we don't
// need to print a tedious 60-line list.
suppressFlagEnumeration: true,
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "json"
options.WriterOptions.OutputFileFormat = "json"
*pargi += 1
return nil
},
},
{
name: "--l2n",
help: "Use JSON Lines for input, NIDX for output.",
// For format-conversion keystroke-savers, a matrix is plenty -- we don't
// need to print a tedious 60-line list.
suppressFlagEnumeration: true,
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "json"
options.WriterOptions.OutputFileFormat = "nidx"
*pargi += 1
return nil
},
},
{
name: "--l2p",
help: "Use JSON Lines for input, PPRINT for output.",
// For format-conversion keystroke-savers, a matrix is plenty -- we don't
// need to print a tedious 60-line list.
suppressFlagEnumeration: true,
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "json"
options.WriterOptions.OutputFileFormat = "pprint"
*pargi += 1
return nil
},
},
{
name: "--l2m",
help: "Use JSON Lines for input, markdown-tabular for output.",
// For format-conversion keystroke-savers, a matrix is plenty -- we don't
// need to print a tedious 60-line list.
suppressFlagEnumeration: true,
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "json"
options.WriterOptions.OutputFileFormat = "markdown"
*pargi += 1
return nil
},
},
{
name: "--l2y",
help: "Use JSON Lines for input, YAML for output.",
suppressFlagEnumeration: true,
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "json"
options.WriterOptions.OutputFileFormat = "yaml"
options.WriterOptions.WrapYAMLOutputInOuterList = true
*pargi += 1
return nil
},
},
{
name: "--l2b",
help: "Use JSON Lines for input, PPRINT with --barred for output.",
// For format-conversion keystroke-savers, a matrix is plenty -- we don't
// need to print a tedious 60-line list.
suppressFlagEnumeration: true,
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "json"
options.WriterOptions.OutputFileFormat = "pprint"
options.WriterOptions.BarredPprintOutput = true
*pargi += 1
return nil
},
},
{
name: "--l2x",
help: "Use JSON Lines for input, XTAB for output.",
// For format-conversion keystroke-savers, a matrix is plenty -- we don't
// need to print a tedious 60-line list.
suppressFlagEnumeration: true,
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "json"
options.WriterOptions.OutputFileFormat = "xtab"
*pargi += 1
return nil
},
},
{
name: "--l2m",
help: "Use JSON Lines for input, markdown-tabular for output.",
// For format-conversion keystroke-savers, a matrix is plenty -- we don't
// need to print a tedious 60-line list.
suppressFlagEnumeration: true,
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "json"
options.WriterOptions.OutputFileFormat = "markdown"
*pargi += 1
return nil
},
},
{
name: "--p2c",
help: "Use PPRINT for input, CSV for output.",
// For format-conversion keystroke-savers, a matrix is plenty -- we don't
// need to print a tedious 60-line list.
suppressFlagEnumeration: true,
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "pprint"
options.ReaderOptions.IFS = " "
options.WriterOptions.OutputFileFormat = "csv"
options.ReaderOptions.ifsWasSpecified = true
options.WriterOptions.orsWasSpecified = true
*pargi += 1
return nil
},
},
{
name: "--p2t",
help: "Use PPRINT for input, TSV for output.",
// For format-conversion keystroke-savers, a matrix is plenty -- we don't
// need to print a tedious 60-line list.
suppressFlagEnumeration: true,
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "pprint"
options.ReaderOptions.IFS = " "
options.WriterOptions.OutputFileFormat = "tsv"
options.ReaderOptions.ifsWasSpecified = true
*pargi += 1
return nil
},
},
{
name: "--p2d",
help: "Use PPRINT for input, DKVP for output.",
// For format-conversion keystroke-savers, a matrix is plenty -- we don't
// need to print a tedious 60-line list.
suppressFlagEnumeration: true,
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "pprint"
options.ReaderOptions.IFS = " "
options.WriterOptions.OutputFileFormat = "dkvp"
options.ReaderOptions.ifsWasSpecified = true
*pargi += 1
return nil
},
},
{
name: "--p2n",
help: "Use PPRINT for input, NIDX for output.",
// For format-conversion keystroke-savers, a matrix is plenty -- we don't
// need to print a tedious 60-line list.
suppressFlagEnumeration: true,
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "pprint"
options.ReaderOptions.IFS = " "
options.WriterOptions.OutputFileFormat = "nidx"
options.ReaderOptions.ifsWasSpecified = true
*pargi += 1
return nil
},
},
{
name: "--p2j",
help: "Use PPRINT for input, JSON for output.",
// For format-conversion keystroke-savers, a matrix is plenty -- we don't
// need to print a tedious 60-line list.
suppressFlagEnumeration: true,
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "pprint"
options.ReaderOptions.IFS = " "
options.WriterOptions.OutputFileFormat = "json"
options.WriterOptions.WrapJSONOutputInOuterList = true
options.WriterOptions.JSONOutputMultiline = true
options.ReaderOptions.ifsWasSpecified = true
*pargi += 1
return nil
},
},
{
name: "--p2l",
help: "Use PPRINT for input, JSON Lines for output.",
// For format-conversion keystroke-savers, a matrix is plenty -- we don't
// need to print a tedious 60-line list.
suppressFlagEnumeration: true,
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "pprint"
options.ReaderOptions.IFS = " "
options.WriterOptions.OutputFileFormat = "json"
options.WriterOptions.WrapJSONOutputInOuterList = false
options.WriterOptions.JSONOutputMultiline = false
options.ReaderOptions.ifsWasSpecified = true
*pargi += 1
return nil
},
},
{
name: "--p2x",
help: "Use PPRINT for input, XTAB for output.",
// For format-conversion keystroke-savers, a matrix is plenty -- we don't
// need to print a tedious 60-line list.
suppressFlagEnumeration: true,
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "pprint"
options.ReaderOptions.IFS = " "
options.WriterOptions.OutputFileFormat = "xtab"
options.ReaderOptions.ifsWasSpecified = true
*pargi += 1
return nil
},
},
{
name: "--p2m",
help: "Use PPRINT for input, markdown-tabular for output.",
// For format-conversion keystroke-savers, a matrix is plenty -- we don't
// need to print a tedious 60-line list.
suppressFlagEnumeration: true,
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "pprint"
options.ReaderOptions.IFS = " "
options.WriterOptions.OutputFileFormat = "markdown"
options.ReaderOptions.ifsWasSpecified = true
*pargi += 1
return nil
},
},
{
name: "--p2y",
help: "Use PPRINT for input, YAML for output.",
suppressFlagEnumeration: true,
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "pprint"
options.ReaderOptions.IFS = " "
options.WriterOptions.OutputFileFormat = "yaml"
options.WriterOptions.WrapYAMLOutputInOuterList = true
options.ReaderOptions.ifsWasSpecified = true
*pargi += 1
return nil
},
},
{
name: "--m2c",
help: "Use markdown-tabular for input, CSV for output.",
// For format-conversion keystroke-savers, a matrix is plenty -- we don't
// need to print a tedious 60-line list.
suppressFlagEnumeration: true,
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "markdown"
options.WriterOptions.OutputFileFormat = "csv"
options.ReaderOptions.ifsWasSpecified = true
options.WriterOptions.orsWasSpecified = true
*pargi += 1
return nil
},
},
{
name: "--m2t",
help: "Use markdown-tabular for input, TSV for output.",
// For format-conversion keystroke-savers, a matrix is plenty -- we don't
// need to print a tedious 60-line list.
suppressFlagEnumeration: true,
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "markdown"
options.WriterOptions.OutputFileFormat = "tsv"
options.ReaderOptions.ifsWasSpecified = true
*pargi += 1
return nil
},
},
{
name: "--m2d",
help: "Use markdown-tabular for input, DKVP for output.",
// For format-conversion keystroke-savers, a matrix is plenty -- we don't
// need to print a tedious 60-line list.
suppressFlagEnumeration: true,
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "markdown"
options.WriterOptions.OutputFileFormat = "dkvp"
options.ReaderOptions.ifsWasSpecified = true
*pargi += 1
return nil
},
},
{
name: "--m2n",
help: "Use markdown-tabular for input, NIDX for output.",
// For format-conversion keystroke-savers, a matrix is plenty -- we don't
// need to print a tedious 60-line list.
suppressFlagEnumeration: true,
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "markdown"
options.WriterOptions.OutputFileFormat = "nidx"
options.ReaderOptions.ifsWasSpecified = true
*pargi += 1
return nil
},
},
{
name: "--m2j",
help: "Use markdown-tabular for input, JSON for output.",
// For format-conversion keystroke-savers, a matrix is plenty -- we don't
// need to print a tedious 60-line list.
suppressFlagEnumeration: true,
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "markdown"
options.WriterOptions.OutputFileFormat = "json"
options.WriterOptions.WrapJSONOutputInOuterList = true
options.WriterOptions.JSONOutputMultiline = true
options.ReaderOptions.ifsWasSpecified = true
*pargi += 1
return nil
},
},
{
name: "--m2l",
help: "Use markdown-tabular for input, JSON Lines for output.",
// For format-conversion keystroke-savers, a matrix is plenty -- we don't
// need to print a tedious 60-line list.
suppressFlagEnumeration: true,
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "markdown"
options.WriterOptions.OutputFileFormat = "json"
options.WriterOptions.WrapJSONOutputInOuterList = false
options.WriterOptions.JSONOutputMultiline = false
options.ReaderOptions.ifsWasSpecified = true
*pargi += 1
return nil
},
},
{
name: "--m2x",
help: "Use markdown-tabular for input, XTAB for output.",
// For format-conversion keystroke-savers, a matrix is plenty -- we don't
// need to print a tedious 60-line list.
suppressFlagEnumeration: true,
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "markdown"
options.WriterOptions.OutputFileFormat = "xtab"
options.ReaderOptions.ifsWasSpecified = true
*pargi += 1
return nil
},
},
{
name: "--m2p",
help: "Use markdown-tabular for input, PPRINT for output.",
// For format-conversion keystroke-savers, a matrix is plenty -- we don't
// need to print a tedious 60-line list.
suppressFlagEnumeration: true,
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "markdown"
options.WriterOptions.OutputFileFormat = "pprint"
*pargi += 1
return nil
},
},
{
name: "--m2y",
help: "Use markdown-tabular for input, YAML for output.",
suppressFlagEnumeration: true,
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "markdown"
options.WriterOptions.OutputFileFormat = "yaml"
options.WriterOptions.WrapYAMLOutputInOuterList = true
options.ReaderOptions.ifsWasSpecified = true
*pargi += 1
return nil
},
},
{
name: "--y2c",
help: "Use YAML for input, CSV for output.",
suppressFlagEnumeration: true,
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "yaml"
options.WriterOptions.OutputFileFormat = "csv"
options.WriterOptions.orsWasSpecified = true
*pargi += 1
return nil
},
},
{
name: "--y2t",
help: "Use YAML for input, TSV for output.",
suppressFlagEnumeration: true,
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "yaml"
options.WriterOptions.OutputFileFormat = "tsv"
*pargi += 1
return nil
},
},
{
name: "--y2j",
help: "Use YAML for input, JSON for output.",
suppressFlagEnumeration: true,
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "yaml"
options.WriterOptions.OutputFileFormat = "json"
options.WriterOptions.WrapJSONOutputInOuterList = true
options.WriterOptions.JSONOutputMultiline = true
*pargi += 1
return nil
},
},
{
name: "--y2l",
help: "Use YAML for input, JSON Lines for output.",
suppressFlagEnumeration: true,
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "yaml"
options.WriterOptions.OutputFileFormat = "jsonl"
*pargi += 1
return nil
},
},
{
name: "--y2d",
help: "Use YAML for input, DKVP for output.",
suppressFlagEnumeration: true,
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "yaml"
options.WriterOptions.OutputFileFormat = "dkvp"
*pargi += 1
return nil
},
},
{
name: "--y2n",
help: "Use YAML for input, NIDX for output.",
suppressFlagEnumeration: true,
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "yaml"
options.WriterOptions.OutputFileFormat = "nidx"
*pargi += 1
return nil
},
},
{
name: "--y2x",
help: "Use YAML for input, XTAB for output.",
suppressFlagEnumeration: true,
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "yaml"
options.WriterOptions.OutputFileFormat = "xtab"
*pargi += 1
return nil
},
},
{
name: "--y2p",
help: "Use YAML for input, PPRINT for output.",
suppressFlagEnumeration: true,
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "yaml"
options.WriterOptions.OutputFileFormat = "pprint"
*pargi += 1
return nil
},
},
{
name: "--y2m",
help: "Use YAML for input, markdown-tabular for output.",
suppressFlagEnumeration: true,
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "yaml"
options.WriterOptions.OutputFileFormat = "markdown"
*pargi += 1
return nil
},
},
{
name: "--y2y",
help: "Use YAML for input and output.",
suppressFlagEnumeration: true,
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "yaml"
options.WriterOptions.OutputFileFormat = "yaml"
options.WriterOptions.WrapYAMLOutputInOuterList = true
*pargi += 1
return nil
},
},
{
name: "--x2c",
help: "Use XTAB for input, CSV for output.",
// For format-conversion keystroke-savers, a matrix is plenty -- we don't
// need to print a tedious 60-line list.
suppressFlagEnumeration: true,
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "xtab"
options.WriterOptions.OutputFileFormat = "csv"
options.WriterOptions.orsWasSpecified = true
*pargi += 1
return nil
},
},
{
name: "--x2t",
help: "Use XTAB for input, TSV for output.",
// For format-conversion keystroke-savers, a matrix is plenty -- we don't
// need to print a tedious 60-line list.
suppressFlagEnumeration: true,
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "xtab"
options.WriterOptions.OutputFileFormat = "tsv"
*pargi += 1
return nil
},
},
{
name: "--x2d",
help: "Use XTAB for input, DKVP for output.",
// For format-conversion keystroke-savers, a matrix is plenty -- we don't
// need to print a tedious 60-line list.
suppressFlagEnumeration: true,
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "xtab"
options.WriterOptions.OutputFileFormat = "dkvp"
*pargi += 1
return nil
},
},
{
name: "--x2n",
help: "Use XTAB for input, NIDX for output.",
// For format-conversion keystroke-savers, a matrix is plenty -- we don't
// need to print a tedious 60-line list.
suppressFlagEnumeration: true,
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "xtab"
options.WriterOptions.OutputFileFormat = "nidx"
*pargi += 1
return nil
},
},
{
name: "--x2j",
help: "Use XTAB for input, JSON for output.",
// For format-conversion keystroke-savers, a matrix is plenty -- we don't
// need to print a tedious 60-line list.
suppressFlagEnumeration: true,
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "xtab"
options.WriterOptions.OutputFileFormat = "json"
options.WriterOptions.WrapJSONOutputInOuterList = true
options.WriterOptions.JSONOutputMultiline = true
*pargi += 1
return nil
},
},
{
name: "--x2l",
help: "Use XTAB for input, JSON Lines for output.",
// For format-conversion keystroke-savers, a matrix is plenty -- we don't
// need to print a tedious 60-line list.
suppressFlagEnumeration: true,
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "xtab"
options.WriterOptions.OutputFileFormat = "json"
options.WriterOptions.WrapJSONOutputInOuterList = false
options.WriterOptions.JSONOutputMultiline = false
*pargi += 1
return nil
},
},
{
name: "--x2p",
help: "Use XTAB for input, PPRINT for output.",
// For format-conversion keystroke-savers, a matrix is plenty -- we don't
// need to print a tedious 60-line list.
suppressFlagEnumeration: true,
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "xtab"
options.WriterOptions.OutputFileFormat = "pprint"
*pargi += 1
return nil
},
},
{
name: "--x2m",
help: "Use XTAB for input, markdown-tabular for output.",
// For format-conversion keystroke-savers, a matrix is plenty -- we don't
// need to print a tedious 60-line list.
suppressFlagEnumeration: true,
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "xtab"
options.WriterOptions.OutputFileFormat = "markdown"
*pargi += 1
return nil
},
},
{
name: "--x2y",
help: "Use XTAB for input, YAML for output.",
suppressFlagEnumeration: true,
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "xtab"
options.WriterOptions.OutputFileFormat = "yaml"
options.WriterOptions.WrapYAMLOutputInOuterList = true
*pargi += 1
return nil
},
},
{
name: "--x2b",
help: "Use XTAB for input, PPRINT with `--barred` for output.",
// For format-conversion keystroke-savers, a matrix is plenty -- we don't
// need to print a tedious 60-line list.
suppressFlagEnumeration: true,
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "xtab"
options.WriterOptions.OutputFileFormat = "pprint"
options.WriterOptions.BarredPprintOutput = true
*pargi += 1
return nil
},
},
{
name: "--x2m",
help: "Use XTAB for input, markdown-tabular for output.",
// For format-conversion keystroke-savers, a matrix is plenty -- we don't
// need to print a tedious 60-line list.
suppressFlagEnumeration: true,
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.InputFileFormat = "xtab"
options.WriterOptions.OutputFileFormat = "markdown"
*pargi += 1
return nil
},
},
},
}
// CSV/TSV FLAGS
func CSVTSVOnlyPrintInfo() {
fmt.Println("These are flags which are applicable to CSV format.")
}
func init() { CSVTSVOnlyFlagSection.Sort() }
var CSVTSVOnlyFlagSection = FlagSection{
name: "CSV/TSV-only flags",
infoPrinter: CSVTSVOnlyPrintInfo,
flags: []Flag{
{
name: "--no-implicit-csv-header",
altNames: []string{"--no-implicit-tsv-header"},
help: "Opposite of `--implicit-csv-header`. This is the default anyway -- the main use is for the flags to `mlr join` if you have main file(s) which are headerless but you want to join in on a file which does have a CSV/TSV header. Then you could use `mlr --csv --implicit-csv-header join --no-implicit-csv-header -l your-join-in-with-header.csv ... your-headerless.csv`.",
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.UseImplicitHeader = false
*pargi += 1
return nil
},
},
{
name: "--allow-ragged-csv-input",
altNames: []string{"--ragged", "--allow-ragged-tsv-input"},
help: "If a data line has fewer fields than the header line, fill remaining keys with empty string. If a data line has more fields than the header line, use integer field labels as in the implicit-header case.",
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.AllowRaggedCSVInput = true
*pargi += 1
return nil
},
},
{
name: "--no-auto-unsparsify",
help: "For CSV/TSV output: if the record keys change from one row to another, emit a blank line and a new header line. This is non-compliant with RFC 4180 but it helpful for heterogeneous data.",
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.WriterOptions.NoAutoUnsparsify = true
*pargi += 1
return nil
},
},
{
name: "--implicit-csv-header",
altNames: []string{"--headerless-csv-input", "--hi", "--implicit-tsv-header"},
help: "Use 1,2,3,... as field labels, rather than from line 1 of input files. Tip: combine with `label` to recreate missing headers.",
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.UseImplicitHeader = true
*pargi += 1
return nil
},
},
{
name: "--headerless-csv-output",
altNames: []string{"--ho", "--headerless-tsv-output"},
help: "Print only CSV/TSV data lines; do not print CSV/TSV header lines.",
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.WriterOptions.HeaderlessOutput = true
*pargi += 1
return nil
},
},
{
name: "-N",
help: "Keystroke-saver for `--implicit-csv-header --headerless-csv-output`.",
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.UseImplicitHeader = true
options.WriterOptions.HeaderlessOutput = true
*pargi += 1
return nil
},
},
{
name: "--lazy-quotes",
help: "Accepts quotes appearing in unquoted fields, and non-doubled quotes appearing in quoted fields.",
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.CSVLazyQuotes = true
*pargi += 1
return nil
},
},
{
name: "--csv-trim-leading-space",
help: `Trims leading spaces in CSV data. Use this for data like '"foo", "bar' which is non-RFC-4180 compliant, but common.`,
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.CSVTrimLeadingSpace = true
*pargi += 1
return nil
},
},
{
name: "--quote-all",
help: "Force double-quoting of CSV fields.",
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.WriterOptions.CSVQuoteAll = true
*pargi += 1
return nil
},
},
},
}
// COMPRESSED-DATA FLAGS
func CompressedDataPrintInfo() {
fmt.Print(`Miller offers a few different ways to handle reading data files
which have been compressed.
* Decompression done within the Miller process itself: ` + "`--bz2in`" + ` ` + "`--gzin`" + ` ` + "`--zin`" + "`--zstdin`" +
`
* Decompression done outside the Miller process: ` + "`--prepipe`" + ` ` + "`--prepipex`" + `
Using ` + "`--prepipe`" + ` and ` + "`--prepipex`" + ` you can specify an action to be
taken on each input file. The prepipe command must be able to read from
standard input; it will be invoked with ` + "`{command} < {filename}`" + `. The
prepipex command must take a filename as argument; it will be invoked with
` + "`{command} {filename}`" + `.
Examples:
mlr --prepipe gunzip
mlr --prepipe zcat -cf
mlr --prepipe xz -cd
mlr --prepipe cat
Note that this feature is quite general and is not limited to decompression
utilities. You can use it to apply per-file filters of your choice. For output
compression (or other) utilities, simply pipe the output:
` + "`mlr ... | {your compression command} > outputfilenamegoeshere`" + `
Lastly, note that if ` + "`--prepipe`" + ` or ` + "`--prepipex`" + ` is specified, it replaces any
decisions that might have been made based on the file suffix. Likewise,
` + "`--gzin`" + `/` + "`--bz2in`" + `/` + "`--zin`" + "`--zin`" + ` are ignored if ` + "`--prepipe`" + ` is also specified.
`)
}
func init() { CompressedDataFlagSection.Sort() }
var CompressedDataFlagSection = FlagSection{
name: "Compressed-data flags",
infoPrinter: CompressedDataPrintInfo,
flags: []Flag{
{
name: "--prepipe",
arg: "{decompression command}",
help: "You can, of course, already do without this for single input files, e.g. `gunzip < myfile.csv.gz | mlr ...`. Allowed at the command line, but not in `.mlrrc` to avoid unexpected code execution.",
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
if err := CheckArgCount(args, *pargi, argc, 2); err != nil {
return err
}
options.ReaderOptions.Prepipe = args[*pargi+1]
options.ReaderOptions.PrepipeIsRaw = false
*pargi += 2
return nil
},
},
{
name: "--prepipex",
arg: "{decompression command}",
help: "Like `--prepipe` with one exception: doesn't insert `<` between command and filename at runtime. Useful for some commands like `unzip -qc` which don't read standard input. Allowed at the command line, but not in `.mlrrc` to avoid unexpected code execution.",
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
if err := CheckArgCount(args, *pargi, argc, 2); err != nil {
return err
}
options.ReaderOptions.Prepipe = args[*pargi+1]
options.ReaderOptions.PrepipeIsRaw = true
*pargi += 2
return nil
},
},
{
name: "--prepipe-gunzip",
help: "Same as `--prepipe gunzip`, except this is allowed in `.mlrrc`.",
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.Prepipe = "gunzip"
options.ReaderOptions.PrepipeIsRaw = false
*pargi += 1
return nil
},
},
{
name: "--prepipe-zcat",
help: "Same as `--prepipe zcat`, except this is allowed in `.mlrrc`.",
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.Prepipe = "zcat"
options.ReaderOptions.PrepipeIsRaw = false
*pargi += 1
return nil
},
},
{
name: "--prepipe-zstdcat",
help: "Same as `--prepipe zstdcat`, except this is allowed in `.mlrrc`.",
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.Prepipe = "zstdcat"
options.ReaderOptions.PrepipeIsRaw = false
*pargi += 1
return nil
},
},
{
name: "--prepipe-bz2",
help: "Same as `--prepipe bz2`, except this is allowed in `.mlrrc`.",
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.Prepipe = "bz2"
options.ReaderOptions.PrepipeIsRaw = false
*pargi += 1
return nil
},
},
{
name: "--gzin",
help: "Uncompress gzip within the Miller process. Done by default if file ends in `.gz`.",
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.FileInputEncoding = lib.FileInputEncodingGzip
*pargi += 1
return nil
},
},
{
name: "--zin",
help: "Uncompress zlib within the Miller process. Done by default if file ends in `.z`.",
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.FileInputEncoding = lib.FileInputEncodingZlib
*pargi += 1
return nil
},
},
{
name: "--bz2in",
help: "Uncompress bzip2 within the Miller process. Done by default if file ends in `.bz2`.",
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.FileInputEncoding = lib.FileInputEncodingBzip2
*pargi += 1
return nil
},
},
{
name: "--zstdin",
help: "Uncompress zstd within the Miller process. Done by default if file ends in `.zstd`.",
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.FileInputEncoding = lib.FileInputEncodingZstd
*pargi += 1
return nil
},
},
},
}
// COMMENTS-IN-DATA FLAGS
func CommentsInDataPrintInfo() {
fmt.Printf(`Miller lets you put comments in your data, such as
# This is a comment for a CSV file
a,b,c
1,2,3
4,5,6
Notes:
* Comments are only honored at the start of a line.
* In the absence of any of the below four options, comments are data like
any other text. (The comments-in-data feature is opt-in.)
* When ` + "`--pass-comments`" + ` is used, comment lines are written to standard output
immediately upon being read; they are not part of the record stream. Results
may be counterintuitive. A suggestion is to place comments at the start of
data files.
`)
}
func init() { CommentsInDataFlagSection.Sort() }
var CommentsInDataFlagSection = FlagSection{
name: "Comments-in-data flags",
infoPrinter: CommentsInDataPrintInfo,
flags: []Flag{
{
name: "--skip-comments",
help: "Ignore commented lines (prefixed by `" + DEFAULT_COMMENT_STRING + "`) within the input.",
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.CommentString = DEFAULT_COMMENT_STRING
options.ReaderOptions.CommentHandling = SkipComments
*pargi += 1
return nil
},
},
{
name: "--skip-comments-with",
arg: "{string}",
help: "Ignore commented lines within input, with specified prefix. For CSV input format, the prefix must be a single character.",
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
if err := CheckArgCount(args, *pargi, argc, 2); err != nil {
return err
}
options.ReaderOptions.CommentString = args[*pargi+1]
options.ReaderOptions.CommentHandling = SkipComments
*pargi += 2
return nil
},
},
{
name: "--pass-comments",
help: "Immediately print commented lines (prefixed by `" + DEFAULT_COMMENT_STRING + "`) within the input.",
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.CommentString = DEFAULT_COMMENT_STRING
options.ReaderOptions.CommentHandling = PassComments
*pargi += 1
return nil
},
},
{
name: "--pass-comments-with",
arg: "{string}",
help: "Immediately print commented lines within input, with specified prefix. For CSV input format, the prefix must be a single character.",
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
if err := CheckArgCount(args, *pargi, argc, 2); err != nil {
return err
}
options.ReaderOptions.CommentString = args[*pargi+1]
options.ReaderOptions.CommentHandling = PassComments
*pargi += 2
return nil
},
},
},
}
// OUTPUT-COLORIZATION FLAGS
func OutputColorizationPrintInfo() {
fmt.Print(`Miller uses colors to highlight outputs. You can specify color preferences.
Note: output colorization does not work on Windows.
Things having colors:
* Keys in CSV header lines, JSON keys, etc
* Values in CSV data lines, JSON scalar values, etc in regression-test output
* Some online-help strings
Rules for coloring:
* By default, colorize output only if writing to stdout and stdout is a TTY.
* Example: color: ` + "`mlr --csv cat foo.csv`" + `
* Example: no color: ` + "`mlr --csv cat foo.csv > bar.csv`" + `
* Example: no color: ` + "`mlr --csv cat foo.csv | less`" + `
* The default colors were chosen since they look OK with white or black
terminal background, and are differentiable with common varieties of human
color vision.
Mechanisms for coloring:
* Miller uses ANSI escape sequences only. This does not work on Windows
except within Cygwin.
* Requires ` + "`TERM`" + ` environment variable to be set to non-empty string.
* Doesn't try to check to see whether the terminal is capable of 256-color
ANSI vs 16-color ANSI. Note that if colors are in the range 0..15
then 16-color ANSI escapes are used, so this is in the user's control.
How you can control colorization:
* Suppression/unsuppression:
* Environment variable ` + "`export MLR_NO_COLOR=true` or `export NO_COLOR=true`" + `
means don't color even if stdout+TTY.
* Environment variable ` + "`export MLR_ALWAYS_COLOR=true`" + ` means do color
even if not stdout+TTY.
For example, you might want to use this when piping mlr output to ` + "`less -r`" + `.
* Command-line flags ` + "`--no-color`" + ` or ` + "`-M`" + `, ` + "`--always-color`" + ` or ` + "`-C`" + `.
* Color choices can be specified by using environment variables, or command-line
flags, with values 0..255:
* ` + "`export MLR_KEY_COLOR=208`" + `, ` + "`MLR_VALUE_COLOR=33`" + `, etc.:
` + "`MLR_KEY_COLOR`" + ` ` + "`MLR_VALUE_COLOR`" + ` ` + "`MLR_PASS_COLOR`" + ` ` + "`MLR_FAIL_COLOR`" + `
` + "`MLR_REPL_PS1_COLOR`" + ` ` + "`MLR_REPL_PS2_COLOR`" + ` ` + "`MLR_HELP_COLOR`" + `
* Command-line flags ` + "`--key-color 208`" + `, ` + "`--value-color 33`" + `, etc.:
` + "`--key-color`" + ` ` + "`--value-color`" + ` ` + "`--pass-color`" + ` ` + "`--fail-color`" + `
` + "`--repl-ps1-color`" + ` ` + "`--repl-ps2-color`" + ` ` + "`--help-color`" + `
* This is particularly useful if your terminal's background color clashes
with current settings.
If environment-variable settings and command-line flags are both provided, the
latter take precedence.
Colors can be specified using names such as "red" or "orchid": please see
` + "`mlr --list-color-names`" + ` to see available names. They can also be specified using
numbers in the range 0..255, like 170: please see ` + "`mlr --list-color-codes`" + `.
You can also use "bold", "underline", and/or "reverse". Additionally, combinations of
those can be joined with a "-", like "red-bold", "bold-170", "bold-underline", etc.
`)
}
func init() { OutputColorizationFlagSection.Sort() }
var OutputColorizationFlagSection = FlagSection{
name: "Output-colorization flags",
infoPrinter: OutputColorizationPrintInfo,
flags: []Flag{
{
name: "--list-color-codes",
help: "Show the available color codes in the range 0..255, such as 170 for example.",
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
colorizer.ListColorCodes()
return lib.NewExitZeroRequest()
},
},
{
name: "--list-color-names",
help: "Show the names for the available color codes, such as `orchid` for example.",
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
colorizer.ListColorNames()
return lib.NewExitZeroRequest()
},
},
{
name: "--no-color",
altNames: []string{"-M"},
help: "Instructs Miller to not colorize any output.",
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
colorizer.SetColorization(colorizer.ColorizeOutputNever)
*pargi += 1
return nil
},
},
{
name: "--always-color",
altNames: []string{"-C"},
help: "Instructs Miller to colorize output even when it normally would not. Useful for piping output to `less -r`.",
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
colorizer.SetColorization(colorizer.ColorizeOutputAlways)
*pargi += 1
return nil
},
},
{
name: "--key-color",
help: "Specify the color (see `--list-color-codes` and `--list-color-names`) for record keys.",
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
if err := CheckArgCount(args, *pargi, argc, 2); err != nil {
return err
}
ok := colorizer.SetKeyColor(args[*pargi+1])
if !ok {
return FlagErrorf("mlr: --key-color argument unrecognized; got \"%s\".",
args[*pargi+1])
}
*pargi += 2
return nil
},
},
{
name: "--value-color",
help: "Specify the color (see `--list-color-codes` and `--list-color-names`) for record values.",
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
if err := CheckArgCount(args, *pargi, argc, 2); err != nil {
return err
}
ok := colorizer.SetValueColor(args[*pargi+1])
if !ok {
return FlagErrorf("mlr: --value-color argument unrecognized; got \"%s\".",
args[*pargi+1])
}
*pargi += 2
return nil
},
},
{
name: "--pass-color",
help: "Specify the color (see `--list-color-codes` and `--list-color-names`) for passing cases in `mlr regtest`.",
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
if err := CheckArgCount(args, *pargi, argc, 2); err != nil {
return err
}
ok := colorizer.SetPassColor(args[*pargi+1])
if !ok {
return FlagErrorf("mlr: --pass-color argument unrecognized; got \"%s\".",
args[*pargi+1])
}
*pargi += 2
return nil
},
},
{
name: "--fail-color",
help: "Specify the color (see `--list-color-codes` and `--list-color-names`) for failing cases in `mlr regtest`.",
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
if err := CheckArgCount(args, *pargi, argc, 2); err != nil {
return err
}
ok := colorizer.SetFailColor(args[*pargi+1])
if !ok {
return FlagErrorf("mlr: --fail-color argument unrecognized; got \"%s\".",
args[*pargi+1])
}
*pargi += 2
return nil
},
},
{
name: "--help-color",
help: "Specify the color (see `--list-color-codes` and `--list-color-names`) for highlights in `mlr help` output.",
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
if err := CheckArgCount(args, *pargi, argc, 2); err != nil {
return err
}
ok := colorizer.SetHelpColor(args[*pargi+1])
if !ok {
return FlagErrorf("mlr: --help-color argument unrecognized; got \"%s\".",
args[*pargi+1])
}
*pargi += 2
return nil
},
},
},
}
// FLATTEN/UNFLATTEN FLAGS
func FlattenUnflattenPrintInfo() {
fmt.Println("These flags control how Miller converts record values which are maps or arrays, when input is JSON/YAML and output is not (flattening) or input is not JSON/YAML and output is JSON/YAML (unflattening).")
fmt.Println()
fmt.Println("See the flatten/unflatten doc page https://miller.readthedocs.io/en/latest/flatten-unflatten for more information.")
}
func init() { FlattenUnflattenFlagSection.Sort() }
var FlattenUnflattenFlagSection = FlagSection{
name: "Flatten-unflatten flags",
infoPrinter: FlattenUnflattenPrintInfo,
flags: []Flag{
{
name: "--flatsep",
altNames: []string{"--jflatsep"},
arg: "{string}",
help: "Separator for flattening multi-level JSON keys, e.g. `{\"a\":{\"b\":3}}` becomes `a:b => 3` for non-JSON formats. Defaults to `" + DEFAULT_JSON_FLATTEN_SEPARATOR + "`.",
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
if err := CheckArgCount(args, *pargi, argc, 2); err != nil {
return err
}
options.WriterOptions.FLATSEP = SeparatorFromArg(args[*pargi+1])
*pargi += 2
return nil
},
},
{
name: "--no-auto-flatten",
help: "When output is not JSON or YAML, suppress the default auto-flatten behavior. Default: if `$y = [7,8,9]` then this flattens to `y.1=7,y.2=8,y.3=9`, and similarly for maps. With `--no-auto-flatten`, instead we get `$y=[1, 2, 3]`.",
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.WriterOptions.AutoFlatten = false
*pargi += 1
return nil
},
},
{
name: "--no-auto-unflatten",
help: "When input is not JSON or YAML and output is JSON or YAML, suppress the default auto-unflatten behavior. Default: if the input has `y.1=7,y.2=8,y.3=9` then this unflattens to `$y=[7,8,9]`. With `--no-auto-flatten`, instead we get `${y.1}=7,${y.2}=8,${y.3}=9`.",
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.WriterOptions.AutoUnflatten = false
*pargi += 1
return nil
},
},
},
}
// PROFILING FLAGS
func ProfilingPrintInfo() {
fmt.Print("These are flags for profiling Miller performance.")
}
func init() { ProfilingFlagSection.Sort() }
var ProfilingFlagSection = FlagSection{
name: "Profiling flags",
infoPrinter: ProfilingPrintInfo,
flags: []Flag{
{
name: "--cpuprofile",
arg: "{CPU-profile file name}",
help: `Create a CPU-profile file for performance analysis. Instructions will be printed to stderr.
This flag must be the very first thing after 'mlr' on the command line.`,
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
// Already handled in main(). Nothing to do here except to accept this as valid syntax.
*pargi += 2
return nil
},
},
{
name: "--traceprofile",
help: `Create a trace-profile file for performance analysis. Instructions will be printed to stderr.
This flag must be the very first thing after 'mlr' on the command line.`,
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
// Already handled in main(). Nothing to do here except to accept this as valid syntax.
*pargi += 1
return nil
},
},
{
name: "--time",
help: "Print elapsed execution time in seconds to stderr at the end of the execution of the program.",
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.PrintElapsedTime = true
*pargi += 1
return nil
},
},
},
}
// MISC FLAGS
func MiscPrintInfo() {
fmt.Print("These are flags which don't fit into any other category.")
}
func init() { MiscFlagSection.Sort() }
var MiscFlagSection = FlagSection{
name: "Miscellaneous flags",
infoPrinter: MiscPrintInfo,
flags: []Flag{
{
name: "--errors-json",
help: "Emit parse errors as a JSON object to stderr instead of a plain text message. Intended for AI agents and scripts that branch on error kind rather than regex-matching prose. Equivalent to setting the `MLR_ERRORS_JSON` environment variable to a truthy value.",
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
// The actual effect is handled by pre-scan in pkg/entrypoint.
// Registration here ensures the flag is recognized (not an
// error) during pass-one flag parsing, and appears in --help.
*pargi += 1
return nil
},
},
{
name: "--no-shell",
help: "Disable Miller's ability to run external commands: the DSL `system` and `exec` functions, piped redirects such as `tee | \"command\"`, and `--prepipe`/`--prepipex` all fail cleanly instead of executing. Equivalent to setting the `MLR_NO_SHELL` environment variable to a truthy value. Intended for running agent-constructed command lines (e.g. via `mlr mcp`) without also granting arbitrary command execution. Once disabled, shell-outs cannot be re-enabled for the rest of the process.",
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
lib.DisableShellOut()
*pargi += 1
return nil
},
},
{
name: "-x",
help: "If any record has an error value in it, report it and stop the process. The default is to print the field value as `(error)` and continue.",
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.WriterOptions.FailOnDataError = true
*pargi += 1
return nil
},
},
{
name: "-n",
help: "Process no input files, nor standard input either. Useful for `mlr put` with `begin`/`end` statements only. (Same as `--from /dev/null`.) Also useful in `mlr -n put -v '...'` for analyzing abstract syntax trees (if that's your thing).",
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.NoInput = true
*pargi += 1
return nil
},
},
{
name: "-I",
help: "Process files in-place. For each file name on the command line, output is written to a temp file in the same directory, which is then renamed over the original. Each file is processed in isolation: if the output format is CSV, CSV headers will be present in each output file, statistics are only over each file's own records; and so on.",
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.DoInPlace = true
*pargi += 1
return nil
},
},
{
name: "--from",
arg: "{filename}",
help: "Use this to specify an input file before the verb(s), rather than after. May be used more than once. Example: `mlr --from a.dat --from b.dat cat` is the same as `mlr cat a.dat b.dat`.",
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
if err := CheckArgCount(args, *pargi, argc, 2); err != nil {
return err
}
options.FileNames = append(options.FileNames, args[*pargi+1])
*pargi += 2
return nil
},
},
{
name: "--mfrom",
arg: "{filenames}",
help: "Use this to specify one of more input files before the verb(s), rather than after. May be used more than once. The list of filename must end with `--`. This is useful for example since `--from *.csv` doesn't do what you might hope but `--mfrom *.csv --` does.",
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
if err := CheckArgCount(args, *pargi, argc, 2); err != nil {
return err
}
*pargi += 1
for *pargi < argc && args[*pargi] != "--" {
options.FileNames = append(options.FileNames, args[*pargi])
*pargi += 1
}
if *pargi >= argc {
return FlagErrorf("mlr: \"--mfrom\" must be terminated by \"--\".")
}
if args[*pargi] == "--" {
*pargi += 1
}
return nil
},
},
{
name: "--files",
arg: "{filename}",
help: "Use this to specify a file which itself contains, one per line, names of input files. May be used more than once.",
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
if err := CheckArgCount(args, *pargi, argc, 2); err != nil {
return err
}
fileName := args[*pargi+1]
handle, err := os.Open(fileName)
if err != nil {
return err
}
defer func() { _ = handle.Close() }()
lineReader := bufio.NewReader(handle)
eof := false
lineno := 0
for !eof {
line, err := lineReader.ReadString('\n')
if err == io.EOF {
break
}
lineno++
if err != nil {
return err
}
// This is how to do a chomp:
// TODO: handle \r\n with libified solution.
line = strings.TrimRight(line, "\n")
options.FileNames = append(options.FileNames, line)
}
*pargi += 2
return nil
},
},
{
name: "--ofmt",
arg: "{format}",
help: "E.g. `%.18f`, `%.0f`, `%9.6e`. Please use sprintf-style codes (https://pkg.go.dev/fmt) for floating-point numbers. If not specified, default formatting is used. See also the `fmtnum` function and the `format-values` verb.",
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
if err := CheckArgCount(args, *pargi, argc, 2); err != nil {
return err
}
options.WriterOptions.FPOFMT = args[*pargi+1]
*pargi += 2
return nil
},
},
{
name: "--ofmte",
arg: "{n}",
help: "Use --ofmte 6 as shorthand for --ofmt %.6e, etc.",
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
if err := CheckArgCount(args, *pargi, argc, 2); err != nil {
return err
}
options.WriterOptions.FPOFMT = "%." + args[*pargi+1] + "e"
*pargi += 2
return nil
},
},
{
name: "--ofmtf",
arg: "{n}",
help: "Use --ofmtf 6 as shorthand for --ofmt %.6f, etc.",
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
if err := CheckArgCount(args, *pargi, argc, 2); err != nil {
return err
}
options.WriterOptions.FPOFMT = "%." + args[*pargi+1] + "f"
*pargi += 2
return nil
},
},
{
name: "--ofmtg",
arg: "{n}",
help: "Use --ofmtg 6 as shorthand for --ofmt %.6g, etc.",
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
if err := CheckArgCount(args, *pargi, argc, 2); err != nil {
return err
}
options.WriterOptions.FPOFMT = "%." + args[*pargi+1] + "g"
*pargi += 2
return nil
},
},
{
name: "--load",
arg: "{filename}",
help: "Load DSL script file for all put/filter operations on the command line. If the name following `--load` is a directory, load all `*.mlr` files in that directory. This is just like `put -f` and `filter -f` except it's up-front on the command line, so you can do something like `alias mlr='mlr --load ~/myscripts'` if you like.",
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
if err := CheckArgCount(args, *pargi, argc, 2); err != nil {
return err
}
options.DSLPreloadFileNames = append(options.DSLPreloadFileNames, args[*pargi+1])
*pargi += 2
return nil
},
},
{
name: "--mload",
arg: "{filenames}",
help: "Like `--load` but works with more than one filename, e.g. `--mload *.mlr --`.",
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
if err := CheckArgCount(args, *pargi, argc, 2); err != nil {
return err
}
*pargi += 1
for *pargi < argc && args[*pargi] != "--" {
options.DSLPreloadFileNames = append(options.DSLPreloadFileNames, args[*pargi])
*pargi += 1
}
if args[*pargi] == "--" {
*pargi += 1
}
return nil
},
},
{
name: "--tz",
arg: "{timezone}",
help: "Specify timezone, overriding `$TZ` environment variable (if any).",
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
if err := CheckArgCount(args, *pargi, argc, 2); err != nil {
return err
}
_ = os.Setenv("TZ", args[*pargi+1])
*pargi += 2
return nil
},
},
{
name: "--nr-progress-mod",
arg: "{m}",
help: "With m a positive integer: print filename and record count to os.Stderr every m input records.",
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
if err := CheckArgCount(args, *pargi, argc, 2); err != nil {
return err
}
nrProgressMod, ok := lib.TryIntFromString(args[*pargi+1])
if !ok || nrProgressMod <= 0 {
return FlagErrorf(
"%s: --nr-progress-mod argument must be a positive integer; got \"%s\".",
"mlr", args[*pargi+1])
}
options.NRProgressMod = nrProgressMod
*pargi += 2
return nil
},
},
{
name: "--seed",
arg: "{n}",
help: "with `n` of the form `12345678` or `0xcafefeed`. For `put`/`filter` `urand`, `urandint`, and `urand32`.",
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
if err := CheckArgCount(args, *pargi, argc, 2); err != nil {
return err
}
randSeed, ok := lib.TryIntFromString(args[*pargi+1])
if ok {
options.RandSeed = randSeed
options.HaveRandSeed = true
} else {
return FlagErrorf(
"mlr: --seed argument must be a decimal or hexadecimal integer; got \"%s\".\nPlease run \"mlr --help\" for detailed usage information.",
args[*pargi+1])
}
*pargi += 2
return nil
},
},
{
name: "--no-dedupe-field-names",
help: `By default, if an input record has a field named ` + "`x`" + ` and
another also named ` + "`x`" + `, the second will be renamed ` + "`x_2`" + `, and so on. With this flag provided, the
second ` + "`x`" + `'s value will replace the first ` + "`x`" + `'s value when the record is read. This flag has no effect
on JSON input records, where duplicate keys always result in the last one's value being retained.`,
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.ReaderOptions.DedupeFieldNames = false
*pargi += 1
return nil
},
},
{
name: "--records-per-batch",
arg: "{n}",
help: "This is an internal parameter for maximum number of records in a batch size. Normally this does not\n" +
"need to be modified, except when input is from `tail -f`. See also\n" +
"https://miller.readthedocs.io/en/latest/reference-main-flag-list/.",
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
if err := CheckArgCount(args, *pargi, argc, 2); err != nil {
return err
}
recordsPerBatch, ok := lib.TryIntFromString(args[*pargi+1])
if !ok || recordsPerBatch <= 0 {
return FlagErrorf(
"%s: --records-per-batch argument must be a positive integer; got \"%s\".",
"mlr", args[*pargi+1])
}
options.ReaderOptions.RecordsPerBatch = recordsPerBatch
*pargi += 2
return nil
},
},
{
name: "--hash-records",
help: `This is an internal parameter which normally does not need to be modified.
It controls the mechanism by which Miller accesses fields within records.
In general --no-hash-records is faster, and is the default. For specific use-cases involving
data having many fields, and many of them being processed during a given processing run,
--hash-records might offer a slight performance benefit.`,
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
mlrval.HashRecords(true)
*pargi += 1
return nil
},
},
{
name: "--no-hash-records",
help: `See --hash-records.`,
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
mlrval.HashRecords(false)
*pargi += 1
return nil
},
},
{
name: "--infer-none",
altNames: []string{"-S"},
help: `Don't treat values like 123 or 456.7 in data files as int/float; leave them as strings.`,
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
mlrval.SetInferrerStringOnly()
*pargi += 1
return nil
},
},
{
name: "--infer-int-as-float",
altNames: []string{"-A"},
help: `Cast all integers in data files to floats.`,
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
mlrval.SetInferrerIntAsFloat()
*pargi += 1
return nil
},
},
{
name: "--infer-octal",
altNames: []string{"-O"},
help: `Treat numbers like 0123 in data files as numeric; default is string.
Note that 00--07 etc scan as int; 08-09 scan as float.`,
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
mlrval.SetInferrerOctalAsInt()
*pargi += 1
return nil
},
},
{
name: "--fflush",
help: `Force buffered output to be written after every output record.
The default is flush output after every record if the output is to the terminal, or less often if
the output is to a file or a pipe. The default is a significant performance optimization for large
files. Use this flag to force frequent updates even when output is to a pipe or file, at a
performance cost.`,
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.WriterOptions.FlushOnEveryRecord = true
options.WriterOptions.flushOnEveryRecordWasSpecified = true
*pargi += 1
return nil
},
},
{
name: "--no-fflush",
help: `Let buffered output not be written after every output record.
The default is flush output after every record if the output is to the terminal, or less often if
the output is to a file or a pipe. The default is a significant performance optimization for large
files. Use this flag to allow less-frequent updates when output is to the terminal. This is
unlikely to be a noticeable performance improvement, since direct-to-screen output for large files
has its own overhead.`,
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
options.WriterOptions.FlushOnEveryRecord = false
options.WriterOptions.flushOnEveryRecordWasSpecified = true
*pargi += 1
return nil
},
},
{
name: "-s",
arg: "{file name}",
help: `Take command-line flags from file name. For more information please see ` +
lib.DOC_URL + `/en/latest/scripting/.`,
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
// Already handled in main(). Nothing to do here except to accept this as valid syntax.
*pargi += 2
return nil
},
},
{
name: "--s-no-comment-strip",
arg: "{file name}",
help: `Take command-line flags from file name, like -s, but with no comment-stripping. For more information please see ` +
lib.DOC_URL + `/en/latest/scripting/.`,
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
// Already handled in main(). Nothing to do here except to accept this as valid syntax.
*pargi += 2
return nil
},
},
{
name: "--norc",
help: "Do not load a .mlrrc file.",
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
*pargi += 1
return nil
},
},
{
name: "--profile",
altNames: []string{"-P"},
arg: "{name}",
help: `Apply the settings from the [name] section of your .mlrrc file, after any global
(pre-section) settings. It's an error if no such section exists in any .mlrrc file processed.
For more information please see ` + lib.DOC_URL + `/en/latest/customization/.`,
parser: func(args []string, argc int, pargi *int, options *TOptions) error {
if err := CheckArgCount(args, *pargi, argc, 2); err != nil {
return err
}
// The actual profile selection is handled in pkg/climain,
// before the .mlrrc file is loaded, which is in turn before
// main-flag sequences are parsed into the options struct.
// Registration here ensures the flag is recognized (not an
// error) during flag parsing, and appears in --help.
*pargi += 2
return nil
},
},
},
}