package render import "strings" // Colour uses ANSI slots 0-15 only -- codes 30-37 and 90-97, plus the // attributes 1 (bold), 2 (dim) and 4 (underline). Never 256-colour indices: // this runs on terminals whose palette remaps the low slots (the phone's is // entirely green), where a hardcoded 38;5;196 would be the one off-palette // thing on screen. const ( Reset = "0" Bold = "1" Dim = "2" Underline = "4" Blue = "34" Cyan = "36" Green = "32" Yellow = "33" Red = "31" BrightBlue = "94" BrightRed = "91" BrightWhite = "97" ) // Styler returns a function that wraps text in an ANSI code, or returns it // unchanged when colour is off. func Styler(colour bool) func(code, text string) string { if !colour { return func(_, text string) string { return text } } return func(code, text string) string { if code == "" { return text } return "\033[" + code + "m" + text + "\033[0m" } } // Cell is one character of chart output with the style it should carry. type Cell struct { Style string Text string } // Paint joins cells, emitting one escape sequence per run of identical style // rather than one per character. A per-character version makes the chart around // ten times larger for output that looks exactly the same. func Paint(cells []Cell, c func(string, string) string) string { var b strings.Builder for i := 0; i < len(cells); { j := i var run strings.Builder for j < len(cells) && cells[j].Style == cells[i].Style { run.WriteString(cells[j].Text) j++ } b.WriteString(c(cells[i].Style, run.String())) i = j } return b.String() }