From e5172fb8bd680d2b5c08e8d42e70884bbefcef2d Mon Sep 17 00:00:00 2001 From: Karuppiah Natarajan Date: Wed, 30 Dec 2020 19:48:09 +0530 Subject: [PATCH] add syntax highlighting for output fixes #39 --- cmd/cmd.go | 29 ++++++++++++++++++++-- cmd/cmd_test.go | 64 +++++++++++++++++++++++++++++++++++++++++++++++++ go.mod | 1 + go.sum | 4 ++++ 4 files changed, 96 insertions(+), 2 deletions(-) diff --git a/cmd/cmd.go b/cmd/cmd.go index fce492a..3aad5c7 100644 --- a/cmd/cmd.go +++ b/cmd/cmd.go @@ -23,16 +23,19 @@ import ( "os/exec" "unicode" + "github.com/andreazorzetto/yh/highlight" "github.com/ghodss/yaml" "github.com/spf13/cobra" ) var outputFormat *string var inputFile *string +var color *bool func init() { outputFormat = rootCmd.PersistentFlags().StringP("output", "o", "yaml", "output format: yaml or json") inputFile = rootCmd.Flags().StringP("file", "f", "-", "file path to neat, or - to read from stdin") + color = rootCmd.PersistentFlags().BoolP("color", "c", false, "colored output with syntax highlighting") rootCmd.SetOut(os.Stdout) rootCmd.SetErr(os.Stderr) rootCmd.MarkFlagFilename("file") @@ -75,7 +78,11 @@ kubectl neat -f ./my-pod.json --output yaml`, if err != nil { return err } - cmd.Print(string(out)) + // cmd.Print(string(out)) + err = printOutput(cmd, out) + if err != nil { + return err + } return nil }, } @@ -123,7 +130,10 @@ kubectl neat get -- svc -n default myservice --output json`, if err != nil { return err } - cmd.Println(string(out)) + err = printOutput(cmd, out) + if err != nil { + return err + } return nil }, } @@ -142,6 +152,21 @@ var versionCmd = &cobra.Command{ }, } +func printOutput(cmd *cobra.Command, out []byte) error { + if *color { + outreader := bytes.NewReader(out) + highlightedOutput, err := highlight.Highlight(outreader) + if err != nil { + return err + } + cmd.Println(highlightedOutput) + } else { + cmd.Println(string(out)) + } + + return nil +} + func isJSON(s []byte) bool { return bytes.HasPrefix(bytes.TrimLeftFunc(s, unicode.IsSpace), []byte{'{'}) } diff --git a/cmd/cmd_test.go b/cmd/cmd_test.go index 66d6969..2270e0d 100644 --- a/cmd/cmd_test.go +++ b/cmd/cmd_test.go @@ -33,12 +33,15 @@ func TestRootCmd(t *testing.T) { if err != nil { t.Errorf("error readin test data file %s: %v", resourceDataJSONPath, err) } + expectedColoredJSON := "\033[30;101m{\033[0m\n\033[91m \"apiVersion\"\033[0m: \033[33m\"v1\",\033[0m" + resourceDataYAMLPath := "../test/fixtures/service1-raw.yaml" resourceDataYAMLBytes, err := ioutil.ReadFile(resourceDataYAMLPath) resourceDataYAML := string(resourceDataYAMLBytes) if err != nil { t.Errorf("error readin test data file %s: %v", resourceDataYAMLPath, err) } + expectedColoredYAML := "\033[91mapiVersion\033[0m: \033[33mv1\033[0m" testcases := []struct { args []string @@ -58,18 +61,36 @@ func TestRootCmd(t *testing.T) { assertError: assertErrorNil, expOut: "apiVersion", }, + { + args: []string{"-c"}, + stdin: resourceDataJSON, + assertError: assertErrorNil, + expOut: expectedColoredJSON, + }, { args: []string{}, stdin: resourceDataYAML, assertError: assertErrorNil, expOut: "apiVersion", }, + { + args: []string{"-c"}, + stdin: resourceDataYAML, + assertError: assertErrorNil, + expOut: expectedColoredYAML, + }, { args: []string{"-f", "-"}, stdin: resourceDataJSON, assertError: assertErrorNil, expOut: "apiVersion", }, + { + args: []string{"-c", "-f", "-"}, + stdin: resourceDataJSON, + assertError: assertErrorNil, + expOut: expectedColoredJSON, + }, { args: []string{"-f", "/nogood"}, stdin: "", @@ -79,18 +100,44 @@ func TestRootCmd(t *testing.T) { }, expOut: "", }, + { + args: []string{"-c", "-f", "/nogood"}, + stdin: "", + assertError: func(err error) bool { + return fmt.Sprintf("%T", err) == "*os.PathError" + }, + expOut: "", + }, { args: []string{"-f", resourceDataJSONPath}, stdin: "", assertError: assertErrorNil, expOut: "apiVersion", }, + { + args: []string{"-c", "-f", resourceDataJSONPath}, + stdin: "", + assertError: assertErrorNil, + expOut: expectedColoredJSON, + }, { args: []string{"-f", resourceDataYAMLPath}, stdin: "", assertError: assertErrorNil, expOut: "apiVersion", }, + { + args: []string{"-c", "-f", resourceDataYAMLPath}, + stdin: "", + assertError: assertErrorNil, + expOut: expectedColoredYAML, + }, + { + args: []string{"-c", "-c", "-f", resourceDataYAMLPath}, + stdin: "", + assertError: assertErrorNil, + expOut: expectedColoredYAML, + }, } for _, tc := range testcases { @@ -126,6 +173,11 @@ func TestRootCmd(t *testing.T) { func TestGetCmd(t *testing.T) { kubectl = "../test/kubectl-stub" + + expectedColoredJSON := "\033[30;101m{\033[0m\n\033[91m \"apiVersion\"\033[0m: \033[33m\"v1\",\033[0m" + + expectedColoredYAML := "\033[91mapiVersion\033[0m: \033[33mv1\033[0m" + testcases := []struct { args []string assertError func(err error) bool @@ -158,12 +210,24 @@ func TestGetCmd(t *testing.T) { expOut: "apiVersion", expErr: "", }, + { + args: []string{"pods", "mypod", "-c", "-o", "yaml"}, + assertError: assertErrorNil, + expOut: expectedColoredYAML, + expErr: "", + }, { args: []string{"pods", "mypod", "-o", "json"}, assertError: assertErrorNil, expOut: "apiVersion", expErr: "", }, + { + args: []string{"pods", "mypod", "-c", "-o", "json"}, + assertError: assertErrorNil, + expOut: expectedColoredJSON, + expErr: "", + }, } for _, tc := range testcases { diff --git a/go.mod b/go.mod index 4ab7eb5..db4cd95 100644 --- a/go.mod +++ b/go.mod @@ -12,6 +12,7 @@ require ( k8s.io/apimachinery v0.17.0 k8s.io/client-go v0.17.0 k8s.io/kubernetes v1.17.0 + github.com/andreazorzetto/yh v0.4.0 ) replace ( diff --git a/go.sum b/go.sum index 3daa47f..b84d777 100644 --- a/go.sum +++ b/go.sum @@ -33,6 +33,8 @@ github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6/go.mod h1:3eOhrU github.com/agnivade/levenshtein v1.0.1/go.mod h1:CURSv5d9Uaml+FovSIICkLbAUZ9S4RqaHDIsdSBg7lM= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/andreazorzetto/yh v0.4.0 h1:kXQJxhT7v9/JqUNifD+yIBRLKXDWeBgO2/UjxwRQsto= +github.com/andreazorzetto/yh v0.4.0/go.mod h1:c7MhXod3cApIEJDb9VSXA9cZVVaEZbvW+GhMPiVg2tM= github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= @@ -297,6 +299,8 @@ github.com/libopenstorage/openstorage v1.0.0/go.mod h1:Sp1sIObHjat1BeXhfMqLZ14wn github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de/go.mod h1:zAbeS9B/r2mtpb6U+EI2rYA5OAXxsYw6wTamcNW+zcE= github.com/lithammer/dedent v1.1.0/go.mod h1:jrXYCQtgg0nJiN+StA2KgR7w6CiQNv9Fd/Z9BP0jIOc= github.com/logrusorgru/aurora v0.0.0-20181002194514-a7b3b318ed4e/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4= +github.com/logrusorgru/aurora v2.0.3+incompatible h1:tOpm7WcpBTn4fjmVfgpQq0EfczGlG91VSDkswnjF5A8= +github.com/logrusorgru/aurora v2.0.3+incompatible/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4= github.com/lpabon/godbc v0.1.1/go.mod h1:Jo9QV0cf3U6jZABgiJ2skINAXb9j8m51r07g4KI92ZA= github.com/lucas-clemente/aes12 v0.0.0-20171027163421-cd47fb39b79f/go.mod h1:JpH9J1c9oX6otFSgdUHwUBUizmKlrMjxWnIAjff4m04= github.com/lucas-clemente/quic-clients v0.1.0/go.mod h1:y5xVIEoObKqULIKivu+gD/LU90pL73bTdtQjPBvtCBk=