diff --git a/cmd/root.go b/cmd/root.go index 441287b..32ce390 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -84,6 +84,7 @@ func Execute() { func init() { rootCmd.PersistentFlags().BoolVarP(&lib.Debug, "debug", "d", false, "Enable debugging") rootCmd.PersistentFlags().BoolVarP(&lib.NoNumbering, "no-numbering", "n", false, "Disable header numbering") + rootCmd.PersistentFlags().BoolVarP(&lib.NoColor, "no-color", "N", false, "Disable pattern highlighting") rootCmd.PersistentFlags().BoolVarP(&lib.ShowVersion, "version", "V", false, "Print program version") rootCmd.PersistentFlags().BoolVarP(&lib.InvertMatch, "invert-match", "v", false, "select non-matching rows") rootCmd.PersistentFlags().BoolVarP(&ShowManual, "man", "m", false, "Display manual page") diff --git a/cmd/tablizer.go b/cmd/tablizer.go index 3e79bde..69c11d8 100644 --- a/cmd/tablizer.go +++ b/cmd/tablizer.go @@ -14,6 +14,7 @@ SYNOPSIS -v, --invert-match select non-matching rows -m, --man Display manual page -n, --no-numbering Disable header numbering + -N, --no-color Disable pattern highlighting -o, --output string Output mode - one of: orgtbl, markdown, extended, ascii(default) -X, --extended Enable extended output -M, --markdown Enable markdown table output @@ -70,6 +71,9 @@ DESCRIPTION The numbering can be suppressed by using the -n option. + By default, if a pattern has been speficied, matches will be + highlighted. You can disable this behavior with the -N option. + Finally the -d option enables debugging output which is mostly usefull for the developer. diff --git a/go.mod b/go.mod index 8b1c9ac..2e2c57e 100644 --- a/go.mod +++ b/go.mod @@ -4,6 +4,7 @@ go 1.18 require ( github.com/alecthomas/repr v0.0.0-20180818092828-117648cd9897 + github.com/gookit/color v1.5.2 github.com/olekukonko/tablewriter v0.0.5 github.com/spf13/cobra v1.5.0 ) @@ -12,5 +13,6 @@ require ( github.com/inconshreveable/mousetrap v1.0.0 // indirect github.com/mattn/go-runewidth v0.0.9 // indirect github.com/spf13/pflag v1.0.5 // indirect - github.com/stretchr/testify v1.8.0 // indirect + github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778 // indirect + golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44 // indirect ) diff --git a/go.sum b/go.sum index 6ec3e3c..58b6e4e 100644 --- a/go.sum +++ b/go.sum @@ -4,6 +4,8 @@ github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46t github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/gookit/color v1.5.2 h1:uLnfXcaFjlrDnQDT+NCBcfhrXqYTx/rcCa6xn01Y8yI= +github.com/gookit/color v1.5.2/go.mod h1:w8h4bGiHeeBpvQVePTutdbERIUf3oJE5lZ8HM0UgXyg= github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= @@ -22,6 +24,10 @@ github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSS github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778 h1:QldyIu/L63oPpyvQmHgvgickp1Yw510KJOqX7H24mg8= +github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778/go.mod h1:2MuV+tbUrU1zIOPMxZ5EncGwgmMJsa+9ucAQZXxsObs= +golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44 h1:Bli41pIlzTzf3KEY06n+xnzK/BESIg2ze4Pgfh/aI8c= +golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/lib/common.go b/lib/common.go index 8ea392f..c1e9b33 100644 --- a/lib/common.go +++ b/lib/common.go @@ -33,12 +33,18 @@ var ( OutflagShell bool OutputMode string InvertMatch bool + Pattern string + + // FIXME: make configurable somehow, config file or ENV + MatchFG string = "black" // see https://github.com/gookit/color + MatchBG string = "green" + NoColor bool // used for validation validOutputmodes = "(orgtbl|markdown|extended|ascii)" // main program version - Version = "v1.0.6" + Version = "v1.0.7" // generated version string, used by -v contains lib.Version on // main branch, and lib.Version-$branch-$lastcommit-$date on diff --git a/lib/helpers.go b/lib/helpers.go index f644da2..38c109a 100644 --- a/lib/helpers.go +++ b/lib/helpers.go @@ -20,6 +20,8 @@ package lib import ( "errors" "fmt" + "github.com/gookit/color" + "os" "regexp" "strconv" "strings" @@ -130,3 +132,21 @@ func trimRow(row []string) []string { return fixedrow } + +func colorizeData(output string) string { + if len(Pattern) > 0 && !NoColor && color.IsConsole(os.Stdout) { + r := regexp.MustCompile("(" + Pattern + ")") + return r.ReplaceAllString(output, "$1") + } else { + return output + } +} + +func isTerminal(f *os.File) bool { + o, _ := f.Stat() + if (o.Mode() & os.ModeCharDevice) == os.ModeCharDevice { + return true + } else { + return false + } +} diff --git a/lib/io.go b/lib/io.go index adab95b..3ad8f75 100644 --- a/lib/io.go +++ b/lib/io.go @@ -19,6 +19,7 @@ package lib import ( "errors" + "github.com/gookit/color" "io" "os" ) @@ -26,6 +27,10 @@ import ( func ProcessFiles(args []string) error { fds, pattern, err := determineIO(args) + if !isTerminal(os.Stdout) { + color.Disable() + } + if err != nil { return err } @@ -52,6 +57,7 @@ func determineIO(args []string) ([]io.Reader, string, error) { // first one is not a file, consider it as regexp and // shift arg list pattern = args[0] + Pattern = args[0] // FIXME args = args[1:] } diff --git a/lib/printer.go b/lib/printer.go index db0844d..ad80bfb 100644 --- a/lib/printer.go +++ b/lib/printer.go @@ -19,8 +19,8 @@ package lib import ( "fmt" + "github.com/gookit/color" "github.com/olekukonko/tablewriter" - "os" "regexp" "strings" ) @@ -76,14 +76,18 @@ func printOrgmodeData(data *Tabdata) { leftR := regexp.MustCompile("(?m)^\\+") rightR := regexp.MustCompile("\\+(?m)$") - fmt.Print(rightR.ReplaceAllString(leftR.ReplaceAllString(tableString.String(), "|"), "|")) + color.Print( + colorizeData( + rightR.ReplaceAllString( + leftR.ReplaceAllString(tableString.String(), "|"), "|"))) } /* Markdown table */ func printMarkdownData(data *Tabdata) { - table := tablewriter.NewWriter(os.Stdout) + tableString := &strings.Builder{} + table := tablewriter.NewWriter(tableString) table.SetHeader(data.headers) @@ -95,13 +99,15 @@ func printMarkdownData(data *Tabdata) { table.SetCenterSeparator("|") table.Render() + color.Print(colorizeData(tableString.String())) } /* Simple ASCII table without any borders etc, just like the input we expect */ func printAsciiData(data *Tabdata) { - table := tablewriter.NewWriter(os.Stdout) + tableString := &strings.Builder{} + table := tablewriter.NewWriter(tableString) table.SetHeader(data.headers) table.AppendBulk(data.entries) @@ -123,6 +129,7 @@ func printAsciiData(data *Tabdata) { table.SetNoWhiteSpace(true) table.Render() + color.Print(colorizeData(tableString.String())) } /* @@ -143,7 +150,7 @@ func printExtendedData(data *Tabdata) { } } - fmt.Printf(format, data.headers[idx], value) + color.Printf(format, data.headers[idx], value) idx++ } fmt.Println() diff --git a/lib/printer_test.go b/lib/printer_test.go index 5ced090..aa14da6 100644 --- a/lib/printer_test.go +++ b/lib/printer_test.go @@ -19,6 +19,7 @@ package lib import ( "fmt" + "github.com/gookit/color" "os" "strings" "testing" @@ -64,6 +65,8 @@ asd igig cxxxncnc ONE="19191" TWO="EDD 1" THREE="X"`, } + NoColor = true + r, w, err := os.Pipe() if err != nil { t.Fatal(err) @@ -71,6 +74,9 @@ ONE="19191" TWO="EDD 1" THREE="X"`, origStdout := os.Stdout os.Stdout = w + // we need to tell the color mode the io.Writer, even if we don't usw colorization + color.SetOutput(w) + for mode, expect := range expects { testname := fmt.Sprintf("print-%s", mode) t.Run(testname, func(t *testing.T) { diff --git a/tablizer.1 b/tablizer.1 index c028cd4..05bf4d6 100644 --- a/tablizer.1 +++ b/tablizer.1 @@ -133,7 +133,7 @@ .\" ======================================================================== .\" .IX Title "TABLIZER 1" -.TH TABLIZER 1 "2022-10-05" "1" "User Commands" +.TH TABLIZER 1 "2022-10-10" "1" "User Commands" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l @@ -153,6 +153,7 @@ tablizer \- Manipulate tabular output of other programs \& \-v, \-\-invert\-match select non\-matching rows \& \-m, \-\-man Display manual page \& \-n, \-\-no\-numbering Disable header numbering +\& \-N, \-\-no\-color Disable pattern highlighting \& \-o, \-\-output string Output mode \- one of: orgtbl, markdown, extended, ascii(default) \& \-X, \-\-extended Enable extended output \& \-M, \-\-markdown Enable markdown table output @@ -218,6 +219,9 @@ the original order. .PP The numbering can be suppressed by using the \fB\-n\fR option. .PP +By default, if a \fBpattern\fR has been speficied, matches will be +highlighted. You can disable this behavior with the \fB\-N\fR option. +.PP Finally the \fB\-d\fR option enables debugging output which is mostly usefull for the developer. .SS "\s-1PATTERNS\s0" diff --git a/tablizer.pod b/tablizer.pod index 37c31ad..266b667 100644 --- a/tablizer.pod +++ b/tablizer.pod @@ -14,6 +14,7 @@ tablizer - Manipulate tabular output of other programs -v, --invert-match select non-matching rows -m, --man Display manual page -n, --no-numbering Disable header numbering + -N, --no-color Disable pattern highlighting -o, --output string Output mode - one of: orgtbl, markdown, extended, ascii(default) -X, --extended Enable extended output -M, --markdown Enable markdown table output @@ -74,6 +75,9 @@ the original order. The numbering can be suppressed by using the B<-n> option. +By default, if a B has been speficied, matches will be +highlighted. You can disable this behavior with the B<-N> option. + Finally the B<-d> option enables debugging output which is mostly usefull for the developer.