File: color.go

package info (click to toggle)
golang-github-jedib0t-go-pretty 6.5.9-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 1,700 kB
  • sloc: makefile: 28; sh: 14
file content (179 lines) | stat: -rw-r--r-- 3,854 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
package text

import (
	"fmt"
	"sort"
	"strconv"
	"strings"
	"sync"
)

var colorsEnabled = areANSICodesSupported()

// DisableColors (forcefully) disables color coding globally.
func DisableColors() {
	colorsEnabled = false
}

// EnableColors (forcefully) enables color coding globally.
func EnableColors() {
	colorsEnabled = true
}

// The logic here is inspired from github.com/fatih/color; the following is
// the bare minimum logic required to print Colored to the console.
// The differences:
// * This one caches the escape sequences for cases with multiple colors
// * This one handles cases where the incoming already has colors in the
//   form of escape sequences; in which case, text that does not have any
//   escape sequences are colored/escaped

// Color represents a single color to render with.
type Color int

// Base colors -- attributes in reality
const (
	Reset Color = iota
	Bold
	Faint
	Italic
	Underline
	BlinkSlow
	BlinkRapid
	ReverseVideo
	Concealed
	CrossedOut
)

// Foreground colors
const (
	FgBlack Color = iota + 30
	FgRed
	FgGreen
	FgYellow
	FgBlue
	FgMagenta
	FgCyan
	FgWhite
)

// Foreground Hi-Intensity colors
const (
	FgHiBlack Color = iota + 90
	FgHiRed
	FgHiGreen
	FgHiYellow
	FgHiBlue
	FgHiMagenta
	FgHiCyan
	FgHiWhite
)

// Background colors
const (
	BgBlack Color = iota + 40
	BgRed
	BgGreen
	BgYellow
	BgBlue
	BgMagenta
	BgCyan
	BgWhite
)

// Background Hi-Intensity colors
const (
	BgHiBlack Color = iota + 100
	BgHiRed
	BgHiGreen
	BgHiYellow
	BgHiBlue
	BgHiMagenta
	BgHiCyan
	BgHiWhite
)

// EscapeSeq returns the ANSI escape sequence for the color.
func (c Color) EscapeSeq() string {
	return EscapeStart + strconv.Itoa(int(c)) + EscapeStop
}

// HTMLProperty returns the "class" attribute for the color.
func (c Color) HTMLProperty() string {
	out := ""
	if class, ok := colorCSSClassMap[c]; ok {
		out = fmt.Sprintf("class=\"%s\"", class)
	}
	return out
}

// Sprint colorizes and prints the given string(s).
func (c Color) Sprint(a ...interface{}) string {
	return colorize(fmt.Sprint(a...), c.EscapeSeq())
}

// Sprintf formats and colorizes and prints the given string(s).
func (c Color) Sprintf(format string, a ...interface{}) string {
	return colorize(fmt.Sprintf(format, a...), c.EscapeSeq())
}

// Colors represents an array of Color objects to render with.
// Example: Colors{FgCyan, BgBlack}
type Colors []Color

// colorsSeqMap caches the escape sequence for a set of colors
var colorsSeqMap = sync.Map{}

// EscapeSeq returns the ANSI escape sequence for the colors set.
func (c Colors) EscapeSeq() string {
	if len(c) == 0 {
		return ""
	}

	colorsKey := fmt.Sprintf("%#v", c)
	escapeSeq, ok := colorsSeqMap.Load(colorsKey)
	if !ok || escapeSeq == "" {
		colorNums := make([]string, len(c))
		for idx, color := range c {
			colorNums[idx] = strconv.Itoa(int(color))
		}
		escapeSeq = EscapeStart + strings.Join(colorNums, ";") + EscapeStop
		colorsSeqMap.Store(colorsKey, escapeSeq)
	}
	return escapeSeq.(string)
}

// HTMLProperty returns the "class" attribute for the colors.
func (c Colors) HTMLProperty() string {
	if len(c) == 0 {
		return ""
	}

	var classes []string
	for _, color := range c {
		if class, ok := colorCSSClassMap[color]; ok {
			classes = append(classes, class)
		}
	}
	if len(classes) > 1 {
		sort.Strings(classes)
	}
	return fmt.Sprintf("class=\"%s\"", strings.Join(classes, " "))
}

// Sprint colorizes and prints the given string(s).
func (c Colors) Sprint(a ...interface{}) string {
	return colorize(fmt.Sprint(a...), c.EscapeSeq())
}

// Sprintf formats and colorizes and prints the given string(s).
func (c Colors) Sprintf(format string, a ...interface{}) string {
	return colorize(fmt.Sprintf(format, a...), c.EscapeSeq())
}

func colorize(s string, escapeSeq string) string {
	if !colorsEnabled || escapeSeq == "" {
		return s
	}
	return Escape(s, escapeSeq)
}