diff --git a/go/.vimrc b/go/.vimrc index 485a70acb..070427325 100644 --- a/go/.vimrc +++ b/go/.vimrc @@ -1,2 +1,2 @@ -map \d :w:!clear;echo Building ...; echo; build-go +map \d :w:!clear;echo Building ...; echo; go build mlr.go map \f :w:!clear;echo Building ...; echo; build; echo; main diff --git a/go/src/auxents/regtest/regtester.go b/go/src/auxents/regtest/regtester.go index b227f7142..ea4641fcc 100644 --- a/go/src/auxents/regtest/regtester.go +++ b/go/src/auxents/regtest/regtester.go @@ -10,7 +10,7 @@ import ( "os" "strings" - "github.com/fatih/color" + "miller/src/platform" ) const DefaultPath = "./reg-test/cases" @@ -22,11 +22,6 @@ const ShouldFailSuffix = ".should-fail" const MajorSeparator = "================================================================" const MinorSeparator = "----------------------------------------------------------------" -var PASS = color.HiGreenString("PASS") -var pass = color.HiGreenString("pass") -var FAIL = color.HiRedString("FAIL") -var fail = color.HiRedString("fail") - // ---------------------------------------------------------------- type RegTester struct { exeName string @@ -129,10 +124,12 @@ func (this *RegTester) Execute( fmt.Println() if this.casePassCount > 0 && this.caseFailCount == 0 { - fmt.Printf("%s overall\n", PASS) + platform.PrintHiGreen("PASS") + fmt.Printf(" overall\n") return true } else { - fmt.Printf("%s overall\n", FAIL) + platform.PrintHiRed("FAIL") + fmt.Printf(" overall\n") return false } } @@ -214,9 +211,11 @@ func (this *RegTester) executeSingleDirectory( // multiply announce. if hasDirectEntries { if passed { - fmt.Printf("%s %s/\n", PASS, dirName) + platform.PrintHiGreen("PASS") + fmt.Printf(" %s/\n", dirName) } else { - fmt.Printf("%s %s/\n", FAIL, dirName) + platform.PrintHiRed("FAIL") + fmt.Printf(" %s/\n", dirName) } } } @@ -433,9 +432,11 @@ func (this *RegTester) executeSingleCmdFile( if verbosityLevel >= 1 { if passed { - fmt.Printf("%s %s\n", pass, cmdFileName) + platform.PrintHiGreen("pass") + fmt.Printf(" %s\n", cmdFileName) } else { - fmt.Printf("%s %s\n", fail, cmdFileName) + platform.PrintHiGreen("fail") + fmt.Printf(" %s\n", cmdFileName) } } diff --git a/go/src/auxents/repl/colors.go b/go/src/auxents/repl/colors.go index c928f0f63..c2608385a 100644 --- a/go/src/auxents/repl/colors.go +++ b/go/src/auxents/repl/colors.go @@ -1,13 +1,15 @@ // ================================================================ -// This is for doing color-highlighting for on-line help +// This is for doing color-highlighting for on-line help. This is a thin layer +// over the package is uses -- the value-add here is to centralize the choice +// of particular color (as of this writing, red) all in one spot. // ================================================================ package repl import ( - "github.com/fatih/color" + "miller/src/platform" ) -func HighlightString(input string) string { - return color.HiRedString(input) +func PrintHighlightString(input string) { + platform.PrintHiRed(input) } diff --git a/go/src/auxents/repl/verbs.go b/go/src/auxents/repl/verbs.go index 57f9788bb..e441e7d3d 100644 --- a/go/src/auxents/repl/verbs.go +++ b/go/src/auxents/repl/verbs.go @@ -823,29 +823,29 @@ func handleHelpSingle(this *Repl, arg string) { if i > 0 { fmt.Println() } - fmt.Printf("%s: \n", HighlightString(strings.Join(entry.verbNames, " or "))) + PrintHighlightString(strings.Join(entry.verbNames, " or ")) entry.usageFunc(this) } return } if arg == "prompt" { - fmt.Printf( - "You can export the environment variable %s to customize the Miller REPL prompt.\n", - HighlightString(ENV_PRIMARY_PROMPT), - ) - fmt.Printf( - "Otherwise, it defaults to \"%s\".\n", - HighlightString(DEFAULT_PRIMARY_PROMPT), - ) - fmt.Printf( - "Likewise you can export the environment variable %s to customize the secondary prompt,\n", - HighlightString(ENV_SECONDARY_PROMPT), - ) - fmt.Printf( - "which defaults to \"%s\". This is used for multi-line input.\n", - HighlightString(DEFAULT_SECONDARY_PROMPT), - ) + fmt.Printf("You can export the environment variable ") + PrintHighlightString(ENV_PRIMARY_PROMPT) + fmt.Printf(" to customize the Miller REPL prompt.\n") + + fmt.Printf("Otherwise, it defaults to \"") + PrintHighlightString(DEFAULT_PRIMARY_PROMPT) + fmt.Printf("\".\n") + + fmt.Printf("Likewise you can export the environment variable ") + PrintHighlightString(ENV_SECONDARY_PROMPT) + fmt.Printf(" to customize the secondary prompt,\n") + + fmt.Printf("which defaults to \"") + PrintHighlightString(DEFAULT_SECONDARY_PROMPT) + fmt.Printf("\". This is used for multi-line input.\n") + return } @@ -857,7 +857,7 @@ func handleHelpSingle(this *Repl, arg string) { if arg == "function-details" { cst.BuiltinFunctionManagerInstance.ListBuiltinFunctionUsagesDecorated( os.Stdout, - func(functionName string) string { return HighlightString(functionName) }, + func(functionName string) { PrintHighlightString(functionName) }, ) return } @@ -876,13 +876,13 @@ func handleHelpSingle(this *Repl, arg string) { } func showREPLIntro(this *Repl) { - fmt.Printf("%s\n", HighlightString("What the Miller REPL is:")) + PrintHighlightString("What the Miller REPL is:\n") fmt.Println( `The Miller REPL (read-evaluate-print loop) is an interactive counterpart to record-processing using the put/filter DSL (domain-specific language).`) fmt.Println() - fmt.Printf("%s\n", HighlightString("Using Miller without the REPL:")) + PrintHighlightString("Using Miller without the REPL:\n") fmt.Printf( `Using put and filter, you can do the following: * Specify input format (e.g. --icsv), output format (e.g. --ojson), etc. using @@ -898,7 +898,7 @@ to record-processing using the put/filter DSL (domain-specific language).`) fmt.Println() fmt.Println() - fmt.Printf("%s\n", HighlightString("Using Miller with the REPL:")) + PrintHighlightString("Using Miller with the REPL:\n") fmt.Println( `Using the REPL, by contrast, you get interactive control over those same steps: * Specify input format (e.g. --icsv), output format (e.g. --ojson), etc. using @@ -935,7 +935,7 @@ included in the output-record stream. But here in the REPL, they are simply printed to the terminal, e.g. if you type '1+2', you will see '3'.`) fmt.Println() - fmt.Printf("%s\n", HighlightString("Entering multi-line statements:")) + PrintHighlightString("Entering multi-line statements:\n") fmt.Println( `* To enter multi-line statements, enter '<' on a line by itself, then the code (taking care for semicolons), then ">" on a line by itself. These will be executed immediately. @@ -944,20 +944,20 @@ printed to the terminal, e.g. if you type '1+2', you will see '3'.`) ':main', as if you had done ':load' to load statements from a file.`) fmt.Println() - fmt.Printf("%s\n", HighlightString("History-editing:")) + PrintHighlightString("History-editing:\n") fmt.Println( `No command-line-history-editing feature is built in but 'rlwrap mlr repl' is a delight. You may need 'brew install rlwrap', 'sudo apt-get install rlwrap', etc. depending on your platform.`) fmt.Println() - fmt.Printf("%s\n", HighlightString("On-line help:")) + PrintHighlightString("On-line help:\n") fmt.Println("Type ':help' to see more about your options. In particular, ':help examples'.") } // ---------------------------------------------------------------- func showREPLExamples(this *Repl) { - fmt.Printf("%s\n", HighlightString("Immediately executed statements:")) + PrintHighlightString("Immediately executed statements:\n") fmt.Println( `[mlr] 1+2 3 @@ -967,7 +967,7 @@ func showREPLExamples(this *Repl) { [mlr] x+y 7`) fmt.Println() - fmt.Printf("%s\n", HighlightString("Defining functions:")) + PrintHighlightString("Defining functions:\n") fmt.Println( `[mlr] < func f(a,b) { @@ -977,7 +977,7 @@ func f(a,b) { [mlr] f(7,5) 16807`) fmt.Println() - fmt.Printf("%s\n", HighlightString("Reading and processing records:")) + PrintHighlightString("Reading and processing records:\n") fmt.Println( `[mlr] :open foo.dat [mlr] :read diff --git a/go/src/dsl/cst/builtin_function_manager.go b/go/src/dsl/cst/builtin_function_manager.go index 9376ea51d..40cfe458b 100644 --- a/go/src/dsl/cst/builtin_function_manager.go +++ b/go/src/dsl/cst/builtin_function_manager.go @@ -1543,7 +1543,7 @@ func (this *BuiltinFunctionManager) ListBuiltinFunctionsRaw(o *os.File) { func (this *BuiltinFunctionManager) ListBuiltinFunctionUsages(o *os.File) { this.ListBuiltinFunctionUsagesDecorated( o, - func(functionName string) string { return functionName }, // no decoration + func(functionName string) { fmt.Print(functionName) }, // no decoration ) } @@ -1552,15 +1552,15 @@ func (this *BuiltinFunctionManager) ListBuiltinFunctionUsages(o *os.File) { // -- capitalization, ANSI color, etc. func (this *BuiltinFunctionManager) ListBuiltinFunctionUsagesDecorated( o *os.File, - nameDecorator func(string) string, + nameEmitter func(string), ) { for i, builtinFunctionInfo := range *this.lookupTable { if i > 0 { fmt.Fprintln(o) } lib.InternalCodingErrorIf(builtinFunctionInfo.help == "") - fmt.Fprintf(o, "%-s (class=%s #args=%s) %s\n", - nameDecorator(builtinFunctionInfo.name), + nameEmitter(builtinFunctionInfo.name) + fmt.Fprintf(o, " (class=%s #args=%s) %s\n", builtinFunctionInfo.class, describeNargs(&builtinFunctionInfo), builtinFunctionInfo.help, diff --git a/go/src/platform/colors.go b/go/src/platform/colors.go new file mode 100644 index 000000000..f99eda468 --- /dev/null +++ b/go/src/platform/colors.go @@ -0,0 +1,21 @@ +package platform + +import ( + "fmt" + + "github.com/fatih/color" +) + +// Outside of Windows, we don't need the Fprintf to color.Output (and in fact +// color.Output is simply os.Stdout inside fatih/color). But inside Windows we +// do. That's why these functions take a string and print it, returning void -- +// rather than taking a string and color-decorating it and returning the +// decoration as a string. + +func PrintHiGreen(s string) { + fmt.Fprintf(color.Output, color.HiGreenString(s)) +} + +func PrintHiRed(s string) { + fmt.Fprintf(color.Output, color.HiRedString(s)) +}