|
| 1 | +// Package prettyprint contains tools for formatting text. |
| 2 | +package prettyprint |
| 3 | + |
| 4 | +import ( |
| 5 | + "bytes" |
| 6 | + "fmt" |
| 7 | + "strings" |
| 8 | + "text/template" |
| 9 | +) |
| 10 | + |
| 11 | +// Colors contains a map of the standard ANSI color codes. |
| 12 | +// |
| 13 | +// There are four variants: |
| 14 | +// - Bare color names (Red, Black) color the characters. |
| 15 | +// - Bold color names add bolding to the characters. |
| 16 | +// - Under color names add underlining to the characters. |
| 17 | +// - Hi color names add highlighting (background colors). |
| 18 | +// |
| 19 | +// These can be used within `text/template` to provide colors. The convenience |
| 20 | +// function `Colorize()` provides this feature. |
| 21 | +var Colors = map[string]string{ |
| 22 | + "Default": "\033[0m", |
| 23 | + "Black": "\033[0;30m", |
| 24 | + "Red": "\033[0;31m", |
| 25 | + "Green": "\033[0;32m", |
| 26 | + "Yellow": "\033[0;33m", |
| 27 | + "Blue": "\033[0;34m", |
| 28 | + "Purple": "\033[0;35m", |
| 29 | + "Cyan": "\033[0;36m", |
| 30 | + "White": "\033[0;37m", |
| 31 | + "BoldBlack": "\033[1;30m", |
| 32 | + "BoldRed": "\033[1;31m", |
| 33 | + "BoldGreen": "\033[1;32m", |
| 34 | + "BoldYellow": "\033[1;33m", |
| 35 | + "BoldBlue": "\033[1;34m", |
| 36 | + "BoldPurple": "\033[1;35m", |
| 37 | + "BoldCyan": "\033[1;36m", |
| 38 | + "BoldWhite": "\033[1;37m", |
| 39 | + "UnderBlack": "\033[4;30m", |
| 40 | + "UnderRed": "\033[4;31m", |
| 41 | + "UnderGreen": "\033[4;32m", |
| 42 | + "UnderYellow": "\033[4;33m", |
| 43 | + "UnderBlue": "\033[4;34m", |
| 44 | + "UnderPurple": "\033[4;35m", |
| 45 | + "UnderCyan": "\033[4;36m", |
| 46 | + "UnderWhite": "\033[4;37m", |
| 47 | + "HiBlack": "\033[30m", |
| 48 | + "HiRed": "\033[31m", |
| 49 | + "HiGreen": "\033[32m", |
| 50 | + "HiYellow": "\033[33m", |
| 51 | + "HiBlue": "\033[34m", |
| 52 | + "HiPurple": "\033[35m", |
| 53 | + "HiCyan": "\033[36m", |
| 54 | + "HiWhite": "\033[37m", |
| 55 | + "Deis1": "\033[31m● \033[34m▴ \033[32m■\033[0m", |
| 56 | + "Deis2": "\033[32m■ \033[31m● \033[34m▴\033[0m", |
| 57 | + "Deis3": "\033[34m▴ \033[32m■ \033[31m●\033[0m", |
| 58 | + "Deis": "\033[31m● \033[34m▴ \033[32m■\n\033[32m■ \033[31m● \033[34m▴\n\033[34m▴ \033[32m■ \033[31m●\n", |
| 59 | +} |
| 60 | + |
| 61 | +// DeisIfy returns a pretty-printed deis logo along with the corresponding message |
| 62 | +func DeisIfy(msg string) string { |
| 63 | + var t = struct { |
| 64 | + Msg string |
| 65 | + C map[string]string |
| 66 | + }{ |
| 67 | + Msg: msg, |
| 68 | + C: Colors, |
| 69 | + } |
| 70 | + tpl := "{{.C.Deis1}}\n{{.C.Deis2}} {{.Msg}}\n{{.C.Deis3}}\n" |
| 71 | + var buf bytes.Buffer |
| 72 | + template.Must(template.New("deis").Parse(tpl)).Execute(&buf, t) |
| 73 | + return buf.String() |
| 74 | +} |
| 75 | + |
| 76 | +// Logo returns a colorized Deis logo with no space for text. |
| 77 | +func Logo() string { |
| 78 | + return Colorize("{{.Deis}}") |
| 79 | +} |
| 80 | + |
| 81 | +// NoColor strips colors from the template. |
| 82 | +// |
| 83 | +// NoColor provides support for non-color ANSI terminals. It can be used |
| 84 | +// as an alternative to Colorize when it is detected that the terminal does |
| 85 | +// not support colors. |
| 86 | +func NoColor(msg string) string { |
| 87 | + empties := make(map[string]string, len(Colors)) |
| 88 | + for k, _ := range Colors { |
| 89 | + empties[k] = "" |
| 90 | + } |
| 91 | + return colorize(msg, empties) |
| 92 | +} |
| 93 | + |
| 94 | +// Colorize makes it easy to add colors to ANSI terminal output. |
| 95 | +// |
| 96 | +// This takes any of the colors defined in the Colors map. Colors are rendered |
| 97 | +// through the `text/template` system, so you may use pipes and functions as |
| 98 | +// well. |
| 99 | +// |
| 100 | +// Example: |
| 101 | +// Colorize("{{.Red}}ERROR:{{.Default}} Something happened.") |
| 102 | +func Colorize(msg string) string { |
| 103 | + return colorize(msg, Colors) |
| 104 | +} |
| 105 | + |
| 106 | +// ColorizeVars provides template rendering with color support. |
| 107 | +// |
| 108 | +// The template is given a datum with two objects: `.V` and `.C`. `.V` contains |
| 109 | +// the `vars` passed into the function. `.C` contains the color map. |
| 110 | +// |
| 111 | +// Assuming `vars` contains a member named `Msg`, a template can be constructed |
| 112 | +// like this: |
| 113 | +// {{.C.Red}}Message:{{.C.Default}} .V.Msg |
| 114 | +func ColorizeVars(msg string, vars interface{}) string { |
| 115 | + var t = struct { |
| 116 | + V interface{} |
| 117 | + C map[string]string |
| 118 | + }{ |
| 119 | + V: vars, |
| 120 | + C: Colors, |
| 121 | + } |
| 122 | + return colorize(msg, t) |
| 123 | +} |
| 124 | + |
| 125 | +func colorize(msg string, vars interface{}) string { |
| 126 | + tpl, err := template.New(msg).Parse(msg) |
| 127 | + // If the template's not valid, we just ignore and return. |
| 128 | + if err != nil { |
| 129 | + return msg |
| 130 | + } |
| 131 | + var buf bytes.Buffer |
| 132 | + if err := tpl.Execute(&buf, vars); err != nil { |
| 133 | + return msg |
| 134 | + } |
| 135 | + |
| 136 | + return buf.String() |
| 137 | +} |
| 138 | + |
| 139 | +// Overwrite sends a line that will be replaced by a subsequent overwrite. |
| 140 | +// |
| 141 | +// Example: |
| 142 | +// Overwrite("foo") |
| 143 | +// Overwrite("bar") |
| 144 | +// |
| 145 | +// The above will print "foo" and then immediately replace it with "var". |
| 146 | +// |
| 147 | +// (Interpretation of \r is left to the shell.) |
| 148 | +func Overwrite(msg string) string { |
| 149 | + lm := len(msg) |
| 150 | + if lm >= 80 { |
| 151 | + return msg + "\r" |
| 152 | + } |
| 153 | + pad := 80 - len(msg) |
| 154 | + return msg + strings.Repeat(" ", pad) + "\r" |
| 155 | + |
| 156 | +} |
| 157 | + |
| 158 | +// Overwritef formats a string and then returns an overwrite line. |
| 159 | +// |
| 160 | +// See `Overwrite` for details. |
| 161 | +func Overwritef(msg string, args ...interface{}) string { |
| 162 | + return Overwrite(fmt.Sprintf(msg, args...)) |
| 163 | +} |
0 commit comments