More neatening of on-line help (#588)

* Continue neatening on-line help
* replace lib.MlrExeName() with "mlr"
* synchronize mlr -l/-L/-f/-F/-k/-K
This commit is contained in:
John Kerl 2021-07-01 00:44:33 +00:00 committed by GitHub
parent 4ff41cd348
commit 89f3962757
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
99 changed files with 1198 additions and 1345 deletions

View file

@ -3,7 +3,7 @@
# In case the user running this has a .mlrrc
export MLRRC=__none__
mlr -F | grep -v '^[a-zA-Z]' | uniq | while read funcname; do
mlr help list-functions | grep -v '^[a-zA-Z]' | uniq | while read funcname; do
displayname=$funcname
linkname="$funcname"
if [ "$funcname" = '+' ]; then
@ -60,7 +60,7 @@ mlr -F | grep -v '^[a-zA-Z]' | uniq | while read funcname; do
echo ''
done
mlr -F | grep '^[a-zA-Z]' | sort -u | while read funcname; do
mlr help list-functions | grep '^[a-zA-Z]' | sort -u | while read funcname; do
displayname=$funcname
linkname="$funcname"
if [ "$funcname" = '+' ]; then

View file

@ -15,7 +15,7 @@ List of functions
Each function takes a specific number of arguments, as shown below, except for functions marked as variadic such as ``min`` and ``max``. (The latter compute min and max of any number of numerical arguments.) There is no notion of optional or default-on-absent arguments. All argument-passing is positional rather than by name; arguments are passed by value, not by reference.
You can get a list of all functions using **mlr -F**.
You can get a list of all functions using **mlr -f**, with details using **mlr -F**.
.. _reference-dsl-colon:

View file

@ -11,6 +11,6 @@ List of functions
Each function takes a specific number of arguments, as shown below, except for functions marked as variadic such as ``min`` and ``max``. (The latter compute min and max of any number of numerical arguments.) There is no notion of optional or default-on-absent arguments. All argument-passing is positional rather than by name; arguments are passed by value, not by reference.
You can get a list of all functions using **mlr -F**.
You can get a list of all functions using **mlr -f**, with details using **mlr -F**.
GENRST_RUN_CONTENT_GENERATOR(mk-func-h2s.sh)

View file

@ -611,7 +611,7 @@ The following ``is...`` functions take a value and return a boolean indicating w
.. code-block:: none
:emphasize-lines: 1-1
mlr -F | grep ^is
mlr -f | grep ^is
is_absent
is_array
is_bool
@ -635,7 +635,7 @@ The following ``is...`` functions take a value and return a boolean indicating w
.. code-block:: none
:emphasize-lines: 1-1
mlr -F | grep ^assert
mlr -f | grep ^assert
asserting_absent
asserting_array
asserting_bool

View file

@ -255,11 +255,11 @@ Type-test and type-assertion expressions
The following ``is...`` functions take a value and return a boolean indicating whether the argument is of the indicated type. The ``assert_...`` functions return their argument if it is of the specified type, and cause a fatal error otherwise:
GENRST_RUN_COMMAND
mlr -F | grep ^is
mlr -f | grep ^is
GENRST_EOF
GENRST_RUN_COMMAND
mlr -F | grep ^assert
mlr -f | grep ^assert
GENRST_EOF
Please see :ref:`cookbook-data-cleaning-examples` for examples of how to use these.

View file

@ -1819,8 +1819,8 @@ most-frequent
square red 1874
triangle red 1560
circle red 1207
square blue 589
square yellow 589
square blue 589
.. code-block:: none
:emphasize-lines: 1-1
@ -1830,8 +1830,8 @@ most-frequent
square red 1874
triangle red 1560
circle red 1207
square yellow 589
square blue 589
square yellow 589
.. code-block:: none
:emphasize-lines: 1-1
@ -1841,8 +1841,8 @@ most-frequent
square red
triangle red
circle red
square yellow
square blue
square yellow
See also :ref:`reference-verbs-least-frequent`.

View file

@ -22,10 +22,6 @@ go build mlr.go
echo Compile OK
echo
# During the C-to-Go port I like to have ../c/mlr and ./mlrgo and have symlinks
# to them from my ~/lbin. Hence the duplicate name here.
cp mlr mlrgo
echo ================================================================
echo UNIT TESTS
go test -v miller/src/...

View file

@ -18,7 +18,7 @@ import (
func TestRegression(t *testing.T) {
regtester := regtest.NewRegTester(
lib.MlrExeName(),
"mlr",
false, // doPopulate
0, // verbosityLevel
0, // firstNFailsToShow

View file

@ -1,5 +1,5 @@
// ================================================================
// TODO: comment
// On-line help
// ================================================================
package help
@ -8,6 +8,8 @@ import (
"fmt"
"os"
"github.com/mattn/go-isatty"
"miller/src/cliutil"
"miller/src/dsl/cst"
"miller/src/lib"
@ -35,16 +37,15 @@ var shorthandLookupTable = []shorthandInfo{}
var handlerLookupTable = []handlerInfo{}
func init() {
// For things like 'mlr -F', invoked through the CLI parser which does not
// For things like 'mlr -f', invoked through the CLI parser which does not
// go through our HelpMain().
shorthandLookupTable = []shorthandInfo{
// TODO: remove handler func & replace with just short/long
{shorthand: "-l", longhand: "list-verbs"},
{shorthand: "-L", longhand: "list-verbs-vertically"},
{shorthand: "-f", longhand: "usage-functions"},
{shorthand: "-F", longhand: "list-functions"},
{shorthand: "-k", longhand: "usage-keywords"},
{shorthand: "-K", longhand: "list-keywords"},
{shorthand: "-L", longhand: "usage-verbs"},
{shorthand: "-f", longhand: "list-functions"},
{shorthand: "-F", longhand: "usage-functions"},
{shorthand: "-k", longhand: "list-keywords"},
{shorthand: "-K", longhand: "usage-keywords"},
}
// For things like 'mlr help foo', invoked through the auxent framework
@ -63,14 +64,15 @@ func init() {
{name: "function", unaryHandlerFunc: helpForFunction},
{name: "keyword", unaryHandlerFunc: helpForKeyword},
{name: "list-functions", zaryHandlerFunc: listFunctions},
{name: "list-functions-vertically", zaryHandlerFunc: listFunctionsVertically},
{name: "list-functions-as-paragraph", zaryHandlerFunc: listFunctionsAsParagraph},
{name: "list-keywords", zaryHandlerFunc: listKeywords},
{name: "list-verbs", zaryHandlerFunc: listVerbsAsParagraph},
{name: "list-verbs-vertically", zaryHandlerFunc: listVerbsVertically},
{name: "list-keywords-as-paragraph", zaryHandlerFunc: listKeywordsAsParagraph},
{name: "list-verbs", zaryHandlerFunc: listVerbs},
{name: "list-verbs-as-paragraph", zaryHandlerFunc: listVerbsAsParagraph},
{name: "misc", zaryHandlerFunc: helpMiscOptions},
{name: "mlrrc", zaryHandlerFunc: helpMlrrc},
{name: "number-formatting", zaryHandlerFunc: helpNumberFormatting},
{name: "output-colorizations", zaryHandlerFunc: helpOutputColorization},
{name: "output-colorization", zaryHandlerFunc: helpOutputColorization},
{name: "separator-options", zaryHandlerFunc: helpSeparatorOptions},
{name: "type-arithmetic-info", zaryHandlerFunc: helpTypeArithmeticInfo},
{name: "usage-functions", zaryHandlerFunc: usageFunctions},
@ -80,13 +82,6 @@ func init() {
}
}
// TODO: keywords listed as paragraph
// TODO: search for function/keyword/verb/etc like in the REPL
// TODO:
// function-list as paragraph (for manpage)
// type-arithmetic-info printTypeArithmeticInfo(os.Stdout, lib.MlrExeName());
// ================================================================
// For things like 'mlr help foo', invoked through the auxent framework which
// goes through our HelpMain(). Here, the args are the full Miller command
@ -125,8 +120,6 @@ func HelpMain(args []string) int {
}
}
// TODO: free-ranging keyword/function/verb/etc search as in mlr repl.
// "mlr help something" where we do not recognize the something
listTopics()
@ -666,58 +659,61 @@ func helpTypeArithmeticInfo() {
fmt.Println("TO BE PORTED")
}
// ================================================================
// TODO: port the paragraphifier
// ----------------------------------------------------------------
func listFunctions() {
cst.BuiltinFunctionManagerInstance.ListBuiltinFunctionNames(os.Stdout)
if isatty.IsTerminal(os.Stdout.Fd()) {
cst.BuiltinFunctionManagerInstance.ListBuiltinFunctionNamesAsParagraph(os.Stdout)
} else {
cst.BuiltinFunctionManagerInstance.ListBuiltinFunctionNames(os.Stdout)
}
}
// ----------------------------------------------------------------
func listFunctionsVertically() {
cst.BuiltinFunctionManagerInstance.ListBuiltinFunctionNames(os.Stdout)
func listFunctionsAsParagraph() {
cst.BuiltinFunctionManagerInstance.ListBuiltinFunctionNamesAsParagraph(os.Stdout)
}
// ----------------------------------------------------------------
func usageFunctions() {
cst.BuiltinFunctionManagerInstance.ListBuiltinFunctionUsages(os.Stdout)
}
// ----------------------------------------------------------------
func helpForFunction(arg string) {
cst.BuiltinFunctionManagerInstance.TryListBuiltinFunctionUsage(arg, os.Stdout)
}
// ================================================================
// ----------------------------------------------------------------
func listKeywords() {
cst.ListKeywords()
if isatty.IsTerminal(os.Stdout.Fd()) {
cst.ListKeywordsAsParagraph()
} else {
cst.ListKeywordsVertically()
}
}
func listKeywordsAsParagraph() {
cst.ListKeywordsAsParagraph()
}
// ----------------------------------------------------------------
func usageKeywords() {
cst.UsageKeywords()
}
// ----------------------------------------------------------------
func helpForKeyword(arg string) {
cst.UsageForKeyword(arg)
}
// ================================================================
// ----------------------------------------------------------------
func listVerbs() {
if isatty.IsTerminal(os.Stdout.Fd()) {
transformers.ListVerbNamesAsParagraph()
} else {
transformers.ListVerbNamesVertically()
}
}
func listVerbsAsParagraph() {
transformers.ListVerbNamesAsParagraph()
}
// ----------------------------------------------------------------
func listVerbsVertically() {
transformers.ListVerbNamesVertically()
}
// ----------------------------------------------------------------
func listVerbNamesAsParagraph() {
transformers.ListVerbNamesAsParagraph()
}
// ----------------------------------------------------------------
func helpForVerb(arg string) {
transformerSetup := transformers.LookUp(arg)
if transformerSetup != nil {
@ -729,7 +725,6 @@ func helpForVerb(arg string) {
}
}
// ----------------------------------------------------------------
func usageVerbs() {
transformers.UsageVerbs()
}

View file

@ -64,7 +64,7 @@ func hexMain(args []string) int {
istream, err := os.Open(filename)
if err != nil {
// TODO: lib.MlrExeName()
// TODO: "mlr"
fmt.Fprintln(os.Stderr, "mlr hex:", err)
os.Exit(1)
}

View file

@ -49,7 +49,7 @@ func lecatMain(args []string) int {
istream, err := os.Open(filename)
if err != nil {
// TODO: lib.MlrExeName()
// TODO: "mlr"
fmt.Fprintln(os.Stderr, "mlr lecat:", err)
os.Exit(1)
}

View file

@ -720,7 +720,7 @@ func (regtester *RegTester) loadEnvFile(
return nil, errors.New(
fmt.Sprintf(
"%s: could not parse line \"%s\" from file \"%s\".\n",
lib.MlrExeName(), line, filename,
"mlr", line, filename,
),
)
}
@ -759,7 +759,7 @@ func (regtester *RegTester) loadStringPairFile(
return nil, errors.New(
fmt.Sprintf(
"%s: could not parse line \"%s\" from file \"%s\".\n",
lib.MlrExeName(), line, filename,
"mlr", line, filename,
),
)
}

View file

@ -9,7 +9,6 @@ import (
"os"
"miller/src/dsl"
"miller/src/lib"
"miller/src/parsing/lexer"
"miller/src/parsing/parser"
)
@ -24,7 +23,7 @@ func (repl *Repl) BuildASTFromStringWithMessage(
// At present it's overly parser-internal, and confusing. :(
// fmt.Fprintln(os.Stderr, err)
fmt.Fprintf(os.Stderr, "%s: cannot parse DSL expression.\n",
lib.MlrExeName())
"mlr")
if repl.astPrintMode != ASTPrintNone {
fmt.Fprintln(os.Stderr, dslString)
}

View file

@ -856,8 +856,7 @@ func handleHelpSingle(repl *Repl, arg string) {
}
if arg == "function-names" {
// TODO: move to src/auxents/help
cst.BuiltinFunctionManagerInstance.ListBuiltinFunctionNames(os.Stdout)
cst.BuiltinFunctionManagerInstance.ListBuiltinFunctionNamesAsParagraph(os.Stdout)
return
}
@ -871,6 +870,10 @@ func handleHelpSingle(repl *Repl, arg string) {
return
}
if cst.TryUsageForKeyword(arg) {
return
}
if cst.BuiltinFunctionManagerInstance.TryListBuiltinFunctionUsage(arg, os.Stdout) {
return
}

View file

@ -82,14 +82,14 @@ func termcvtMain(args []string) int {
istream, err := os.Open(filename)
if err != nil {
// TODO: lib.MlrExeName()
// TODO: "mlr"
fmt.Fprintln(os.Stderr, "mlr termcvt:", err)
os.Exit(1)
}
ostream, err := os.Open(tempname)
if err != nil {
// TODO: lib.MlrExeName()
// TODO: "mlr"
fmt.Fprintln(os.Stderr, "mlr termcvt:", err)
os.Exit(1)
}
@ -102,7 +102,7 @@ func termcvtMain(args []string) int {
err = os.Rename(tempname, filename)
if err != nil {
// TODO: lib.MlrExeName()
// TODO: "mlr"
fmt.Fprintln(os.Stderr, "mlr termcvt:", err)
os.Exit(1)
}
@ -113,7 +113,7 @@ func termcvtMain(args []string) int {
istream, err := os.Open(filename)
if err != nil {
// TODO: lib.MlrExeName()
// TODO: "mlr"
fmt.Fprintln(os.Stderr, "mlr termcvt:", err)
os.Exit(1)
}
@ -137,7 +137,7 @@ func termcvtFile(istream *os.File, ostream *os.File, inTerm string, outTerm stri
}
if err != nil {
// TODO: lib.MlrExeName()
// TODO: "mlr"
fmt.Fprintln(os.Stderr, "mlr termcvt:", err)
os.Exit(1)
}

View file

@ -9,7 +9,6 @@ import (
"strings"
"miller/src/cliutil"
"miller/src/lib"
)
// ----------------------------------------------------------------
@ -66,7 +65,7 @@ func tryLoadMlrrc(
lineno++
if err != nil {
fmt.Fprintln(os.Stderr, lib.MlrExeName(), err)
fmt.Fprintln(os.Stderr, "mlr", err)
os.Exit(1)
return false
}
@ -77,7 +76,7 @@ func tryLoadMlrrc(
if !handleMlrrcLine(options, line) {
fmt.Fprintf(os.Stderr, "%s: parse error at file \"%s\" line %d: %s\n",
lib.MlrExeName(), path, lineno, line,
"mlr", path, lineno, line,
)
os.Exit(1)
}

View file

@ -59,8 +59,8 @@ func ParseCommandLine(args []string) (
// handled
} else {
// unhandled
fmt.Fprintf(os.Stderr, "%s: option \"%s\" not recognized.\n", lib.MlrExeName(), args[argi])
fmt.Fprintf(os.Stderr, "Please run \"%s --help\" for usage information.\n", lib.MlrExeName())
fmt.Fprintf(os.Stderr, "%s: option \"%s\" not recognized.\n", "mlr", args[argi])
fmt.Fprintf(os.Stderr, "Please run \"%s --help\" for usage information.\n", "mlr")
os.Exit(1)
}
}
@ -114,7 +114,7 @@ func ParseCommandLine(args []string) (
}
if options.DoInPlace && (options.FileNames == nil || len(options.FileNames) == 0) {
fmt.Fprintf(os.Stderr, "%s: -I option (in-place operation) requires input files.\n", lib.MlrExeName())
fmt.Fprintf(os.Stderr, "%s: -I option (in-place operation) requires input files.\n", "mlr")
os.Exit(1)
}
@ -152,7 +152,7 @@ func parseTransformers(
}
if (argc - argi) < 1 {
fmt.Fprintf(os.Stderr, "%s: no verb supplied.\n", lib.MlrExeName())
fmt.Fprintf(os.Stderr, "%s: no verb supplied.\n", "mlr")
help.MainUsage(os.Stderr)
os.Exit(1)
}
@ -167,7 +167,7 @@ func parseTransformers(
if transformerSetup == nil {
fmt.Fprintf(os.Stderr,
"%s: verb \"%s\" not found. Please use \"%s --help\" for a list.\n",
lib.MlrExeName(), verb, lib.MlrExeName())
"mlr", verb, "mlr")
os.Exit(1)
}
@ -200,7 +200,7 @@ func parseTransformers(
break
} else {
if argi == argc-1 {
fmt.Fprintf(os.Stderr, "%s: missing next verb after \"then\".\n", lib.MlrExeName())
fmt.Fprintf(os.Stderr, "%s: missing next verb after \"then\".\n", "mlr")
os.Exit(1)
} else {
argi++

View file

@ -3,16 +3,14 @@ package cliutil
import (
"fmt"
"os"
"miller/src/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.
func CheckArgCount(args []string, argi int, argc int, n int) {
if (argc - argi) < n {
fmt.Fprintf(os.Stderr, "%s: option \"%s\" missing argument(s).\n", lib.MlrExeName(), args[argi])
fmt.Fprintf(os.Stderr, "Please run \"%s --help\" for detailed usage information.\n", lib.MlrExeName())
fmt.Fprintf(os.Stderr, "%s: option \"%s\" missing argument(s).\n", "mlr", args[argi])
fmt.Fprintf(os.Stderr, "Please run \"%s --help\" for detailed usage information.\n", "mlr")
os.Exit(1)
}
}

View file

@ -97,7 +97,7 @@ func ParseReaderOptions(
// CheckArgCount(args, argi, argc, 2);
// if (sscanf(args[argi+1], "%lld", &readerOptions.generator_opts.start) != 1) {
// fmt.Fprintf(os.Stderr, "%s: could not scan \"%s\".\n",
// lib.MlrExeName(), args[argi+1]);
// "mlr", args[argi+1]);
// }
// argi += 2;
// } else if args[argi] == "--gen-stop" {
@ -105,7 +105,7 @@ func ParseReaderOptions(
// CheckArgCount(args, argi, argc, 2);
// if (sscanf(args[argi+1], "%lld", &readerOptions.generator_opts.stop) != 1) {
// fmt.Fprintf(os.Stderr, "%s: could not scan \"%s\".\n",
// lib.MlrExeName(), args[argi+1]);
// "mlr", args[argi+1]);
// }
// argi += 2;
// } else if args[argi] == "--gen-step" {
@ -113,7 +113,7 @@ func ParseReaderOptions(
// CheckArgCount(args, argi, argc, 2);
// if (sscanf(args[argi+1], "%lld", &readerOptions.generator_opts.step) != 1) {
// fmt.Fprintf(os.Stderr, "%s: could not scan \"%s\".\n",
// lib.MlrExeName(), args[argi+1]);
// "mlr", args[argi+1]);
// }
// argi += 2;
@ -487,7 +487,7 @@ func ParseWriterOptions(
if !ok {
fmt.Fprintf(os.Stderr,
"%s: --key-color argument must be a decimal integer; got \"%s\".\n",
lib.MlrExeName(), args[argi+1])
"mlr", args[argi+1])
os.Exit(1)
}
colorizer.SetKeyColor(code)
@ -500,7 +500,7 @@ func ParseWriterOptions(
if !ok {
fmt.Fprintf(os.Stderr,
"%s: --value-color argument must be a decimal integer; got \"%s\".\n",
lib.MlrExeName(), args[argi+1])
"mlr", args[argi+1])
os.Exit(1)
}
colorizer.SetValueColor(code)
@ -513,7 +513,7 @@ func ParseWriterOptions(
if !ok {
fmt.Fprintf(os.Stderr,
"%s: --pass-color argument must be a decimal integer; got \"%s\".\n",
lib.MlrExeName(), args[argi+1])
"mlr", args[argi+1])
os.Exit(1)
}
colorizer.SetPassColor(code)
@ -526,7 +526,7 @@ func ParseWriterOptions(
if !ok {
fmt.Fprintf(os.Stderr,
"%s: --fail-color argument must be a decimal integer; got \"%s\".\n",
lib.MlrExeName(), args[argi+1])
"mlr", args[argi+1])
os.Exit(1)
}
colorizer.SetFailColor(code)
@ -539,7 +539,7 @@ func ParseWriterOptions(
if !ok {
fmt.Fprintf(os.Stderr,
"%s: --help-color argument must be a decimal integer; got \"%s\".\n",
lib.MlrExeName(), args[argi+1])
"mlr", args[argi+1])
os.Exit(1)
}
colorizer.SetHelpColor(code)
@ -600,7 +600,7 @@ func ParseReaderWriterOptions(
CheckArgCount(args, argi, argc, 2)
if defaultFSes[args[argi+1]] == "" {
fmt.Fprintf(os.Stderr, "%s: unrecognized I/O format \"%s\".\n",
lib.MlrExeName(), args[argi+1])
"mlr", args[argi+1])
os.Exit(1)
}
readerOptions.InputFileFormat = args[argi+1]
@ -1132,14 +1132,14 @@ func ParseMiscOptions(
// if (sscanf(args[argi+1], "%lld", &options.nr_progress_mod) != 1) {
// fmt.Fprintf(os.Stderr,
// "%s: --nr-progress-mod argument must be a positive integer; got \"%s\".\n",
// lib.MlrExeName(), args[argi+1]);
// "mlr", args[argi+1]);
// mainUsageShort()
// os.Exit(1);
// }
// if (options.nr_progress_mod <= 0) {
// fmt.Fprintf(os.Stderr,
// "%s: --nr-progress-mod argument must be a positive integer; got \"%s\".\n",
// lib.MlrExeName(), args[argi+1]);
// "mlr", args[argi+1]);
// mainUsageShort()
// os.Exit(1);
// }
@ -1154,8 +1154,8 @@ func ParseMiscOptions(
} else {
fmt.Fprintf(os.Stderr,
"%s: --seed argument must be a decimal or hexadecimal integer; got \"%s\".\n",
lib.MlrExeName(), args[argi+1])
fmt.Fprintf(os.Stderr, "Please run \"%s --help\" for detailed usage information.\n", lib.MlrExeName())
"mlr", args[argi+1])
fmt.Fprintf(os.Stderr, "Please run \"%s --help\" for detailed usage information.\n", "mlr")
os.Exit(1)
}
argi += 2

View file

@ -18,7 +18,7 @@ import (
func verbCheckArgCount(verb string, opt string, args []string, argi int, argc int, n int) {
if (argc - argi) < n {
fmt.Fprintf(os.Stderr, "%s %s: option \"%s\" missing argument(s).\n",
lib.MlrExeName(), verb, opt,
"mlr", verb, opt,
)
os.Exit(1)
}
@ -48,7 +48,7 @@ func VerbGetIntArgOrDie(verb string, opt string, args []string, pargi *int, argc
if err != nil {
fmt.Fprintf(os.Stderr,
"%s %s: could not scan flag \"%s\" argument \"%s\" as int.\n",
lib.MlrExeName(), verb, flag, stringArg,
"mlr", verb, flag, stringArg,
)
os.Exit(1)
}
@ -64,7 +64,7 @@ func VerbGetFloatArgOrDie(verb string, opt string, args []string, pargi *int, ar
if err != nil {
fmt.Fprintf(os.Stderr,
"%s %s: could not scan flag \"%s\" argument \"%s\" as float.\n",
lib.MlrExeName(), verb, flag, stringArg,
"mlr", verb, flag, stringArg,
)
os.Exit(1)
}

View file

@ -55,22 +55,49 @@ type BuiltinFunctionInfo struct {
func init() {
// Go sort API: for ascending sort, return true if element i < element j.
sort.Slice(_BUILTIN_FUNCTION_LOOKUP_TABLE, func(i, j int) bool {
//if _BUILTIN_FUNCTION_LOOKUP_TABLE[i].class < _BUILTIN_FUNCTION_LOOKUP_TABLE[j].class {
//return true
//}
//if _BUILTIN_FUNCTION_LOOKUP_TABLE[i].class > _BUILTIN_FUNCTION_LOOKUP_TABLE[j].class {
//return false
//}
if _BUILTIN_FUNCTION_LOOKUP_TABLE[i].name < _BUILTIN_FUNCTION_LOOKUP_TABLE[j].name {
namei := _BUILTIN_FUNCTION_LOOKUP_TABLE[i].name
namej := _BUILTIN_FUNCTION_LOOKUP_TABLE[j].name
si := startsWithLetter(namei)
sj := startsWithLetter(namej)
if si && !sj {
return true
}
if _BUILTIN_FUNCTION_LOOKUP_TABLE[i].name > _BUILTIN_FUNCTION_LOOKUP_TABLE[j].name {
} else if !si && sj {
return false
} else {
// classi := _BUILTIN_FUNCTION_LOOKUP_TABLE[i].class
// classj := _BUILTIN_FUNCTION_LOOKUP_TABLE[j].class
//if classi < classj {
// return true
//}
//if classi > classj {
// return false
//}
if namei < namej {
return true
} else {
return false
}
}
return false
})
}
// TODO: move
func isLetter(c byte) bool {
return ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z')
}
func startsWithLetter(s string) bool {
if len(s) < 1 {
return false
} else {
return isLetter(s[0])
}
}
var _BUILTIN_FUNCTION_LOOKUP_TABLE = []BuiltinFunctionInfo{
// ----------------------------------------------------------------
@ -1582,6 +1609,15 @@ func (manager *BuiltinFunctionManager) ListBuiltinFunctionNames(o *os.File) {
}
}
// ----------------------------------------------------------------
func (manager *BuiltinFunctionManager) ListBuiltinFunctionNamesAsParagraph(o *os.File) {
functionNames := make([]string, len(*manager.lookupTable))
for i, builtinFunctionInfo := range *manager.lookupTable {
functionNames[i] = builtinFunctionInfo.name
}
lib.PrintWordsAsParagraph(functionNames, o)
}
// ----------------------------------------------------------------
func (manager *BuiltinFunctionManager) ListBuiltinFunctionUsages(o *os.File) {
manager.ListBuiltinFunctionUsagesDecorated(

View file

@ -141,7 +141,7 @@ func (root *RootNode) buildDumpxStatementNode(
return nil, errors.New(
fmt.Sprintf(
"%s: unhandled redirector node type %s.",
lib.MlrExeName(), string(redirectorNode.Type),
"mlr", string(redirectorNode.Type),
),
)
}
@ -219,7 +219,7 @@ func (node *DumpStatementNode) dumpToFileOrPipe(
return errors.New(
fmt.Sprintf(
"%s: output redirection yielded %s, not string.",
lib.MlrExeName(), redirectorTarget.GetTypeName(),
"mlr", redirectorTarget.GetTypeName(),
),
)
}

View file

@ -198,7 +198,7 @@ func (root *RootNode) buildEmitXStatementNode(
return nil, errors.New(
fmt.Sprintf(
"%s: unhandled redirector node type %s.",
lib.MlrExeName(), string(redirectorNode.Type),
"mlr", string(redirectorNode.Type),
),
)
}
@ -427,7 +427,7 @@ func (node *EmitXStatementNode) emitToFileOrPipe(
return errors.New(
fmt.Sprintf(
"%s: output redirection yielded %s, not string.",
lib.MlrExeName(), redirectorTarget.GetTypeName(),
"mlr", redirectorTarget.GetTypeName(),
),
)
}

View file

@ -122,7 +122,7 @@ func (root *RootNode) BuildEmitFStatementNode(astNode *dsl.ASTNode) (IExecutable
return nil, errors.New(
fmt.Sprintf(
"%s: unhandled redirector node type %s.",
lib.MlrExeName(), string(redirectorNode.Type),
"mlr", string(redirectorNode.Type),
),
)
}
@ -171,7 +171,7 @@ func getNameFromNamedNode(astNode *dsl.ASTNode, description string) (string, err
return "", errors.New(
fmt.Sprintf(
"%s: can't get name of node type \"%s\" for %s.",
lib.MlrExeName(), string(astNode.Type), description,
"mlr", string(astNode.Type), description,
),
)
}
@ -200,7 +200,7 @@ func (node *EmitFStatementNode) emitfToFileOrPipe(
return errors.New(
fmt.Sprintf(
"%s: output redirection yielded %s, not string.",
lib.MlrExeName(), redirectorTarget.GetTypeName(),
"mlr", redirectorTarget.GetTypeName(),
),
)
}

View file

@ -2,6 +2,7 @@ package cst
import (
"fmt"
"os"
"miller/src/lib"
)
@ -82,26 +83,37 @@ func UsageKeywords() {
}
func UsageForKeyword(name string) {
found := false
for _, entry := range KEYWORD_USAGE_TABLE {
if entry.name == name {
entry.usageFunc()
found = true
break
}
}
if !found {
if !TryUsageForKeyword(name) {
fmt.Printf("mlr: unrecognized keyword \"%s\".\n", name)
}
}
func TryUsageForKeyword(name string) bool {
for _, entry := range KEYWORD_USAGE_TABLE {
if entry.name == name {
entry.usageFunc()
return true
}
}
return false
}
// ----------------------------------------------------------------
func ListKeywords() {
func ListKeywordsVertically() {
for _, entry := range KEYWORD_USAGE_TABLE {
fmt.Println(entry.name)
}
}
// ----------------------------------------------------------------
func ListKeywordsAsParagraph() {
keywords := make([]string, len(KEYWORD_USAGE_TABLE))
for i, entry := range KEYWORD_USAGE_TABLE {
keywords[i] = entry.name
}
lib.PrintWordsAsParagraph(keywords, os.Stdout)
}
// ----------------------------------------------------------------
func allKeywordUsage() {
fmt.Println(

View file

@ -284,7 +284,7 @@ func (root *RootNode) buildPrintxStatementNode(
return nil, errors.New(
fmt.Sprintf(
"%s: unhandled redirector node type %s.",
lib.MlrExeName(), string(redirectorNode.Type),
"mlr", string(redirectorNode.Type),
),
)
}
@ -365,7 +365,7 @@ func (node *PrintStatementNode) printToFileOrPipe(
return errors.New(
fmt.Sprintf(
"%s: output redirection yielded %s, not string.",
lib.MlrExeName(), redirectorTarget.GetTypeName(),
"mlr", redirectorTarget.GetTypeName(),
),
)
}

View file

@ -13,7 +13,6 @@ import (
"miller/src/cliutil"
"miller/src/dsl"
"miller/src/lib"
"miller/src/output"
"miller/src/runtime"
"miller/src/types"
@ -81,7 +80,7 @@ func (root *RootNode) IngestAST(
if warningsAreFatal {
fmt.Printf(
"%s: Exiting due to warnings treated as fatal.\n",
lib.MlrExeName(),
"mlr",
)
os.Exit(1)
}
@ -281,7 +280,7 @@ func (root *RootNode) ProcessEndOfStream() {
fmt.Fprintf(
os.Stderr,
"%s: error on end-of-stream close: %v\n",
lib.MlrExeName(),
"mlr",
err,
)
}

View file

@ -124,7 +124,7 @@ func (root *RootNode) BuildTeeStatementNode(astNode *dsl.ASTNode) (IExecutable,
return nil, errors.New(
fmt.Sprintf(
"%s: unhandled redirector node type %s.",
lib.MlrExeName(), string(redirectorNode.Type),
"mlr", string(redirectorNode.Type),
),
)
}
@ -146,7 +146,7 @@ func (node *TeeStatementNode) Execute(state *runtime.State) (*BlockExitPayload,
return nil, errors.New(
fmt.Sprintf(
"%s: tee-evaluaiton yielded %s, not map.",
lib.MlrExeName(), expression.GetTypeName(),
"mlr", expression.GetTypeName(),
),
)
}
@ -164,7 +164,7 @@ func (node *TeeStatementNode) teeToFileOrPipe(
return errors.New(
fmt.Sprintf(
"%s: output redirection yielded %s, not string.",
lib.MlrExeName(), redirectorTarget.GetTypeName(),
"mlr", redirectorTarget.GetTypeName(),
),
)
}

View file

@ -276,7 +276,7 @@ func validateForLoopTwoVariableUniqueNames(astNode *dsl.ASTNode) error {
return errors.New(
fmt.Sprintf(
"%s: redefinition of variable %s in the same scope.",
lib.MlrExeName(),
"mlr",
keyVarName,
),
)
@ -312,7 +312,7 @@ func validateForLoopMultivariableUniqueNames(astNode *dsl.ASTNode) error {
return errors.New(
fmt.Sprintf(
"%s: redefinition of variable %s in the same scope.",
lib.MlrExeName(),
"mlr",
name,
),
)
@ -325,7 +325,7 @@ func validateForLoopMultivariableUniqueNames(astNode *dsl.ASTNode) error {
return errors.New(
fmt.Sprintf(
"%s: redefinition of variable %s in the same scope.",
lib.MlrExeName(),
"mlr",
valVarName,
),
)

View file

@ -101,7 +101,7 @@ func processInPlace(
for _, fileName := range fileNames {
if _, err := os.Stat(fileName); os.IsNotExist(err) {
fmt.Fprintf(os.Stderr, "%s: %v\n", lib.MlrExeName(), err)
fmt.Fprintf(os.Stderr, "%s: %v\n", "mlr", err)
os.Exit(1)
}
@ -115,7 +115,7 @@ func processInPlace(
// as revealed by printing handle.Name().
handle, err := os.CreateTemp(containingDirectory, "mlr-in-place-")
if err != nil {
fmt.Fprintf(os.Stderr, "%s: %v\n", lib.MlrExeName(), err)
fmt.Fprintf(os.Stderr, "%s: %v\n", "mlr", err)
os.Exit(1)
}
tempFileName := handle.Name()
@ -134,13 +134,13 @@ func processInPlace(
err = handle.Close()
if err != nil {
fmt.Fprintf(os.Stderr, "%s: %v\n", lib.MlrExeName(), err)
fmt.Fprintf(os.Stderr, "%s: %v\n", "mlr", err)
os.Exit(1)
}
err = os.Rename(tempFileName, fileName)
if err != nil {
fmt.Fprintf(os.Stderr, "%s: %v\n", lib.MlrExeName(), err)
fmt.Fprintf(os.Stderr, "%s: %v\n", "mlr", err)
os.Exit(1)
}
}

View file

@ -1,12 +0,0 @@
package lib
func MlrExeName() string {
// TODO:
// This is ideal, so if someone has a 'mlr.debug' or somesuch, the messages will reflect that:
// return path.Base(os.Args[0])
// ... however it makes automated regression-testing hard, cross-platform. For example,
// 'mlr' vs 'C:\something\something\mlr.exe'.
return "mlr"
}

View file

@ -79,7 +79,7 @@ func OpenInboundHalfPipe(commandString string) (*os.File, error) {
go func(process *os.Process, readPipe *os.File) {
_, err := process.Wait()
if err != nil {
fmt.Fprintf(os.Stderr, "%s: %v\n", MlrExeName(), err)
fmt.Fprintf(os.Stderr, "%s: %v\n", "mlr", err)
}
readPipe.Close()
}(process, readPipe)
@ -90,7 +90,7 @@ func OpenInboundHalfPipe(commandString string) (*os.File, error) {
func waitAndClose(process *os.Process, readPipe *os.File) {
_, err := process.Wait()
if err != nil {
fmt.Fprintf(os.Stderr, "%s: %v\n", MlrExeName(), err)
fmt.Fprintf(os.Stderr, "%s: %v\n", "mlr", err)
}
readPipe.Close()
}

View file

@ -176,7 +176,7 @@ func GetRealSymmetricEigensystem(
if !found {
fmt.Fprintf(os.Stderr,
"%s: Jacobi eigensolver: max iterations (%d) exceeded. Non-symmetric input?\n",
MlrExeName(),
"mlr",
JACOBI_MAXITER,
)
os.Exit(1)

34
go/src/lib/paragraph.go Normal file
View file

@ -0,0 +1,34 @@
package lib
import (
"fmt"
"os"
)
// For on-line help contexts like printing all the built-in DSL functions, or
// the list of all verbs.
func PrintWordsAsParagraph(words []string, o *os.File) {
separator := " "
maxlen := 80
separatorlen := len(separator)
linelen := 0
j := 0
for _, word := range words {
wordlen := len(word)
linelen += separatorlen + wordlen
if linelen >= maxlen {
fmt.Fprintf(o, "\n")
linelen = separatorlen + wordlen
j = 0
}
if j > 0 {
fmt.Fprint(o, separator)
}
fmt.Fprint(o, word)
j++
}
fmt.Printf("\n")
}

View file

@ -282,7 +282,7 @@ func NewPipeWriteOutputHandler(
return nil, errors.New(
fmt.Sprintf(
"%s: could not launch command \"%s\" for pipe-to.",
lib.MlrExeName(),
"mlr",
commandString,
),
)

View file

@ -453,7 +453,7 @@ func (frame *StackFrame) defineTyped(
return errors.New(
fmt.Sprintf(
"%s: variable %s has already been defined in the same scope.",
lib.MlrExeName(), stackVariable.name,
"mlr", stackVariable.name,
),
)
}
@ -477,7 +477,7 @@ func (frame *StackFrame) setIndexed(
return errors.New(
fmt.Sprintf(
"%s: map indices must be int or string; got %s.\n",
lib.MlrExeName(), leadingIndex.GetTypeName(),
"mlr", leadingIndex.GetTypeName(),
),
)
}

View file

@ -7,7 +7,6 @@ import (
"miller/src/cliutil"
"miller/src/input"
"miller/src/lib"
"miller/src/output"
"miller/src/transformers"
"miller/src/types"
@ -75,7 +74,7 @@ func Stream(
for !done {
select {
case err := <-errorChannel:
fmt.Fprintln(os.Stderr, lib.MlrExeName(), ": ", err)
fmt.Fprintln(os.Stderr, "mlr", ": ", err)
os.Exit(1)
case _ = <-doneChannel:
done = true

View file

@ -88,29 +88,13 @@ func ListVerbNamesVertically() {
// ----------------------------------------------------------------
func ListVerbNamesAsParagraph() {
separator := " "
verbNames := make([]string, len(TRANSFORMER_LOOKUP_TABLE))
separatorlen := len(separator)
linelen := 0
j := 0
for _, transformerSetup := range TRANSFORMER_LOOKUP_TABLE {
verb := transformerSetup.Verb
verblen := len(verb)
linelen += separatorlen + verblen
if linelen >= 80 {
fmt.Printf("\n")
linelen = separatorlen + verblen
j = 0
}
if j > 0 {
fmt.Print(separator)
}
fmt.Print(verb)
j++
for i, transformerSetup := range TRANSFORMER_LOOKUP_TABLE {
verbNames[i] = transformerSetup.Verb
}
fmt.Printf("\n")
lib.PrintWordsAsParagraph(verbNames, os.Stdout)
}
// ----------------------------------------------------------------

View file

@ -7,7 +7,6 @@ import (
"strings"
"miller/src/cliutil"
"miller/src/lib"
"miller/src/types"
)
@ -26,7 +25,7 @@ func transformerAltkvUsage(
doExit bool,
exitCode int,
) {
fmt.Fprintf(o, "Usage: %s %s [options]\n", lib.MlrExeName(), verbNameAltkv)
fmt.Fprintf(o, "Usage: %s %s [options]\n", "mlr", verbNameAltkv)
fmt.Fprintf(o, "Given fields with values of the form a,b,c,d,e,f emits a=b,c=d,e=f pairs.\n")
fmt.Fprintf(o, "Options:\n")
fmt.Fprintf(o, "-h|--help Show this message.\n")

View file

@ -8,7 +8,6 @@ import (
"strings"
"miller/src/cliutil"
"miller/src/lib"
"miller/src/types"
)
@ -34,7 +33,7 @@ func transformerBarUsage(
doExit bool,
exitCode int,
) {
fmt.Fprintf(o, "Usage: %s %s [options]\n", lib.MlrExeName(), verbNameBar)
fmt.Fprintf(o, "Usage: %s %s [options]\n", "mlr", verbNameBar)
fmt.Fprintf(o, "Replaces a numeric field with a number of asterisks, allowing for cheesy\n")
fmt.Fprintf(o, "bar plots. These align best with --opprint or --oxtab output format.\n")
fmt.Fprintf(o, "Options:\n")

View file

@ -26,11 +26,11 @@ func transformerBootstrapUsage(
doExit bool,
exitCode int,
) {
fmt.Fprintf(o, "Usage: %s %s [options]\n", lib.MlrExeName(), verbNameBootstrap)
fmt.Fprintf(o, "Usage: %s %s [options]\n", "mlr", verbNameBootstrap)
fmt.Fprintf(o,
`Emits an n-sample, with replacement, of the input records.
See also %s sample and %s shuffle.
`, lib.MlrExeName(), lib.MlrExeName())
`, "mlr", "mlr")
fmt.Fprintf(o, "Options:\n")
fmt.Fprintf(o,
` -n Number of samples to output. Defaults to number of input records.

View file

@ -6,7 +6,6 @@ import (
"strings"
"miller/src/cliutil"
"miller/src/lib"
"miller/src/types"
)
@ -25,7 +24,7 @@ func transformerCatUsage(
doExit bool,
exitCode int,
) {
fmt.Fprintf(o, "Usage: %s %s [options]\n", lib.MlrExeName(), verbNameCat)
fmt.Fprintf(o, "Usage: %s %s [options]\n", "mlr", verbNameCat)
fmt.Fprintf(o, "Passes input records directly to output. Most useful for format conversion.\n")
fmt.Fprintf(o, "Options:\n")
fmt.Fprintf(o, "-n Prepend field \"n\" to each record with record-counter starting at 1.\n")

View file

@ -6,7 +6,6 @@ import (
"strings"
"miller/src/cliutil"
"miller/src/lib"
"miller/src/types"
)
@ -25,7 +24,7 @@ func transformerCheckUsage(
doExit bool,
exitCode int,
) {
fmt.Fprintf(o, "Usage: %s %s [options]\n", lib.MlrExeName(), verbNameCheck)
fmt.Fprintf(o, "Usage: %s %s [options]\n", "mlr", verbNameCheck)
fmt.Fprintf(o, "Consumes records without printing any output.\n")
fmt.Fprintf(o, "Useful for doing a well-formatted check on input data.\n")
fmt.Fprintf(o, "Options:\n")

View file

@ -6,7 +6,6 @@ import (
"strings"
"miller/src/cliutil"
"miller/src/lib"
"miller/src/types"
)
@ -25,7 +24,7 @@ func transformerCleanWhitespaceUsage(
doExit bool,
exitCode int,
) {
fmt.Fprintf(o, "Usage: %s %s [options]\n", lib.MlrExeName(), verbNameCleanWhitespace)
fmt.Fprintf(o, "Usage: %s %s [options]\n", "mlr", verbNameCleanWhitespace)
fmt.Fprintf(o, "For each record, for each field in the record, whitespace-cleans the keys and/or\n")
fmt.Fprintf(o, "values. Whitespace-cleaning entails stripping leading and trailing whitespace,\n")
fmt.Fprintf(o, "and replacing multiple whitespace with singles. For finer-grained control,\n")

View file

@ -26,7 +26,7 @@ func transformerCountSimilarUsage(
doExit bool,
exitCode int,
) {
fmt.Fprintf(o, "Usage: %s %s [options]\n", lib.MlrExeName(), verbNameCountSimilar)
fmt.Fprintf(o, "Usage: %s %s [options]\n", "mlr", verbNameCountSimilar)
fmt.Fprintf(o, "Ingests all records, then emits each record augmented by a count of\n")
fmt.Fprintf(o, "the number of other records having the same group-by field values.\n")
fmt.Fprintf(o, "Options:\n")

View file

@ -25,7 +25,7 @@ func transformerCountUsage(
doExit bool,
exitCode int,
) {
fmt.Fprintf(o, "Usage: %s %s [options]\n", lib.MlrExeName(), verbNameCount)
fmt.Fprintf(o, "Usage: %s %s [options]\n", "mlr", verbNameCount)
fmt.Fprint(o,
`Prints number of records, optionally grouped by distinct values for specified field names.
`)

View file

@ -26,7 +26,7 @@ func transformerCutUsage(
doExit bool,
exitCode int,
) {
fmt.Fprintf(o, "Usage: %s %s [options]\n", lib.MlrExeName(), verbNameCut)
fmt.Fprintf(o, "Usage: %s %s [options]\n", "mlr", verbNameCut)
fmt.Fprintf(o, "Passes through input records with specified fields included/excluded.\n")
fmt.Fprintf(o, "Options:\n")
fmt.Fprintf(o, " -f {a,b,c} Comma-separated field names for cut, e.g. a,b,c.\n")
@ -39,11 +39,11 @@ func transformerCutUsage(
fmt.Fprintf(o, " be used. The -o flag is ignored when -r is present.\n")
fmt.Fprintf(o, "-h|--help Show this message.\n")
fmt.Fprintf(o, "Examples:\n")
fmt.Fprintf(o, " %s %s -f hostname,status\n", lib.MlrExeName(), verbNameCut)
fmt.Fprintf(o, " %s %s -x -f hostname,status\n", lib.MlrExeName(), verbNameCut)
fmt.Fprintf(o, " %s %s -r -f '^status$,sda[0-9]'\n", lib.MlrExeName(), verbNameCut)
fmt.Fprintf(o, " %s %s -r -f '^status$,\"sda[0-9]\"'\n", lib.MlrExeName(), verbNameCut)
fmt.Fprintf(o, " %s %s -r -f '^status$,\"sda[0-9]\"i' (this is case-insensitive)\n", lib.MlrExeName(), verbNameCut)
fmt.Fprintf(o, " %s %s -f hostname,status\n", "mlr", verbNameCut)
fmt.Fprintf(o, " %s %s -x -f hostname,status\n", "mlr", verbNameCut)
fmt.Fprintf(o, " %s %s -r -f '^status$,sda[0-9]'\n", "mlr", verbNameCut)
fmt.Fprintf(o, " %s %s -r -f '^status$,\"sda[0-9]\"'\n", "mlr", verbNameCut)
fmt.Fprintf(o, " %s %s -r -f '^status$,\"sda[0-9]\"i' (this is case-insensitive)\n", "mlr", verbNameCut)
if doExit {
os.Exit(exitCode)
@ -158,7 +158,7 @@ func NewTransformerCut(
fmt.Fprintf(
os.Stderr,
"%s %s: cannot compile regex [%s]\n",
lib.MlrExeName(), verbNameCut, regexString,
"mlr", verbNameCut, regexString,
)
os.Exit(1)
}

View file

@ -6,7 +6,6 @@ import (
"strings"
"miller/src/cliutil"
"miller/src/lib"
"miller/src/types"
)
@ -25,7 +24,7 @@ func transformerDecimateUsage(
doExit bool,
exitCode int,
) {
fmt.Fprintf(o, "Usage: %s %s [options]\n", lib.MlrExeName(), verbNameDecimate)
fmt.Fprintf(o, "Usage: %s %s [options]\n", "mlr", verbNameDecimate)
fmt.Fprintf(o, "Passes through one of every n records, optionally by category.\n")
fmt.Fprintf(o, "Options:\n")
fmt.Fprintf(o, " -b Decimate by printing first of every n.\n")

View file

@ -6,7 +6,6 @@ import (
"strings"
"miller/src/cliutil"
"miller/src/lib"
"miller/src/types"
)
@ -25,7 +24,7 @@ func transformerFillDownUsage(
doExit bool,
exitCode int,
) {
fmt.Fprintf(o, "Usage: %s %s [options]\n", lib.MlrExeName(), verbNameFillDown)
fmt.Fprintf(o, "Usage: %s %s [options]\n", "mlr", verbNameFillDown)
fmt.Fprintln(o, "If a given record has a missing value for a given field, fill that from")
fmt.Fprintln(o, "the corresponding value from a previous record, if any.")
fmt.Fprintln(o, "By default, a 'missing' field either is absent, or has the empty-string value.")

View file

@ -6,7 +6,6 @@ import (
"strings"
"miller/src/cliutil"
"miller/src/lib"
"miller/src/types"
)
@ -26,7 +25,7 @@ func transformerFillEmptyUsage(
doExit bool,
exitCode int,
) {
fmt.Fprintf(o, "Usage: %s %s [options]\n", lib.MlrExeName(), verbNameFillEmpty)
fmt.Fprintf(o, "Usage: %s %s [options]\n", "mlr", verbNameFillEmpty)
fmt.Fprintf(o, "Fills empty-string fields with specified fill-value.\n")
fmt.Fprintf(o, "Options:\n")
fmt.Fprintf(o, "-v {string} Fill-value: defaults to \"%s\"\n", defaultFillEmptyString)

View file

@ -25,14 +25,14 @@ func transformerFlattenUsage(
doExit bool,
exitCode int,
) {
fmt.Fprintf(o, "Usage: %s %s [options]\n", lib.MlrExeName(), verbNameFlatten)
fmt.Fprintf(o, "Usage: %s %s [options]\n", "mlr", verbNameFlatten)
fmt.Fprint(o,
`Flattens multi-level maps to single-level ones. Example: field with name 'a'
and value '{"b": { "c": 4 }}' becomes name 'a.b.c' and value 4.
`)
fmt.Fprint(o, "Options:\n")
fmt.Fprint(o, "-f Comma-separated list of field names to flatten (default all).\n")
fmt.Fprintf(o, "-s Separator, defaulting to %s --oflatsep value.\n", lib.MlrExeName())
fmt.Fprintf(o, "-s Separator, defaulting to %s --oflatsep value.\n", "mlr")
fmt.Fprintf(o, "-h|--help Show this message.\n")
if doExit {

View file

@ -6,7 +6,6 @@ import (
"strings"
"miller/src/cliutil"
"miller/src/lib"
"miller/src/types"
)
@ -30,7 +29,7 @@ func transformerFormatValuesUsage(
doExit bool,
exitCode int,
) {
fmt.Fprintf(o, "Usage: %s %s [options]\n", lib.MlrExeName(), verbNameFormatValues)
fmt.Fprintf(o, "Usage: %s %s [options]\n", "mlr", verbNameFormatValues)
fmt.Fprintf(o, "Applies format strings to all field values, depending on autodetected type.\n")
fmt.Fprintf(o, "* If a field value is detected to be integer, applies integer format.\n")
fmt.Fprintf(o, "* Else, if a field value is detected to be float, applies float format.\n")

View file

@ -26,7 +26,7 @@ func transformerFractionUsage(
doExit bool,
exitCode int,
) {
argv0 := lib.MlrExeName()
argv0 := "mlr"
verb := verbNameFraction
fmt.Fprintf(o, "Usage: %s %s [options]\n", argv0, verb)
fmt.Fprintf(o, "For each record's value in specified fields, computes the ratio of that\n")

View file

@ -6,7 +6,6 @@ import (
"strings"
"miller/src/cliutil"
"miller/src/lib"
"miller/src/types"
)
@ -25,7 +24,7 @@ func transformerGapUsage(
doExit bool,
exitCode int,
) {
fmt.Fprintf(o, "Usage: %s %s [options]\n", lib.MlrExeName(), verbNameGap)
fmt.Fprintf(o, "Usage: %s %s [options]\n", "mlr", verbNameGap)
fmt.Fprint(o, "Emits an empty record every n records, or when certain values change.\n")
fmt.Fprintf(o, "Options:\n")

View file

@ -7,7 +7,6 @@ import (
"strings"
"miller/src/cliutil"
"miller/src/lib"
"miller/src/types"
)
@ -26,7 +25,7 @@ func transformerGrepUsage(
doExit bool,
exitCode int,
) {
fmt.Fprintf(o, "Usage: %s %s [options] {regular expression}\n", lib.MlrExeName(), verbNameGrep)
fmt.Fprintf(o, "Usage: %s %s [options] {regular expression}\n", "mlr", verbNameGrep)
fmt.Fprintf(o, "Passes through records which match the regular expression.\n")
fmt.Fprint(o, "Options:\n")
@ -45,7 +44,7 @@ be matched, not against either of these lines, but against the DKVP line
and this command is intended to be merely a keystroke-saver. To get all the
features of system grep, you can do
"%s --odkvp ... | grep ... | %s --idkvp ..."
`, lib.MlrExeName(), lib.MlrExeName(), lib.MlrExeName(), lib.MlrExeName())
`, "mlr", "mlr", "mlr", "mlr")
if doExit {
os.Exit(exitCode)
@ -103,7 +102,7 @@ func transformerGrepParseCLI(
regexp, err := regexp.Compile(pattern)
if err != nil {
fmt.Fprintf(os.Stderr, "%s %s: couldn't compile regex \"%s\"\n",
lib.MlrExeName(), verb, pattern)
"mlr", verb, pattern)
os.Exit(1)
}

View file

@ -26,7 +26,7 @@ func transformerGroupByUsage(
doExit bool,
exitCode int,
) {
fmt.Fprintf(o, "Usage: %s %s [options] {comma-separated field names}\n", lib.MlrExeName(), verbNameGroupBy)
fmt.Fprintf(o, "Usage: %s %s [options] {comma-separated field names}\n", "mlr", verbNameGroupBy)
fmt.Fprint(o, "Outputs records in batches having identical values at specified field names.")
fmt.Fprintf(o, "Options:\n")
fmt.Fprintf(o, "-h|--help Show this message.\n")

View file

@ -26,7 +26,7 @@ func transformerGroupLikeUsage(
doExit bool,
exitCode int,
) {
fmt.Fprintf(o, "Usage: %s %s [options]\n", lib.MlrExeName(), verbNameGroupLike)
fmt.Fprintf(o, "Usage: %s %s [options]\n", "mlr", verbNameGroupLike)
fmt.Fprint(o, "Outputs records in batches having identical field names.")
fmt.Fprintf(o, "Options:\n")
fmt.Fprintf(o, "-h|--help Show this message.\n")

View file

@ -39,9 +39,9 @@ func transformerHavingFieldsUsage(
doExit bool,
exitCode int,
) {
exeName := lib.MlrExeName()
exeName := "mlr"
verb := verbNameHavingFields
fmt.Fprintf(o, "Usage: %s %s [options]\n", lib.MlrExeName(), verbNameHavingFields)
fmt.Fprintf(o, "Usage: %s %s [options]\n", "mlr", verbNameHavingFields)
fmt.Fprintf(o, "Conditionally passes through records depending on each record's field names.\n")
fmt.Fprintf(o, "Options:\n")
@ -187,7 +187,7 @@ func NewTransformerHavingFields(
fmt.Fprintf(
os.Stderr,
"%s %s: cannot compile regex \"%s\"\n",
lib.MlrExeName(),
"mlr",
verbNameHavingFields,
regexString,
)

View file

@ -6,7 +6,6 @@ import (
"strings"
"miller/src/cliutil"
"miller/src/lib"
"miller/src/types"
)
@ -25,7 +24,7 @@ func transformerHeadUsage(
doExit bool,
exitCode int,
) {
fmt.Fprintf(o, "Usage: %s %s [options]\n", lib.MlrExeName(), verbNameHead)
fmt.Fprintf(o, "Usage: %s %s [options]\n", "mlr", verbNameHead)
fmt.Fprintf(o, "Passes through the first n records, optionally by category.\n")
fmt.Fprintf(o, "Options:\n")

View file

@ -25,7 +25,7 @@ func transformerHistogramUsage(
doExit bool,
exitCode int,
) {
argv0 := lib.MlrExeName()
argv0 := "mlr"
verb := verbNameHistogram
fmt.Fprintf(o, "Just a histogram. Input values < lo or > hi are not counted.\n")
fmt.Fprintf(o, "Usage: %s %s [options]\n", argv0, verb)
@ -217,7 +217,7 @@ func (tr *TransformerHistogram) ingestNonAuto(
fmt.Fprintf(
os.Stderr,
"%s %s: cannot parse \"%s\" as float.\n",
lib.MlrExeName(), verbNameHistogram, stringValue.String(),
"mlr", verbNameHistogram, stringValue.String(),
)
os.Exit(1)
}

View file

@ -77,7 +77,7 @@ func transformerJoinUsage(
doExit bool,
exitCode int,
) {
fmt.Fprintf(o, "Usage: %s %s [options]\n", lib.MlrExeName(), verbNameJoin)
fmt.Fprintf(o, "Usage: %s %s [options]\n", "mlr", verbNameJoin)
fmt.Fprintf(o, "Joins records from specified left file name with records from all file names\n")
fmt.Fprintf(o, "at the end of the Miller argument list.\n")
fmt.Fprintf(o, "Functionality is essentially the same as the system \"join\" command, but for\n")
@ -103,13 +103,13 @@ func transformerJoinUsage(
fmt.Fprintf(o, " -u Enable unsorted input. (This is the default even without -u.)\n")
fmt.Fprintf(o, " In this case, the entire left file will be loaded into memory.\n")
fmt.Fprintf(o, " --prepipe {command} As in main input options; see %s --help for details.\n",
lib.MlrExeName())
"mlr")
fmt.Fprintf(o, " If you wish to use a prepipe command for the main input as well\n")
fmt.Fprintf(o, " as here, it must be specified there as well as here.\n")
fmt.Fprintf(o, " --prepipex {command} Likewise.\n")
fmt.Fprintf(o, "File-format options default to those for the right file names on the Miller\n")
fmt.Fprintf(o, "argument list, but may be overridden for the left file as follows. Please see\n")
fmt.Fprintf(o, "the main \"%s --help\" for more information on syntax for these arguments:\n", lib.MlrExeName())
fmt.Fprintf(o, "the main \"%s --help\" for more information on syntax for these arguments:\n", "mlr")
fmt.Fprintf(o, " -i {one of csv,dkvp,nidx,pprint,xtab}\n")
fmt.Fprintf(o, " --irs {record-separator character}\n")
fmt.Fprintf(o, " --ifs {field-separator character}\n")
@ -123,7 +123,7 @@ func transformerJoinUsage(
fmt.Fprintf(o, "Likewise, if you have 'mlr --csv --implicit-csv-header ...' then the join-in file will be\n")
fmt.Fprintf(o, "expected to be headerless as well unless you put '--no-implicit-csv-header' after 'join'.\n")
fmt.Fprintf(o, "Please use \"%s --usage-separator-options\" for information on specifying separators.\n",
lib.MlrExeName())
"mlr")
fmt.Fprintf(o, "Please see https://miller.readthedocs.io/en/latest/reference-verbs.html#join for more information\n")
fmt.Fprintf(o, "including examples.\n")
@ -220,20 +220,20 @@ func transformerJoinParseCLI(
}
if opts.leftFileName == "" {
fmt.Fprintf(os.Stderr, "%s %s: need left file name\n", lib.MlrExeName(), verb)
fmt.Fprintf(os.Stderr, "%s %s: need left file name\n", "mlr", verb)
transformerSortUsage(os.Stderr, true, 1)
return nil
}
if !opts.emitPairables && !opts.emitLeftUnpairables && !opts.emitRightUnpairables {
fmt.Fprintf(os.Stderr, "%s %s: all emit flags are unset; no output is possible.\n",
lib.MlrExeName(), verb)
"mlr", verb)
transformerSortUsage(os.Stderr, true, 1)
return nil
}
if opts.outputJoinFieldNames == nil {
fmt.Fprintf(os.Stderr, "%s %s: need output field names\n", lib.MlrExeName(), verb)
fmt.Fprintf(os.Stderr, "%s %s: need output field names\n", "mlr", verb)
transformerSortUsage(os.Stderr, true, 1)
return nil
}
@ -251,7 +251,7 @@ func transformerJoinParseCLI(
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",
lib.MlrExeName(), verb, llen, rlen, olen)
"mlr", verb, llen, rlen, olen)
os.Exit(1)
}
@ -475,7 +475,7 @@ func (tr *TransformerJoin) ingestLeftFile() {
select {
case err := <-errorChannel:
fmt.Fprintln(os.Stderr, lib.MlrExeName(), ": ", err)
fmt.Fprintln(os.Stderr, "mlr", ": ", err)
os.Exit(1)
case leftrecAndContext := <-inputChannel:

View file

@ -25,7 +25,7 @@ func transformerJSONParseUsage(
doExit bool,
exitCode int,
) {
fmt.Fprintf(o, "Usage: %s %s [options]\n", lib.MlrExeName(), verbNameJSONParse)
fmt.Fprintf(o, "Usage: %s %s [options]\n", "mlr", verbNameJSONParse)
fmt.Fprintln(
o,
`Tries to convert string field values to parsed JSON, e.g. "[1,2,3]" -> [1,2,3].`,

View file

@ -25,7 +25,7 @@ func transformerJSONStringifyUsage(
doExit bool,
exitCode int,
) {
fmt.Fprintf(o, "Usage: %s %s [options]\n", lib.MlrExeName(), verbNameJSONStringify)
fmt.Fprintf(o, "Usage: %s %s [options]\n", "mlr", verbNameJSONStringify)
fmt.Fprint(o,
`Produces string field values from field-value data, e.g. [1,2,3] -> "[1,2,3]".
`)

View file

@ -26,7 +26,7 @@ func transformerLabelUsage(
doExit bool,
exitCode int,
) {
fmt.Fprintf(o, "Usage: %s %s [options] {new1,new2,new3,...}\n", lib.MlrExeName(), verbNameLabel)
fmt.Fprintf(o, "Usage: %s %s [options] {new1,new2,new3,...}\n", "mlr", verbNameLabel)
fmt.Fprintf(o, "Given n comma-separated names, renames the first n fields of each record to\n")
fmt.Fprintf(o, "have the respective name. (Fields past the nth are left with their original\n")
fmt.Fprintf(o, "names.) Particularly useful with --inidx or --implicit-csv-header, to give\n")

View file

@ -37,7 +37,7 @@ func transformerMergeFieldsUsage(
doExit bool,
exitCode int,
) {
argv0 := lib.MlrExeName()
argv0 := "mlr"
verb := verbNameMergeFields
fmt.Fprintf(o, "Usage: %s %s [options]\n", argv0, verb)
fmt.Fprintf(o, "Computes univariate statistics for each input record, accumulated across\n")
@ -143,13 +143,13 @@ func transformerMergeFieldsParseCLI(
// TODO: libify for use across verbs.
if len(accumulatorNameList) == 0 {
fmt.Fprintf(os.Stderr, "%s %s: -a option is required.\n", lib.MlrExeName(), verbNameMergeFields)
fmt.Fprintf(os.Stderr, "Please see %s %s --help for more information.\n", lib.MlrExeName(), verbNameMergeFields)
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)
}
if len(valueFieldNameList) == 0 {
fmt.Fprintf(os.Stderr, "%s %s: -f option is required.\n", lib.MlrExeName(), verbNameMergeFields)
fmt.Fprintf(os.Stderr, "Please see %s %s --help for more information.\n", lib.MlrExeName(), verbNameMergeFields)
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)
}
if outputFieldBasename == "" {
@ -251,7 +251,7 @@ func NewTransformerMergeFields(
return nil, errors.New(
fmt.Sprintf(
"%s %s: accumulator \"%s\" not found.\n",
lib.MlrExeName(), verbNameMergeFields, accumulatorName,
"mlr", verbNameMergeFields, accumulatorName,
),
)
}
@ -275,7 +275,7 @@ func NewTransformerMergeFields(
fmt.Fprintf(
os.Stderr,
"%s %s: cannot compile regex [%s]\n",
lib.MlrExeName(), verbNameCut, regexString,
"mlr", verbNameCut, regexString,
)
os.Exit(1)
}

View file

@ -7,7 +7,6 @@ import (
"strings"
"miller/src/cliutil"
"miller/src/lib"
"miller/src/types"
)
@ -37,7 +36,7 @@ func transformerMostFrequentUsage(
doExit bool,
exitCode int,
) {
argv0 := lib.MlrExeName()
argv0 := "mlr"
verb := verbNameMostFrequent
fmt.Fprintf(o, "Usage: %s %s [options]\n", argv0, verb)
fmt.Fprintf(o, "Shows the most frequently occurring distinct values for specified field names.\n")
@ -58,7 +57,7 @@ func transformerLeastFrequentUsage(
doExit bool,
exitCode int,
) {
argv0 := lib.MlrExeName()
argv0 := "mlr"
verb := verbNameLeastFrequent
fmt.Fprintf(o, "Usage: %s %s [options]\n", argv0, verb)
fmt.Fprintf(o, "Shows the least frequently occurring distinct values for specified field names.\n")

View file

@ -29,7 +29,7 @@ func transformerNestUsage(
doExit bool,
exitCode int,
) {
argv0 := lib.MlrExeName()
argv0 := "mlr"
verb := verbNameNest
fmt.Fprintf(o, "Usage: %s %s [options]\n", argv0, verb)
@ -251,7 +251,7 @@ func NewTransformerNest(
fmt.Fprintf(
os.Stderr,
"%s %s: cannot compile regex [%s]\n",
lib.MlrExeName(), verbNameNest, regexString,
"mlr", verbNameNest, regexString,
)
os.Exit(1)
}

View file

@ -6,7 +6,6 @@ import (
"strings"
"miller/src/cliutil"
"miller/src/lib"
"miller/src/types"
)
@ -25,7 +24,7 @@ func transformerNothingUsage(
doExit bool,
exitCode int,
) {
fmt.Fprintf(o, "Usage: %s %s [options]\n", lib.MlrExeName(), verbNameNothing)
fmt.Fprintf(o, "Usage: %s %s [options]\n", "mlr", verbNameNothing)
fmt.Fprintf(o, "Drops all input records. Useful for testing, or after tee/print/etc. have\n")
fmt.Fprintf(o, "produced other output.\n")
fmt.Fprintf(o, "Options:\n")

View file

@ -58,7 +58,7 @@ func transformerPutOrFilterUsage(
exitCode int,
verb string,
) {
fmt.Fprintf(o, "Usage: %s %s [options] {DSL expression}\n", lib.MlrExeName(), verb)
fmt.Fprintf(o, "Usage: %s %s [options] {DSL expression}\n", "mlr", verb)
fmt.Fprintf(o, "Options:\n")
fmt.Fprintf(o,
`-f {file name} File containing a DSL expression. If the filename is a directory,
@ -157,7 +157,7 @@ func transformerPutOrFilterParseCLI(
theseDSLStrings, err := lib.LoadStringsFromFileOrDir(filename, ".mlr")
if err != nil {
fmt.Fprintf(os.Stderr, "%s %s: cannot load DSL expression from \"%s\": ",
lib.MlrExeName(), verb, filename)
"mlr", verb, filename)
fmt.Println(err)
return nil
}
@ -181,7 +181,7 @@ func transformerPutOrFilterParseCLI(
theseDSLStrings, err := lib.LoadStringsFromFileOrDir(filename, ".mlr")
if err != nil {
fmt.Fprintf(os.Stderr, "%s %s: cannot load DSL expression from file \"%s\": ",
lib.MlrExeName(), verb, filename)
"mlr", verb, filename)
fmt.Println(err)
return nil
}
@ -404,7 +404,7 @@ func BuildASTFromStringWithMessage(dslString string) (*dsl.AST, error) {
// At present it's overly parser-internal, and confusing. :(
// fmt.Fprintln(os.Stderr, err)
fmt.Fprintf(os.Stderr, "%s: cannot parse DSL expression.\n",
lib.MlrExeName())
"mlr")
fmt.Fprintln(os.Stderr, err)
return nil, err
} else {

View file

@ -25,7 +25,7 @@ func transformerRegularizeUsage(
doExit bool,
exitCode int,
) {
fmt.Fprintf(o, "Usage: %s %s [options]\n", lib.MlrExeName(), verbNameRegularize)
fmt.Fprintf(o, "Usage: %s %s [options]\n", "mlr", verbNameRegularize)
fmt.Fprint(o, "Outputs records sorted lexically ascending by keys.")
fmt.Fprintf(o, "Options:\n")
fmt.Fprintf(o, "-h|--help Show this message.\n")

View file

@ -7,7 +7,6 @@ import (
"strings"
"miller/src/cliutil"
"miller/src/lib"
"miller/src/types"
)
@ -26,7 +25,7 @@ func transformerRemoveEmptyColumnsUsage(
doExit bool,
exitCode int,
) {
fmt.Fprintf(o, "Usage: %s %s [options]\n", lib.MlrExeName(), verbNameRemoveEmptyColumns)
fmt.Fprintf(o, "Usage: %s %s [options]\n", "mlr", verbNameRemoveEmptyColumns)
fmt.Fprintf(o, "Omits fields which are empty on every input row. Non-streaming.\n")
fmt.Fprintf(o, "Options:\n")
fmt.Fprintf(o, "-h|--help Show this message.\n")

View file

@ -28,10 +28,10 @@ func transformerRenameUsage(
doExit bool,
exitCode int,
) {
exeName := lib.MlrExeName()
exeName := "mlr"
verb := verbNameRename
fmt.Fprintf(o, "Usage: %s %s [options] {old1,new1,old2,new2,...}\n", lib.MlrExeName(), verbNameRename)
fmt.Fprintf(o, "Usage: %s %s [options] {old1,new1,old2,new2,...}\n", "mlr", verbNameRename)
fmt.Fprintf(o, "Renames specified fields.\n")
fmt.Fprintf(o, "Options:\n")
fmt.Fprintf(o, "-r Treat old field names as regular expressions. \"ab\", \"a.*b\"\n")

View file

@ -25,7 +25,7 @@ func transformerReorderUsage(
doExit bool,
exitCode int,
) {
argv0 := lib.MlrExeName()
argv0 := "mlr"
verb := verbNameReorder
fmt.Fprintf(o, "Usage: %s %s [options]\n", argv0, verb)
fmt.Fprint(o,

View file

@ -6,7 +6,6 @@ import (
"strings"
"miller/src/cliutil"
"miller/src/lib"
"miller/src/types"
)
@ -34,7 +33,7 @@ func transformerRepeatUsage(
doExit bool,
exitCode int,
) {
fmt.Fprintf(o, "Usage: %s %s [options]\n", lib.MlrExeName(), verbNameRepeat)
fmt.Fprintf(o, "Usage: %s %s [options]\n", "mlr", verbNameRepeat)
fmt.Fprintf(o, "Copies input records to output records multiple times.\n")
fmt.Fprintf(o, "Options must be exactly one of the following:\n")
fmt.Fprintf(o, "-n {repeat count} Repeat each input record this many times.\n")
@ -42,19 +41,19 @@ func transformerRepeatUsage(
fmt.Fprintf(o, " field name of each input record.\n")
fmt.Fprintf(o, "-h|--help Show this message.\n")
fmt.Fprintf(o, "Example:\n")
fmt.Fprintf(o, " echo x=0 | %s %s -n 4 then put '$x=urand()'\n", lib.MlrExeName(), verbNameRepeat)
fmt.Fprintf(o, " echo x=0 | %s %s -n 4 then put '$x=urand()'\n", "mlr", verbNameRepeat)
fmt.Fprintf(o, "produces:\n")
fmt.Fprintf(o, " x=0.488189\n")
fmt.Fprintf(o, " x=0.484973\n")
fmt.Fprintf(o, " x=0.704983\n")
fmt.Fprintf(o, " x=0.147311\n")
fmt.Fprintf(o, "Example:\n")
fmt.Fprintf(o, " echo a=1,b=2,c=3 | %s %s -f b\n", lib.MlrExeName(), verbNameRepeat)
fmt.Fprintf(o, " echo a=1,b=2,c=3 | %s %s -f b\n", "mlr", verbNameRepeat)
fmt.Fprintf(o, "produces:\n")
fmt.Fprintf(o, " a=1,b=2,c=3\n")
fmt.Fprintf(o, " a=1,b=2,c=3\n")
fmt.Fprintf(o, "Example:\n")
fmt.Fprintf(o, " echo a=1,b=2,c=3 | %s %s -f c\n", lib.MlrExeName(), verbNameRepeat)
fmt.Fprintf(o, " echo a=1,b=2,c=3 | %s %s -f c\n", "mlr", verbNameRepeat)
fmt.Fprintf(o, "produces:\n")
fmt.Fprintf(o, " a=1,b=2,c=3\n")
fmt.Fprintf(o, " a=1,b=2,c=3\n")

View file

@ -53,7 +53,7 @@ func transformerReshapeUsage(
doExit bool,
exitCode int,
) {
argv0 := lib.MlrExeName()
argv0 := "mlr"
verb := verbNameReshape
fmt.Fprintf(o, "Usage: %s %s [options]\n", argv0, verb)
@ -250,7 +250,7 @@ func NewTransformerReshape(
fmt.Fprintf(
os.Stderr,
"%s %s: cannot compile regex [%s]\n",
lib.MlrExeName(), verbNameReshape, inputFieldRegexString,
"mlr", verbNameReshape, inputFieldRegexString,
)
os.Exit(1)
}

View file

@ -25,11 +25,11 @@ func transformerSampleUsage(
doExit bool,
exitCode int,
) {
fmt.Fprintf(o, "Usage: %s %s [options]\n", lib.MlrExeName(), verbNameSample)
fmt.Fprintf(o, "Usage: %s %s [options]\n", "mlr", verbNameSample)
fmt.Fprintf(o,
`Reservoir sampling (subsampling without replacement), optionally by category.
See also %s bootstrap and %s shuffle.
`, lib.MlrExeName(), lib.MlrExeName())
`, "mlr", "mlr")
fmt.Fprintf(o, "Options:\n")
fmt.Fprintf(o, "-g {a,b,c} Optional: group-by-field names for samples, e.g. a,b,c.\n")
fmt.Fprintf(o, "-k {k} Required: number of records to output in total, or by group if using -g.\n")

View file

@ -24,13 +24,13 @@ func transformerSec2GMTUsage(
doExit bool,
exitCode int,
) {
fmt.Fprintf(o, "Usage: %s %s [options] {comma-separated list of field names}\n", lib.MlrExeName(), verbNameSec2GMT)
fmt.Fprintf(o, "Usage: %s %s [options] {comma-separated list of field names}\n", "mlr", verbNameSec2GMT)
fmt.Fprintf(o, "Replaces a numeric field representing seconds since the epoch with the\n")
fmt.Fprintf(o, "corresponding GMT timestamp; leaves non-numbers as-is. This is nothing\n")
fmt.Fprintf(o, "more than a keystroke-saver for the sec2gmt function:\n")
fmt.Fprintf(o, " %s %s time1,time2\n", lib.MlrExeName(), verbNameSec2GMT)
fmt.Fprintf(o, " %s %s time1,time2\n", "mlr", verbNameSec2GMT)
fmt.Fprintf(o, "is the same as\n")
fmt.Fprintf(o, " %s put '$time1 = sec2gmt($time1); $time2 = sec2gmt($time2)'\n", lib.MlrExeName())
fmt.Fprintf(o, " %s put '$time1 = sec2gmt($time1); $time2 = sec2gmt($time2)'\n", "mlr")
fmt.Fprintf(o, "Options:\n")
fmt.Fprintf(o, "-1 through -9: format the seconds using 1..9 decimal places, respectively.\n")
fmt.Fprintf(o, "--millis Input numbers are treated as milliseconds since the epoch.\n")

View file

@ -7,7 +7,6 @@ import (
"strings"
"miller/src/cliutil"
"miller/src/lib"
"miller/src/types"
)
@ -26,7 +25,7 @@ func transformerSeqgenUsage(
doExit bool,
exitCode int,
) {
fmt.Fprintf(o, "Usage: %s %s [options]\n", lib.MlrExeName(), verbNameSeqgen)
fmt.Fprintf(o, "Usage: %s %s [options]\n", "mlr", verbNameSeqgen)
fmt.Fprintf(o, "Passes input records directly to output. Most useful for format conversion.\n")
fmt.Fprintf(o, "Produces a sequence of counters. Discards the input record stream. Produces\n")
fmt.Fprintf(o, "output as specified by the options\n")

View file

@ -26,10 +26,10 @@ func transformerShuffleUsage(
doExit bool,
exitCode int,
) {
fmt.Fprintf(o, "Usage: %s %s [options]\n", lib.MlrExeName(), verbNameShuffle)
fmt.Fprintf(o, "Usage: %s %s [options]\n", "mlr", verbNameShuffle)
fmt.Fprintf(o, "Outputs records randomly permuted. No output records are produced until\n")
fmt.Fprintf(o, "all input records are read. See also %s bootstrap and %s sample.\n",
lib.MlrExeName(), lib.MlrExeName(),
"mlr", "mlr",
)
fmt.Fprintf(o, "Options:\n")
fmt.Fprintf(o, "-h|--help Show this message.\n")

View file

@ -6,7 +6,6 @@ import (
"strings"
"miller/src/cliutil"
"miller/src/lib"
"miller/src/types"
)
@ -25,7 +24,7 @@ func transformerSkipTrivialRecordsUsage(
doExit bool,
exitCode int,
) {
fmt.Fprintf(o, "Usage: %s %s [options]\n", lib.MlrExeName(), verbNameSkipTrivialRecords)
fmt.Fprintf(o, "Usage: %s %s [options]\n", "mlr", verbNameSkipTrivialRecords)
fmt.Fprintf(o, "Passes through all records except those with zero fields,\n")
fmt.Fprintf(o, "or those for which all fields have empty value.\n")
fmt.Fprintf(o, "Options:\n")

View file

@ -6,7 +6,6 @@ import (
"strings"
"miller/src/cliutil"
"miller/src/lib"
"miller/src/types"
)
@ -25,7 +24,7 @@ func transformerSortWithinRecordsUsage(
doExit bool,
exitCode int,
) {
fmt.Fprintf(o, "Usage: %s %s [options]\n", lib.MlrExeName(), verbNameSortWithinRecords)
fmt.Fprintf(o, "Usage: %s %s [options]\n", "mlr", verbNameSortWithinRecords)
fmt.Fprintln(o, "Outputs records sorted lexically ascending by keys.")
fmt.Fprintf(o, "Options:\n")
fmt.Fprintf(o, "-r Recursively sort subobjects/submaps, e.g. for JSON input.\n")

View file

@ -68,7 +68,7 @@ func transformerSortUsage(
doExit bool,
exitCode int,
) {
fmt.Fprintf(o, "Usage: %s %s {flags}\n", lib.MlrExeName(), verbNameSort)
fmt.Fprintf(o, "Usage: %s %s {flags}\n", "mlr", verbNameSort)
fmt.Fprintf(o, "Sorts records primarily by the first specified field, secondarily by the second\n")
fmt.Fprintf(o, "field, and so on. (Any records not having all specified sort keys will appear\n")
fmt.Fprintf(o, "at the end of the output, in the order they were encountered, regardless of the\n")
@ -84,9 +84,9 @@ func transformerSortUsage(
fmt.Fprintf(o, "-h|--help Show this message.\n")
fmt.Fprintf(o, "\n")
fmt.Fprintf(o, "Example:\n")
fmt.Fprintf(o, " %s %s -f a,b -nr x,y,z\n", lib.MlrExeName(), verbNameSort)
fmt.Fprintf(o, " %s %s -f a,b -nr x,y,z\n", "mlr", verbNameSort)
fmt.Fprintf(o, "which is the same as:\n")
fmt.Fprintf(o, " %s %s -f a -f b -nr x -nr y -nr z\n", lib.MlrExeName(), verbNameSort)
fmt.Fprintf(o, " %s %s -f a -f b -nr x -nr y -nr z\n", "mlr", verbNameSort)
if doExit {
os.Exit(exitCode)

View file

@ -27,7 +27,7 @@ func transformerStats1Usage(
doExit bool,
exitCode int,
) {
fmt.Fprintf(o, "Usage: %s %s [options]\n", lib.MlrExeName(), verbNameStats1)
fmt.Fprintf(o, "Usage: %s %s [options]\n", "mlr", verbNameStats1)
fmt.Fprint(o,
`Computes univariate statistics for one or more given fields, accumulated across
the input record stream.
@ -52,13 +52,13 @@ Options:
`)
fmt.Fprintln(o,
"Example: mlr stats1 -a min,p10,p50,p90,max -f value -g size,shape\n", lib.MlrExeName(), verbNameStats1)
"Example: mlr stats1 -a min,p10,p50,p90,max -f value -g size,shape\n", "mlr", verbNameStats1)
fmt.Fprintln(o,
"Example: mlr stats1 -a count,mode -f size\n", lib.MlrExeName(), verbNameStats1)
"Example: mlr stats1 -a count,mode -f size\n", "mlr", verbNameStats1)
fmt.Fprintln(o,
"Example: mlr stats1 -a count,mode -f size -g shape\n", lib.MlrExeName(), verbNameStats1)
"Example: mlr stats1 -a count,mode -f size -g shape\n", "mlr", verbNameStats1)
fmt.Fprintln(o,
"Example: mlr stats1 -a count,mode --fr '^[a-h].*$' -gr '^k.*$'\n", lib.MlrExeName(), verbNameStats1)
"Example: mlr stats1 -a count,mode --fr '^[a-h].*$' -gr '^k.*$'\n", "mlr", verbNameStats1)
fmt.Fprintln(o,
` This computes count and mode statistics on all field names beginning
with a through h, grouped by all field names starting with k.`)
@ -141,13 +141,13 @@ func transformerStats1ParseCLI(
// TODO: libify for use across verbs.
if len(accumulatorNameList) == 0 {
fmt.Fprintf(os.Stderr, "%s %s: -a option is required.\n", lib.MlrExeName(), verbNameStats1)
fmt.Fprintf(os.Stderr, "Please see %s %s --help for more information.\n", lib.MlrExeName(), verbNameStats1)
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)
}
if len(valueFieldNameList) == 0 {
fmt.Fprintf(os.Stderr, "%s %s: -f option is required.\n", lib.MlrExeName(), verbNameStats1)
fmt.Fprintf(os.Stderr, "Please see %s %s --help for more information.\n", lib.MlrExeName(), verbNameStats1)
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)
}
@ -244,7 +244,7 @@ func NewTransformerStats1(
return nil, errors.New(
fmt.Sprintf(
"%s stats1: accumulator \"%s\" not found.\n",
lib.MlrExeName(), name,
"mlr", name,
),
)
}

View file

@ -32,7 +32,7 @@ func transformerStats2Usage(
doExit bool,
exitCode int,
) {
argv0 := lib.MlrExeName()
argv0 := "mlr"
verb := verbNameStats2
fmt.Fprintf(o, "Usage: %s %s [options]\n", argv0, verb)
@ -76,7 +76,7 @@ func transformerStats2ParseCLI(
verb := args[argi]
argi++
argv0 := lib.MlrExeName()
argv0 := "mlr"
var accumulatorNameList []string = nil
var valueFieldNameList []string = nil
@ -204,7 +204,7 @@ func NewTransformerStats2(
return nil, errors.New(
fmt.Sprintf(
"%s stats2: accumulator \"%s\" not found.\n",
lib.MlrExeName(), name,
"mlr", name,
),
)
}
@ -352,7 +352,7 @@ func (tr *TransformerStats2) ingest(
)
if accumulator == nil {
fmt.Fprintf(os.Stderr, "%s %s: accumulator \"%s\" not found.\n",
lib.MlrExeName(), verbNameStats2, accumulatorName,
"mlr", verbNameStats2, accumulatorName,
)
os.Exit(1)
}

View file

@ -28,7 +28,7 @@ func transformerStepUsage(
doExit bool,
exitCode int,
) {
fmt.Fprintf(o, "Usage: %s %s [options]\n", lib.MlrExeName(), verbNameStep)
fmt.Fprintf(o, "Usage: %s %s [options]\n", "mlr", verbNameStep)
fmt.Fprintf(o, "Computes values dependent on the previous record, optionally grouped by category.\n")
fmt.Fprintf(o, "Options:\n")
@ -49,7 +49,7 @@ func transformerStepUsage(
fmt.Fprintf(o, "-d {x,y,z} Weights for ewma. 1 means current sample gets all weight (no\n")
fmt.Fprintf(o, " smoothing), near under under 1 is light smoothing, near over 0 is\n")
fmt.Fprintf(o, " heavy smoothing. Multiple weights may be specified, e.g.\n")
fmt.Fprintf(o, " \"%s %s -a ewma -f sys_load -d 0.01,0.1,0.9\". Default if omitted\n", lib.MlrExeName(), verbNameStep)
fmt.Fprintf(o, " \"%s %s -a ewma -f sys_load -d 0.01,0.1,0.9\". Default if omitted\n", "mlr", verbNameStep)
fmt.Fprintf(o, " is \"-d %s\".\n", DEFAULT_STRING_ALPHA)
fmt.Fprintf(o, "-o {a,b,c} Custom suffixes for EWMA output fields. If omitted, these default to\n")
@ -59,11 +59,11 @@ func transformerStepUsage(
fmt.Fprintf(o, "\n")
fmt.Fprintf(o, "Examples:\n")
fmt.Fprintf(o, " %s %s -a rsum -f request_size\n", lib.MlrExeName(), verbNameStep)
fmt.Fprintf(o, " %s %s -a delta -f request_size -g hostname\n", lib.MlrExeName(), verbNameStep)
fmt.Fprintf(o, " %s %s -a ewma -d 0.1,0.9 -f x,y\n", lib.MlrExeName(), verbNameStep)
fmt.Fprintf(o, " %s %s -a ewma -d 0.1,0.9 -o smooth,rough -f x,y\n", lib.MlrExeName(), verbNameStep)
fmt.Fprintf(o, " %s %s -a ewma -d 0.1,0.9 -o smooth,rough -f x,y -g group_name\n", lib.MlrExeName(), verbNameStep)
fmt.Fprintf(o, " %s %s -a rsum -f request_size\n", "mlr", verbNameStep)
fmt.Fprintf(o, " %s %s -a delta -f request_size -g hostname\n", "mlr", verbNameStep)
fmt.Fprintf(o, " %s %s -a ewma -d 0.1,0.9 -f x,y\n", "mlr", verbNameStep)
fmt.Fprintf(o, " %s %s -a ewma -d 0.1,0.9 -o smooth,rough -f x,y\n", "mlr", verbNameStep)
fmt.Fprintf(o, " %s %s -a ewma -d 0.1,0.9 -o smooth,rough -f x,y -g group_name\n", "mlr", verbNameStep)
fmt.Fprintf(o, "\n")
fmt.Fprintf(o, "Please see https://miller.readthedocs.io/en/latest/reference-verbs.html#filter or\n")

View file

@ -7,7 +7,6 @@ import (
"strings"
"miller/src/cliutil"
"miller/src/lib"
"miller/src/types"
)
@ -26,7 +25,7 @@ func transformerTacUsage(
doExit bool,
exitCode int,
) {
fmt.Fprintf(o, "Usage: %s %s [options]\n", lib.MlrExeName(), verbNameTac)
fmt.Fprintf(o, "Usage: %s %s [options]\n", "mlr", verbNameTac)
fmt.Fprintf(o, "Prints records in reverse order from the order in which they were encountered.\n")
fmt.Fprintf(o, "Options:\n")
fmt.Fprintf(o, "-h|--help Show this message.\n")

View file

@ -26,7 +26,7 @@ func transformerTailUsage(
doExit bool,
exitCode int,
) {
fmt.Fprintf(o, "Usage: %s %s [options]\n", lib.MlrExeName(), verbNameTail)
fmt.Fprintf(o, "Usage: %s %s [options]\n", "mlr", verbNameTail)
fmt.Fprintln(o, "Passes through the last n records, optionally by category.")
fmt.Fprintf(o, "Options:\n")

View file

@ -6,7 +6,6 @@ import (
"strings"
"miller/src/cliutil"
"miller/src/lib"
"miller/src/output"
"miller/src/types"
)
@ -26,7 +25,7 @@ func transformerTeeUsage(
doExit bool,
exitCode int,
) {
fmt.Fprintf(o, "Usage: %s %s [options] {filename}\n", lib.MlrExeName(), verbNameTee)
fmt.Fprintf(o, "Usage: %s %s [options] {filename}\n", "mlr", verbNameTee)
fmt.Fprintf(o, "Options:\n")
fmt.Fprintf(o,
`-a Append to existing file, if any, rather than overwriting.
@ -166,7 +165,7 @@ func (tr *TransformerTee) Transform(
fmt.Fprintf(
os.Stderr,
"%s: error writing to tee \"%s\":\n",
lib.MlrExeName(), tr.filenameOrCommandForDisplay,
"mlr", tr.filenameOrCommandForDisplay,
)
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
@ -179,7 +178,7 @@ func (tr *TransformerTee) Transform(
fmt.Fprintf(
os.Stderr,
"%s: error closing tee \"%s\":\n",
lib.MlrExeName(), tr.filenameOrCommandForDisplay,
"mlr", tr.filenameOrCommandForDisplay,
)
fmt.Fprintln(os.Stderr, err)
os.Exit(1)

View file

@ -27,7 +27,7 @@ func transformerTopUsage(
doExit bool,
exitCode int,
) {
argv0 := lib.MlrExeName()
argv0 := "mlr"
verb := verbNameTop
fmt.Fprintf(o, "Usage: %s %s [options]\n", argv0, verb)
fmt.Fprintf(o, "-f {a,b,c} Value-field names for top counts.\n")

View file

@ -25,14 +25,14 @@ func transformerUnflattenUsage(
doExit bool,
exitCode int,
) {
fmt.Fprintf(o, "Usage: %s %s [options]\n", lib.MlrExeName(), verbNameUnflatten)
fmt.Fprintf(o, "Usage: %s %s [options]\n", "mlr", verbNameUnflatten)
fmt.Fprint(o,
`Reverses flatten. Example: field with name 'a.b.c' and value 4
becomes name 'a' and value '{"b": { "c": 4 }}'.
`)
fmt.Fprintf(o, "Options:\n")
fmt.Fprintf(o, "-f {a,b,c} Comma-separated list of field names to unflatten (default all).\n")
fmt.Fprintf(o, "-s {string} Separator, defaulting to %s --oflatsep value.\n", lib.MlrExeName())
fmt.Fprintf(o, "-s {string} Separator, defaulting to %s --oflatsep value.\n", "mlr")
fmt.Fprintf(o, "-h|--help Show this message.\n")
if doExit {

View file

@ -35,7 +35,7 @@ func transformerCountDistinctUsage(
doExit bool,
exitCode int,
) {
argv0 := lib.MlrExeName()
argv0 := "mlr"
verb := verbNameCountDistinct
fmt.Fprintf(o, "Usage: %s %s [options]\n", argv0, verb)
fmt.Fprintf(o, "Prints number of records having distinct values for specified field names.\n")
@ -135,7 +135,7 @@ func transformerUniqUsage(
doExit bool,
exitCode int,
) {
argv0 := lib.MlrExeName()
argv0 := "mlr"
verb := verbNameUniq
fmt.Fprintf(o, "Usage: %s %s [options]\n", argv0, verb)
fmt.Fprintf(o, "Prints distinct values for specified field names. With -c, same as\n")

View file

@ -26,7 +26,7 @@ func transformerUnsparsifyUsage(
doExit bool,
exitCode int,
) {
fmt.Fprintf(o, "Usage: %s %s [options]\n", lib.MlrExeName(), verbNameUnsparsify)
fmt.Fprintf(o, "Usage: %s %s [options]\n", "mlr", verbNameUnsparsify)
fmt.Fprint(o,
`Prints records with the union of field names over all input records.
For field names absent in a given record but present in others, fills in

View file

@ -170,7 +170,7 @@ func NewJoinBucketKeeper(
fmt.Fprintf(
os.Stderr,
"%s join: Input format %s not found.\n",
lib.MlrExeName(),
"mlr",
joinReaderOptions.InputFileFormat,
)
os.Exit(1)
@ -314,7 +314,7 @@ func (keeper *JoinBucketKeeper) FindJoinBucket(
fmt.Fprintf(
os.Stderr,
"%s: internal coding error: failed transition from prefill state.\n",
lib.MlrExeName(),
"mlr",
)
os.Exit(1)
}
@ -464,7 +464,7 @@ func (keeper *JoinBucketKeeper) fillNextJoinBucket() {
fmt.Fprintf(
os.Stderr,
"%s: internal coding error: peek record should have had join keys.\n",
lib.MlrExeName(),
"mlr",
)
os.Exit(1)
}
@ -572,7 +572,7 @@ func (keeper *JoinBucketKeeper) readRecord() *types.RecordAndContext {
select {
case err := <-keeper.errorChannel:
fmt.Fprintln(os.Stderr, lib.MlrExeName(), ": ", err)
fmt.Fprintln(os.Stderr, "mlr", ": ", err)
os.Exit(1)
case leftrecAndContext := <-keeper.inputChannel:
if leftrecAndContext.EndOfStream { // end-of-stream marker

View file

@ -144,7 +144,7 @@ func (mv *Mlrval) GetNumericToFloatValueOrDie() (floatValue float64) {
fmt.Fprintf(
os.Stderr,
"%s: couldn't parse \"%s\" as number.",
lib.MlrExeName(), mv.String(),
"mlr", mv.String(),
)
os.Exit(1)
}

View file

@ -4,12 +4,10 @@ TOP OF LIST:
* emit * regex * fmtnum * localtime *
* --nr-progress-mod * mlr -k *
* cli-audits * doc6 * survey * check issues *
* split up mlr -h
* survey email followups
* convert all code-blocks to cardify
* most/least-frequent: map -> odict
* lib.MlrExeName() -> "mlr" throughout
----------------------------------------------------------------
colorizer:
@ -24,20 +22,21 @@ doclink etc:
----------------------------------------------------------------
HELP
! TABLE -> getTABLE() w/ lazy sorted/sorter
* split up help/entry.go -- ?
! improved sort for functions-table
? integrate repl help with main help?
o repl help keyword
* manpage & main help need some basic examples
! type-arithmetic-info
----------------------------------------------------------------
----------------------------------------------------------------
DOC6
* wip
go get github.com/kisielk/godepgraph
godepgraph miller | dot -Tpng -o ~/Desktop/mlrdeps.png
* flamegraph etc double-check
* memory page:
o open with "out of memory" -- what next?
o streaming vs non-streaming
o unsparsify -f
o no out-of-core sort yet ...
o older versions
? quick-examples needs fewer inputs, and outputs for all retained inputs
? or q-e more links to 10min
@ -49,7 +48,6 @@ DOC6
o differences from other languages (cf. juliadocs)
* doc notes about --jknquotein & --jvquoteall. make sure they're ignore-accepted in the CLIP.
* audit for mlb -> lib.MlrExeName() (in case mlr.foo)
* items:
o file-formats:
@ -58,6 +56,10 @@ DOC6
o format ordering: pick one for sphinx, manpage, olh
o autodetect: tbd
* separator options -- olh also
* number formatting -- olh also
* double quoting -- olh also
* code to-do items:
o stats1 --fr
cookbook2.rst.in
@ -84,6 +86,12 @@ DOC6
* case auxfiles: cat them too
----------------------------------------------------------------
REPLv2
* consider making it a verb
o 'put --repl' maybe
----------------------------------------------------------------
* mlr -k
o c,go
@ -108,7 +116,6 @@ w survey
----------------------------------------------------------------
* debug && || on windows more ...
* list-of-verbs shortlist @ top ...
* blocker: regexes
o finish stats1 -r
@ -171,6 +178,11 @@ w survey
- TBD writer -- defer factory until first context?
- deeper refactor pulling format out of reader/writer options entirely -- ?
* pkg graph:
go get github.com/kisielk/godepgraph
godepgraph miller | dot -Tpng -o ~/Desktop/mlrdeps.png
flamegraph etc double-check
----------------------------------------------------------------
* emph go 1.16 @ go.mod & README.md; also gha yaml

View file

@ -12,10 +12,10 @@ top: .always
echo mkman end
# These targets are only for local dev work.
install:
install: top
mkdir -p $(INSTALLDIR)
cp mlr6.1 $(INSTALLDIR)/mlr6.1
installhome:
installhome: top
mkdir -p $(INSTALLHOME)
cp mlr6.1 $(INSTALLHOME)/mlr6.1

View file

@ -95,14 +95,40 @@ DATA FORMATS
| fox jumped | Record 2: "1" => "fox", "2" => "jumped"
+---------------------+
OPTIONS
In the following option flags, the version with "i" designates the
input stream, "o" the output stream, and the version without prefix
sets the option for both input and output stream. For example: --irs
sets the input record separator, --ors the output record separator, and
--rs sets both the input and output separator to the given value.
VERB LIST
altkv bar bootstrap cat check clean-whitespace count-distinct count
count-similar cut decimate fill-down fill-empty filter flatten format-values
fraction gap grep group-by group-like having-fields head histogram json-parse
json-stringify join label least-frequent merge-fields most-frequent nest
nothing put regularize remove-empty-columns rename reorder repeat reshape
sample sec2gmtdate sec2gmt seqgen shuffle skip-trivial-records sort
sort-within-records stats1 stats2 step tac tail tee top unflatten uniq
unsparsify
HELP OPTIONS
FUNCTION LIST
abs acos acosh append arrayify asin asinh asserting_absent asserting_array
asserting_bool asserting_boolean asserting_empty asserting_empty_map
asserting_error asserting_float asserting_int asserting_map
asserting_nonempty_map asserting_not_array asserting_not_empty
asserting_not_map asserting_not_null asserting_null asserting_numeric
asserting_present asserting_string atan atan2 atanh bitcount boolean
capitalize cbrt ceil clean_whitespace collapse_whitespace cos cosh depth
dhms2fsec dhms2sec erf erfc exp expm1 flatten float floor fmtnum fsec2dhms
fsec2hms get_keys get_values gmt2sec gsub haskey hexfmt hms2fsec hms2sec
hostname int invqnorm is_absent is_array is_bool is_boolean is_empty
is_empty_map is_error is_float is_int is_map is_nonempty_map is_not_array
is_not_empty is_not_map is_not_null is_null is_numeric is_present is_string
joink joinkv joinv json_parse json_stringify leafcount length log log10 log1p
logifit lstrip madd mapdiff mapexcept mapselect mapsum max md5 mexp min mmul
msub os pow qnorm regextract regextract_or_else round roundm rstrip sec2dhms
sec2gmt sec2gmtdate sec2hms sgn sha1 sha256 sha512 sin sinh splita splitax
splitkv splitkvx splitnv splitnvx sqrt ssub strftime string strip strlen
strptime sub substr substr0 substr1 system systime systimeint tan tanh tolower
toupper truncate typeof unflatten uptime urand urand32 urandint urandrange
version ! != !=~ % & && * ** + - . .* .+ .- ./ / // < << <= == =~ > >= >> >>>
?: ?? ??? ^ ^^ | || ~
HELP OPTIONS
Type 'mlr help {topic}' for any of the following:
mlr help topics
mlr help auxents
@ -117,309 +143,94 @@ OPTIONS
mlr help function
mlr help keyword
mlr help list-functions
mlr help list-functions-vertically
mlr help list-functions-as-paragraph
mlr help list-keywords
mlr help list-keywords-as-paragraph
mlr help list-verbs
mlr help list-verbs-vertically
mlr help list-verbs-as-paragraph
mlr help misc
mlr help mlrrc
mlr help number-formatting
mlr help output-colorizations
mlr help output-colorization
mlr help separator-options
mlr help type-arithmetic-info
mlr help usage-functions
mlr help usage-keywords
mlr help usage-verbs
mlr help verb
Shorthands:
mlr -l = mlr help list-verbs
mlr -L = mlr help list-verbs-vertically
mlr -f = mlr help usage-functions
mlr -F = mlr help list-functions
mlr -k = mlr help usage-keywords
mlr -K = mlr help list-keywords
mlr -L = mlr help usage-verbs
mlr -f = mlr help list-functions
mlr -F = mlr help usage-functions
mlr -k = mlr help list-keywords
mlr -K = mlr help usage-keywords
VERB LIST
altkv bar bootstrap cat check clean-whitespace count-distinct count
count-similar cut decimate fill-down fill-empty filter flatten format-values
fraction gap grep group-by group-like having-fields head histogram json-parse
json-stringify join label least-frequent merge-fields most-frequent nest
nothing put regularize remove-empty-columns rename reorder repeat reshape
sample sec2gmtdate sec2gmt seqgen shuffle skip-trivial-records sort
sort-within-records stats1 stats2 step tac tail tee top unflatten uniq
unsparsify
OPTIONS
In the following option flags, the version with "i" designates the
input stream, "o" the output stream, and the version without prefix
sets the option for both input and output stream. For example: --irs
sets the input record separator, --ors the output record separator, and
--rs sets both the input and output separator to the given value.
FUNCTION LIST
!
!=
!=~
%
&
&&
*
**
+
-
.
.*
.+
.-
./
/
//
<
<<
<=
==
=~
>
>=
>>
>>>
?:
??
???
^
^^
abs
acos
acosh
append
arrayify
asin
asinh
asserting_absent
asserting_array
asserting_bool
asserting_boolean
asserting_empty
asserting_empty_map
asserting_error
asserting_float
asserting_int
asserting_map
asserting_nonempty_map
asserting_not_array
asserting_not_empty
asserting_not_map
asserting_not_null
asserting_null
asserting_numeric
asserting_present
asserting_string
atan
atan2
atanh
bitcount
boolean
capitalize
cbrt
ceil
clean_whitespace
collapse_whitespace
cos
cosh
depth
dhms2fsec
dhms2sec
erf
erfc
exp
expm1
flatten
float
floor
fmtnum
fsec2dhms
fsec2hms
get_keys
get_values
gmt2sec
gsub
haskey
hexfmt
hms2fsec
hms2sec
hostname
int
invqnorm
is_absent
is_array
is_bool
is_boolean
is_empty
is_empty_map
is_error
is_float
is_int
is_map
is_nonempty_map
is_not_array
is_not_empty
is_not_map
is_not_null
is_null
is_numeric
is_present
is_string
joink
joinkv
joinv
json_parse
json_stringify
leafcount
length
log
log10
log1p
logifit
lstrip
madd
mapdiff
mapexcept
mapselect
mapsum
max
md5
mexp
min
mmul
msub
os
pow
qnorm
regextract
regextract_or_else
round
roundm
rstrip
sec2dhms
sec2gmt
sec2gmtdate
sec2hms
sgn
sha1
sha256
sha512
sin
sinh
splita
splitax
splitkv
splitkvx
splitnv
splitnvx
sqrt
ssub
strftime
string
strip
strlen
strptime
sub
substr
substr0
substr1
system
systime
systimeint
tan
tanh
tolower
toupper
truncate
typeof
unflatten
uptime
urand
urand32
urandint
urandrange
version
|
||
~
Please use "mlr --help-function {function name}" for function-specific help.
DATA-FORMAT OPTIONS
--idkvp --odkvp --dkvp Delimited key-value pairs, e.g "a=1,b=2"
(Miller's default format).
I/O FORMATTING
CSV/CSV-lite: comma-separated values with separate header line
TSV: same but with tabs in places of commas
+---------------------+
| apple,bat,cog |
| 1,2,3 | Record 1: "apple => "1", "bat" => "2", "cog" => "3"
| 4,5,6 | Record 2: "apple" => "4", "bat" => "5", "cog" => "6"
+---------------------+
--inidx --onidx --nidx Implicitly-integer-indexed fields (Unix-toolkit style).
-T Synonymous with "--nidx --fs tab".
JSON (sequence or array of objects):
+---------------------+
| { |
| "apple": 1, | Record 1: "apple" => "1", "bat" => "2", "cog" => "3"
| "bat": 2, |
| "cog": 3 |
| } |
| { |
| "dish": { | Record 2: "dish:egg" => "7", "dish:flint" => "8", "garlic" => ""
| "egg": 7, |
| "flint": 8 |
| }, |
| "garlic": "" |
| } |
+---------------------+
--icsv --ocsv --csv Comma-separated value (or tab-separated with --fs tab, etc.)
PPRINT: pretty-printed tabular
+---------------------+
| apple bat cog |
| 1 2 3 | Record 1: "apple => "1", "bat" => "2", "cog" => "3"
| 4 5 6 | Record 2: "apple" => "4", "bat" => "5", "cog" => "6"
+---------------------+
--itsv --otsv --tsv Keystroke-savers for "--icsv --ifs tab",
"--ocsv --ofs tab", "--csv --fs tab".
--iasv --oasv --asv Similar but using ASCII FS 0x1f and RS 0x1e\n",
--iusv --ousv --usv Similar but using Unicode FS U+241F (UTF-8 0xe2909f)\n",
and RS U+241E (UTF-8 0xe2909e)\n",
Markdown tabular (supported for output only):
+-----------------------+
| | apple | bat | cog | |
| | --- | --- | --- | |
| | 1 | 2 | 3 | | Record 1: "apple => "1", "bat" => "2", "cog" => "3"
| | 4 | 5 | 6 | | Record 2: "apple" => "4", "bat" => "5", "cog" => "6"
+-----------------------+
--icsvlite --ocsvlite --csvlite Comma-separated value (or tab-separated with --fs tab, etc.).
The 'lite' CSV does not handle RFC-CSV double-quoting rules; is
slightly faster and handles heterogeneity in the input stream via
empty newline followed by new header line. See also
https://johnkerl.org/miller6/file-formats.html#csv-tsv-asv-usv-etc
XTAB: pretty-printed transposed tabular
+---------------------+
| apple 1 | Record 1: "apple" => "1", "bat" => "2", "cog" => "3"
| bat 2 |
| cog 3 |
| |
| dish 7 | Record 2: "dish" => "7", "egg" => "8"
| egg 8 |
+---------------------+
--itsvlite --otsvlite --tsvlite Keystroke-savers for "--icsvlite --ifs tab",
"--ocsvlite --ofs tab", "--csvlite --fs tab".
-t Synonymous with --tsvlite.
--iasvlite --oasvlite --asvlite Similar to --itsvlite et al. but using ASCII FS 0x1f and RS 0x1e\n",
--iusvlite --ousvlite --usvlite Similar to --itsvlite et al. but using Unicode FS U+241F (UTF-8 0xe2909f)\n",
and RS U+241E (UTF-8 0xe2909e)\n",
DKVP: delimited key-value pairs (Miller default format)
+---------------------+
| apple=1,bat=2,cog=3 | Record 1: "apple" => "1", "bat" => "2", "cog" => "3"
| dish=7,egg=8,flint | Record 2: "dish" => "7", "egg" => "8", "3" => "flint"
+---------------------+
--ipprint --opprint --pprint Pretty-printed tabular (produces no
output until all input is in).
--right Right-justifies all fields for PPRINT output.
--barred Prints a border around PPRINT output
(only available for output).
NIDX: implicitly numerically indexed (Unix-toolkit style)
+---------------------+
| the quick brown | Record 1: "1" => "the", "2" => "quick", "3" => "brown"
| fox jumped | Record 2: "1" => "fox", "2" => "jumped"
+---------------------+
--omd Markdown-tabular (only available for output).
COMMENTS IN DATA
--skip-comments Ignore commented lines (prefixed by "#")
within the input.
--skip-comments-with {string} Ignore commented lines within input, with
specified prefix.
--pass-comments Immediately print commented lines (prefixed by "#")
within the input.
--pass-comments-with {string} Immediately print commented lines within input, with
specified prefix.
--ixtab --oxtab --xtab Pretty-printed vertical-tabular.
--xvright Right-justifies values for XTAB format.
Notes:
* Comments are only honored at the start of a line.
* In the absence of any of the above four options, comments are data like
any other text.
* When pass-comments is used, comment lines are written to standard output
immediately upon being read; they are not part of the record stream. Results
may be counterintuitive. A suggestion is to place comments at the start of
data files.
--ijson --ojson --json JSON tabular: sequence or list of one-level
maps: {...}{...} or [{...},{...}].
--jvstack Put one key-value pair per line for JSON output.
--no-jvstack Put objects/arrays all on one line for JSON output.
--jsonx --ojsonx Keystroke-savers for --json --jvstack
--jsonx --ojsonx and --ojson --jvstack, respectively.
--jlistwrap Wrap JSON output in outermost [ ].
--oflatsep {string} Separator for flattening multi-level JSON keys,
e.g. '{"a":{"b":3}}' becomes a:b => 3 for
non-JSON formats. Defaults to ..\n",
-p is a keystroke-saver for --nidx --fs space --repifs
Examples: --csv for CSV-formatted input and output; --icsv --opprint for
CSV-formatted input and pretty-printed output.
Please use --iformat1 --oformat2 rather than --format1 --oformat2.
The latter sets up input and output flags for format1, not all of which
are overridden in all cases by setting output format to format2.
FORMAT-CONVERSION KEYSTROKE-SAVERS
As keystroke-savers for format-conversion you may use the following:
@ -434,6 +245,9 @@ OPTIONS
PPRINT, and markdown, respectively. Note that markdown format is available for
output only.
SEPARATORS
THIS IS STILL TBD FOR MILLER 6
COMPRESSED I/O
Decompression done within the Miller process itself:
--gzin Uncompress gzip within the Miller process. Done by default if file ends in ".gz".
@ -466,8 +280,24 @@ OPTIONS
decisions that might have been made based on the file suffix. Also,
--gzin/--bz2in/--zin are ignored if --prepipe is also specified.
SEPARATORS
THIS IS STILL TBD FOR MILLER 6
COMMENTS IN DATA
--skip-comments Ignore commented lines (prefixed by "#")
within the input.
--skip-comments-with {string} Ignore commented lines within input, with
specified prefix.
--pass-comments Immediately print commented lines (prefixed by "#")
within the input.
--pass-comments-with {string} Immediately print commented lines within input, with
specified prefix.
Notes:
* Comments are only honored at the start of a line.
* In the absence of any of the above four options, comments are data like
any other text.
* When pass-comments is used, comment lines are written to standard output
immediately upon being read; they are not part of the record stream. Results
may be counterintuitive. A suggestion is to place comments at the start of
data files.
CSV-SPECIFIC OPTIONS
--implicit-csv-header Use 1,2,3,... as field labels, rather than from line 1
@ -501,7 +331,6 @@ OPTIONS
"put '$c = $a . $b'" then field c won't inherit a or b's
was-quoted-on-input flag.
NUMBER FORMATTING
THIS IS STILL WIP FOR MILLER 6
--ofmt {format} E.g. %.18f, %.0f, %9.6e. Please use sprintf-style codes for
@ -541,7 +370,7 @@ OPTIONS
CSV, CSV headers will be present in each output file
statistics are only over each file's own records; and so on.
AUXILIARY COMMANDS
AUXILIARY COMMANDS
Available subcommands:
aux-list
hex
@ -553,6 +382,79 @@ OPTIONS
repl
For more information, please invoke mlr {subcommand} --help.
REPL
Usage: mlr repl [options] {zero or more data-file names}
-v Prints the expressions's AST (abstract syntax tree), which gives
full transparency on the precedence and associativity rules of
Miller's grammar, to stdout.
-d Like -v but uses a parenthesized-expression format for the AST.
-D Like -d but with output all on one line.
-w Show warnings about uninitialized variables
-q Don't show startup banner
-s Don't show prompts
--load {DSL script file} Load script file before presenting the prompt.
If the name following --load is a directory, load all "*.mlr" files
in that directory.
--mload {DSL script files} -- Like --load but works with more than one filename,
e.g. '--mload *.mlr --'.
-h|--help Show this message.
Or any --icsv, --ojson, etc. reader/writer options as for the main Miller command line.
Any data-file names are opened just as if you had waited and typed :open {filenames}
at the Miller REPL prompt.
OUTPUT COLORIZATION
Things having colors:
* Keys in CSV header lines, JSON keys, etc
* Values in CSV data lines, JSON scalar values, etc
in regression-test output
* Some online-help strings
Rules for coloring:
* By default, colorize output only if writing to stdout and stdout is a TTY.
* Example: color: mlr --csv cat foo.csv
* Example: no color: mlr --csv cat foo.csv > bar.csv
* Example: no color: mlr --csv cat foo.csv | less
* The default colors were chosen since they look OK with white or black terminal background,
and are differentiable with common varieties of human color vision.
Mechanisms for coloring:
* Miller uses ANSI escape sequences only. This does not work on Windows except on Cygwin.
* Requires TERM environment variable to be set to non-empty string.
* Doesn't try to check to see whether the terminal is capable of 256-color
ANSI vs 16-color ANSI. Note that if colors are in the range 0..15
then 16-color ANSI escapes are used, so this is in the user's control.
How you can control colorization:
* Suppression/unsuppression:
* Environment variable export MLR_NO_COLOR=true means don't color even if stdout+TTY.
* Environment variable export MLR_ALWAYS_COLOR=true means do color even if not stdout+TTY.
For example, you might want to use this when piping mlr output to less -r.
* Command-line flags --no-color or -M, --always-color or -C.
* Color choices can be specified by using environment variables, or command-line flags,
with values 0..255:
* export MLR_KEY_COLOR=208, MLR_VALUE_COLOR-33, etc.:
MLR_KEY_COLOR MLR_VALUE_COLOR MLR_PASS_COLOR MLR_FAIL_COLOR
MLR_REPL_PS1_COLOR MLR_REPL_PS2_COLOR MLR_HELP_COLOR
* Command-line flags --key-color 208, --value-color 33, etc.:
--key-color --value-color --pass-color --fail-color
--repl-ps1-color --repl-ps2-color --help-color
* This is particularly useful if your terminal's background color clashes with current settings.
If environment-variable settings and command-line flags are both provided,the latter take precedence.
Please do mlr --list-colors to see the available color codes.
MLRRC
You can set up personal defaults via a $HOME/.mlrrc and/or ./.mlrrc.
For example, if you usually process CSV, then you can put "--csv" in your .mlrrc file
@ -1581,99 +1483,6 @@ VERBS
'a=,b=3,c=4'.
FUNCTIONS FOR FILTER/PUT
!
(class=boolean #args=1) Logical negation.
!=
(class=boolean #args=2) String/numeric inequality. Mixing number and string results in string compare.
!=~
(class=boolean #args=2) String (left-hand side) does not match regex (right-hand side), e.g. '$name !=~ "^a.*b$"'.
%
(class=arithmetic #args=2) Remainder; never negative-valued (pythonic).
&
(class=arithmetic #args=2) Bitwise AND.
&&
(class=boolean #args=2) Logical AND.
*
(class=arithmetic #args=2) Multiplication, with integer*integer overflow to float.
**
(class=arithmetic #args=2) Exponentiation. Same as pow, but as an infix operator.
+
(class=arithmetic #args=1,2) Addition as binary operator; unary plus operator.
-
(class=arithmetic #args=1,2) Subtraction as binary operator; unary negation operator.
.
(class=string #args=2) String concatenation.
.*
(class=arithmetic #args=2) Multiplication, with integer-to-integer overflow.
.+
(class=arithmetic #args=2) Addition, with integer-to-integer overflow.
.-
(class=arithmetic #args=2) Subtraction, with integer-to-integer overflow.
./
(class=arithmetic #args=2) Integer division; not pythonic.
/
(class=arithmetic #args=2) Division. Integer / integer is floating-point.
//
(class=arithmetic #args=2) Pythonic integer division, rounding toward negative.
<
(class=boolean #args=2) String/numeric less-than. Mixing number and string results in string compare.
<<
(class=arithmetic #args=2) Bitwise left-shift.
<=
(class=boolean #args=2) String/numeric less-than-or-equals. Mixing number and string results in string compare.
==
(class=boolean #args=2) String/numeric equality. Mixing number and string results in string compare.
=~
(class=boolean #args=2) String (left-hand side) matches regex (right-hand side), e.g. '$name =~ "^a.*b$"'.
>
(class=boolean #args=2) String/numeric greater-than. Mixing number and string results in string compare.
>=
(class=boolean #args=2) String/numeric greater-than-or-equals. Mixing number and string results in string compare.
>>
(class=arithmetic #args=2) Bitwise signed right-shift.
>>>
(class=arithmetic #args=2) Bitwise unsigned right-shift.
?:
(class=boolean #args=3) Standard ternary operator.
??
(class=boolean #args=2) Absent-coalesce operator. $a ?? 1 evaluates to 1 if $a isn't defined in the current record.
???
(class=boolean #args=2) Absent-coalesce operator. $a ?? 1 evaluates to 1 if $a isn't defined in the current record, or has empty value.
^
(class=arithmetic #args=2) Bitwise XOR.
^^
(class=boolean #args=2) Logical XOR.
abs
(class=math #args=1) Absolute value.
@ -2217,6 +2026,99 @@ FUNCTIONS FOR FILTER/PUT
version
(class=system #args=0) Returns the Miller version as a string.
!
(class=boolean #args=1) Logical negation.
!=
(class=boolean #args=2) String/numeric inequality. Mixing number and string results in string compare.
!=~
(class=boolean #args=2) String (left-hand side) does not match regex (right-hand side), e.g. '$name !=~ "^a.*b$"'.
%
(class=arithmetic #args=2) Remainder; never negative-valued (pythonic).
&
(class=arithmetic #args=2) Bitwise AND.
&&
(class=boolean #args=2) Logical AND.
*
(class=arithmetic #args=2) Multiplication, with integer*integer overflow to float.
**
(class=arithmetic #args=2) Exponentiation. Same as pow, but as an infix operator.
+
(class=arithmetic #args=1,2) Addition as binary operator; unary plus operator.
-
(class=arithmetic #args=1,2) Subtraction as binary operator; unary negation operator.
.
(class=string #args=2) String concatenation.
.*
(class=arithmetic #args=2) Multiplication, with integer-to-integer overflow.
.+
(class=arithmetic #args=2) Addition, with integer-to-integer overflow.
.-
(class=arithmetic #args=2) Subtraction, with integer-to-integer overflow.
./
(class=arithmetic #args=2) Integer division; not pythonic.
/
(class=arithmetic #args=2) Division. Integer / integer is floating-point.
//
(class=arithmetic #args=2) Pythonic integer division, rounding toward negative.
<
(class=boolean #args=2) String/numeric less-than. Mixing number and string results in string compare.
<<
(class=arithmetic #args=2) Bitwise left-shift.
<=
(class=boolean #args=2) String/numeric less-than-or-equals. Mixing number and string results in string compare.
==
(class=boolean #args=2) String/numeric equality. Mixing number and string results in string compare.
=~
(class=boolean #args=2) String (left-hand side) matches regex (right-hand side), e.g. '$name =~ "^a.*b$"'.
>
(class=boolean #args=2) String/numeric greater-than. Mixing number and string results in string compare.
>=
(class=boolean #args=2) String/numeric greater-than-or-equals. Mixing number and string results in string compare.
>>
(class=arithmetic #args=2) Bitwise signed right-shift.
>>>
(class=arithmetic #args=2) Bitwise unsigned right-shift.
?:
(class=boolean #args=3) Standard ternary operator.
??
(class=boolean #args=2) Absent-coalesce operator. $a ?? 1 evaluates to 1 if $a isn't defined in the current record.
???
(class=boolean #args=2) Absent-coalesce operator. $a ?? 1 evaluates to 1 if $a isn't defined in the current record, or has empty value.
^
(class=arithmetic #args=2) Bitwise XOR.
^^
(class=boolean #args=2) Logical XOR.
|
(class=arithmetic #args=2) Bitwise OR.
@ -2602,4 +2504,4 @@ SEE ALSO
2021-06-28 MILLER(1)
2021-07-01 MILLER(1)

View file

@ -43,6 +43,15 @@ a special case.) This manpage documents #{`mlr --version`.chomp}."""
print make_section('DATA FORMATS', [])
print make_code_block(`mlr help data-formats`)
print make_section('VERB LIST', [])
print make_code_block(`mlr help list-verbs-as-paragraph`)
print make_section('FUNCTION LIST', [])
print make_code_block(`mlr help list-functions-as-paragraph`)
print make_section('HELP OPTIONS', [])
print make_code_block(`mlr help topics`)
print make_section('OPTIONS', [
"""In the following option flags, the version with \"i\" designates the input
stream, \"o\" the output stream, and the version without prefix sets the option
@ -51,31 +60,20 @@ separator, --ors the output record separator, and --rs sets both the input and
output separator to the given value."""
])
# TODO: output colorization and repl
print make_subsection('HELP OPTIONS', [])
print make_code_block(`mlr help topics`)
print make_subsection('VERB LIST', [])
print make_code_block(`mlr help list-verbs`)
print make_subsection('FUNCTION LIST', [])
# TODO: list as paragraph
print make_code_block(`mlr help list-functions`)
print make_subsection('I/O FORMATTING', [])
print make_code_block(`mlr help data-formats`)
print make_subsection('COMMENTS IN DATA', [])
print make_code_block(`mlr help comments-in-data`)
print make_subsection('DATA-FORMAT OPTIONS', [])
print make_code_block(`mlr help data-format-options`)
print make_subsection('FORMAT-CONVERSION KEYSTROKE-SAVERS', [])
print make_code_block(`mlr help format-conversion`)
print make_subsection('SEPARATORS', [])
print make_code_block(`mlr help separator-options`)
print make_subsection('COMPRESSED I/O', [])
print make_code_block(`mlr help compressed-data`)
print make_subsection('SEPARATORS', [])
print make_code_block(`mlr help separator-options`)
print make_subsection('COMMENTS IN DATA', [])
print make_code_block(`mlr help comments-in-data`)
print make_subsection('CSV-SPECIFIC OPTIONS', [])
print make_code_block(`mlr help csv-options`)
@ -89,13 +87,19 @@ output separator to the given value."""
print make_subsection('OTHER OPTIONS', [])
print make_code_block(`mlr help misc`)
print make_subsection('AUXILIARY COMMANDS', [])
print make_section('AUXILIARY COMMANDS', [])
print make_code_block(`mlr aux-list`)
print make_section('REPL', [])
print make_code_block(`mlr repl -h`)
print make_section('OUTPUT COLORIZATION', [])
print make_code_block(`mlr help output-colorization`)
print make_section('MLRRC', [])
print make_code_block(`mlr help mlrrc`)
verbs = `mlr help list-verbs-vertically`
verbs = `mlr help list-verbs`
print make_section('VERBS', [
""
])
@ -105,7 +109,7 @@ output separator to the given value."""
print make_code_block(`mlr #{verb} -h`)
end
functions = `mlr help list-functions-vertically`
functions = `mlr help list-functions`
print make_section('FUNCTIONS FOR FILTER/PUT', [
""
])

File diff suppressed because it is too large Load diff