github.com/andrewhsu/cli/v2@v2.0.1-0.20210910131313-d4b4061f5b89/pkg/jsoncolor/jsoncolor.go (about) 1 package jsoncolor 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "io" 7 "strings" 8 ) 9 10 const ( 11 colorDelim = "1;38" // bright white 12 colorKey = "1;34" // bright blue 13 colorNull = "36" // cyan 14 colorString = "32" // green 15 colorBool = "33" // yellow 16 ) 17 18 // Write colorized JSON output parsed from reader 19 func Write(w io.Writer, r io.Reader, indent string) error { 20 dec := json.NewDecoder(r) 21 dec.UseNumber() 22 23 var idx int 24 var stack []json.Delim 25 26 for { 27 t, err := dec.Token() 28 if err == io.EOF { 29 break 30 } 31 if err != nil { 32 return err 33 } 34 35 switch tt := t.(type) { 36 case json.Delim: 37 switch tt { 38 case '{', '[': 39 stack = append(stack, tt) 40 idx = 0 41 fmt.Fprintf(w, "\x1b[%sm%s\x1b[m", colorDelim, tt) 42 if dec.More() { 43 fmt.Fprint(w, "\n", strings.Repeat(indent, len(stack))) 44 } 45 continue 46 case '}', ']': 47 stack = stack[:len(stack)-1] 48 idx = 0 49 fmt.Fprintf(w, "\x1b[%sm%s\x1b[m", colorDelim, tt) 50 } 51 default: 52 b, err := json.Marshal(tt) 53 if err != nil { 54 return err 55 } 56 57 isKey := len(stack) > 0 && stack[len(stack)-1] == '{' && idx%2 == 0 58 idx++ 59 60 var color string 61 if isKey { 62 color = colorKey 63 } else if tt == nil { 64 color = colorNull 65 } else { 66 switch t.(type) { 67 case string: 68 color = colorString 69 case bool: 70 color = colorBool 71 } 72 } 73 74 if color == "" { 75 _, _ = w.Write(b) 76 } else { 77 fmt.Fprintf(w, "\x1b[%sm%s\x1b[m", color, b) 78 } 79 80 if isKey { 81 fmt.Fprintf(w, "\x1b[%sm:\x1b[m ", colorDelim) 82 continue 83 } 84 } 85 86 if dec.More() { 87 fmt.Fprintf(w, "\x1b[%sm,\x1b[m\n%s", colorDelim, strings.Repeat(indent, len(stack))) 88 } else if len(stack) > 0 { 89 fmt.Fprint(w, "\n", strings.Repeat(indent, len(stack)-1)) 90 } else { 91 fmt.Fprint(w, "\n") 92 } 93 } 94 95 return nil 96 }