Improve error propagation (#1975)

This commit is contained in:
John Kerl 2026-02-16 16:48:41 -05:00 committed by GitHub
parent 1e762d7c4c
commit e1346691da
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
71 changed files with 1252 additions and 911 deletions

13
pkg/cli/errors.go Normal file
View file

@ -0,0 +1,13 @@
package cli
import "errors"
// ErrHelpRequested is returned by verb ParseCLIFunc when -h or --help is used.
// The caller (CLI layer) should exit with code 0 after the verb has printed its
// usage to stdout.
var ErrHelpRequested = errors.New("help requested")
// ErrUsagePrinted is returned by verb ParseCLIFunc when validation fails. The
// verb has already printed its usage to stderr. The caller should exit 1
// without printing the error again.
var ErrUsagePrinted = errors.New("usage printed")

View file

@ -1,70 +1,83 @@
// Utilities for Miller verbs to share for command-line parsing.
// These return error instead of os.Exit, so callers (e.g. transformer ParseCLIFunc)
// can propagate errors to the CLI entrypoint layer.
package cli
import (
"fmt"
"os"
"strconv"
"github.com/johnkerl/miller/v6/pkg/lib"
)
// For flags with values, e.g. ["-n" "10"], while we're looking at the "-n" this let us see if the "10" slot exists.
// The verb is nominally something from a ways earlier in args[]; the opt is nominally what's at args[argi-1].
// So this function should be called with args[argi] pointing to the "10" slot.
func VerbCheckArgCount(verb string, opt string, args []string, argi int, argc int, n int) {
// VerbCheckArgCount returns an error if there aren't enough args remaining.
// For flags with values, e.g. ["-n" "10"], while we're looking at the "-n"
// this lets us see if the "10" slot exists. The verb is nominally something
// from a ways earlier in args[]; the opt is nominally what's at args[argi-1].
// This function should be called with args[argi] pointing to the "10" slot.
func VerbCheckArgCount(verb string, opt string, args []string, argi int, argc int, n int) error {
if (argc - argi) < n {
fmt.Fprintf(os.Stderr, "%s %s: option \"%s\" missing argument(s).\n",
"mlr", verb, opt,
)
os.Exit(1)
return fmt.Errorf("%s %s: option \"%s\" missing argument(s)", "mlr", verb, opt)
}
return nil
}
// E.g. with ["-f", "a,b,c"], makes sure there is something in the "a,b,c" position, and returns it.
func VerbGetStringArgOrDie(verb string, opt string, args []string, pargi *int, argc int) string {
VerbCheckArgCount(verb, opt, args, *pargi, argc, 1)
// VerbGetStringArg ensures there is something in the value position and returns it.
// E.g. with ["-f", "a,b,c"], returns "a,b,c".
func VerbGetStringArg(verb string, opt string, args []string, pargi *int, argc int) (string, error) {
if err := VerbCheckArgCount(verb, opt, args, *pargi, argc, 1); err != nil {
return "", err
}
retval := args[*pargi]
*pargi += 1
return retval
return retval, nil
}
// E.g. with ["-f", "a,b,c"], makes sure there is something in the "a,b,c" position,
// splits it on commas, and returns it.
func VerbGetStringArrayArgOrDie(verb string, opt string, args []string, pargi *int, argc int) []string {
stringArg := VerbGetStringArgOrDie(verb, opt, args, pargi, argc)
return lib.SplitString(stringArg, ",")
// VerbGetStringArrayArg ensures there is something in the value position,
// splits it on commas, and returns it. E.g. with ["-f", "a,b,c"], returns ["a","b","c"].
func VerbGetStringArrayArg(verb string, opt string, args []string, pargi *int, argc int) ([]string, error) {
stringArg, err := VerbGetStringArg(verb, opt, args, pargi, argc)
if err != nil {
return nil, err
}
return lib.SplitString(stringArg, ","), nil
}
// E.g. with ["-n", "10"], makes sure there is something in the "10" position,
// scans it as int, and returns it.
func VerbGetIntArgOrDie(verb string, opt string, args []string, pargi *int, argc int) int64 {
// VerbErrorf returns an error prefixed with "mlr {verb}: " so the entrypoint
// can print it without double-prefixing.
func VerbErrorf(verb, format string, args ...interface{}) error {
return fmt.Errorf("mlr "+verb+": "+format, args...)
}
// VerbGetIntArg ensures there is something in the value position and parses it as int64.
// E.g. with ["-n", "10"], returns 10.
func VerbGetIntArg(verb string, opt string, args []string, pargi *int, argc int) (int64, error) {
flag := args[*pargi]
stringArg := VerbGetStringArgOrDie(verb, opt, args, pargi, argc)
stringArg, err := VerbGetStringArg(verb, opt, args, pargi, argc)
if err != nil {
return 0, err
}
retval, err := strconv.ParseInt(stringArg, 10, 64)
if err != nil {
fmt.Fprintf(os.Stderr,
"%s %s: could not scan flag \"%s\" argument \"%s\" as int.\n",
"mlr", verb, flag, stringArg,
)
os.Exit(1)
return 0, fmt.Errorf("%s %s: could not scan flag \"%s\" argument \"%s\" as int",
"mlr", verb, flag, stringArg)
}
return retval
return retval, nil
}
// E.g. with ["-n", "10.3"], makes sure there is something in the "10.3"
// position, scans it as float, and returns it.
func VerbGetFloatArgOrDie(verb string, opt string, args []string, pargi *int, argc int) float64 {
// VerbGetFloatArg ensures there is something in the value position and parses it as float64.
// E.g. with ["-n", "10.3"], returns 10.3.
func VerbGetFloatArg(verb string, opt string, args []string, pargi *int, argc int) (float64, error) {
flag := args[*pargi]
stringArg := VerbGetStringArgOrDie(verb, opt, args, pargi, argc)
stringArg, err := VerbGetStringArg(verb, opt, args, pargi, argc)
if err != nil {
return 0, err
}
retval, err := strconv.ParseFloat(stringArg, 64)
if err != nil {
fmt.Fprintf(os.Stderr,
"%s %s: could not scan flag \"%s\" argument \"%s\" as float.\n",
"mlr", verb, flag, stringArg,
)
os.Exit(1)
return 0, fmt.Errorf("%s %s: could not scan flag \"%s\" argument \"%s\" as float",
"mlr", verb, flag, stringArg)
}
return retval
return retval, nil
}

View file

@ -69,6 +69,7 @@
package climain
import (
"errors"
"fmt"
"os"
@ -205,16 +206,24 @@ func parseCommandLinePassOne(
os.Exit(1)
}
// It's up to the parse func to print its usage, and exit 1, on
// CLI-parse failure. Also note: this assumes main reader/writer opts
// are all parsed *before* transformer parse-CLI methods are invoked.
transformer := transformerSetup.ParseCLIFunc(
// ParseCLIFunc returns (nil, nil) on pass-one success, (nil, err) on failure.
transformer, err := transformerSetup.ParseCLIFunc(
&argi,
argc,
args,
options,
false, // false for first pass of CLI-parse, true for second pass -- this is the first pass
)
if err != nil {
if errors.Is(err, cli.ErrHelpRequested) {
os.Exit(0)
}
if errors.Is(err, cli.ErrUsagePrinted) {
os.Exit(1)
}
fmt.Fprintf(os.Stderr, "mlr: %v\n", err)
os.Exit(1)
}
// For pass one we want the verbs to identify the arg-sequences
// they own within the command line, but not construct
// transformers.
@ -348,15 +357,22 @@ func parseCommandLinePassTwo(
transformerSetup := transformers.LookUp(args[0])
lib.InternalCodingErrorIf(transformerSetup == nil)
// It's up to the parse func to print its usage, and exit 1, on
// CLI-parse failure.
transformer := transformerSetup.ParseCLIFunc(
transformer, err := transformerSetup.ParseCLIFunc(
&argi,
argc,
args,
options,
true, // false for first pass of CLI-parse, true for second pass -- this is the first pass
true, // false for first pass of CLI-parse, true for second pass -- this is pass two
)
if err != nil {
if errors.Is(err, cli.ErrHelpRequested) {
os.Exit(0)
}
if errors.Is(err, cli.ErrUsagePrinted) {
os.Exit(1)
}
return nil, nil, err
}
// Unparsable verb-setups should have been found in pass one.
lib.InternalCodingErrorIf(transformer == nil)
// Make sure we consumed the entire verb sequence as parsed by pass one.

View file

@ -7,6 +7,7 @@ import (
"fmt"
"os"
"path"
"strings"
"github.com/johnkerl/miller/v6/pkg/auxents"
"github.com/johnkerl/miller/v6/pkg/cli"
@ -41,7 +42,7 @@ func Main() MainReturn {
options, recordTransformers, err := climain.ParseCommandLine(os.Args)
if err != nil {
fmt.Fprintf(os.Stderr, "mlr: %v\n", err)
printError(err)
os.Exit(1)
}
@ -51,7 +52,7 @@ func Main() MainReturn {
err = processFilesInPlace(options)
}
if err != nil {
fmt.Fprintf(os.Stderr, "mlr: %v\n", err)
printError(err)
os.Exit(1)
}
@ -60,6 +61,16 @@ func Main() MainReturn {
}
}
// printError prints err to stderr. Errors that already start with "mlr " (e.g.
// "mlr stats1: ...") are printed as-is to avoid double-prefixing.
func printError(err error) {
if strings.HasPrefix(err.Error(), "mlr ") {
fmt.Fprintf(os.Stderr, "%v\n", err)
} else {
fmt.Fprintf(os.Stderr, "mlr: %v\n", err)
}
}
// processToStdout is normal processing without mlr -I.
func processToStdout(

View file

@ -7,8 +7,10 @@ import (
"runtime"
)
// InternalCodingErrorIf is a lookalike for C's __FILE__ and __LINE__ printing,
// with exit 1 if the condition is true.
// InternalCodingErrorIf reports an internal bug and exits. Use only for
// "should never happen" conditions (assertions), not for user or I/O errors.
// This is intentionally an exit helper: these indicate programmer error,
// and the codebase prefers returning error for recoverable failures.
func InternalCodingErrorIf(condition bool) {
if !condition {
return

View file

@ -36,13 +36,18 @@ type TransformerUsageFunc func(
ostream *os.File,
)
// TransformerParseCLIFunc parses verb options from the CLI. Returns (nil, nil) on
// success for pass one (doConstruct=false). Returns (transformer, nil) on success
// for pass two (doConstruct=true). Returns (nil, cli.ErrHelpRequested) when -h/--help
// was used (caller should exit 0; usage already printed). Returns (nil, err) on
// parse or constructor failure (caller should print and exit 1).
type TransformerParseCLIFunc func(
pargi *int,
argc int,
args []string,
mainOptions *cli.TOptions,
doConstruct bool, // false for first pass of CLI-parse, true for second pass
) RecordTransformer
) (RecordTransformer, error)
type TransformerSetup struct {
Verb string

View file

@ -35,7 +35,7 @@ func transformerAltkvParseCLI(
args []string,
_ *cli.TOptions,
doConstruct bool, // false for first pass of CLI-parse, true for second pass
) RecordTransformer {
) (RecordTransformer, error) {
// Skip the verb name from the current spot in the mlr command line
argi := *pargi
@ -53,25 +53,23 @@ func transformerAltkvParseCLI(
if opt == "-h" || opt == "--help" {
transformerAltkvUsage(os.Stdout)
os.Exit(0)
return nil, cli.ErrHelpRequested
}
transformerAltkvUsage(os.Stderr)
os.Exit(1)
return nil, fmt.Errorf("%s %s: option \"%s\" not recognized", "mlr", verbNameAltkv, opt)
}
*pargi = argi
if !doConstruct { // All transformers must do this for main command-line parsing
return nil
return nil, nil
}
transformer, err := NewTransformerAltkv()
if err != nil {
fmt.Fprintf(os.Stderr, "mlr: %v\n", err)
os.Exit(1)
return nil, err
}
return transformer
return transformer, nil
}
type TransformerAltkv struct {

View file

@ -54,7 +54,7 @@ func transformerBarParseCLI(
args []string,
_ *cli.TOptions,
doConstruct bool, // false for first pass of CLI-parse, true for second pass
) RecordTransformer {
) (RecordTransformer, error) {
// Skip the verb name from the current spot in the mlr command line
argi := *pargi
@ -62,6 +62,7 @@ func transformerBarParseCLI(
argi++
// Parse local flags
var err error
var fieldNames []string = nil
lo := barDefaultLo
hi := barDefaultHi
@ -83,42 +84,61 @@ func transformerBarParseCLI(
if opt == "-h" || opt == "--help" {
transformerBarUsage(os.Stdout)
os.Exit(0)
return nil, cli.ErrHelpRequested
} else if opt == "-f" {
fieldNames = cli.VerbGetStringArrayArgOrDie(verb, opt, args, &argi, argc)
fieldNames, err = cli.VerbGetStringArrayArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
} else if opt == "--lo" {
lo = cli.VerbGetFloatArgOrDie(verb, opt, args, &argi, argc)
lo, err = cli.VerbGetFloatArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
} else if opt == "-w" {
width = cli.VerbGetIntArgOrDie(verb, opt, args, &argi, argc)
width, err = cli.VerbGetIntArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
} else if opt == "--hi" {
hi = cli.VerbGetFloatArgOrDie(verb, opt, args, &argi, argc)
hi, err = cli.VerbGetFloatArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
} else if opt == "-c" {
fillString = cli.VerbGetStringArgOrDie(verb, opt, args, &argi, argc)
fillString, err = cli.VerbGetStringArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
} else if opt == "-x" {
oobString = cli.VerbGetStringArgOrDie(verb, opt, args, &argi, argc)
oobString, err = cli.VerbGetStringArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
} else if opt == "-b" {
blankString = cli.VerbGetStringArgOrDie(verb, opt, args, &argi, argc)
blankString, err = cli.VerbGetStringArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
} else if opt == "--auto" {
doAuto = true
} else {
transformerBarUsage(os.Stderr)
os.Exit(1)
return nil, cli.VerbErrorf(verb, "option \"%s\" not recognized", opt)
}
}
if fieldNames == nil {
transformerBarUsage(os.Stderr)
os.Exit(1)
return nil, cli.VerbErrorf(verb, "-f field names required")
}
*pargi = argi
if !doConstruct { // All transformers must do this for main command-line parsing
return nil
return nil, nil
}
transformer, err := NewTransformerBar(
@ -132,11 +152,10 @@ func transformerBarParseCLI(
blankString,
)
if err != nil {
fmt.Fprintf(os.Stderr, "mlr: %v\n", err)
os.Exit(1)
return nil, err
}
return transformer
return transformer, nil
}
type TransformerBar struct {

View file

@ -41,13 +41,14 @@ func transformerBootstrapParseCLI(
args []string,
_ *cli.TOptions,
doConstruct bool, // false for first pass of CLI-parse, true for second pass
) RecordTransformer {
) (RecordTransformer, error) {
// Skip the verb name from the current spot in the mlr command line
argi := *pargi
verb := args[argi]
argi++
var err error
nout := int64(-1)
for argi < argc /* variable increment: 1 or 2 depending on flag */ {
@ -62,29 +63,30 @@ func transformerBootstrapParseCLI(
if opt == "-h" || opt == "--help" {
transformerBootstrapUsage(os.Stdout)
os.Exit(0)
return nil, cli.ErrHelpRequested
} else if opt == "-n" {
nout = cli.VerbGetIntArgOrDie(verb, opt, args, &argi, argc)
nout, err = cli.VerbGetIntArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
} else {
transformerBootstrapUsage(os.Stderr)
os.Exit(1)
return nil, cli.VerbErrorf(verb, "option \"%s\" not recognized", opt)
}
}
*pargi = argi
if !doConstruct { // All transformers must do this for main command-line parsing
return nil
return nil, nil
}
transformer, err := NewTransformerBootstrap(nout)
if err != nil {
fmt.Fprintf(os.Stderr, "mlr: %v\n", err)
os.Exit(1)
return nil, err
}
return transformer
return transformer, nil
}
type TransformerBootstrap struct {

View file

@ -53,13 +53,14 @@ func transformerCaseParseCLI(
args []string,
_ *cli.TOptions,
doConstruct bool, // false for first pass of CLI-parse, true for second pass
) RecordTransformer {
) (RecordTransformer, error) {
// Skip the verb name from the current spot in the mlr command line
argi := *pargi
verb := args[argi]
argi++
var err error
which := "keys_and_values"
style := e_UNSPECIFIED_CASE
var fieldNames []string = nil
@ -76,7 +77,7 @@ func transformerCaseParseCLI(
if opt == "-h" || opt == "--help" {
transformerCaseUsage(os.Stdout)
os.Exit(0)
return nil, cli.ErrHelpRequested
} else if opt == "-k" {
which = "keys_only"
@ -85,7 +86,10 @@ func transformerCaseParseCLI(
which = "values_only"
} else if opt == "-f" {
fieldNames = cli.VerbGetStringArrayArgOrDie(verb, opt, args, &argi, argc)
fieldNames, err = cli.VerbGetStringArrayArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
} else if opt == "-u" {
style = e_UPPER_CASE
@ -97,23 +101,21 @@ func transformerCaseParseCLI(
style = e_TITLE_CASE
} else {
transformerCaseUsage(os.Stderr)
os.Exit(1)
return nil, cli.VerbErrorf(verb, "option \"%s\" not recognized", opt)
}
}
*pargi = argi
if !doConstruct { // All transformers must do this for main command-line parsing
return nil
return nil, nil
}
transformer, err := NewTransformerCase(which, fieldNames, style)
if err != nil {
fmt.Fprintf(os.Stderr, "mlr: %v\n", err)
os.Exit(1)
return nil, err
}
return transformer
return transformer, nil
}
type caserFuncT func(input string) string

View file

@ -39,13 +39,14 @@ func transformerCatParseCLI(
args []string,
_ *cli.TOptions,
doConstruct bool, // false for first pass of CLI-parse, true for second pass
) RecordTransformer {
) (RecordTransformer, error) {
// Skip the verb name from the current spot in the mlr command line
argi := *pargi
verb := args[argi]
argi++
var err error
// Parse local flags
doCounters := false
counterFieldName := ""
@ -65,16 +66,22 @@ func transformerCatParseCLI(
if opt == "-h" || opt == "--help" {
transformerCatUsage(os.Stdout)
os.Exit(0)
return nil, cli.ErrHelpRequested
} else if opt == "-n" {
counterFieldName = "n"
} else if opt == "-N" {
counterFieldName = cli.VerbGetStringArgOrDie(verb, opt, args, &argi, argc)
counterFieldName, err = cli.VerbGetStringArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
} else if opt == "-g" {
groupByFieldNames = cli.VerbGetStringArrayArgOrDie(verb, opt, args, &argi, argc)
groupByFieldNames, err = cli.VerbGetStringArrayArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
} else if opt == "--filename" {
doFileName = true
@ -83,14 +90,13 @@ func transformerCatParseCLI(
doFileNum = true
} else {
transformerCatUsage(os.Stderr)
os.Exit(1)
return nil, cli.VerbErrorf(verb, "option \"%s\" not recognized", opt)
}
}
*pargi = argi
if !doConstruct { // All transformers must do this for main command-line parsing
return nil
return nil, nil
}
transformer, err := NewTransformerCat(
@ -101,11 +107,10 @@ func transformerCatParseCLI(
doFileNum,
)
if err != nil {
fmt.Fprintf(os.Stderr, "mlr: %v\n", err)
os.Exit(1)
return nil, err
}
return transformer
return transformer, nil
}
type TransformerCat struct {

View file

@ -38,7 +38,7 @@ func transformerCheckParseCLI(
args []string,
_ *cli.TOptions,
doConstruct bool, // false for first pass of CLI-parse, true for second pass
) RecordTransformer {
) (RecordTransformer, error) {
// Skip the verb name from the current spot in the mlr command line
argi := *pargi
@ -56,25 +56,23 @@ func transformerCheckParseCLI(
if opt == "-h" || opt == "--help" {
transformerCheckUsage(os.Stdout)
os.Exit(0)
return nil, cli.ErrHelpRequested
}
transformerCheckUsage(os.Stderr)
os.Exit(1)
return nil, cli.VerbErrorf(verbNameCheck, "option \"%s\" not recognized", opt)
}
*pargi = argi
if !doConstruct { // All transformers must do this for main command-line parsing
return nil
return nil, nil
}
transformer, err := NewTransformerCheck()
if err != nil {
fmt.Fprintf(os.Stderr, "mlr: %v\n", err)
os.Exit(1)
return nil, err
}
return transformer
return transformer, nil
}
type TransformerCheck struct {

View file

@ -44,7 +44,7 @@ func transformerCleanWhitespaceParseCLI(
args []string,
_ *cli.TOptions,
doConstruct bool, // false for first pass of CLI-parse, true for second pass
) RecordTransformer {
) (RecordTransformer, error) {
doKeys := true
doValues := true
@ -65,7 +65,7 @@ func transformerCleanWhitespaceParseCLI(
if opt == "-h" || opt == "--help" {
transformerCleanWhitespaceUsage(os.Stdout)
os.Exit(0)
return nil, cli.ErrHelpRequested
} else if opt == "-k" || opt == "--keys-only" {
doKeys = true
@ -75,19 +75,17 @@ func transformerCleanWhitespaceParseCLI(
doValues = true
} else {
transformerCleanWhitespaceUsage(os.Stderr)
os.Exit(1)
return nil, cli.VerbErrorf(verbNameCleanWhitespace, "option \"%s\" not recognized", opt)
}
}
if !doKeys && !doValues {
transformerCleanWhitespaceUsage(os.Stderr)
os.Exit(1)
return nil, cli.VerbErrorf(verbNameCleanWhitespace, "-k or -v is required")
}
*pargi = argi
if !doConstruct { // All transformers must do this for main command-line parsing
return nil
return nil, nil
}
transformer, err := NewTransformerCleanWhitespace(
@ -95,11 +93,10 @@ func transformerCleanWhitespaceParseCLI(
doValues,
)
if err != nil {
fmt.Fprintf(os.Stderr, "mlr: %v\n", err)
os.Exit(1)
return nil, err
}
return transformer
return transformer, nil
}
type TransformerCleanWhitespace struct {

View file

@ -40,7 +40,7 @@ func transformerCountParseCLI(
args []string,
_ *cli.TOptions,
doConstruct bool, // false for first pass of CLI-parse, true for second pass
) RecordTransformer {
) (RecordTransformer, error) {
// Skip the verb name from the current spot in the mlr command line
argi := *pargi
@ -51,6 +51,7 @@ func transformerCountParseCLI(
showCountsOnly := false
outputFieldName := "count"
var err error
for argi < argc /* variable increment: 1 or 2 depending on flag */ {
opt := args[argi]
if !strings.HasPrefix(opt, "-") {
@ -63,26 +64,31 @@ func transformerCountParseCLI(
if opt == "-h" || opt == "--help" {
transformerCountUsage(os.Stdout)
os.Exit(0)
return nil, cli.ErrHelpRequested
} else if opt == "-g" {
groupByFieldNames = cli.VerbGetStringArrayArgOrDie(verb, opt, args, &argi, argc)
groupByFieldNames, err = cli.VerbGetStringArrayArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
} else if opt == "-n" {
showCountsOnly = true
} else if opt == "-o" {
outputFieldName = cli.VerbGetStringArgOrDie(verb, opt, args, &argi, argc)
outputFieldName, err = cli.VerbGetStringArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
} else {
transformerCountUsage(os.Stderr)
os.Exit(1)
return nil, cli.VerbErrorf(verb, "option \"%s\" not recognized", opt)
}
}
*pargi = argi
if !doConstruct { // All transformers must do this for main command-line parsing
return nil
return nil, nil
}
transformer, err := NewTransformerCount(
@ -91,11 +97,10 @@ func transformerCountParseCLI(
outputFieldName,
)
if err != nil {
fmt.Fprintf(os.Stderr, "mlr: %v\n", err)
os.Exit(1)
return nil, err
}
return transformer
return transformer, nil
}
type TransformerCount struct {

View file

@ -38,7 +38,7 @@ func transformerCountSimilarParseCLI(
args []string,
_ *cli.TOptions,
doConstruct bool, // false for first pass of CLI-parse, true for second pass
) RecordTransformer {
) (RecordTransformer, error) {
// Skip the verb name from the current spot in the mlr command line
argi := *pargi
@ -48,6 +48,7 @@ func transformerCountSimilarParseCLI(
var groupByFieldNames []string = nil
counterFieldName := "count"
var err error
for argi < argc /* variable increment: 1 or 2 depending on flag */ {
opt := args[argi]
if !strings.HasPrefix(opt, "-") {
@ -60,28 +61,32 @@ func transformerCountSimilarParseCLI(
if opt == "-h" || opt == "--help" {
transformerCountSimilarUsage(os.Stdout)
os.Exit(0)
return nil, cli.ErrHelpRequested
} else if opt == "-g" {
groupByFieldNames = cli.VerbGetStringArrayArgOrDie(verb, opt, args, &argi, argc)
groupByFieldNames, err = cli.VerbGetStringArrayArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
} else if opt == "-o" {
counterFieldName = cli.VerbGetStringArgOrDie(verb, opt, args, &argi, argc)
counterFieldName, err = cli.VerbGetStringArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
} else {
transformerCountSimilarUsage(os.Stderr)
os.Exit(1)
return nil, cli.VerbErrorf(verb, "option \"%s\" not recognized", opt)
}
}
if groupByFieldNames == nil {
transformerCountSimilarUsage(os.Stderr)
os.Exit(1)
return nil, cli.VerbErrorf(verb, "-g field names required")
}
*pargi = argi
if !doConstruct { // All transformers must do this for main command-line parsing
return nil
return nil, nil
}
transformer, err := NewTransformerCountSimilar(
@ -89,11 +94,10 @@ func transformerCountSimilarParseCLI(
counterFieldName,
)
if err != nil {
fmt.Fprintf(os.Stderr, "mlr: %v\n", err)
os.Exit(1)
return nil, err
}
return transformer
return transformer, nil
}
type TransformerCountSimilar struct {

View file

@ -52,13 +52,14 @@ func transformerCutParseCLI(
args []string,
_ *cli.TOptions,
doConstruct bool, // false for first pass of CLI-parse, true for second pass
) RecordTransformer {
) (RecordTransformer, error) {
// Skip the verb name from the current spot in the mlr command line
argi := *pargi
verb := args[argi]
argi++
var err error
var fieldNames []string = nil
doArgOrder := false
doComplement := false
@ -76,10 +77,13 @@ func transformerCutParseCLI(
if opt == "-h" || opt == "--help" {
transformerCutUsage(os.Stdout)
os.Exit(0)
return nil, cli.ErrHelpRequested
} else if opt == "-f" {
fieldNames = cli.VerbGetStringArrayArgOrDie(verb, opt, args, &argi, argc)
fieldNames, err = cli.VerbGetStringArrayArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
} else if opt == "-o" {
doArgOrder = true
@ -94,19 +98,17 @@ func transformerCutParseCLI(
doRegexes = true
} else {
transformerCutUsage(os.Stderr)
os.Exit(1)
return nil, cli.VerbErrorf(verb, "option \"%s\" not recognized", opt)
}
}
if fieldNames == nil {
transformerCutUsage(os.Stderr)
os.Exit(1)
return nil, cli.VerbErrorf(verb, "-f field names required")
}
*pargi = argi
if !doConstruct { // All transformers must do this for main command-line parsing
return nil
return nil, nil
}
transformer, err := NewTransformerCut(
@ -116,11 +118,10 @@ func transformerCutParseCLI(
doRegexes,
)
if err != nil {
fmt.Fprintf(os.Stderr, "mlr: %v\n", err)
os.Exit(1)
return nil, err
}
return transformer
return transformer, nil
}
type TransformerCut struct {

View file

@ -37,13 +37,14 @@ func transformerDecimateParseCLI(
args []string,
_ *cli.TOptions,
doConstruct bool, // false for first pass of CLI-parse, true for second pass
) RecordTransformer {
) (RecordTransformer, error) {
// Skip the verb name from the current spot in the mlr command line
argi := *pargi
verb := args[argi]
argi++
var err error
decimateCount := int64(10)
atStart := false
atEnd := false
@ -61,13 +62,15 @@ func transformerDecimateParseCLI(
if opt == "-h" || opt == "--help" {
transformerDecimateUsage(os.Stdout)
os.Exit(0)
return nil, cli.ErrHelpRequested
} else if opt == "-n" {
decimateCount = cli.VerbGetIntArgOrDie(verb, opt, args, &argi, argc)
decimateCount, err = cli.VerbGetIntArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
if decimateCount <= 0 {
transformerDecimateUsage(os.Stderr)
os.Exit(1)
return nil, cli.VerbErrorf(verb, "-n must be positive")
}
} else if opt == "-b" {
@ -77,17 +80,19 @@ func transformerDecimateParseCLI(
atEnd = true
} else if opt == "-g" {
groupByFieldNames = cli.VerbGetStringArrayArgOrDie(verb, opt, args, &argi, argc)
groupByFieldNames, err = cli.VerbGetStringArrayArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
} else {
transformerDecimateUsage(os.Stderr)
os.Exit(1)
return nil, cli.VerbErrorf(verb, "option \"%s\" not recognized", opt)
}
}
*pargi = argi
if !doConstruct { // All transformers must do this for main command-line parsing
return nil
return nil, nil
}
transformer, err := NewTransformerDecimate(
@ -97,11 +102,10 @@ func transformerDecimateParseCLI(
groupByFieldNames,
)
if err != nil {
fmt.Fprintf(os.Stderr, "mlr: %v\n", err)
os.Exit(1)
return nil, err
}
return transformer
return transformer, nil
}
type TransformerDecimate struct {

View file

@ -44,7 +44,7 @@ func transformerFillDownParseCLI(
args []string,
_ *cli.TOptions,
doConstruct bool, // false for first pass of CLI-parse, true for second pass
) RecordTransformer {
) (RecordTransformer, error) {
// Skip the verb name from the current spot in the mlr command line
argi := *pargi
@ -55,6 +55,7 @@ func transformerFillDownParseCLI(
doAll := false
onlyIfAbsent := false
var err error
for argi < argc /* variable increment: 1 or 2 depending on flag */ {
opt := args[argi]
if !strings.HasPrefix(opt, "-") {
@ -67,10 +68,13 @@ func transformerFillDownParseCLI(
if opt == "-h" || opt == "--help" {
transformerFillDownUsage(os.Stdout)
os.Exit(0)
return nil, cli.ErrHelpRequested
} else if opt == "-f" {
fillDownFieldNames = cli.VerbGetStringArrayArgOrDie(verb, opt, args, &argi, argc)
fillDownFieldNames, err = cli.VerbGetStringArrayArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
} else if opt == "--all" {
doAll = true
@ -82,19 +86,17 @@ func transformerFillDownParseCLI(
onlyIfAbsent = true
} else {
transformerFillDownUsage(os.Stderr)
os.Exit(1)
return nil, cli.VerbErrorf(verb, "option \"%s\" not recognized", opt)
}
}
if fillDownFieldNames == nil && !doAll {
transformerFillDownUsage(os.Stderr)
os.Exit(1)
return nil, cli.VerbErrorf(verb, "-f field names or --all required")
}
*pargi = argi
if !doConstruct { // All transformers must do this for main command-line parsing
return nil
return nil, nil
}
transformer, err := NewTransformerFillDown(
@ -103,11 +105,10 @@ func transformerFillDownParseCLI(
onlyIfAbsent,
)
if err != nil {
fmt.Fprintf(os.Stderr, "mlr: %v\n", err)
os.Exit(1)
return nil, err
}
return transformer
return transformer, nil
}
type TransformerFillDown struct {

View file

@ -36,7 +36,7 @@ func transformerFillEmptyParseCLI(
args []string,
_ *cli.TOptions,
doConstruct bool, // false for first pass of CLI-parse, true for second pass
) RecordTransformer {
) (RecordTransformer, error) {
// Skip the verb name from the current spot in the mlr command line
argi := *pargi
@ -46,6 +46,7 @@ func transformerFillEmptyParseCLI(
fillString := defaultFillEmptyString
inferType := true
var err error
for argi < argc /* variable increment: 1 or 2 depending on flag */ {
opt := args[argi]
if !strings.HasPrefix(opt, "-") {
@ -58,32 +59,33 @@ func transformerFillEmptyParseCLI(
if opt == "-h" || opt == "--help" {
transformerFillEmptyUsage(os.Stdout)
os.Exit(0)
return nil, cli.ErrHelpRequested
} else if opt == "-v" {
fillString = cli.VerbGetStringArgOrDie(verb, opt, args, &argi, argc)
fillString, err = cli.VerbGetStringArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
} else if opt == "-S" {
inferType = false
} else {
transformerFillEmptyUsage(os.Stderr)
os.Exit(1)
return nil, cli.VerbErrorf(verb, "option \"%s\" not recognized", opt)
}
}
*pargi = argi
if !doConstruct { // All transformers must do this for main command-line parsing
return nil
return nil, nil
}
transformer, err := NewTransformerFillEmpty(fillString, inferType)
if err != nil {
fmt.Fprintf(os.Stderr, "mlr: %v\n", err)
os.Exit(1)
return nil, err
}
return transformer
return transformer, nil
}
type TransformerFillEmpty struct {

View file

@ -39,7 +39,7 @@ func transformerFlattenParseCLI(
args []string,
options *cli.TOptions,
doConstruct bool, // false for first pass of CLI-parse, true for second pass
) RecordTransformer {
) (RecordTransformer, error) {
// Skip the verb name from the current spot in the mlr command line
argi := *pargi
@ -49,6 +49,7 @@ func transformerFlattenParseCLI(
oFlatSep := "" // means take it from the record context
var fieldNames []string = nil
var err error
for argi < argc /* variable increment: 1 or 2 depending on flag */ {
opt := args[argi]
if !strings.HasPrefix(opt, "-") {
@ -61,23 +62,28 @@ func transformerFlattenParseCLI(
if opt == "-h" || opt == "--help" {
transformerFlattenUsage(os.Stdout)
os.Exit(0)
return nil, cli.ErrHelpRequested
} else if opt == "-s" {
oFlatSep = cli.VerbGetStringArgOrDie(verb, opt, args, &argi, argc)
oFlatSep, err = cli.VerbGetStringArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
} else if opt == "-f" {
fieldNames = cli.VerbGetStringArrayArgOrDie(verb, opt, args, &argi, argc)
fieldNames, err = cli.VerbGetStringArrayArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
} else {
transformerFlattenUsage(os.Stderr)
os.Exit(1)
return nil, cli.VerbErrorf(verb, "option \"%s\" not recognized", opt)
}
}
*pargi = argi
if !doConstruct { // All transformers must do this for main command-line parsing
return nil
return nil, nil
}
transformer, err := NewTransformerFlatten(
@ -86,11 +92,10 @@ func transformerFlattenParseCLI(
fieldNames,
)
if err != nil {
fmt.Fprintf(os.Stderr, "mlr: %v\n", err)
os.Exit(1)
return nil, err
}
return transformer
return transformer, nil
}
type TransformerFlatten struct {

View file

@ -63,7 +63,7 @@ func transformerFormatValuesParseCLI(
args []string,
_ *cli.TOptions,
doConstruct bool, // false for first pass of CLI-parse, true for second pass
) RecordTransformer {
) (RecordTransformer, error) {
// Skip the verb name from the current spot in the mlr command line
argi := *pargi
@ -75,6 +75,7 @@ func transformerFormatValuesParseCLI(
floatFormat := defaultFormatValuesFloatFormat
coerceIntToFloat := false
var err error
for argi < argc /* variable increment: 1 or 2 depending on flag */ {
opt := args[argi]
if !strings.HasPrefix(opt, "-") {
@ -87,26 +88,34 @@ func transformerFormatValuesParseCLI(
if opt == "-h" || opt == "--help" {
transformerFormatValuesUsage(os.Stdout)
os.Exit(0)
return nil, cli.ErrHelpRequested
} else if opt == "-s" {
stringFormat = cli.VerbGetStringArgOrDie(verb, opt, args, &argi, argc)
stringFormat, err = cli.VerbGetStringArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
} else if opt == "-i" {
intFormat = cli.VerbGetStringArgOrDie(verb, opt, args, &argi, argc)
intFormat, err = cli.VerbGetStringArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
} else if opt == "-f" {
floatFormat = cli.VerbGetStringArgOrDie(verb, opt, args, &argi, argc)
floatFormat, err = cli.VerbGetStringArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
} else if opt == "-n" {
coerceIntToFloat = true
} else {
transformerFormatValuesUsage(os.Stderr)
os.Exit(1)
return nil, cli.VerbErrorf(verb, "option \"%s\" not recognized", opt)
}
}
*pargi = argi
if !doConstruct { // All transformers must do this for main command-line parsing
return nil
return nil, nil
}
transformer, err := NewTransformerFormatValues(
@ -116,11 +125,10 @@ func transformerFormatValuesParseCLI(
coerceIntToFloat,
)
if err != nil {
fmt.Fprintf(os.Stderr, "mlr: %v\n", err)
os.Exit(1)
return nil, err
}
return transformer
return transformer, nil
}
type TransformerFormatValues struct {

View file

@ -55,7 +55,7 @@ func transformerFractionParseCLI(
args []string,
_ *cli.TOptions,
doConstruct bool, // false for first pass of CLI-parse, true for second pass
) RecordTransformer {
) (RecordTransformer, error) {
// Skip the verb name from the current spot in the mlr command line
argi := *pargi
@ -68,6 +68,7 @@ func transformerFractionParseCLI(
doPercents := false
doCumu := false
var err error
for argi < argc /* variable increment: 1 or 2 depending on flag */ {
opt := args[argi]
if !strings.HasPrefix(opt, "-") {
@ -80,13 +81,19 @@ func transformerFractionParseCLI(
if opt == "-h" || opt == "--help" {
transformerFractionUsage(os.Stdout)
os.Exit(0)
return nil, cli.ErrHelpRequested
} else if opt == "-f" {
fractionFieldNames = cli.VerbGetStringArrayArgOrDie(verb, opt, args, &argi, argc)
fractionFieldNames, err = cli.VerbGetStringArrayArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
} else if opt == "-g" {
groupByFieldNames = cli.VerbGetStringArrayArgOrDie(verb, opt, args, &argi, argc)
groupByFieldNames, err = cli.VerbGetStringArrayArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
} else if opt == "-p" {
doPercents = true
@ -95,19 +102,17 @@ func transformerFractionParseCLI(
doCumu = true
} else {
transformerFractionUsage(os.Stderr)
os.Exit(1)
return nil, cli.VerbErrorf(verb, "option \"%s\" not recognized", opt)
}
}
if fractionFieldNames == nil {
transformerFractionUsage(os.Stderr)
os.Exit(1)
return nil, cli.VerbErrorf(verb, "-f field names required")
}
*pargi = argi
if !doConstruct { // All transformers must do this for main command-line parsing
return nil
return nil, nil
}
transformer, err := NewTransformerFraction(
@ -117,11 +122,10 @@ func transformerFractionParseCLI(
doCumu,
)
if err != nil {
fmt.Fprintf(os.Stderr, "mlr: %v\n", err)
os.Exit(1)
return nil, err
}
return transformer
return transformer, nil
}
type TransformerFraction struct {

View file

@ -40,7 +40,7 @@ func transformerGapParseCLI(
args []string,
_ *cli.TOptions,
doConstruct bool, // false for first pass of CLI-parse, true for second pass
) RecordTransformer {
) (RecordTransformer, error) {
// Skip the verb name from the current spot in the mlr command line
argi := *pargi
@ -50,6 +50,7 @@ func transformerGapParseCLI(
gapCount := int64(-1)
var groupByFieldNames []string = nil
var err error
for argi < argc /* variable increment: 1 or 2 depending on flag */ {
opt := args[argi]
if !strings.HasPrefix(opt, "-") {
@ -62,28 +63,33 @@ func transformerGapParseCLI(
if opt == "-h" || opt == "--help" {
transformerGapUsage(os.Stdout)
os.Exit(0)
return nil, cli.ErrHelpRequested
} else if opt == "-n" {
gapCount = cli.VerbGetIntArgOrDie(verb, opt, args, &argi, argc)
gapCount, err = cli.VerbGetIntArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
} else if opt == "-g" {
groupByFieldNames = cli.VerbGetStringArrayArgOrDie(verb, opt, args, &argi, argc)
groupByFieldNames, err = cli.VerbGetStringArrayArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
} else {
transformerGapUsage(os.Stderr)
os.Exit(1)
return nil, cli.VerbErrorf(verb, "option \"%s\" not recognized", opt)
}
}
if gapCount == -1 && groupByFieldNames == nil {
transformerGapUsage(os.Stderr)
os.Exit(1)
return nil, cli.ErrUsagePrinted
}
*pargi = argi
if !doConstruct { // All transformers must do this for main command-line parsing
return nil
return nil, nil
}
transformer, err := NewTransformerGap(
@ -91,11 +97,10 @@ func transformerGapParseCLI(
groupByFieldNames,
)
if err != nil {
fmt.Fprintf(os.Stderr, "mlr: %v\n", err)
os.Exit(1)
return nil, err
}
return transformer
return transformer, nil
}
type TransformerGap struct {

View file

@ -51,7 +51,7 @@ func transformerGrepParseCLI(
args []string,
_ *cli.TOptions,
doConstruct bool, // false for first pass of CLI-parse, true for second pass
) RecordTransformer {
) (RecordTransformer, error) {
// Skip the verb name from the current spot in the mlr command line
argi := *pargi
@ -74,7 +74,7 @@ func transformerGrepParseCLI(
if opt == "-h" || opt == "--help" {
transformerGrepUsage(os.Stdout)
os.Exit(0)
return nil, cli.ErrHelpRequested
} else if opt == "-i" {
ignoreCase = true
@ -86,15 +86,13 @@ func transformerGrepParseCLI(
valuesOnly = true
} else {
transformerGrepUsage(os.Stderr)
os.Exit(1)
return nil, cli.VerbErrorf(verb, "option \"%s\" not recognized", opt)
}
}
// Get the regex from the command line
if argi >= argc {
transformerGrepUsage(os.Stderr)
os.Exit(1)
return nil, cli.VerbErrorf(verb, "pattern required")
}
pattern := args[argi]
argi++
@ -106,14 +104,12 @@ func transformerGrepParseCLI(
// TODO: maybe CompilePOSIX
regexp, err := regexp.Compile(pattern)
if err != nil {
fmt.Fprintf(os.Stderr, "%s %s: couldn't compile regex \"%s\"\n",
"mlr", verb, pattern)
os.Exit(1)
return nil, cli.VerbErrorf(verb, "invalid regex \"%s\": %w", pattern, err)
}
*pargi = argi
if !doConstruct { // All transformers must do this for main command-line parsing
return nil
return nil, nil
}
transformer, err := NewTransformerGrep(
@ -122,11 +118,10 @@ func transformerGrepParseCLI(
valuesOnly,
)
if err != nil {
fmt.Fprintf(os.Stderr, "mlr: %v\n", err)
os.Exit(1)
return nil, err
}
return transformer
return transformer, nil
}
type TransformerGrep struct {

View file

@ -34,7 +34,7 @@ func transformerGroupByParseCLI(
args []string,
_ *cli.TOptions,
doConstruct bool, // false for first pass of CLI-parse, true for second pass
) RecordTransformer {
) (RecordTransformer, error) {
// Skip the verb name from the current spot in the mlr command line
argi := *pargi
@ -52,35 +52,32 @@ func transformerGroupByParseCLI(
if opt == "-h" || opt == "--help" {
transformerGroupByUsage(os.Stdout)
os.Exit(0)
return nil, cli.ErrHelpRequested
}
transformerGroupByUsage(os.Stderr)
os.Exit(1)
return nil, cli.VerbErrorf(verbNameGroupBy, "option \"%s\" not recognized", opt)
}
// Get the group-by field names from the command line
if argi >= argc {
transformerGroupByUsage(os.Stderr)
os.Exit(1)
return nil, cli.VerbErrorf(verbNameGroupBy, "group-by field names required")
}
groupByFieldNames := lib.SplitString(args[argi], ",")
argi++
*pargi = argi
if !doConstruct { // All transformers must do this for main command-line parsing
return nil
return nil, nil
}
transformer, err := NewTransformerGroupBy(
groupByFieldNames,
)
if err != nil {
fmt.Fprintf(os.Stderr, "mlr: %v\n", err)
os.Exit(1)
return nil, err
}
return transformer
return transformer, nil
}
type TransformerGroupBy struct {

View file

@ -34,7 +34,7 @@ func transformerGroupLikeParseCLI(
args []string,
_ *cli.TOptions,
doConstruct bool, // false for first pass of CLI-parse, true for second pass
) RecordTransformer {
) (RecordTransformer, error) {
// Skip the verb name from the current spot in the mlr command line
argi := *pargi
@ -52,25 +52,23 @@ func transformerGroupLikeParseCLI(
if opt == "-h" || opt == "--help" {
transformerGroupLikeUsage(os.Stdout)
os.Exit(0)
return nil, cli.ErrHelpRequested
}
transformerGroupLikeUsage(os.Stderr)
os.Exit(1)
return nil, cli.VerbErrorf(verbNameGroupLike, "option \"%s\" not recognized", opt)
}
*pargi = argi
if !doConstruct { // All transformers must do this for main command-line parsing
return nil
return nil, nil
}
transformer, err := NewTransformerGroupLike()
if err != nil {
fmt.Fprintf(os.Stderr, "mlr: %v\n", err)
os.Exit(1)
return nil, err
}
return transformer
return transformer, nil
}
type TransformerGroupLike struct {

View file

@ -61,7 +61,7 @@ func transformerHavingFieldsParseCLI(
args []string,
_ *cli.TOptions,
doConstruct bool, // false for first pass of CLI-parse, true for second pass
) RecordTransformer {
) (RecordTransformer, error) {
havingFieldsCriterion := havingFieldsCriterionUnspecified
var fieldNames []string = nil
@ -72,6 +72,7 @@ func transformerHavingFieldsParseCLI(
verb := args[argi]
argi++
var err error
for argi < argc /* variable increment: 1 or 2 depending on flag */ {
opt := args[argi]
if !strings.HasPrefix(opt, "-") {
@ -84,56 +85,71 @@ func transformerHavingFieldsParseCLI(
if opt == "-h" || opt == "--help" {
transformerHavingFieldsUsage(os.Stdout)
os.Exit(0)
return nil, cli.ErrHelpRequested
} else if opt == "--at-least" {
havingFieldsCriterion = havingFieldsAtLeast
fieldNames = cli.VerbGetStringArrayArgOrDie(verb, opt, args, &argi, argc)
fieldNames, err = cli.VerbGetStringArrayArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
regexString = ""
} else if opt == "--which-are" {
havingFieldsCriterion = havingFieldsWhichAre
fieldNames = cli.VerbGetStringArrayArgOrDie(verb, opt, args, &argi, argc)
fieldNames, err = cli.VerbGetStringArrayArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
regexString = ""
} else if opt == "--at-most" {
havingFieldsCriterion = havingFieldsAtMost
fieldNames = cli.VerbGetStringArrayArgOrDie(verb, opt, args, &argi, argc)
fieldNames, err = cli.VerbGetStringArrayArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
regexString = ""
} else if opt == "--all-matching" {
havingFieldsCriterion = havingAllFieldsMatching
regexString = cli.VerbGetStringArgOrDie(verb, opt, args, &argi, argc)
regexString, err = cli.VerbGetStringArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
fieldNames = nil
} else if opt == "--any-matching" {
havingFieldsCriterion = havingAnyFieldsMatching
regexString = cli.VerbGetStringArgOrDie(verb, opt, args, &argi, argc)
regexString, err = cli.VerbGetStringArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
fieldNames = nil
} else if opt == "--none-matching" {
havingFieldsCriterion = havingNoFieldsMatching
regexString = cli.VerbGetStringArgOrDie(verb, opt, args, &argi, argc)
regexString, err = cli.VerbGetStringArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
fieldNames = nil
} else {
transformerHavingFieldsUsage(os.Stderr)
os.Exit(1)
return nil, cli.VerbErrorf(verb, "option \"%s\" not recognized", opt)
}
}
if havingFieldsCriterion == havingFieldsCriterionUnspecified {
transformerHavingFieldsUsage(os.Stderr)
os.Exit(1)
return nil, cli.VerbErrorf(verb, "-a, -b, -n, or --any-matching/--all-matching/--none-matching is required")
}
if fieldNames == nil && regexString == "" {
transformerHavingFieldsUsage(os.Stderr)
os.Exit(1)
return nil, cli.VerbErrorf(verb, "field names or regex required")
}
*pargi = argi
if !doConstruct { // All transformers must do this for main command-line parsing
return nil
return nil, nil
}
transformer, err := NewTransformerHavingFields(
@ -142,11 +158,10 @@ func transformerHavingFieldsParseCLI(
regexString,
)
if err != nil {
fmt.Fprintf(os.Stderr, "mlr: %v\n", err)
os.Exit(1)
return nil, err
}
return transformer
return transformer, nil
}
type TransformerHavingFields struct {

View file

@ -37,7 +37,7 @@ func transformerHeadParseCLI(
args []string,
_ *cli.TOptions,
doConstruct bool, // false for first pass of CLI-parse, true for second pass
) RecordTransformer {
) (RecordTransformer, error) {
// Skip the verb name from the current spot in the mlr command line
argi := *pargi
@ -59,10 +59,14 @@ func transformerHeadParseCLI(
if opt == "-h" || opt == "--help" {
transformerHeadUsage(os.Stdout)
os.Exit(0)
return nil, cli.ErrHelpRequested
} else if opt == "-n" {
headCount = cli.VerbGetIntArgOrDie(verb, opt, args, &argi, argc)
n, err := cli.VerbGetIntArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
headCount = n
// This is a bit of a hack. In our Getoptify routine we preprocess
// the command line sending '-xyz' to '-x -y -z', but leaving
@ -75,17 +79,21 @@ func transformerHeadParseCLI(
}
} else if opt == "-g" {
groupByFieldNames = cli.VerbGetStringArrayArgOrDie(verb, opt, args, &argi, argc)
names, err := cli.VerbGetStringArrayArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
groupByFieldNames = names
} else {
transformerHeadUsage(os.Stderr)
os.Exit(1)
return nil, fmt.Errorf("%s %s: option \"%s\" not recognized", "mlr", verb, opt)
}
}
*pargi = argi
if !doConstruct { // All transformers must do this for main command-line parsing
return nil
return nil, nil
}
transformer, err := NewTransformerHead(
@ -93,11 +101,10 @@ func transformerHeadParseCLI(
groupByFieldNames,
)
if err != nil {
fmt.Fprintf(os.Stderr, "mlr: %v\n", err)
os.Exit(1)
return nil, err
}
return transformer
return transformer, nil
}
type TransformerHead struct {

View file

@ -44,7 +44,7 @@ func transformerHistogramParseCLI(
args []string,
_ *cli.TOptions,
doConstruct bool, // false for first pass of CLI-parse, true for second pass
) RecordTransformer {
) (RecordTransformer, error) {
// Skip the verb name from the current spot in the mlr command line
argi := *pargi
@ -59,6 +59,7 @@ func transformerHistogramParseCLI(
doAuto := false
outputPrefix := ""
var err error
for argi < argc /* variable increment: 1 or 2 depending on flag */ {
opt := args[argi]
if !strings.HasPrefix(opt, "-") {
@ -71,50 +72,61 @@ func transformerHistogramParseCLI(
if opt == "-h" || opt == "--help" {
transformerHistogramUsage(os.Stdout)
os.Exit(0)
return nil, cli.ErrHelpRequested
} else if opt == "-f" {
valueFieldNames = cli.VerbGetStringArrayArgOrDie(verb, opt, args, &argi, argc)
valueFieldNames, err = cli.VerbGetStringArrayArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
} else if opt == "--lo" {
lo = cli.VerbGetFloatArgOrDie(verb, opt, args, &argi, argc)
lo, err = cli.VerbGetFloatArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
} else if opt == "--nbins" {
nbins = cli.VerbGetIntArgOrDie(verb, opt, args, &argi, argc)
nbins, err = cli.VerbGetIntArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
} else if opt == "--hi" {
hi = cli.VerbGetFloatArgOrDie(verb, opt, args, &argi, argc)
hi, err = cli.VerbGetFloatArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
} else if opt == "--auto" {
doAuto = true
} else if opt == "-o" {
outputPrefix = cli.VerbGetStringArgOrDie(verb, opt, args, &argi, argc)
outputPrefix, err = cli.VerbGetStringArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
} else {
transformerHistogramUsage(os.Stderr)
os.Exit(1)
return nil, cli.VerbErrorf(verb, "option \"%s\" not recognized", opt)
}
}
if valueFieldNames == nil {
transformerHistogramUsage(os.Stderr)
os.Exit(1)
return nil, cli.VerbErrorf(verb, "-f field names required")
}
if nbins <= 0 {
transformerHistogramUsage(os.Stderr)
os.Exit(1)
return nil, cli.VerbErrorf(verb, "number of bins must be positive")
}
if lo == hi && !doAuto {
transformerHistogramUsage(os.Stderr)
os.Exit(1)
return nil, cli.VerbErrorf(verb, "lo and hi must differ, or use --auto")
}
*pargi = argi
if !doConstruct { // All transformers must do this for main command-line parsing
return nil
return nil, nil
}
transformer, err := NewTransformerHistogram(
@ -126,11 +138,10 @@ func transformerHistogramParseCLI(
outputPrefix,
)
if err != nil {
fmt.Fprintf(os.Stderr, "mlr: %v\n", err)
os.Exit(1)
return nil, err
}
return transformer
return transformer, nil
}
const histogramVectorInitialSize = 1024

View file

@ -136,7 +136,7 @@ func transformerJoinParseCLI(
args []string,
mainOptions *cli.TOptions, // Options for the right-files
doConstruct bool, // false for first pass of CLI-parse, true for second pass
) RecordTransformer {
) (RecordTransformer, error) {
// Skip the verb name from the current spot in the mlr command line
argi := *pargi
@ -151,6 +151,7 @@ func transformerJoinParseCLI(
opts.joinFlagOptions = *mainOptions // struct copy
}
var err error
for argi < argc /* variable increment: 1 or 2 depending on flag */ {
opt := args[argi]
if !strings.HasPrefix(opt, "-") {
@ -163,36 +164,63 @@ func transformerJoinParseCLI(
if opt == "-h" || opt == "--help" {
transformerJoinUsage(os.Stdout)
os.Exit(0)
return nil, cli.ErrHelpRequested
} else if opt == "--prepipe" {
opts.prepipe = cli.VerbGetStringArgOrDie(verb, opt, args, &argi, argc)
opts.prepipe, err = cli.VerbGetStringArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
opts.prepipeIsRaw = false
} else if opt == "--prepipex" {
opts.prepipe = cli.VerbGetStringArgOrDie(verb, opt, args, &argi, argc)
opts.prepipe, err = cli.VerbGetStringArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
opts.prepipeIsRaw = true
} else if opt == "-f" {
opts.leftFileName = cli.VerbGetStringArgOrDie(verb, opt, args, &argi, argc)
opts.leftFileName, err = cli.VerbGetStringArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
} else if opt == "-j" {
opts.outputJoinFieldNames = cli.VerbGetStringArrayArgOrDie(verb, opt, args, &argi, argc)
opts.outputJoinFieldNames, err = cli.VerbGetStringArrayArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
} else if opt == "-l" {
opts.leftJoinFieldNames = cli.VerbGetStringArrayArgOrDie(verb, opt, args, &argi, argc)
opts.leftJoinFieldNames, err = cli.VerbGetStringArrayArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
} else if opt == "--lk" || opt == "--left-keep-field-names" {
opts.leftKeepFieldNames = cli.VerbGetStringArrayArgOrDie(verb, opt, args, &argi, argc)
opts.leftKeepFieldNames, err = cli.VerbGetStringArrayArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
} else if opt == "-r" {
opts.rightJoinFieldNames = cli.VerbGetStringArrayArgOrDie(verb, opt, args, &argi, argc)
opts.rightJoinFieldNames, err = cli.VerbGetStringArrayArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
} else if opt == "--lp" {
opts.leftPrefix = cli.VerbGetStringArgOrDie(verb, opt, args, &argi, argc)
opts.leftPrefix, err = cli.VerbGetStringArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
} else if opt == "--rp" {
opts.rightPrefix = cli.VerbGetStringArgOrDie(verb, opt, args, &argi, argc)
opts.rightPrefix, err = cli.VerbGetStringArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
} else if opt == "--np" {
opts.emitPairables = false
@ -219,8 +247,7 @@ func transformerJoinParseCLI(
// Nothing else to handle here.
argi = largi
} else {
transformerJoinUsage(os.Stderr)
os.Exit(1)
return nil, cli.VerbErrorf(verb, "input format option not recognized")
}
}
}
@ -228,25 +255,15 @@ func transformerJoinParseCLI(
cli.FinalizeReaderOptions(&opts.joinFlagOptions.ReaderOptions)
if opts.leftFileName == "" {
fmt.Fprintf(os.Stderr, "%s %s: need left file name\n", "mlr", verb)
transformerJoinUsage(os.Stderr)
os.Exit(1)
return nil
return nil, cli.VerbErrorf(verb, "need left file name")
}
if !opts.emitPairables && !opts.emitLeftUnpairables && !opts.emitRightUnpairables {
fmt.Fprintf(os.Stderr, "%s %s: all emit flags are unset; no output is possible.\n",
"mlr", verb)
transformerJoinUsage(os.Stderr)
os.Exit(1)
return nil
return nil, cli.VerbErrorf(verb, "all emit flags are unset; no output is possible")
}
if opts.outputJoinFieldNames == nil {
fmt.Fprintf(os.Stderr, "%s %s: need output field names\n", "mlr", verb)
transformerJoinUsage(os.Stderr)
os.Exit(1)
return nil
return nil, cli.VerbErrorf(verb, "need output field names")
}
if opts.leftJoinFieldNames == nil {
@ -260,24 +277,20 @@ func transformerJoinParseCLI(
rlen := len(opts.rightJoinFieldNames)
olen := len(opts.outputJoinFieldNames)
if llen != rlen || llen != olen {
fmt.Fprintf(os.Stderr,
"%s %s: must have equal left,right,output field-name lists; got lengths %d,%d,%d.\n",
"mlr", verb, llen, rlen, olen)
os.Exit(1)
return nil, cli.VerbErrorf(verb, "left, right, and output field lists must have same length")
}
*pargi = argi
if !doConstruct { // All transformers must do this for main command-line parsing
return nil
return nil, nil
}
transformer, err := NewTransformerJoin(opts)
if err != nil {
fmt.Fprintf(os.Stderr, "mlr: %v\n", err)
os.Exit(1)
return nil, err
}
return transformer
return transformer, nil
}
type TransformerJoin struct {
@ -470,9 +483,9 @@ func (tr *TransformerJoin) ingestLeftFile() {
// Instantiate the record-reader
// TODO: perhaps increase recordsPerBatch, and/or refactor
recordReader, err := input.Create(readerOpts, 1)
if recordReader == nil {
fmt.Fprintf(os.Stderr, "mlr join: %v\n", err)
os.Exit(1)
if err != nil {
// TODO: propagate error to caller
return
}
// Set the initial context for the left-file.
@ -501,8 +514,9 @@ func (tr *TransformerJoin) ingestLeftFile() {
select {
case err := <-errorChannel:
fmt.Fprintf(os.Stderr, "mlr: %v\n", err)
os.Exit(1)
// TODO: propagate error to caller
_ = err
return
case leftrecsAndContexts := <-readerChannel:
// TODO: temp for batch-reader refactor

View file

@ -40,7 +40,7 @@ func transformerJSONParseParseCLI(
args []string,
_ *cli.TOptions,
doConstruct bool, // false for first pass of CLI-parse, true for second pass
) RecordTransformer {
) (RecordTransformer, error) {
// Skip the verb name from the current spot in the mlr command line
argi := *pargi
@ -50,6 +50,7 @@ func transformerJSONParseParseCLI(
var fieldNames []string = nil
var err error
for argi < argc /* variable increment: 1 or 2 depending on flag */ {
opt := args[argi]
if !strings.HasPrefix(opt, "-") {
@ -62,23 +63,25 @@ func transformerJSONParseParseCLI(
if opt == "-h" || opt == "--help" {
transformerJSONParseUsage(os.Stdout)
os.Exit(0)
return nil, cli.ErrHelpRequested
} else if opt == "-f" {
fieldNames = cli.VerbGetStringArrayArgOrDie(verb, opt, args, &argi, argc)
fieldNames, err = cli.VerbGetStringArrayArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
} else if opt == "-k" {
keepFailed = true
} else {
transformerJSONParseUsage(os.Stderr)
os.Exit(1)
return nil, cli.VerbErrorf(verb, "option \"%s\" not recognized", opt)
}
}
*pargi = argi
if !doConstruct { // All transformers must do this for main command-line parsing
return nil
return nil, nil
}
transformer, err := NewTransformerJSONParse(
@ -86,11 +89,10 @@ func transformerJSONParseParseCLI(
keepFailed,
)
if err != nil {
fmt.Fprintf(os.Stderr, "mlr: %v\n", err)
os.Exit(1)
return nil, err
}
return transformer
return transformer, nil
}
type TransformerJSONParse struct {

View file

@ -40,7 +40,7 @@ func transformerJSONStringifyParseCLI(
args []string,
_ *cli.TOptions,
doConstruct bool, // false for first pass of CLI-parse, true for second pass
) RecordTransformer {
) (RecordTransformer, error) {
// Skip the verb name from the current spot in the mlr command line
argi := *pargi
@ -50,6 +50,7 @@ func transformerJSONStringifyParseCLI(
var fieldNames []string = nil
jvStack := false // TODO: ??
var err error
for argi < argc /* variable increment: 1 or 2 depending on flag */ {
opt := args[argi]
if !strings.HasPrefix(opt, "-") {
@ -62,10 +63,13 @@ func transformerJSONStringifyParseCLI(
if opt == "-h" || opt == "--help" {
transformerJSONStringifyUsage(os.Stdout)
os.Exit(0)
return nil, cli.ErrHelpRequested
} else if opt == "-f" {
fieldNames = cli.VerbGetStringArrayArgOrDie(verb, opt, args, &argi, argc)
fieldNames, err = cli.VerbGetStringArrayArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
} else if opt == "--jvstack" {
jvStack = true
@ -74,8 +78,7 @@ func transformerJSONStringifyParseCLI(
jvStack = false
} else {
transformerJSONStringifyUsage(os.Stderr)
os.Exit(1)
return nil, cli.VerbErrorf(verb, "option \"%s\" not recognized", opt)
}
}
@ -88,7 +91,7 @@ func transformerJSONStringifyParseCLI(
*pargi = argi
if !doConstruct { // All transformers must do this for main command-line parsing
return nil
return nil, nil
}
transformer, err := NewTransformerJSONStringify(
@ -96,11 +99,10 @@ func transformerJSONStringifyParseCLI(
fieldNames,
)
if err != nil {
fmt.Fprintf(os.Stderr, "mlr: %v\n", err)
os.Exit(1)
return nil, err
}
return transformer
return transformer, nil
}
type TransformerJSONStringify struct {

View file

@ -38,7 +38,7 @@ func transformerLabelParseCLI(
args []string,
_ *cli.TOptions,
doConstruct bool, // false for first pass of CLI-parse, true for second pass
) RecordTransformer {
) (RecordTransformer, error) {
// Skip the verb name from the current spot in the mlr command line
argi := *pargi
@ -56,36 +56,32 @@ func transformerLabelParseCLI(
if opt == "-h" || opt == "--help" {
transformerLabelUsage(os.Stdout)
os.Exit(0)
return nil, cli.ErrHelpRequested
}
transformerLabelUsage(os.Stderr)
os.Exit(1)
return nil, cli.VerbErrorf(verbNameLabel, "option \"%s\" not recognized", opt)
}
// Get the label field names from the command line
if argi >= argc {
transformerLabelUsage(os.Stderr)
os.Exit(1)
return nil, cli.VerbErrorf(verbNameLabel, "field names required")
}
newNames := lib.SplitString(args[argi], ",")
argi++
*pargi = argi
if !doConstruct { // All transformers must do this for main command-line parsing
return nil
return nil, nil
}
transformer, err := NewTransformerLabel(
newNames,
)
if err != nil {
fmt.Fprintf(os.Stderr, "mlr label: %v\n", err)
os.Exit(1)
// TODO: return nil to caller and have it exit, maybe
return nil, err
}
return transformer
return transformer, nil
}
type TransformerLabel struct {
@ -100,7 +96,7 @@ func NewTransformerLabel(
for _, newName := range newNames {
_, ok := uniquenessChecker[newName]
if ok {
return nil, fmt.Errorf(`labels must be unique; got duplicate "%s"`, newName)
return nil, fmt.Errorf(`mlr label: labels must be unique; got duplicate "%s"`, newName)
}
uniquenessChecker[newName] = true
}

View file

@ -36,7 +36,7 @@ func transformerLatin1ToUTF8ParseCLI(
args []string,
_ *cli.TOptions,
doConstruct bool, // false for first pass of CLI-parse, true for second pass
) RecordTransformer {
) (RecordTransformer, error) {
// Skip the verb name from the current spot in the mlr command line
argi := *pargi
@ -54,25 +54,23 @@ func transformerLatin1ToUTF8ParseCLI(
if opt == "-h" || opt == "--help" {
transformerLatin1ToUTF8Usage(os.Stdout)
os.Exit(0)
return nil, cli.ErrHelpRequested
}
transformerLatin1ToUTF8Usage(os.Stderr)
os.Exit(1)
return nil, cli.VerbErrorf(verbNameLatin1ToUTF8, "option \"%s\" not recognized", opt)
}
*pargi = argi
if !doConstruct { // All transformers must do this for main command-line parsing
return nil
return nil, nil
}
transformer, err := NewTransformerLatin1ToUTF8()
if err != nil {
fmt.Fprintf(os.Stderr, "mlr: %v\n", err)
os.Exit(1)
return nil, err
}
return transformer
return transformer, nil
}
type TransformerLatin1ToUTF8 struct {

View file

@ -75,7 +75,7 @@ func transformerMergeFieldsParseCLI(
args []string,
_ *cli.TOptions,
doConstruct bool, // false for first pass of CLI-parse, true for second pass
) RecordTransformer {
) (RecordTransformer, error) {
// Skip the verb name from the current spot in the mlr command line
argi := *pargi
@ -89,6 +89,7 @@ func transformerMergeFieldsParseCLI(
keepInputFields := false
doInterpolatedPercentiles := false
var err error
for argi < argc /* variable increment: 1 or 2 depending on flag */ {
opt := args[argi]
if !strings.HasPrefix(opt, "-") {
@ -101,25 +102,40 @@ func transformerMergeFieldsParseCLI(
if opt == "-h" || opt == "--help" {
transformerMergeFieldsUsage(os.Stdout)
os.Exit(0)
return nil, cli.ErrHelpRequested
} else if opt == "-a" {
accumulatorNameList = cli.VerbGetStringArrayArgOrDie(verb, opt, args, &argi, argc)
accumulatorNameList, err = cli.VerbGetStringArrayArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
} else if opt == "-f" {
valueFieldNameList = cli.VerbGetStringArrayArgOrDie(verb, opt, args, &argi, argc)
valueFieldNameList, err = cli.VerbGetStringArrayArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
doWhich = e_MERGE_BY_NAME_LIST
} else if opt == "-r" {
valueFieldNameList = cli.VerbGetStringArrayArgOrDie(verb, opt, args, &argi, argc)
valueFieldNameList, err = cli.VerbGetStringArrayArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
doWhich = e_MERGE_BY_NAME_REGEX
} else if opt == "-c" {
valueFieldNameList = cli.VerbGetStringArrayArgOrDie(verb, opt, args, &argi, argc)
valueFieldNameList, err = cli.VerbGetStringArrayArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
doWhich = e_MERGE_BY_COLLAPSING
} else if opt == "-o" {
outputFieldBasename = cli.VerbGetStringArgOrDie(verb, opt, args, &argi, argc)
outputFieldBasename, err = cli.VerbGetStringArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
} else if opt == "-k" {
keepInputFields = true
@ -134,32 +150,26 @@ func transformerMergeFieldsParseCLI(
// No-op pass-through for backward compatibility with Miller 5
} else {
transformerMergeFieldsUsage(os.Stderr)
os.Exit(1)
return nil, cli.VerbErrorf(verb, "option \"%s\" not recognized", opt)
}
}
// TODO: libify for use across verbs.
if len(accumulatorNameList) == 0 {
fmt.Fprintf(os.Stderr, "%s %s: -a option is required.\n", "mlr", verbNameMergeFields)
fmt.Fprintf(os.Stderr, "Please see %s %s --help for more information.\n", "mlr", verbNameMergeFields)
os.Exit(1)
return nil, cli.VerbErrorf(verbNameMergeFields, "-a option is required")
}
if len(valueFieldNameList) == 0 {
fmt.Fprintf(os.Stderr, "%s %s: -f option is required.\n", "mlr", verbNameMergeFields)
fmt.Fprintf(os.Stderr, "Please see %s %s --help for more information.\n", "mlr", verbNameMergeFields)
os.Exit(1)
return nil, cli.VerbErrorf(verbNameMergeFields, "-f option is required")
}
if outputFieldBasename == "" {
if doWhich == e_MERGE_BY_NAME_LIST || doWhich == e_MERGE_BY_NAME_REGEX {
transformerMergeFieldsUsage(os.Stderr)
os.Exit(1)
return nil, cli.VerbErrorf(verbNameMergeFields, "-o output field basename required")
}
}
*pargi = argi
if !doConstruct { // All transformers must do this for main command-line parsing
return nil
return nil, nil
}
transformer, err := NewTransformerMergeFields(
@ -171,11 +181,10 @@ func transformerMergeFieldsParseCLI(
keepInputFields,
)
if err != nil {
fmt.Fprintf(os.Stderr, "mlr: %v\n", err)
os.Exit(1)
return nil, err
}
return transformer
return transformer, nil
}
// Given: accumulate count,sum on values x,y group by a,b.

View file

@ -70,7 +70,7 @@ func transformerMostFrequentParseCLI(
args []string,
_ *cli.TOptions,
doConstruct bool, // false for first pass of CLI-parse, true for second pass
) RecordTransformer {
) (RecordTransformer, error) {
return transformerMostOrLeastFrequentParseCLI(pargi, argc, args, true, transformerMostFrequentUsage, doConstruct)
}
@ -80,7 +80,7 @@ func transformerLeastFrequentParseCLI(
args []string,
_ *cli.TOptions,
doConstruct bool, // false for first pass of CLI-parse, true for second pass
) RecordTransformer {
) (RecordTransformer, error) {
return transformerMostOrLeastFrequentParseCLI(pargi, argc, args, false, transformerLeastFrequentUsage, doConstruct)
}
@ -91,7 +91,7 @@ func transformerMostOrLeastFrequentParseCLI(
descending bool,
usageFunc TransformerUsageFunc,
doConstruct bool, // false for first pass of CLI-parse, true for second pass
) RecordTransformer {
) (RecordTransformer, error) {
// Skip the verb name from the current spot in the mlr command line
argi := *pargi
@ -104,6 +104,7 @@ func transformerMostOrLeastFrequentParseCLI(
showCounts := true
outputFieldName := mostLeastFrequentDefaultOutputFieldName
var err error
for argi < argc /* variable increment: 1 or 2 depending on flag */ {
opt := args[argi]
if !strings.HasPrefix(opt, "-") {
@ -116,35 +117,41 @@ func transformerMostOrLeastFrequentParseCLI(
if opt == "-h" || opt == "--help" {
usageFunc(os.Stdout)
os.Exit(0)
return nil, cli.ErrHelpRequested
} else if opt == "-f" {
groupByFieldNames = cli.VerbGetStringArrayArgOrDie(verb, opt, args, &argi, argc)
groupByFieldNames, err = cli.VerbGetStringArrayArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
} else if opt == "-n" {
maxOutputLength = cli.VerbGetIntArgOrDie(verb, opt, args, &argi, argc)
maxOutputLength, err = cli.VerbGetIntArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
} else if opt == "-b" {
showCounts = false
} else if opt == "-o" {
outputFieldName = cli.VerbGetStringArgOrDie(verb, opt, args, &argi, argc)
outputFieldName, err = cli.VerbGetStringArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
} else {
usageFunc(os.Stderr)
os.Exit(1)
return nil, cli.VerbErrorf(verb, "option \"%s\" not recognized", opt)
}
}
if groupByFieldNames == nil {
usageFunc(os.Stderr)
os.Exit(1)
return nil
return nil, cli.VerbErrorf(verb, "-f field names required")
}
*pargi = argi
if !doConstruct { // All transformers must do this for main command-line parsing
return nil
return nil, nil
}
transformer, err := NewTransformerMostOrLeastFrequent(
@ -155,11 +162,10 @@ func transformerMostOrLeastFrequentParseCLI(
descending,
)
if err != nil {
fmt.Fprintf(os.Stderr, "mlr: %v\n", err)
os.Exit(1)
return nil, err
}
return transformer
return transformer, nil
}
type TransformerMostOrLeastFrequent struct {

View file

@ -94,7 +94,7 @@ func transformerNestParseCLI(
args []string,
_ *cli.TOptions,
doConstruct bool, // false for first pass of CLI-parse, true for second pass
) RecordTransformer {
) (RecordTransformer, error) {
// Skip the verb name from the current spot in the mlr command line
argi := *pargi
@ -127,14 +127,22 @@ func transformerNestParseCLI(
if opt == "-h" || opt == "--help" {
transformerNestUsage(os.Stdout)
os.Exit(0)
return nil, cli.ErrHelpRequested
} else if opt == "-f" {
fieldName = cli.VerbGetStringArgOrDie(verb, opt, args, &argi, argc)
s, err := cli.VerbGetStringArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
fieldName = s
} else if opt == "-r" {
doRegexes = true
fieldName = cli.VerbGetStringArgOrDie(verb, opt, args, &argi, argc)
s, err := cli.VerbGetStringArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
fieldName = s
} else if opt == "--explode" || opt == "-e" {
doExplode = true
@ -158,12 +166,24 @@ func transformerNestParseCLI(
doAcrossFieldsSpecified = true
} else if opt == "--nested-fs" || opt == "-S" {
nestedFS = cli.VerbGetStringArgOrDie(verb, opt, args, &argi, argc)
s, err := cli.VerbGetStringArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
nestedFS = s
} else if opt == "--nested-ps" || opt == "-P" {
nestedPS = cli.VerbGetStringArgOrDie(verb, opt, args, &argi, argc)
s, err := cli.VerbGetStringArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
nestedPS = s
} else if opt == "--evar" {
evfs = cli.VerbGetStringArgOrDie(verb, opt, args, &argi, argc)
s, err := cli.VerbGetStringArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
evfs = s
doExplode = true
doExplodeSpecified = true
doPairs = false
@ -172,7 +192,11 @@ func transformerNestParseCLI(
doAcrossFieldsSpecified = true
} else if opt == "--ivar" {
ivfs = cli.VerbGetStringArgOrDie(verb, opt, args, &argi, argc)
s, err := cli.VerbGetStringArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
ivfs = s
doExplode = false
doExplodeSpecified = true
doPairs = false
@ -182,7 +206,7 @@ func transformerNestParseCLI(
} else {
transformerNestUsage(os.Stderr)
os.Exit(1)
return nil, fmt.Errorf("%s %s: option \"%s\" not recognized", "mlr", verb, opt)
}
}
@ -201,32 +225,31 @@ func transformerNestParseCLI(
if fieldName == "" {
transformerNestUsage(os.Stderr)
os.Exit(1)
return nil, fmt.Errorf("%s %s: -f or -r is required", "mlr", verb)
}
if !doExplodeSpecified {
transformerNestUsage(os.Stderr)
os.Exit(1)
return nil, fmt.Errorf("%s %s: --explode or --implode is required", "mlr", verb)
}
if !doPairsSpecified {
transformerNestUsage(os.Stderr)
os.Exit(1)
return nil, fmt.Errorf("%s %s: --values or --pairs is required", "mlr", verb)
}
if !doAcrossFieldsSpecified {
transformerNestUsage(os.Stderr)
os.Exit(1)
return nil, fmt.Errorf("%s %s: --across-records or --across-fields is required", "mlr", verb)
}
if doPairs && !doExplode {
transformerNestUsage(os.Stderr)
os.Exit(1)
return nil, fmt.Errorf("%s %s: --implode with --pairs doesn't make sense", "mlr", verb)
}
if doRegexes && !doExplode {
fmt.Fprintf(os.Stderr, "mlr nest: -r is only supported with --explode, not --implode.\n")
os.Exit(1)
return nil, fmt.Errorf("mlr nest: -r is only supported with --explode, not --implode")
}
*pargi = argi
if !doConstruct { // All transformers must do this for main command-line parsing
return nil
return nil, nil
}
transformer, err := NewTransformerNest(
@ -239,11 +262,10 @@ func transformerNestParseCLI(
doAcrossFields,
)
if err != nil {
fmt.Fprintf(os.Stderr, "mlr: %v\n", err)
os.Exit(1)
return nil, err
}
return transformer
return transformer, nil
}
type TransformerNest struct {

View file

@ -34,7 +34,7 @@ func transformerNothingParseCLI(
args []string,
_ *cli.TOptions,
doConstruct bool, // false for first pass of CLI-parse, true for second pass
) RecordTransformer {
) (RecordTransformer, error) {
// Skip the verb name from the current spot in the mlr command line
argi := *pargi
@ -52,25 +52,23 @@ func transformerNothingParseCLI(
if opt == "-h" || opt == "--help" {
transformerNothingUsage(os.Stdout)
os.Exit(0)
return nil, cli.ErrHelpRequested
}
transformerNothingUsage(os.Stderr)
os.Exit(1)
return nil, fmt.Errorf("%s %s: option \"%s\" not recognized", "mlr", verbNameNothing, opt)
}
*pargi = argi
if !doConstruct { // All transformers must do this for main command-line parsing
return nil
return nil, nil
}
transformer, err := NewTransformerNothing()
if err != nil {
fmt.Fprintf(os.Stderr, "mlr: %v\n", err)
os.Exit(1)
return nil, err
}
return transformer
return transformer, nil
}
type TransformerNothing struct {

View file

@ -184,7 +184,7 @@ func transformerPutOrFilterParseCLI(
args []string,
mainOptions *cli.TOptions,
doConstruct bool, // false for first pass of CLI-parse, true for second pass
) RecordTransformer {
) (RecordTransformer, error) {
// Skip the verb name from the current spot in the mlr command line
argi := *pargi
@ -217,10 +217,8 @@ func transformerPutOrFilterParseCLI(
for _, filename := range options.DSLPreloadFileNames {
theseDSLStrings, err := lib.LoadStringsFromFileOrDir(filename, ".mlr")
if err != nil {
fmt.Fprintf(os.Stderr, "%s %s: cannot load DSL expression from \"%s\": ",
"mlr", verb, filename)
fmt.Println(err)
os.Exit(1)
return nil, fmt.Errorf("%s %s: cannot load DSL expression from \"%s\": %w",
"mlr", verb, filename, err)
}
dslStrings = append(dslStrings, theseDSLStrings...)
}
@ -238,11 +236,14 @@ func transformerPutOrFilterParseCLI(
if opt == "-h" || opt == "--help" {
transformerPutOrFilterUsage(os.Stdout, verb)
os.Exit(0)
return nil, cli.ErrHelpRequested
} else if opt == "-f" {
// Get a DSL string from the user-specified filename
filename := cli.VerbGetStringArgOrDie(verb, opt, args, &argi, argc)
filename, err := cli.VerbGetStringArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
// Miller has a two-pass command-line parser. If the user does
// `mlr put -f foo.mlr`
@ -258,17 +259,18 @@ func transformerPutOrFilterParseCLI(
if doConstruct {
theseDSLStrings, err := lib.LoadStringsFromFileOrDir(filename, ".mlr")
if err != nil {
fmt.Fprintf(os.Stderr, "%s %s: cannot load DSL expression from file \"%s\": ",
"mlr", verb, filename)
fmt.Println(err)
os.Exit(1)
return nil, fmt.Errorf("%s %s: cannot load DSL expression from file \"%s\": %w",
"mlr", verb, filename, err)
}
dslStrings = append(dslStrings, theseDSLStrings...)
}
haveDSLStringsHere = true
} else if opt == "-e" {
dslString := cli.VerbGetStringArgOrDie(verb, opt, args, &argi, argc)
dslString, err := cli.VerbGetStringArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
dslStrings = append(dslStrings, dslString)
haveDSLStringsHere = true
@ -277,7 +279,10 @@ func transformerPutOrFilterParseCLI(
// mlr put -s sum=0
// is like
// mlr put -s 'begin {@sum = 0}'
preset := cli.VerbGetStringArgOrDie(verb, opt, args, &argi, argc)
preset, err := cli.VerbGetStringArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
presets = append(presets, preset)
} else if opt == "-x" {
@ -328,8 +333,7 @@ func transformerPutOrFilterParseCLI(
// Nothing else to handle here.
argi = largi
} else {
transformerPutOrFilterUsage(os.Stderr, verb)
os.Exit(1)
return nil, cli.VerbErrorf(verb, "option not recognized")
}
}
}
@ -342,8 +346,7 @@ func transformerPutOrFilterParseCLI(
if !haveDSLStringsHere {
// Get the DSL string from the command line, after the flags
if argi >= argc {
fmt.Fprintf(os.Stderr, "mlr %s: -f/-e requires a filename as argument.\n", verb)
os.Exit(1)
return nil, cli.VerbErrorf(verb, "expression or -f/-e is required")
}
dslString := args[argi]
dslStrings = append(dslStrings, dslString)
@ -352,7 +355,7 @@ func transformerPutOrFilterParseCLI(
*pargi = argi
if !doConstruct { // All transformers must do this for main command-line parsing
return nil
return nil, nil
}
var dslInstanceType cst.DSLInstanceType = cst.DSLInstanceTypePut
@ -380,11 +383,10 @@ func transformerPutOrFilterParseCLI(
options,
)
if err != nil {
fmt.Fprintf(os.Stderr, "mlr: %v\n", err)
os.Exit(1)
return nil, err
}
return transformer
return transformer, nil
}
type TransformerPut struct {

View file

@ -35,7 +35,7 @@ func transformerRegularizeParseCLI(
args []string,
_ *cli.TOptions,
doConstruct bool, // false for first pass of CLI-parse, true for second pass
) RecordTransformer {
) (RecordTransformer, error) {
// Skip the verb name from the current spot in the mlr command line
argi := *pargi
@ -53,25 +53,23 @@ func transformerRegularizeParseCLI(
if opt == "-h" || opt == "--help" {
transformerRegularizeUsage(os.Stdout)
os.Exit(0)
return nil, cli.ErrHelpRequested
}
transformerRegularizeUsage(os.Stderr)
os.Exit(1)
return nil, cli.VerbErrorf(verbNameRegularize, "option \"%s\" not recognized", opt)
}
*pargi = argi
if !doConstruct { // All transformers must do this for main command-line parsing
return nil
return nil, nil
}
transformer, err := NewTransformerRegularize()
if err != nil {
fmt.Fprintf(os.Stderr, "mlr: %v\n", err)
os.Exit(1)
return nil, err
}
return transformer
return transformer, nil
}
type TransformerRegularize struct {

View file

@ -34,7 +34,7 @@ func transformerRemoveEmptyColumnsParseCLI(
args []string,
_ *cli.TOptions,
doConstruct bool, // false for first pass of CLI-parse, true for second pass
) RecordTransformer {
) (RecordTransformer, error) {
// Skip the verb name from the current spot in the mlr command line
argi := *pargi
@ -52,25 +52,23 @@ func transformerRemoveEmptyColumnsParseCLI(
if opt == "-h" || opt == "--help" {
transformerRemoveEmptyColumnsUsage(os.Stdout)
os.Exit(0)
return nil, cli.ErrHelpRequested
}
transformerRemoveEmptyColumnsUsage(os.Stderr)
os.Exit(1)
return nil, cli.VerbErrorf(verbNameRemoveEmptyColumns, "option \"%s\" not recognized", opt)
}
*pargi = argi
if !doConstruct { // All transformers must do this for main command-line parsing
return nil
return nil, nil
}
transformer, err := NewTransformerRemoveEmptyColumns()
if err != nil {
fmt.Fprintf(os.Stderr, "mlr: %v\n", err)
os.Exit(1)
return nil, err
}
return transformer
return transformer, nil
}
type TransformerRemoveEmptyColumns struct {

View file

@ -55,7 +55,7 @@ func transformerRenameParseCLI(
args []string,
_ *cli.TOptions,
doConstruct bool, // false for first pass of CLI-parse, true for second pass
) RecordTransformer {
) (RecordTransformer, error) {
// Skip the verb name from the current spot in the mlr command line
argi := *pargi
@ -76,7 +76,7 @@ func transformerRenameParseCLI(
if opt == "-h" || opt == "--help" {
transformerRenameUsage(os.Stdout)
os.Exit(0)
return nil, cli.ErrHelpRequested
} else if opt == "-r" {
doRegexes = true
@ -85,8 +85,7 @@ func transformerRenameParseCLI(
doGsub = true
} else {
transformerRenameUsage(os.Stderr)
os.Exit(1)
return nil, cli.VerbErrorf(verbNameRename, "option \"%s\" not recognized", opt)
}
}
@ -96,19 +95,17 @@ func transformerRenameParseCLI(
// Get the rename field names from the command line
if argi >= argc {
transformerRenameUsage(os.Stderr)
os.Exit(1)
return nil, cli.VerbErrorf(verbNameRename, "old1,new1,old2,new2,... required")
}
names := lib.SplitString(args[argi], ",")
if len(names)%2 != 0 {
transformerRenameUsage(os.Stderr)
os.Exit(1)
return nil, cli.VerbErrorf(verbNameRename, "names string must have even length")
}
argi++
*pargi = argi
if !doConstruct { // All transformers must do this for main command-line parsing
return nil
return nil, nil
}
transformer, err := NewTransformerRename(
@ -117,11 +114,10 @@ func transformerRenameParseCLI(
doGsub,
)
if err != nil {
fmt.Fprintf(os.Stderr, "mlr: %v\n", err)
os.Exit(1)
return nil, err
}
return transformer
return transformer, nil
}
type tRegexAndReplacement struct {

View file

@ -56,7 +56,7 @@ func transformerReorderParseCLI(
args []string,
_ *cli.TOptions,
doConstruct bool, // false for first pass of CLI-parse, true for second pass
) RecordTransformer {
) (RecordTransformer, error) {
// Skip the verb name from the current spot in the mlr command line
argi := *pargi
@ -68,6 +68,7 @@ func transformerReorderParseCLI(
putAfter := false
centerFieldName := ""
var err error
for argi < argc /* variable increment: 1 or 2 depending on flag */ {
opt := args[argi]
if !strings.HasPrefix(opt, "-") {
@ -80,22 +81,34 @@ func transformerReorderParseCLI(
if opt == "-h" || opt == "--help" {
transformerReorderUsage(os.Stdout)
os.Exit(0)
return nil, cli.ErrHelpRequested
} else if opt == "-f" {
fieldNames = cli.VerbGetStringArrayArgOrDie(verb, opt, args, &argi, argc)
fieldNames, err = cli.VerbGetStringArrayArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
doRegexes = false
} else if opt == "-r" {
fieldNames = cli.VerbGetStringArrayArgOrDie(verb, opt, args, &argi, argc)
fieldNames, err = cli.VerbGetStringArrayArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
doRegexes = true
} else if opt == "-b" {
centerFieldName = cli.VerbGetStringArgOrDie(verb, opt, args, &argi, argc)
centerFieldName, err = cli.VerbGetStringArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
putAfter = false
} else if opt == "-a" {
centerFieldName = cli.VerbGetStringArgOrDie(verb, opt, args, &argi, argc)
centerFieldName, err = cli.VerbGetStringArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
putAfter = true
} else if opt == "-e" {
@ -103,19 +116,17 @@ func transformerReorderParseCLI(
centerFieldName = ""
} else {
transformerReorderUsage(os.Stderr)
os.Exit(1)
return nil, cli.VerbErrorf(verb, "option \"%s\" not recognized", opt)
}
}
if fieldNames == nil {
transformerReorderUsage(os.Stderr)
os.Exit(1)
return nil, cli.VerbErrorf(verb, "-f field names required")
}
*pargi = argi
if !doConstruct { // All transformers must do this for main command-line parsing
return nil
return nil, nil
}
transformer, err := NewTransformerReorder(
@ -125,11 +136,10 @@ func transformerReorderParseCLI(
centerFieldName,
)
if err != nil {
fmt.Fprintf(os.Stderr, "mlr: %v\n", err)
os.Exit(1)
return nil, err
}
return transformer
return transformer, nil
}
type TransformerReorder struct {

View file

@ -63,7 +63,7 @@ func transformerRepeatParseCLI(
args []string,
_ *cli.TOptions,
doConstruct bool, // false for first pass of CLI-parse, true for second pass
) RecordTransformer {
) (RecordTransformer, error) {
repeatCountSource := repeatCountSourceUnspecified
repeatCount := int64(0)
@ -74,6 +74,7 @@ func transformerRepeatParseCLI(
verb := args[argi]
argi++
var err error
for argi < argc /* variable increment: 1 or 2 depending on flag */ {
opt := args[argi]
if !strings.HasPrefix(opt, "-") {
@ -86,30 +87,34 @@ func transformerRepeatParseCLI(
if opt == "-h" || opt == "--help" {
transformerRepeatUsage(os.Stdout)
os.Exit(0)
return nil, cli.ErrHelpRequested
} else if opt == "-n" {
repeatCount = cli.VerbGetIntArgOrDie(verb, opt, args, &argi, argc)
repeatCount, err = cli.VerbGetIntArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
repeatCountSource = repeatCountFromInt
} else if opt == "-f" {
repeatCountFieldName = cli.VerbGetStringArgOrDie(verb, opt, args, &argi, argc)
repeatCountFieldName, err = cli.VerbGetStringArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
repeatCountSource = repeatCountFromFieldName
} else {
transformerRepeatUsage(os.Stderr)
os.Exit(1)
return nil, cli.VerbErrorf(verb, "option \"%s\" not recognized", opt)
}
}
if repeatCountSource == repeatCountSourceUnspecified {
transformerRepeatUsage(os.Stderr)
os.Exit(1)
return nil, cli.VerbErrorf(verb, "-n or -f is required")
}
*pargi = argi
if !doConstruct { // All transformers must do this for main command-line parsing
return nil
return nil, nil
}
transformer, err := NewTransformerRepeat(
@ -118,11 +123,10 @@ func transformerRepeatParseCLI(
repeatCountFieldName,
)
if err != nil {
fmt.Fprintf(os.Stderr, "mlr: %v\n", err)
os.Exit(1)
return nil, err
}
return transformer
return transformer, nil
}
type TransformerRepeat struct {

View file

@ -120,7 +120,7 @@ func transformerReshapeParseCLI(
args []string,
_ *cli.TOptions,
doConstruct bool, // false for first pass of CLI-parse, true for second pass
) RecordTransformer {
) (RecordTransformer, error) {
// Skip the verb name from the current spot in the mlr command line
argi := *pargi
@ -133,6 +133,7 @@ func transformerReshapeParseCLI(
var outputFieldNames []string = nil
var splitOutFieldNames []string = nil
var err error
for argi < argc /* variable increment: 1 or 2 depending on flag */ {
opt := args[argi]
if !strings.HasPrefix(opt, "-") {
@ -145,24 +146,35 @@ func transformerReshapeParseCLI(
if opt == "-h" || opt == "--help" {
transformerReshapeUsage(os.Stdout)
os.Exit(0)
return nil, cli.ErrHelpRequested
} else if opt == "-i" {
inputFieldNames = cli.VerbGetStringArrayArgOrDie(verb, opt, args, &argi, argc)
inputFieldNames, err = cli.VerbGetStringArrayArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
} else if opt == "-r" {
inputFieldRegexString := cli.VerbGetStringArgOrDie(verb, opt, args, &argi, argc)
inputFieldRegexString, err := cli.VerbGetStringArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
if inputFieldRegexStrings == nil {
inputFieldRegexStrings = []string{}
}
inputFieldRegexStrings = append(inputFieldRegexStrings, inputFieldRegexString)
} else if opt == "-o" {
outputFieldNames = cli.VerbGetStringArrayArgOrDie(verb, opt, args, &argi, argc)
outputFieldNames, err = cli.VerbGetStringArrayArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
} else if opt == "-s" {
splitOutFieldNames = cli.VerbGetStringArrayArgOrDie(verb, opt, args, &argi, argc)
splitOutFieldNames, err = cli.VerbGetStringArrayArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
} else {
transformerReshapeUsage(os.Stderr)
os.Exit(1)
return nil, cli.VerbErrorf(verb, "option \"%s\" not recognized", opt)
}
}
@ -174,25 +186,21 @@ func transformerReshapeParseCLI(
if splitOutFieldNames == nil {
// wide to long
if inputFieldNames == nil && inputFieldRegexStrings == nil {
transformerReshapeUsage(os.Stderr)
os.Exit(1)
return nil, cli.VerbErrorf(verb, "-i or -r is required for wide-to-long")
}
if outputFieldNames == nil {
transformerReshapeUsage(os.Stderr)
os.Exit(1)
return nil, cli.VerbErrorf(verb, "-o is required for wide-to-long")
}
if len(outputFieldNames) != 2 {
transformerReshapeUsage(os.Stderr)
os.Exit(1)
return nil, cli.VerbErrorf(verb, "-o must have exactly 2 field names for wide-to-long")
}
outputKeyFieldName = outputFieldNames[0]
outputValueFieldName = outputFieldNames[1]
} else {
// long to wide
if len(splitOutFieldNames) != 2 {
transformerReshapeUsage(os.Stderr)
os.Exit(1)
return nil, cli.VerbErrorf(verb, "-s must have exactly 2 field names for long-to-wide")
}
splitOutKeyFieldName = splitOutFieldNames[0]
splitOutValueFieldName = splitOutFieldNames[1]
@ -200,7 +208,7 @@ func transformerReshapeParseCLI(
*pargi = argi
if !doConstruct { // All transformers must do this for main command-line parsing
return nil
return nil, nil
}
transformer, err := NewTransformerReshape(
@ -212,11 +220,10 @@ func transformerReshapeParseCLI(
splitOutValueFieldName,
)
if err != nil {
fmt.Fprintf(os.Stderr, "mlr: %v\n", err)
os.Exit(1)
return nil, err
}
return transformer
return transformer, nil
}
type TransformerReshape struct {

View file

@ -39,7 +39,7 @@ func transformerSampleParseCLI(
args []string,
_ *cli.TOptions,
doConstruct bool, // false for first pass of CLI-parse, true for second pass
) RecordTransformer {
) (RecordTransformer, error) {
// Skip the verb name from the current spot in the mlr command line
argi := *pargi
@ -49,6 +49,7 @@ func transformerSampleParseCLI(
sampleCount := int64(-1)
var groupByFieldNames []string = nil
var err error
for argi < argc /* variable increment: 1 or 2 depending on flag */ {
opt := args[argi]
if !strings.HasPrefix(opt, "-") {
@ -61,28 +62,32 @@ func transformerSampleParseCLI(
if opt == "-h" || opt == "--help" {
transformerSampleUsage(os.Stdout)
os.Exit(0)
return nil, cli.ErrHelpRequested
} else if opt == "-k" {
sampleCount = cli.VerbGetIntArgOrDie(verb, opt, args, &argi, argc)
sampleCount, err = cli.VerbGetIntArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
} else if opt == "-g" {
groupByFieldNames = cli.VerbGetStringArrayArgOrDie(verb, opt, args, &argi, argc)
groupByFieldNames, err = cli.VerbGetStringArrayArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
} else {
transformerSampleUsage(os.Stderr)
os.Exit(1)
return nil, cli.VerbErrorf(verb, "option \"%s\" not recognized", opt)
}
}
if sampleCount < 0 {
transformerSampleUsage(os.Stderr)
os.Exit(1)
return nil, cli.VerbErrorf(verb, "sample count must be non-negative")
}
*pargi = argi
if !doConstruct { // All transformers must do this for main command-line parsing
return nil
return nil, nil
}
transformer, err := NewTransformerSample(
@ -90,11 +95,10 @@ func transformerSampleParseCLI(
groupByFieldNames,
)
if err != nil {
fmt.Fprintf(os.Stderr, "mlr: %v\n", err)
os.Exit(1)
return nil, err
}
return transformer
return transformer, nil
}
type sampleBucketType struct {

View file

@ -43,7 +43,7 @@ func transformerSec2GMTParseCLI(
args []string,
_ *cli.TOptions,
doConstruct bool, // false for first pass of CLI-parse, true for second pass
) RecordTransformer {
) (RecordTransformer, error) {
// Skip the verb name from the current spot in the mlr command line
argi := *pargi
@ -64,7 +64,7 @@ func transformerSec2GMTParseCLI(
if opt == "-h" || opt == "--help" {
transformerSec2GMTUsage(os.Stdout)
os.Exit(0)
return nil, cli.ErrHelpRequested
} else if opt == "-1" {
numDecimalPlaces = 1
@ -93,21 +93,19 @@ func transformerSec2GMTParseCLI(
preDivide = 1.0e9
} else {
transformerSec2GMTUsage(os.Stderr)
os.Exit(1)
return nil, cli.VerbErrorf(verbNameSec2GMT, "option \"%s\" not recognized", opt)
}
}
if argi >= argc {
transformerSec2GMTUsage(os.Stderr)
os.Exit(1)
return nil, cli.VerbErrorf(verbNameSec2GMT, "field names required")
}
fieldNames := args[argi]
argi++
*pargi = argi
if !doConstruct { // All transformers must do this for main command-line parsing
return nil
return nil, nil
}
transformer, err := NewTransformerSec2GMT(
@ -116,11 +114,10 @@ func transformerSec2GMTParseCLI(
numDecimalPlaces,
)
if err != nil {
fmt.Fprintf(os.Stderr, "mlr: %v\n", err)
os.Exit(1)
return nil, err
}
return transformer
return transformer, nil
}
type TransformerSec2GMT struct {

View file

@ -37,7 +37,7 @@ func transformerSec2GMTDateParseCLI(
args []string,
_ *cli.TOptions,
doConstruct bool, // false for first pass of CLI-parse, true for second pass
) RecordTransformer {
) (RecordTransformer, error) {
// Skip the verb name from the current spot in the mlr command line
argi := *pargi
@ -55,34 +55,31 @@ func transformerSec2GMTDateParseCLI(
if opt == "-h" || opt == "--help" {
transformerSec2GMTDateUsage(os.Stdout)
os.Exit(0)
return nil, cli.ErrHelpRequested
}
transformerSec2GMTDateUsage(os.Stderr)
os.Exit(1)
return nil, cli.VerbErrorf(verbNameSec2GMTDate, "option \"%s\" not recognized", opt)
}
if argi >= argc {
transformerSec2GMTDateUsage(os.Stderr)
os.Exit(1)
return nil, cli.VerbErrorf(verbNameSec2GMTDate, "field names required")
}
fieldNames := args[argi]
argi++
*pargi = argi
if !doConstruct { // All transformers must do this for main command-line parsing
return nil
return nil, nil
}
transformer, err := NewTransformerSec2GMTDate(
fieldNames,
)
if err != nil {
fmt.Fprintf(os.Stderr, "mlr: %v\n", err)
os.Exit(1)
return nil, err
}
return transformer
return transformer, nil
}
type TransformerSec2GMTDate struct {

View file

@ -46,7 +46,7 @@ func transformerSeqgenParseCLI(
args []string,
_ *cli.TOptions,
doConstruct bool, // false for first pass of CLI-parse, true for second pass
) RecordTransformer {
) (RecordTransformer, error) {
// Skip the verb name from the current spot in the mlr command line
argi := *pargi
@ -58,6 +58,7 @@ func transformerSeqgenParseCLI(
stopString := "100"
stepString := "1"
var err error
for argi < argc /* variable increment: 1 or 2 depending on flag */ {
opt := args[argi]
if !strings.HasPrefix(opt, "-") {
@ -70,29 +71,40 @@ func transformerSeqgenParseCLI(
if opt == "-h" || opt == "--help" {
transformerSeqgenUsage(os.Stdout)
os.Exit(0)
return nil, cli.ErrHelpRequested
} else if opt == "-f" {
fieldName = cli.VerbGetStringArgOrDie(verb, opt, args, &argi, argc)
fieldName, err = cli.VerbGetStringArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
} else if opt == "--start" {
startString = cli.VerbGetStringArgOrDie(verb, opt, args, &argi, argc)
startString, err = cli.VerbGetStringArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
} else if opt == "--stop" {
stopString = cli.VerbGetStringArgOrDie(verb, opt, args, &argi, argc)
stopString, err = cli.VerbGetStringArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
} else if opt == "--step" {
stepString = cli.VerbGetStringArgOrDie(verb, opt, args, &argi, argc)
stepString, err = cli.VerbGetStringArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
} else {
transformerSeqgenUsage(os.Stderr)
os.Exit(1)
return nil, cli.VerbErrorf(verb, "option \"%s\" not recognized", opt)
}
}
*pargi = argi
if !doConstruct { // All transformers must do this for main command-line parsing
return nil
return nil, nil
}
transformer, err := NewTransformerSeqgen(
@ -102,11 +114,10 @@ func transformerSeqgenParseCLI(
stepString,
)
if err != nil {
fmt.Fprintf(os.Stderr, "mlr: %v\n", err)
os.Exit(1)
return nil, err
}
return transformer
return transformer, nil
}
type TransformerSeqgen struct {

View file

@ -37,7 +37,7 @@ func transformerShuffleParseCLI(
args []string,
_ *cli.TOptions,
doConstruct bool, // false for first pass of CLI-parse, true for second pass
) RecordTransformer {
) (RecordTransformer, error) {
// Skip the verb name from the current spot in the mlr command line
argi := *pargi
@ -55,25 +55,23 @@ func transformerShuffleParseCLI(
if opt == "-h" || opt == "--help" {
transformerShuffleUsage(os.Stdout)
os.Exit(0)
return nil, cli.ErrHelpRequested
}
transformerShuffleUsage(os.Stderr)
os.Exit(1)
return nil, cli.VerbErrorf(verbNameShuffle, "option \"%s\" not recognized", opt)
}
*pargi = argi
if !doConstruct { // All transformers must do this for main command-line parsing
return nil
return nil, nil
}
transformer, err := NewTransformerShuffle()
if err != nil {
fmt.Fprintf(os.Stderr, "mlr: %v\n", err)
os.Exit(1)
return nil, err
}
return transformer
return transformer, nil
}
type TransformerShuffle struct {

View file

@ -34,7 +34,7 @@ func transformerSkipTrivialRecordsParseCLI(
args []string,
_ *cli.TOptions,
doConstruct bool, // false for first pass of CLI-parse, true for second pass
) RecordTransformer {
) (RecordTransformer, error) {
// Skip the verb name from the current spot in the mlr command line
argi := *pargi
@ -52,25 +52,23 @@ func transformerSkipTrivialRecordsParseCLI(
if opt == "-h" || opt == "--help" {
transformerSkipTrivialRecordsUsage(os.Stdout)
os.Exit(0)
return nil, cli.ErrHelpRequested
}
transformerSkipTrivialRecordsUsage(os.Stderr)
os.Exit(1)
return nil, cli.VerbErrorf(verbNameSkipTrivialRecords, "option \"%s\" not recognized", opt)
}
*pargi = argi
if !doConstruct { // All transformers must do this for main command-line parsing
return nil
return nil, nil
}
transformer, err := NewTransformerSkipTrivialRecords()
if err != nil {
fmt.Fprintf(os.Stderr, "mlr: %v\n", err)
os.Exit(1)
return nil, err
}
return transformer
return transformer, nil
}
type TransformerSkipTrivialRecords struct {

View file

@ -95,7 +95,7 @@ func transformerSortParseCLI(
args []string,
_ *cli.TOptions,
doConstruct bool, // false for first pass of CLI-parse, true for second pass
) RecordTransformer {
) (RecordTransformer, error) {
// Skip the verb name from the current spot in the mlr command line
argi := *pargi
@ -118,10 +118,13 @@ func transformerSortParseCLI(
if opt == "-h" || opt == "--help" {
transformerSortUsage(os.Stdout)
os.Exit(0)
return nil, cli.ErrHelpRequested
} else if opt == "-f" {
subList := cli.VerbGetStringArrayArgOrDie(verb, opt, args, &argi, argc)
subList, err := cli.VerbGetStringArrayArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
for _, item := range subList {
groupByFieldNames = append(groupByFieldNames, item)
comparatorFuncs = append(comparatorFuncs, mlrval.LexicalAscendingComparator)
@ -131,16 +134,24 @@ func transformerSortParseCLI(
// See comments over "-n" -- similar hack.
if args[argi] == "-r" {
// Treat like "-cr"
cli.VerbCheckArgCount(verb, args[argi], args, argi, argc, 1)
if err := cli.VerbCheckArgCount(verb, args[argi], args, argi, argc, 1); err != nil {
return nil, err
}
argi++
subList := cli.VerbGetStringArrayArgOrDie(verb, "-nr", args, &argi, argc)
subList, err := cli.VerbGetStringArrayArg(verb, "-nr", args, &argi, argc)
if err != nil {
return nil, err
}
for _, item := range subList {
groupByFieldNames = append(groupByFieldNames, item)
comparatorFuncs = append(comparatorFuncs, mlrval.CaseFoldDescendingComparator)
}
} else {
subList := cli.VerbGetStringArrayArgOrDie(verb, opt, args, &argi, argc)
subList, err := cli.VerbGetStringArrayArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
for _, item := range subList {
groupByFieldNames = append(groupByFieldNames, item)
comparatorFuncs = append(comparatorFuncs, mlrval.CaseFoldAscendingComparator)
@ -149,18 +160,28 @@ func transformerSortParseCLI(
} else if opt == "-t" {
// See comments over "-n" -- similar hack.
cli.VerbCheckArgCount(verb, opt, args, argi, argc, 1)
if err := cli.VerbCheckArgCount(verb, opt, args, argi, argc, 1); err != nil {
return nil, err
}
if args[argi] == "-r" {
// Treat like "-tr"
cli.VerbCheckArgCount(verb, args[argi], args, argi, argc, 1)
if err := cli.VerbCheckArgCount(verb, args[argi], args, argi, argc, 1); err != nil {
return nil, err
}
argi++
subList := cli.VerbGetStringArrayArgOrDie(verb, "-tr", args, &argi, argc)
subList, err := cli.VerbGetStringArrayArg(verb, "-tr", args, &argi, argc)
if err != nil {
return nil, err
}
for _, item := range subList {
groupByFieldNames = append(groupByFieldNames, item)
comparatorFuncs = append(comparatorFuncs, mlrval.NaturalAscendingComparator)
}
} else {
subList := cli.VerbGetStringArrayArgOrDie(verb, opt, args, &argi, argc)
subList, err := cli.VerbGetStringArrayArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
for _, item := range subList {
groupByFieldNames = append(groupByFieldNames, item)
comparatorFuncs = append(comparatorFuncs, mlrval.NaturalDescendingComparator)
@ -169,18 +190,28 @@ func transformerSortParseCLI(
} else if opt == "-r" {
// See comments over "-n" -- similar hack.
cli.VerbCheckArgCount(verb, opt, args, argi, argc, 1)
if err := cli.VerbCheckArgCount(verb, opt, args, argi, argc, 1); err != nil {
return nil, err
}
if args[argi] == "-t" {
// Treat like "-rt" which is same as "-tr"
cli.VerbCheckArgCount(verb, args[argi], args, argi, argc, 1)
if err := cli.VerbCheckArgCount(verb, args[argi], args, argi, argc, 1); err != nil {
return nil, err
}
argi++
subList := cli.VerbGetStringArrayArgOrDie(verb, "-tr", args, &argi, argc)
subList, err := cli.VerbGetStringArrayArg(verb, "-tr", args, &argi, argc)
if err != nil {
return nil, err
}
for _, item := range subList {
groupByFieldNames = append(groupByFieldNames, item)
comparatorFuncs = append(comparatorFuncs, mlrval.NaturalAscendingComparator)
}
} else {
subList := cli.VerbGetStringArrayArgOrDie(verb, opt, args, &argi, argc)
subList, err := cli.VerbGetStringArrayArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
for _, item := range subList {
groupByFieldNames = append(groupByFieldNames, item)
comparatorFuncs = append(comparatorFuncs, mlrval.LexicalDescendingComparator)
@ -210,12 +241,17 @@ func transformerSortParseCLI(
// So here we special-case this: if "-n" is followed immediately by
// "-f", we treat it the same as "-nf". Likewise, "-n" followed by
// "-r" is treated like "-nr".
cli.VerbCheckArgCount(verb, opt, args, argi, argc, 1)
if err := cli.VerbCheckArgCount(verb, opt, args, argi, argc, 1); err != nil {
return nil, err
}
if args[argi] == "-f" {
// Treat like "-nf"
argi++
subList := cli.VerbGetStringArrayArgOrDie(verb, "-nf", args, &argi, argc)
subList, err := cli.VerbGetStringArrayArg(verb, "-nf", args, &argi, argc)
if err != nil {
return nil, err
}
for _, item := range subList {
groupByFieldNames = append(groupByFieldNames, item)
comparatorFuncs = append(comparatorFuncs, mlrval.NumericAscendingComparator)
@ -224,7 +260,10 @@ func transformerSortParseCLI(
} else if args[argi] == "-r" {
// Treat like "-nr"
argi++
subList := cli.VerbGetStringArrayArgOrDie(verb, "-nr", args, &argi, argc)
subList, err := cli.VerbGetStringArrayArg(verb, "-nr", args, &argi, argc)
if err != nil {
return nil, err
}
for _, item := range subList {
groupByFieldNames = append(groupByFieldNames, item)
comparatorFuncs = append(comparatorFuncs, mlrval.NumericDescendingComparator)
@ -232,7 +271,10 @@ func transformerSortParseCLI(
} else {
// Treat like "-n"
subList := cli.VerbGetStringArrayArgOrDie(verb, opt, args, &argi, argc)
subList, err := cli.VerbGetStringArrayArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
for _, item := range subList {
groupByFieldNames = append(groupByFieldNames, item)
comparatorFuncs = append(comparatorFuncs, mlrval.NumericAscendingComparator)
@ -240,14 +282,20 @@ func transformerSortParseCLI(
}
} else if opt == "-nf" {
subList := cli.VerbGetStringArrayArgOrDie(verb, opt, args, &argi, argc)
subList, err := cli.VerbGetStringArrayArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
for _, item := range subList {
groupByFieldNames = append(groupByFieldNames, item)
comparatorFuncs = append(comparatorFuncs, mlrval.NumericAscendingComparator)
}
} else if opt == "-nr" {
subList := cli.VerbGetStringArrayArgOrDie(verb, opt, args, &argi, argc)
subList, err := cli.VerbGetStringArrayArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
for _, item := range subList {
groupByFieldNames = append(groupByFieldNames, item)
comparatorFuncs = append(comparatorFuncs, mlrval.NumericDescendingComparator)
@ -257,19 +305,17 @@ func transformerSortParseCLI(
doMoveToHead = true
} else {
transformerSortUsage(os.Stderr)
os.Exit(1)
return nil, cli.VerbErrorf(verb, "option \"%s\" not recognized", opt)
}
}
if len(groupByFieldNames) == 0 {
transformerSortUsage(os.Stderr)
os.Exit(1)
return nil, cli.VerbErrorf(verb, "-f sort fields required")
}
*pargi = argi
if !doConstruct { // All transformers must do this for main command-line parsing
return nil
return nil, nil
}
transformer, err := NewTransformerSort(
@ -278,11 +324,10 @@ func transformerSortParseCLI(
doMoveToHead,
)
if err != nil {
fmt.Fprintf(os.Stderr, "mlr: %v\n", err)
os.Exit(1)
return nil, err
}
return transformer
return transformer, nil
}
// Example:

View file

@ -34,7 +34,7 @@ func transformerSortWithinRecordsParseCLI(
args []string,
_ *cli.TOptions,
doConstruct bool, // false for first pass of CLI-parse, true for second pass
) RecordTransformer {
) (RecordTransformer, error) {
// Skip the verb name from the current spot in the mlr command line
argi := *pargi
@ -53,14 +53,13 @@ func transformerSortWithinRecordsParseCLI(
if opt == "-h" || opt == "--help" {
transformerSortWithinRecordsUsage(os.Stdout)
os.Exit(0)
return nil, cli.ErrHelpRequested
} else if opt == "-r" {
doRecurse = true
} else {
transformerSortWithinRecordsUsage(os.Stderr)
os.Exit(1)
return nil, cli.VerbErrorf(verbNameSortWithinRecords, "option \"%s\" not recognized", opt)
}
}
@ -69,16 +68,15 @@ func transformerSortWithinRecordsParseCLI(
*pargi = argi
if !doConstruct { // All transformers must do this for main command-line parsing
return nil
return nil, nil
}
transformer, err := NewTransformerSortWithinRecords(doRecurse)
if err != nil {
fmt.Fprintf(os.Stderr, "mlr: %v\n", err)
os.Exit(1)
return nil, err
}
return transformer
return transformer, nil
}
type TransformerSortWithinRecords struct {

View file

@ -46,7 +46,7 @@ func transformerSparsifyParseCLI(
args []string,
_ *cli.TOptions,
doConstruct bool, // false for first pass of CLI-parse, true for second pass
) RecordTransformer {
) (RecordTransformer, error) {
// Skip the verb name from the current spot in the mlr command line
argi := *pargi
@ -56,6 +56,7 @@ func transformerSparsifyParseCLI(
fillerString := ""
var specifiedFieldNames []string = nil
var err error
for argi < argc /* variable increment: 1 or 2 depending on flag */ {
opt := args[argi]
if !strings.HasPrefix(opt, "-") {
@ -68,23 +69,28 @@ func transformerSparsifyParseCLI(
if opt == "-h" || opt == "--help" {
transformerSparsifyUsage(os.Stdout)
os.Exit(0)
return nil, cli.ErrHelpRequested
} else if opt == "-s" {
fillerString = cli.VerbGetStringArgOrDie(verb, opt, args, &argi, argc)
fillerString, err = cli.VerbGetStringArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
} else if opt == "-f" {
specifiedFieldNames = cli.VerbGetStringArrayArgOrDie(verb, opt, args, &argi, argc)
specifiedFieldNames, err = cli.VerbGetStringArrayArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
} else {
transformerSparsifyUsage(os.Stderr)
os.Exit(1)
return nil, cli.VerbErrorf(verb, "option \"%s\" not recognized", opt)
}
}
*pargi = argi
if !doConstruct { // All transformers must do this for main command-line parsing
return nil
return nil, nil
}
transformer, err := NewTransformerSparsify(
@ -92,11 +98,10 @@ func transformerSparsifyParseCLI(
specifiedFieldNames,
)
if err != nil {
fmt.Fprintf(os.Stderr, "mlr: %v\n", err)
os.Exit(1)
return nil, err
}
return transformer
return transformer, nil
}
type TransformerSparsify struct {

View file

@ -80,7 +80,7 @@ func transformerSplitParseCLI(
args []string,
mainOptions *cli.TOptions,
doConstruct bool, // false for first pass of CLI-parse, true for second pass
) RecordTransformer {
) (RecordTransformer, error) {
// Skip the verb name from the current spot in the mlr command line
argi := *pargi
@ -107,6 +107,7 @@ func transformerSplitParseCLI(
}
// Parse local flags.
var err error
for argi < argc /* variable increment: 1 or 2 depending on flag */ {
opt := args[argi]
if !strings.HasPrefix(opt, "-") {
@ -119,28 +120,46 @@ func transformerSplitParseCLI(
if opt == "-h" || opt == "--help" {
transformerSplitUsage(os.Stdout)
os.Exit(0)
return nil, cli.ErrHelpRequested
} else if opt == "-n" {
n = cli.VerbGetIntArgOrDie(verb, opt, args, &argi, argc)
n, err = cli.VerbGetIntArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
doSize = true
} else if opt == "-m" {
n = cli.VerbGetIntArgOrDie(verb, opt, args, &argi, argc)
n, err = cli.VerbGetIntArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
doMod = true
} else if opt == "-g" {
groupByFieldNames = cli.VerbGetStringArrayArgOrDie(verb, opt, args, &argi, argc)
groupByFieldNames, err = cli.VerbGetStringArrayArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
} else if opt == "--prefix" {
outputFileNamePrefix = cli.VerbGetStringArgOrDie(verb, opt, args, &argi, argc)
outputFileNamePrefix, err = cli.VerbGetStringArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
} else if opt == "--suffix" {
outputFileNameSuffix = cli.VerbGetStringArgOrDie(verb, opt, args, &argi, argc)
outputFileNameSuffix, err = cli.VerbGetStringArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
haveOutputFileNameSuffix = true
} else if opt == "--folder" {
outputFolder = cli.VerbGetStringArgOrDie(verb, opt, args, &argi, argc)
outputFolder, err = cli.VerbGetStringArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
} else if opt == "-a" {
doAppend = true
@ -152,7 +171,10 @@ func transformerSplitParseCLI(
escapeFileNameCharacters = false
} else if opt == "-j" {
fileNamePartJoiner = cli.VerbGetStringArgOrDie(verb, opt, args, &argi, argc)
fileNamePartJoiner, err = cli.VerbGetStringArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
} else {
// This is inelegant. For error-proofing we advance argi already in our
@ -164,20 +186,17 @@ func transformerSplitParseCLI(
// Nothing else to handle here.
argi = largi
} else {
transformerSplitUsage(os.Stderr)
os.Exit(1)
return nil, cli.VerbErrorf(verb, "output format not recognized")
}
}
}
doGroup := groupByFieldNames != nil
if !doMod && !doSize && !doGroup {
fmt.Fprintf(os.Stderr, "mlr %s: At least one of -m, -n, or -g is required.\n", verb)
os.Exit(1)
return nil, cli.VerbErrorf(verb, "-n, -g, or -s is required")
}
if (doMod && doSize) || (doMod && doGroup) || (doSize && doGroup) {
fmt.Fprintf(os.Stderr, "mlr %s: Only one of -m, -n, or -g is required.\n", verb)
os.Exit(1)
return nil, cli.VerbErrorf(verb, "-n, -g, and -s are mutually exclusive")
}
cli.FinalizeWriterOptions(&localOptions.WriterOptions)
@ -187,7 +206,7 @@ func transformerSplitParseCLI(
*pargi = argi
if !doConstruct { // All transformers must do this for main command-line parsing
return nil
return nil, nil
}
transformer, err := NewTransformerSplit(
@ -209,7 +228,7 @@ func transformerSplitParseCLI(
os.Exit(1)
}
return transformer
return transformer, nil
}
type TransformerSplit struct {
@ -310,7 +329,7 @@ func (tr *TransformerSplit) splitModUngrouped(
err := tr.outputHandlerManager.WriteRecordAndContext(inrecAndContext, filename)
if err != nil {
fmt.Fprintf(os.Stderr, "mlr: file-write error: %v\n", err)
fmt.Fprintf(os.Stderr, "mlr: %v\n", err)
os.Exit(1)
}
@ -346,7 +365,7 @@ func (tr *TransformerSplit) splitSizeUngrouped(
if tr.outputHandler != nil {
err = tr.outputHandler.Close()
if err != nil {
fmt.Fprintf(os.Stderr, "mlr: file-close error: %v\n", err)
fmt.Fprintf(os.Stderr, "mlr: %v\n", err)
os.Exit(1)
}
}
@ -358,7 +377,7 @@ func (tr *TransformerSplit) splitSizeUngrouped(
tr.doAppend,
)
if err != nil {
fmt.Fprintf(os.Stderr, "mlr: file-open error: %v\n", err)
fmt.Fprintf(os.Stderr, "mlr: %v\n", err)
os.Exit(1)
}
@ -367,7 +386,7 @@ func (tr *TransformerSplit) splitSizeUngrouped(
err = tr.outputHandler.WriteRecordAndContext(inrecAndContext)
if err != nil {
fmt.Fprintf(os.Stderr, "mlr: file-write error: %v\n", err)
fmt.Fprintf(os.Stderr, "mlr: %v\n", err)
os.Exit(1)
}
@ -383,7 +402,7 @@ func (tr *TransformerSplit) splitSizeUngrouped(
if tr.outputHandler != nil {
err := tr.outputHandler.Close()
if err != nil {
fmt.Fprintf(os.Stderr, "mlr: file-close error: %v\n", err)
fmt.Fprintf(os.Stderr, "mlr: %v\n", err)
os.Exit(1)
}
}

View file

@ -92,7 +92,7 @@ func transformerStats1ParseCLI(
args []string,
_ *cli.TOptions,
doConstruct bool, // false for first pass of CLI-parse, true for second pass
) RecordTransformer {
) (RecordTransformer, error) {
// Skip the verb name from the current spot in the mlr command line
argi := *pargi
@ -111,6 +111,7 @@ func transformerStats1ParseCLI(
doInterpolatedPercentiles := false
doIterativeStats := false
var err error
for argi < argc /* variable increment: 1 or 2 depending on flag */ {
opt := args[argi]
if !strings.HasPrefix(opt, "-") {
@ -123,30 +124,51 @@ func transformerStats1ParseCLI(
if opt == "-h" || opt == "--help" {
transformerStats1Usage(os.Stdout)
os.Exit(0)
return nil, cli.ErrHelpRequested
} else if opt == "-a" {
accumulatorNameList = cli.VerbGetStringArrayArgOrDie(verb, opt, args, &argi, argc)
accumulatorNameList, err = cli.VerbGetStringArrayArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
} else if opt == "-f" {
valueFieldNameList = cli.VerbGetStringArrayArgOrDie(verb, opt, args, &argi, argc)
valueFieldNameList, err = cli.VerbGetStringArrayArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
} else if opt == "-g" {
groupByFieldNameList = cli.VerbGetStringArrayArgOrDie(verb, opt, args, &argi, argc)
groupByFieldNameList, err = cli.VerbGetStringArrayArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
} else if opt == "--fr" {
valueFieldNameList = cli.VerbGetStringArrayArgOrDie(verb, opt, args, &argi, argc)
valueFieldNameList, err = cli.VerbGetStringArrayArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
doRegexValueFieldNames = true
} else if opt == "--fx" {
valueFieldNameList = cli.VerbGetStringArrayArgOrDie(verb, opt, args, &argi, argc)
valueFieldNameList, err = cli.VerbGetStringArrayArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
doRegexValueFieldNames = true
invertRegexValueFieldNames = true
} else if opt == "--gr" {
groupByFieldNameList = cli.VerbGetStringArrayArgOrDie(verb, opt, args, &argi, argc)
groupByFieldNameList, err = cli.VerbGetStringArrayArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
doRegexGroupByFieldNames = true
} else if opt == "--gx" {
groupByFieldNameList = cli.VerbGetStringArrayArgOrDie(verb, opt, args, &argi, argc)
groupByFieldNameList, err = cli.VerbGetStringArrayArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
doRegexGroupByFieldNames = true
invertRegexGroupByFieldNames = true
@ -154,7 +176,10 @@ func transformerStats1ParseCLI(
doRegexValueFieldNames = true
doRegexGroupByFieldNames = true
invertRegexValueFieldNames = true
valueFieldNameList = cli.VerbGetStringArrayArgOrDie(verb, opt, args, &argi, argc)
valueFieldNameList, err = cli.VerbGetStringArrayArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
groupByFieldNameList = lib.CopyStringArray(valueFieldNameList)
} else if opt == "-i" {
@ -170,26 +195,21 @@ func transformerStats1ParseCLI(
// No-op pass-through for backward compatibility with Miller 5
} else {
transformerStats1Usage(os.Stderr)
os.Exit(1)
return nil, cli.VerbErrorf(verbNameStats1, "option \"%s\" not recognized", opt)
}
}
// TODO: libify for use across verbs.
if len(accumulatorNameList) == 0 {
fmt.Fprintf(os.Stderr, "%s %s: -a option is required.\n", "mlr", verbNameStats1)
fmt.Fprintf(os.Stderr, "Please see %s %s --help for more information.\n", "mlr", verbNameStats1)
os.Exit(1)
return nil, cli.VerbErrorf(verbNameStats1, "-a option is required")
}
if len(valueFieldNameList) == 0 {
fmt.Fprintf(os.Stderr, "%s %s: -f option is required.\n", "mlr", verbNameStats1)
fmt.Fprintf(os.Stderr, "Please see %s %s --help for more information.\n", "mlr", verbNameStats1)
os.Exit(1)
return nil, cli.VerbErrorf(verbNameStats1, "-f option is required")
}
*pargi = argi
if !doConstruct { // All transformers must do this for main command-line parsing
return nil
return nil, nil
}
transformer, err := NewTransformerStats1(
@ -206,11 +226,10 @@ func transformerStats1ParseCLI(
doIterativeStats,
)
if err != nil {
fmt.Fprintf(os.Stderr, "mlr stats1: %v\n", err)
os.Exit(1)
return nil, err
}
return transformer
return transformer, nil
}
type TransformerStats1 struct {
@ -309,7 +328,7 @@ func NewTransformerStats1(
) (*TransformerStats1, error) {
for _, name := range accumulatorNameList {
if !utils.ValidateStats1AccumulatorName(name) {
return nil, fmt.Errorf(`accumulator "%s" not found`, name)
return nil, fmt.Errorf(`mlr stats1: accumulator "%s" not found`, name)
}
}

View file

@ -62,15 +62,13 @@ func transformerStats2ParseCLI(
args []string,
_ *cli.TOptions,
doConstruct bool, // false for first pass of CLI-parse, true for second pass
) RecordTransformer {
) (RecordTransformer, error) {
// Skip the verb name from the current spot in the mlr command line
argi := *pargi
verb := args[argi]
argi++
argv0 := "mlr"
var accumulatorNameList []string = nil
var valueFieldNameList []string = nil
groupByFieldNameList := []string{}
@ -78,6 +76,7 @@ func transformerStats2ParseCLI(
doIterativeStats := false
doHoldAndFit := false
var err error
for argi < argc /* variable increment: 1 or 2 depending on flag */ {
opt := args[argi]
if !strings.HasPrefix(opt, "-") {
@ -90,16 +89,25 @@ func transformerStats2ParseCLI(
if opt == "-h" || opt == "--help" {
transformerStats2Usage(os.Stdout)
os.Exit(0)
return nil, cli.ErrHelpRequested
} else if opt == "-a" {
accumulatorNameList = cli.VerbGetStringArrayArgOrDie(verb, opt, args, &argi, argc)
accumulatorNameList, err = cli.VerbGetStringArrayArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
} else if opt == "-f" {
valueFieldNameList = cli.VerbGetStringArrayArgOrDie(verb, opt, args, &argi, argc)
valueFieldNameList, err = cli.VerbGetStringArrayArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
} else if opt == "-g" {
groupByFieldNameList = cli.VerbGetStringArrayArgOrDie(verb, opt, args, &argi, argc)
groupByFieldNameList, err = cli.VerbGetStringArrayArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
} else if opt == "-v" {
doVerbose = true
@ -120,34 +128,26 @@ func transformerStats2ParseCLI(
// for all applicable stats2 accumulators (i.e. none of them).
} else {
transformerStats2Usage(os.Stderr)
os.Exit(1)
return nil, cli.VerbErrorf(verb, "option \"%s\" not recognized", opt)
}
}
if doIterativeStats && doHoldAndFit {
transformerStats2Usage(os.Stderr)
os.Exit(1)
return nil, cli.VerbErrorf(verb, "cannot combine -I and -H")
}
if accumulatorNameList == nil {
fmt.Fprintf(os.Stderr, "%s %s: -a option is required.\n", argv0, verb)
fmt.Fprintf(os.Stderr, "Please see %s %s --help for more information.\n", argv0, verb)
os.Exit(1)
return nil, cli.VerbErrorf(verb, "-a option is required")
}
if valueFieldNameList == nil {
fmt.Fprintf(os.Stderr, "%s %s: -f option is required.\n", argv0, verb)
fmt.Fprintf(os.Stderr, "Please see %s %s --help for more information.\n", argv0, verb)
os.Exit(1)
return nil, cli.VerbErrorf(verb, "-f option is required")
}
if len(valueFieldNameList)%2 != 0 {
fmt.Fprintf(os.Stderr, "%s %s: argument to -f must have even number of fields.\n", argv0, verb)
fmt.Fprintf(os.Stderr, "Please see %s %s --help for more information.\n", argv0, verb)
os.Exit(1)
return nil, cli.VerbErrorf(verb, "argument to -f must have even number of fields")
}
*pargi = argi
if !doConstruct { // All transformers must do this for main command-line parsing
return nil
return nil, nil
}
transformer, err := NewTransformerStats2(
@ -159,11 +159,10 @@ func transformerStats2ParseCLI(
doHoldAndFit,
)
if err != nil {
fmt.Fprintf(os.Stderr, "mlr: %v\n", err)
os.Exit(1)
return nil, err
}
return transformer
return transformer, nil
}
type TransformerStats2 struct {
@ -348,9 +347,7 @@ func (tr *TransformerStats2) ingest(
tr.doVerbose,
)
if accumulator == nil {
fmt.Fprintf(os.Stderr, "%s %s: accumulator \"%s\" not found.\n",
"mlr", verbNameStats2, accumulatorName,
)
fmt.Fprintf(os.Stderr, "mlr stats2: accumulator creation failed\n")
os.Exit(1)
}
valueFieldsToAccumulator.Put(accumulatorName, accumulator)

View file

@ -143,7 +143,7 @@ func transformerStepParseCLI(
args []string,
_ *cli.TOptions,
doConstruct bool, // false for first pass of CLI-parse, true for second pass
) RecordTransformer {
) (RecordTransformer, error) {
// Skip the verb name from the current spot in the mlr command line
argi := *pargi
@ -168,51 +168,67 @@ func transformerStepParseCLI(
if opt == "-h" || opt == "--help" {
transformerStepUsage(os.Stdout)
os.Exit(0)
return nil, cli.ErrHelpRequested
} else if opt == "-a" {
// Let them do '-a delta -a rsum' or '-a delta,rsum'
stepperNames := cli.VerbGetStringArrayArgOrDie(verb, opt, args, &argi, argc)
stepperNames, err := cli.VerbGetStringArrayArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
for _, stepperName := range stepperNames {
stepperInput := stepperInputFromName(stepperName)
if stepperInput == nil {
fmt.Fprintf(os.Stderr, "mlr %s: stepper \"%s\" not found.\n",
verbNameStep, stepperName)
os.Exit(1)
return nil, cli.VerbErrorf(verb, "stepper \"%s\" not found", stepperName)
}
stepperInputs = append(stepperInputs, stepperInput)
}
} else if opt == "-f" {
// Let them do '-f x -f y' or '-f x,y'
valueFieldNames = append(valueFieldNames, cli.VerbGetStringArrayArgOrDie(verb, opt, args, &argi, argc)...)
arr, err := cli.VerbGetStringArrayArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
valueFieldNames = append(valueFieldNames, arr...)
} else if opt == "-g" {
// Let them do '-g a -g b' or '-g a,b'
groupByFieldNames = append(groupByFieldNames, cli.VerbGetStringArrayArgOrDie(verb, opt, args, &argi, argc)...)
arr, err := cli.VerbGetStringArrayArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
groupByFieldNames = append(groupByFieldNames, arr...)
} else if opt == "-d" {
// Let them do '-d 0.8 -d 0.9' or '-d 0.8,0.9'
stringAlphas = append(stringAlphas, cli.VerbGetStringArrayArgOrDie(verb, opt, args, &argi, argc)...)
arr, err := cli.VerbGetStringArrayArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
stringAlphas = append(stringAlphas, arr...)
} else if opt == "-o" {
// Let them do '-o fast -o slow' or '-o fast,slow'
ewmaSuffixes = append(ewmaSuffixes, cli.VerbGetStringArrayArgOrDie(verb, opt, args, &argi, argc)...)
arr, err := cli.VerbGetStringArrayArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
ewmaSuffixes = append(ewmaSuffixes, arr...)
} else if opt == "-F" {
// As of Miller 6 this happens automatically, but the flag is accepted
// as a no-op for backward compatibility with Miller 5 and below.
} else {
transformerStepUsage(os.Stderr)
os.Exit(1)
return nil, cli.VerbErrorf(verb, "option \"%s\" not recognized", opt)
}
}
*pargi = argi
if !doConstruct { // All transformers must do this for main command-line parsing
return nil
return nil, nil
}
transformer, err := NewTransformerStep(
@ -223,11 +239,10 @@ func transformerStepParseCLI(
ewmaSuffixes,
)
if err != nil {
fmt.Fprintf(os.Stderr, "mlr: %v\n", err)
os.Exit(1)
return nil, err
}
return transformer
return transformer, nil
}
// This is the "stepper log" referred to in comments at the top of this file.
@ -436,8 +451,7 @@ func (tr *TransformerStep) handleRecord(
tr.ewmaSuffixes,
)
if stepper == nil {
fmt.Fprintf(os.Stderr, "mlr %s: stepper \"%s\" not found.\n",
verbNameStep, stepperInput.name)
fmt.Fprintf(os.Stderr, "mlr step: stepper allocation failed\n")
os.Exit(1)
}
accFieldToAccState[stepperInput.name] = stepper

View file

@ -97,7 +97,7 @@ func transformerSubParseCLI(
args []string,
opts *cli.TOptions,
doConstruct bool, // false for first pass of CLI-parse, true for second pass
) RecordTransformer {
) (RecordTransformer, error) {
return transformerSubsParseCLI(pargi, argc, args, opts, doConstruct, transformerSubUsage, NewTransformerSub)
}
@ -107,7 +107,7 @@ func transformerGsubParseCLI(
args []string,
opts *cli.TOptions,
doConstruct bool, // false for first pass of CLI-parse, true for second pass
) RecordTransformer {
) (RecordTransformer, error) {
return transformerSubsParseCLI(pargi, argc, args, opts, doConstruct, transformerGsubUsage, NewTransformerGsub)
}
@ -117,7 +117,7 @@ func transformerSsubParseCLI(
args []string,
opts *cli.TOptions,
doConstruct bool, // false for first pass of CLI-parse, true for second pass
) RecordTransformer {
) (RecordTransformer, error) {
return transformerSubsParseCLI(pargi, argc, args, opts, doConstruct, transformerSsubUsage, NewTransformerSsub)
}
@ -130,7 +130,7 @@ func transformerSubsParseCLI(
doConstruct bool, // false for first pass of CLI-parse, true for second pass
usageFunc TransformerUsageFunc,
constructorFunc subConstructorFunc,
) RecordTransformer {
) (RecordTransformer, error) {
// Skip the verb name from the current spot in the mlr command line
argi := *pargi
@ -144,6 +144,7 @@ func transformerSubsParseCLI(
var oldText string
var newText string
var err error
for argi < argc /* variable increment: 1 or 2 depending on flag */ {
opt := args[argi]
if !strings.HasPrefix(opt, "-") {
@ -167,7 +168,10 @@ func transformerSubsParseCLI(
doRegexes = true
} else if opt == "-f" {
fieldNames = cli.VerbGetStringArrayArgOrDie(verb, opt, args, &argi, argc)
fieldNames, err = cli.VerbGetStringArrayArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
doAllFieldNames = false
} else {
usageFunc(os.Stderr)
@ -192,7 +196,7 @@ func transformerSubsParseCLI(
*pargi = argi
if !doConstruct { // All transformers must do this for main command-line parsing
return nil
return nil, nil
}
transformer, err := constructorFunc(
@ -203,11 +207,10 @@ func transformerSubsParseCLI(
newText,
)
if err != nil {
fmt.Fprintf(os.Stderr, "mlr: %v\n", err)
os.Exit(1)
return nil, err
}
return transformer
return transformer, nil
}
type TransformerSubs struct {
@ -273,8 +276,7 @@ func NewTransformerSubs(
// Handles "a.*b"i Miller case-insensitive-regex specification
regex, err := lib.CompileMillerRegex(regexString)
if err != nil {
fmt.Fprintf(os.Stderr, "%s %s: cannot compile regex [%s]\n", "mlr", verbNameCut, regexString)
os.Exit(1)
return nil, cli.VerbErrorf("sub", "invalid regex \"%s\": %w", regexString, err)
}
tr.regexes[i] = regex
}

View file

@ -114,7 +114,7 @@ func transformerSummaryParseCLI(
args []string,
_ *cli.TOptions,
doConstruct bool, // false for first pass of CLI-parse, true for second pass
) RecordTransformer {
) (RecordTransformer, error) {
// Skip the verb name from the current spot in the mlr command line
argi := *pargi
@ -135,6 +135,7 @@ func transformerSummaryParseCLI(
transposeOutput := false
var err error
for argi < argc /* variable increment: 1 or 2 depending on flag */ {
opt := args[argi]
if !strings.HasPrefix(opt, "-") {
@ -147,30 +148,30 @@ func transformerSummaryParseCLI(
if opt == "-h" || opt == "--help" {
transformerSummaryUsage(os.Stdout)
os.Exit(0)
return nil, cli.ErrHelpRequested
} else if opt == "--all" {
summarizerNames = allSummarizerNamesList
} else if opt == "-a" {
summarizerNames = cli.VerbGetStringArrayArgOrDie(verb, opt, args, &argi, argc)
summarizerNames, err = cli.VerbGetStringArrayArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
for _, summarizerName := range summarizerNames {
if !allSummarizerNamesSet[summarizerName] {
fmt.Fprintf(os.Stderr, "mlr %s: unrecognized summarizer name %s\n",
verb, summarizerName,
)
os.Exit(1)
return nil, cli.VerbErrorf(verb, "summarizer \"%s\" not found", summarizerName)
}
}
} else if opt == "-x" {
excludeSummarizerNames := cli.VerbGetStringArrayArgOrDie(verb, opt, args, &argi, argc)
excludeSummarizerNames, err := cli.VerbGetStringArrayArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
for _, excludeSummarizerName := range excludeSummarizerNames {
if !allSummarizerNamesSet[excludeSummarizerName] {
fmt.Fprintf(os.Stderr, "mlr %s: unrecognized Summarizer name %s\n",
verb, excludeSummarizerName,
)
os.Exit(1)
return nil, cli.VerbErrorf(verb, "exclude summarizer \"%s\" not found", excludeSummarizerName)
}
}
@ -190,23 +191,21 @@ func transformerSummaryParseCLI(
transposeOutput = true
} else {
transformerSummaryUsage(os.Stderr)
os.Exit(1)
return nil, cli.VerbErrorf(verb, "option \"%s\" not recognized", opt)
}
}
*pargi = argi
if !doConstruct { // All transformers must do this for main command-line parsing
return nil
return nil, nil
}
transformer, err := NewTransformerSummary(summarizerNames, transposeOutput)
if err != nil {
fmt.Fprintf(os.Stderr, "mlr: %v\n", err)
os.Exit(1)
return nil, err
}
return transformer
return transformer, nil
}
type tFieldSummary struct {

View file

@ -39,7 +39,7 @@ func transformerSurvParseCLI(
args []string,
_ *cli.TOptions,
doConstruct bool,
) RecordTransformer {
) (RecordTransformer, error) {
argi := *pargi
verb := args[argi]
argi++
@ -53,19 +53,17 @@ func transformerSurvParseCLI(
}
if opt == "-h" || opt == "--help" {
transformerSurvUsage(os.Stdout)
os.Exit(0)
return nil, cli.ErrHelpRequested
} else if opt == "-d" {
if argi+1 >= argc {
fmt.Fprintf(os.Stderr, "mlr %s: %s requires an argument\n", verb, opt)
os.Exit(1)
return nil, cli.VerbErrorf(verb, "-d requires an argument")
}
argi++
durationField = args[argi]
argi++
} else if opt == "-s" {
if argi+1 >= argc {
fmt.Fprintf(os.Stderr, "mlr %s: %s requires an argument\n", verb, opt)
os.Exit(1)
return nil, cli.VerbErrorf(verb, "-s requires an argument")
}
argi++
statusField = args[argi]
@ -76,17 +74,13 @@ func transformerSurvParseCLI(
}
*pargi = argi
if !doConstruct {
return nil
return nil, nil
}
if durationField == "" {
fmt.Fprintf(os.Stderr, "mlr %s: -d option is required.\n", verbNameSurv)
fmt.Fprintf(os.Stderr, "Please see 'mlr %s --help' for more information.\n", verbNameSurv)
os.Exit(1)
return nil, fmt.Errorf("mlr %s: -d option is required", verb)
}
if statusField == "" {
fmt.Fprintf(os.Stderr, "mlr %s: -s option is required.\n", verbNameSurv)
fmt.Fprintf(os.Stderr, "Please see 'mlr %s --help' for more information.\n", verbNameSurv)
os.Exit(1)
return nil, fmt.Errorf("mlr %s: -s option is required", verb)
}
return NewTransformerSurv(durationField, statusField)
}
@ -100,13 +94,13 @@ type TransformerSurv struct {
}
// NewTransformerSurv constructs a new surv transformer.
func NewTransformerSurv(durationField, statusField string) RecordTransformer {
func NewTransformerSurv(durationField, statusField string) (*TransformerSurv, error) {
return &TransformerSurv{
durationField: durationField,
statusField: statusField,
times: []float64{},
events: []bool{},
}
}, nil
}
// Transform processes each record or emits results at end-of-stream.
@ -121,14 +115,14 @@ func (tr *TransformerSurv) Transform(
rec := inrecAndContext.Record
mvDur := rec.Get(tr.durationField)
if mvDur == nil {
fmt.Fprintf(os.Stderr, "mlr surv: duration field '%s' not found\n", tr.durationField)
os.Exit(1)
// Skip records missing the duration field
return
}
duration := mvDur.GetNumericToFloatValueOrDie()
mvStat := rec.Get(tr.statusField)
if mvStat == nil {
fmt.Fprintf(os.Stderr, "mlr surv: status field '%s' not found\n", tr.statusField)
os.Exit(1)
// Skip records missing the status field
return
}
status := mvStat.GetNumericToFloatValueOrDie() != 0
tr.times = append(tr.times, duration)

View file

@ -33,7 +33,7 @@ func transformerTacParseCLI(
args []string,
_ *cli.TOptions,
doConstruct bool, // false for first pass of CLI-parse, true for second pass
) RecordTransformer {
) (RecordTransformer, error) {
// Skip the verb name from the current spot in the mlr command line
argi := *pargi
@ -51,25 +51,23 @@ func transformerTacParseCLI(
if opt == "-h" || opt == "--help" {
transformerTacUsage(os.Stdout)
os.Exit(0)
return nil, cli.ErrHelpRequested
}
transformerTacUsage(os.Stderr)
os.Exit(1)
return nil, cli.VerbErrorf(verbNameTac, "option \"%s\" not recognized", opt)
}
*pargi = argi
if !doConstruct { // All transformers must do this for main command-line parsing
return nil
return nil, nil
}
transformer, err := NewTransformerTac()
if err != nil {
fmt.Fprintf(os.Stderr, "mlr: %v\n", err)
os.Exit(1)
return nil, err
}
return transformer
return transformer, nil
}
type TransformerTac struct {

View file

@ -37,7 +37,7 @@ func transformerTailParseCLI(
args []string,
_ *cli.TOptions,
doConstruct bool, // false for first pass of CLI-parse, true for second pass
) RecordTransformer {
) (RecordTransformer, error) {
// Skip the verb name from the current spot in the mlr command line
argi := *pargi
@ -59,10 +59,14 @@ func transformerTailParseCLI(
if opt == "-h" || opt == "--help" {
transformerTailUsage(os.Stdout)
os.Exit(0)
return nil, cli.ErrHelpRequested
} else if opt == "-n" {
tailCount = cli.VerbGetIntArgOrDie(verb, opt, args, &argi, argc)
n, err := cli.VerbGetIntArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
tailCount = n
// This is a bit of a hack. In our Getoptify routine we preprocess
// the command line sending '-xyz' to '-x -y -z', but leaving
@ -75,17 +79,21 @@ func transformerTailParseCLI(
}
} else if opt == "-g" {
groupByFieldNames = cli.VerbGetStringArrayArgOrDie(verb, opt, args, &argi, argc)
names, err := cli.VerbGetStringArrayArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
groupByFieldNames = names
} else {
transformerTailUsage(os.Stderr)
os.Exit(1)
return nil, fmt.Errorf("%s %s: option \"%s\" not recognized", "mlr", verb, opt)
}
}
*pargi = argi
if !doConstruct { // All transformers must do this for main command-line parsing
return nil
return nil, nil
}
transformer, err := NewTransformerTail(
@ -93,11 +101,10 @@ func transformerTailParseCLI(
groupByFieldNames,
)
if err != nil {
fmt.Fprintf(os.Stderr, "mlr: %v\n", err)
os.Exit(1)
return nil, err
}
return transformer
return transformer, nil
}
type TransformerTail struct {

View file

@ -42,7 +42,7 @@ func transformerTeeParseCLI(
args []string,
mainOptions *cli.TOptions,
doConstruct bool, // false for first pass of CLI-parse, true for second pass
) RecordTransformer {
) (RecordTransformer, error) {
// Skip the verb name from the current spot in the mlr command line
argi := *pargi
@ -72,7 +72,7 @@ func transformerTeeParseCLI(
if opt == "-h" || opt == "--help" {
transformerTeeUsage(os.Stdout)
os.Exit(0)
return nil, cli.ErrHelpRequested
} else if opt == "-a" {
appending = true
@ -92,7 +92,6 @@ func transformerTeeParseCLI(
// Nothing else to handle here.
argi = largi
} else {
transformerTeeUsage(os.Stderr)
os.Exit(1)
}
}
@ -102,15 +101,14 @@ func transformerTeeParseCLI(
// Get the filename/command from the command line, after the flags
if argi >= argc {
transformerTeeUsage(os.Stderr)
os.Exit(1)
return nil, cli.VerbErrorf(verbNameTee, "filename or command required")
}
filenameOrCommand = args[argi]
argi++
*pargi = argi
if !doConstruct { // All transformers must do this for main command-line parsing
return nil
return nil, nil
}
transformer, err := NewTransformerTee(
@ -124,7 +122,7 @@ func transformerTeeParseCLI(
os.Exit(1)
}
return transformer
return transformer, nil
}
type TransformerTee struct {
@ -195,7 +193,6 @@ func (tr *TransformerTee) Transform(
"%s: error writing to tee \"%s\":\n",
"mlr", tr.filenameOrCommandForDisplay,
)
fmt.Fprintf(os.Stderr, "mlr: %v\n", err)
os.Exit(1)
}
@ -208,7 +205,6 @@ func (tr *TransformerTee) Transform(
"%s: error closing tee \"%s\":\n",
"mlr", tr.filenameOrCommandForDisplay,
)
fmt.Fprintf(os.Stderr, "mlr: %v\n", err)
os.Exit(1)
}
*outputRecordsAndContexts = append(*outputRecordsAndContexts, inrecAndContext)

View file

@ -44,7 +44,7 @@ func transformerTemplateParseCLI(
args []string,
_ *cli.TOptions,
doConstruct bool, // false for first pass of CLI-parse, true for second pass
) RecordTransformer {
) (RecordTransformer, error) {
// Skip the verb name from the current spot in the mlr command line
argi := *pargi
@ -54,6 +54,7 @@ func transformerTemplateParseCLI(
var fieldNames []string = nil
fillWith := ""
var err error
for argi < argc /* variable increment: 1 or 2 depending on flag */ {
opt := args[argi]
if !strings.HasPrefix(opt, "-") {
@ -66,37 +67,43 @@ func transformerTemplateParseCLI(
if opt == "-h" || opt == "--help" {
transformerTemplateUsage(os.Stdout)
os.Exit(0)
return nil, cli.ErrHelpRequested
} else if opt == "-f" {
fieldNames = cli.VerbGetStringArrayArgOrDie(verb, opt, args, &argi, argc)
fieldNames, err = cli.VerbGetStringArrayArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
} else if opt == "-t" {
templateFileName := cli.VerbGetStringArgOrDie(verb, opt, args, &argi, argc)
templateFileName, err := cli.VerbGetStringArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
temp, err := lib.ReadCSVHeader(templateFileName)
if err != nil {
fmt.Println(err)
os.Exit(1)
return nil, fmt.Errorf("mlr %s: cannot read template file: %w", verb, err)
}
fieldNames = temp
} else if opt == "--fill-with" {
fillWith = cli.VerbGetStringArgOrDie(verb, opt, args, &argi, argc)
fillWith, err = cli.VerbGetStringArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
} else {
transformerTemplateUsage(os.Stderr)
os.Exit(1)
return nil, cli.VerbErrorf(verb, "option \"%s\" not recognized", opt)
}
}
if fieldNames == nil {
transformerTemplateUsage(os.Stderr)
os.Exit(1)
return nil, cli.VerbErrorf(verb, "-f or -t is required")
}
*pargi = argi
if !doConstruct { // All transformers must do this for main command-line parsing
return nil
return nil, nil
}
transformer, err := NewTransformerTemplate(
@ -104,11 +111,10 @@ func transformerTemplateParseCLI(
fillWith,
)
if err != nil {
fmt.Fprintf(os.Stderr, "mlr: %v\n", err)
os.Exit(1)
return nil, err
}
return transformer
return transformer, nil
}
type TransformerTemplate struct {

View file

@ -52,7 +52,7 @@ func transformerTopParseCLI(
args []string,
_ *cli.TOptions,
doConstruct bool, // false for first pass of CLI-parse, true for second pass
) RecordTransformer {
) (RecordTransformer, error) {
// Skip the verb name from the current spot in the mlr command line
argi := *pargi
@ -67,6 +67,7 @@ func transformerTopParseCLI(
doMax := true
outputFieldName := verbTopDefaultOutputFieldName
var err error
for argi < argc /* variable increment: 1 or 2 depending on flag */ {
opt := args[argi]
if !strings.HasPrefix(opt, "-") {
@ -79,14 +80,23 @@ func transformerTopParseCLI(
if opt == "-h" || opt == "--help" {
transformerTopUsage(os.Stdout)
os.Exit(0)
return nil, cli.ErrHelpRequested
} else if opt == "-n" {
topCount = cli.VerbGetIntArgOrDie(verb, opt, args, &argi, argc)
topCount, err = cli.VerbGetIntArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
} else if opt == "-f" {
valueFieldNames = cli.VerbGetStringArrayArgOrDie(verb, opt, args, &argi, argc)
valueFieldNames, err = cli.VerbGetStringArrayArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
} else if opt == "-g" {
groupByFieldNames = cli.VerbGetStringArrayArgOrDie(verb, opt, args, &argi, argc)
groupByFieldNames, err = cli.VerbGetStringArrayArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
} else if opt == "-a" {
showFullRecords = true
} else if opt == "--max" {
@ -96,26 +106,26 @@ func transformerTopParseCLI(
} else if opt == "-F" {
// Ignored in Miller 6; allowed for command-line backward compatibility
} else if opt == "-o" {
outputFieldName = cli.VerbGetStringArgOrDie(verb, opt, args, &argi, argc)
outputFieldName, err = cli.VerbGetStringArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
} else {
transformerTopUsage(os.Stderr)
os.Exit(1)
return nil, cli.VerbErrorf(verb, "option \"%s\" not recognized", opt)
}
}
if valueFieldNames == nil {
transformerTopUsage(os.Stderr)
os.Exit(1)
return nil, cli.VerbErrorf(verb, "-f field names required")
}
if len(valueFieldNames) > 1 && showFullRecords {
transformerTopUsage(os.Stderr)
os.Exit(1)
return nil, cli.VerbErrorf(verb, "-a (full records) incompatible with multiple -f fields")
}
*pargi = argi
if !doConstruct { // All transformers must do this for main command-line parsing
return nil
return nil, nil
}
transformer, _ := NewTransformerTop(
@ -127,7 +137,7 @@ func transformerTopParseCLI(
outputFieldName,
)
return transformer
return transformer, nil
}
type TransformerTop struct {

View file

@ -39,7 +39,7 @@ func transformerUnflattenParseCLI(
args []string,
options *cli.TOptions,
doConstruct bool, // false for first pass of CLI-parse, true for second pass
) RecordTransformer {
) (RecordTransformer, error) {
// Skip the verb name from the current spot in the mlr command line
argi := *pargi
@ -49,6 +49,7 @@ func transformerUnflattenParseCLI(
oFlatSep := "" // means take it from the record context
var fieldNames []string = nil
var err error
for argi < argc /* variable increment: 1 or 2 depending on flag */ {
opt := args[argi]
if !strings.HasPrefix(opt, "-") {
@ -61,23 +62,28 @@ func transformerUnflattenParseCLI(
if opt == "-h" || opt == "--help" {
transformerUnflattenUsage(os.Stdout)
os.Exit(0)
return nil, cli.ErrHelpRequested
} else if opt == "-s" {
oFlatSep = cli.VerbGetStringArgOrDie(verb, opt, args, &argi, argc)
oFlatSep, err = cli.VerbGetStringArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
} else if opt == "-f" {
fieldNames = cli.VerbGetStringArrayArgOrDie(verb, opt, args, &argi, argc)
fieldNames, err = cli.VerbGetStringArrayArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
} else {
transformerUnflattenUsage(os.Stderr)
os.Exit(1)
return nil, cli.VerbErrorf(verb, "option \"%s\" not recognized", opt)
}
}
*pargi = argi
if !doConstruct { // All transformers must do this for main command-line parsing
return nil
return nil, nil
}
transformer, err := NewTransformerUnflatten(
@ -86,11 +92,10 @@ func transformerUnflattenParseCLI(
fieldNames,
)
if err != nil {
fmt.Fprintf(os.Stderr, "mlr: %v\n", err)
os.Exit(1)
return nil, err
}
return transformer
return transformer, nil
}
type TransformerUnflatten struct {

View file

@ -57,7 +57,7 @@ func transformerCountDistinctParseCLI(
args []string,
_ *cli.TOptions,
doConstruct bool, // false for first pass of CLI-parse, true for second pass
) RecordTransformer {
) (RecordTransformer, error) {
// Skip the verb name from the current spot in the mlr command line
argi := *pargi
@ -71,6 +71,7 @@ func transformerCountDistinctParseCLI(
outputFieldName := uniqDefaultOutputFieldName
doLashed := true
var err error
for argi < argc /* variable increment: 1 or 2 depending on flag */ {
opt := args[argi]
if !strings.HasPrefix(opt, "-") {
@ -83,37 +84,43 @@ func transformerCountDistinctParseCLI(
if opt == "-h" || opt == "--help" {
transformerCountDistinctUsage(os.Stdout)
os.Exit(0)
return nil, cli.ErrHelpRequested
} else if opt == "-g" || opt == "-f" {
fieldNames = cli.VerbGetStringArrayArgOrDie(verb, opt, args, &argi, argc)
fieldNames, err = cli.VerbGetStringArrayArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
} else if opt == "-x" {
fieldNames = cli.VerbGetStringArrayArgOrDie(verb, opt, args, &argi, argc)
fieldNames, err = cli.VerbGetStringArrayArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
invertFieldNames = true
} else if opt == "-n" {
showNumDistinctOnly = true
} else if opt == "-o" {
outputFieldName = cli.VerbGetStringArgOrDie(verb, opt, args, &argi, argc)
outputFieldName, err = cli.VerbGetStringArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
} else if opt == "-u" {
doLashed = false
} else {
transformerCountDistinctUsage(os.Stderr)
os.Exit(1)
return nil, cli.VerbErrorf(verb, "option \"%s\" not recognized", opt)
}
}
if fieldNames == nil {
transformerCountDistinctUsage(os.Stderr)
os.Exit(1)
return nil, cli.VerbErrorf(verb, "-g or -x field names required")
}
if !doLashed && showNumDistinctOnly {
transformerCountDistinctUsage(os.Stderr)
os.Exit(1)
return nil, cli.VerbErrorf(verb, "-n requires -a (uniqify entire records)")
}
showCounts := true
@ -121,7 +128,7 @@ func transformerCountDistinctParseCLI(
*pargi = argi
if !doConstruct { // All transformers must do this for main command-line parsing
return nil
return nil, nil
}
transformer, err := NewTransformerUniq(
@ -134,11 +141,10 @@ func transformerCountDistinctParseCLI(
uniqifyEntireRecords,
)
if err != nil {
fmt.Fprintf(os.Stderr, "mlr: %v\n", err)
os.Exit(1)
return nil, err
}
return transformer
return transformer, nil
}
func transformerUniqUsage(
@ -168,7 +174,7 @@ func transformerUniqParseCLI(
args []string,
_ *cli.TOptions,
doConstruct bool, // false for first pass of CLI-parse, true for second pass
) RecordTransformer {
) (RecordTransformer, error) {
// Skip the verb name from the current spot in the mlr command line
argi := *pargi
@ -183,6 +189,7 @@ func transformerUniqParseCLI(
outputFieldName := uniqDefaultOutputFieldName
uniqifyEntireRecords := false
var err error
for argi < argc /* variable increment: 1 or 2 depending on flag */ {
opt := args[argi]
if !strings.HasPrefix(opt, "-") {
@ -195,13 +202,19 @@ func transformerUniqParseCLI(
if opt == "-h" || opt == "--help" {
transformerUniqUsage(os.Stdout)
os.Exit(0)
return nil, cli.ErrHelpRequested
} else if opt == "-g" || opt == "-f" {
fieldNames = cli.VerbGetStringArrayArgOrDie(verb, opt, args, &argi, argc)
fieldNames, err = cli.VerbGetStringArrayArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
} else if opt == "-x" {
fieldNames = cli.VerbGetStringArrayArgOrDie(verb, opt, args, &argi, argc)
fieldNames, err = cli.VerbGetStringArrayArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
invertFieldNames = true
} else if opt == "-c" {
@ -211,30 +224,29 @@ func transformerUniqParseCLI(
showNumDistinctOnly = true
} else if opt == "-o" {
outputFieldName = cli.VerbGetStringArgOrDie(verb, opt, args, &argi, argc)
outputFieldName, err = cli.VerbGetStringArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
} else if opt == "-a" {
uniqifyEntireRecords = true
} else {
transformerUniqUsage(os.Stderr)
os.Exit(1)
return nil, cli.VerbErrorf(verb, "option \"%s\" not recognized", opt)
}
}
if uniqifyEntireRecords {
if fieldNames != nil {
transformerUniqUsage(os.Stderr)
os.Exit(1)
return nil, cli.VerbErrorf(verb, "-a (uniqify entire records) is incompatible with -g/-x")
}
if showCounts && showNumDistinctOnly {
transformerUniqUsage(os.Stderr)
os.Exit(1)
return nil, cli.VerbErrorf(verb, "-c and -n are mutually exclusive with -a")
}
} else {
if fieldNames == nil {
transformerUniqUsage(os.Stderr)
os.Exit(1)
return nil, cli.VerbErrorf(verb, "-g or -x field names required")
}
}
@ -242,7 +254,7 @@ func transformerUniqParseCLI(
*pargi = argi
if !doConstruct { // All transformers must do this for main command-line parsing
return nil
return nil, nil
}
transformer, _ := NewTransformerUniq(
@ -255,7 +267,7 @@ func transformerUniqParseCLI(
uniqifyEntireRecords,
)
return transformer
return transformer, nil
}
type TransformerUniq struct {

View file

@ -37,7 +37,7 @@ func transformerUnspaceParseCLI(
args []string,
_ *cli.TOptions,
doConstruct bool, // false for first pass of CLI-parse, true for second pass
) RecordTransformer {
) (RecordTransformer, error) {
// Skip the verb name from the current spot in the mlr command line
argi := *pargi
@ -47,6 +47,7 @@ func transformerUnspaceParseCLI(
filler := "_"
which := "keys_and_values"
var err error
for argi < argc /* variable increment: 1 or 2 depending on flag */ {
opt := args[argi]
if !strings.HasPrefix(opt, "-") {
@ -59,10 +60,13 @@ func transformerUnspaceParseCLI(
if opt == "-h" || opt == "--help" {
transformerUnspaceUsage(os.Stdout)
os.Exit(0)
return nil, cli.ErrHelpRequested
} else if opt == "-f" {
filler = cli.VerbGetStringArgOrDie(verb, opt, args, &argi, argc)
filler, err = cli.VerbGetStringArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
} else if opt == "-k" {
which = "keys_only"
@ -71,23 +75,21 @@ func transformerUnspaceParseCLI(
which = "values_only"
} else {
transformerUnspaceUsage(os.Stderr)
os.Exit(1)
return nil, cli.VerbErrorf(verb, "option \"%s\" not recognized", opt)
}
}
*pargi = argi
if !doConstruct { // All transformers must do this for main command-line parsing
return nil
return nil, nil
}
transformer, err := NewTransformerUnspace(filler, which)
if err != nil {
fmt.Fprintf(os.Stderr, "mlr: %v\n", err)
os.Exit(1)
return nil, err
}
return transformer
return transformer, nil
}
type TransformerUnspace struct {

View file

@ -50,7 +50,7 @@ func transformerUnsparsifyParseCLI(
args []string,
_ *cli.TOptions,
doConstruct bool, // false for first pass of CLI-parse, true for second pass
) RecordTransformer {
) (RecordTransformer, error) {
// Skip the verb name from the current spot in the mlr command line
argi := *pargi
@ -60,6 +60,7 @@ func transformerUnsparsifyParseCLI(
fillerString := ""
var specifiedFieldNames []string = nil
var err error
for argi < argc /* variable increment: 1 or 2 depending on flag */ {
opt := args[argi]
if !strings.HasPrefix(opt, "-") {
@ -72,23 +73,28 @@ func transformerUnsparsifyParseCLI(
if opt == "-h" || opt == "--help" {
transformerUnsparsifyUsage(os.Stdout)
os.Exit(0)
return nil, cli.ErrHelpRequested
} else if opt == "--fill-with" {
fillerString = cli.VerbGetStringArgOrDie(verb, opt, args, &argi, argc)
fillerString, err = cli.VerbGetStringArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
} else if opt == "-f" {
specifiedFieldNames = cli.VerbGetStringArrayArgOrDie(verb, opt, args, &argi, argc)
specifiedFieldNames, err = cli.VerbGetStringArrayArg(verb, opt, args, &argi, argc)
if err != nil {
return nil, err
}
} else {
transformerUnsparsifyUsage(os.Stderr)
os.Exit(1)
return nil, cli.VerbErrorf(verb, "option \"%s\" not recognized", opt)
}
}
*pargi = argi
if !doConstruct { // All transformers must do this for main command-line parsing
return nil
return nil, nil
}
transformer, err := NewTransformerUnsparsify(
@ -96,11 +102,10 @@ func transformerUnsparsifyParseCLI(
specifiedFieldNames,
)
if err != nil {
fmt.Fprintf(os.Stderr, "mlr: %v\n", err)
os.Exit(1)
return nil, err
}
return transformer
return transformer, nil
}
type TransformerUnsparsify struct {

View file

@ -36,7 +36,7 @@ func transformerUTF8ToLatin1ParseCLI(
args []string,
_ *cli.TOptions,
doConstruct bool, // false for first pass of CLI-parse, true for second pass
) RecordTransformer {
) (RecordTransformer, error) {
// Skip the verb name from the current spot in the mlr command line
argi := *pargi
@ -54,25 +54,23 @@ func transformerUTF8ToLatin1ParseCLI(
if opt == "-h" || opt == "--help" {
transformerUTF8ToLatin1Usage(os.Stdout)
os.Exit(0)
return nil, cli.ErrHelpRequested
}
transformerUTF8ToLatin1Usage(os.Stderr)
os.Exit(1)
return nil, cli.VerbErrorf(verbNameUTF8ToLatin1, "option \"%s\" not recognized", opt)
}
*pargi = argi
if !doConstruct { // All transformers must do this for main command-line parsing
return nil
return nil, nil
}
transformer, err := NewTransformerUTF8ToLatin1()
if err != nil {
fmt.Fprintf(os.Stderr, "mlr: %v\n", err)
os.Exit(1)
return nil, err
}
return transformer
return transformer, nil
}
type TransformerUTF8ToLatin1 struct {