1package pp
2
3import (
4	"fmt"
5	"reflect"
6)
7
8const (
9	// No color
10	NoColor uint16 = 1 << 15
11)
12
13const (
14	// Foreground colors for ColorScheme.
15	_ uint16 = iota | NoColor
16	Black
17	Red
18	Green
19	Yellow
20	Blue
21	Magenta
22	Cyan
23	White
24	bitsForeground       = 0
25	maskForegorund       = 0xf
26	ansiForegroundOffset = 30 - 1
27)
28
29const (
30	// Background colors for ColorScheme.
31	_ uint16 = iota<<bitsBackground | NoColor
32	BackgroundBlack
33	BackgroundRed
34	BackgroundGreen
35	BackgroundYellow
36	BackgroundBlue
37	BackgroundMagenta
38	BackgroundCyan
39	BackgroundWhite
40	bitsBackground       = 4
41	maskBackground       = 0xf << bitsBackground
42	ansiBackgroundOffset = 40 - 1
43)
44
45const (
46	// Bold flag for ColorScheme.
47	Bold     uint16 = 1<<bitsBold | NoColor
48	bitsBold        = 8
49	maskBold        = 1 << bitsBold
50	ansiBold        = 1
51)
52
53// To use with SetColorScheme.
54type ColorScheme struct {
55	Bool            uint16
56	Integer         uint16
57	Float           uint16
58	String          uint16
59	StringQuotation uint16
60	EscapedChar     uint16
61	FieldName       uint16
62	PointerAdress   uint16
63	Nil             uint16
64	Time            uint16
65	StructName      uint16
66	ObjectLength    uint16
67}
68
69var (
70	// If you set false to this variable, you can use pretty formatter
71	// without coloring.
72	ColoringEnabled = true
73
74	defaultScheme = ColorScheme{
75		Bool:            Cyan | Bold,
76		Integer:         Blue | Bold,
77		Float:           Magenta | Bold,
78		String:          Red,
79		StringQuotation: Red | Bold,
80		EscapedChar:     Magenta | Bold,
81		FieldName:       Yellow,
82		PointerAdress:   Blue | Bold,
83		Nil:             Cyan | Bold,
84		Time:            Blue | Bold,
85		StructName:      Green,
86		ObjectLength:    Blue,
87	}
88)
89
90func (cs *ColorScheme) fixColors() {
91	typ := reflect.Indirect(reflect.ValueOf(cs))
92	defaultType := reflect.ValueOf(defaultScheme)
93	for i := 0; i < typ.NumField(); i++ {
94		field := typ.Field(i)
95		if field.Uint() == 0 {
96			field.SetUint(defaultType.Field(i).Uint())
97		}
98	}
99}
100
101func colorize(text string, color uint16) string {
102	if !ColoringEnabled {
103		return text
104	}
105
106	foreground := color & maskForegorund >> bitsForeground
107	background := color & maskBackground >> bitsBackground
108	bold := color & maskBold
109
110	if foreground == 0 && background == 0 && bold == 0 {
111		return text
112	}
113
114	modBold := ""
115	modForeground := ""
116	modBackground := ""
117
118	if bold > 0 {
119		modBold = "\033[1m"
120	}
121	if foreground > 0 {
122		modForeground = fmt.Sprintf("\033[%dm", foreground+ansiForegroundOffset)
123	}
124	if background > 0 {
125		modBackground = fmt.Sprintf("\033[%dm", background+ansiBackgroundOffset)
126	}
127
128	return fmt.Sprintf("%s%s%s%s\033[0m", modForeground, modBackground, modBold, text)
129}
130