1package main
2
3import (
4	"github.com/xyproto/env"
5	"github.com/xyproto/syntax"
6	"github.com/xyproto/vt100"
7)
8
9var envNoColor = env.Bool("NO_COLOR")
10
11// Theme contains iformation about:
12// * If the theme is light or dark
13// * If syntax highlighting should be enabled
14// * If no colors should be used
15// * Colors for all the textual elements
16type Theme struct {
17	Light bool
18	Foreground, Background,
19	StatusForeground, StatusBackground,
20	StatusErrorForeground, StatusErrorBackground,
21	SearchHighlight, MultiLineComment, MultiLineString,
22	Git vt100.AttributeColor
23	String, Keyword, Comment, Type, Literal, Punctuation, Plaintext, Tag, TextTag, TextAttrName, TextAttrValue,
24	Decimal, AndOr, Dollar, Star, Class, Private, Protected, Public, Whitespace, AssemblyEnd string
25	RainbowParenColors []vt100.AttributeColor
26	MarkdownTextColor, HeaderBulletColor, HeaderTextColor, ListBulletColor, ListTextColor,
27	ListCodeColor, CodeColor, CodeBlockColor, ImageColor, LinkColor, QuoteColor, QuoteTextColor,
28	HTMLColor, CommentColor, BoldColor, ItalicsColor, StrikeColor, TableColor, CheckboxColor,
29	XColor, TableBackground, UnmatchedParenColor, MenuTitleColor, MenuArrowColor, MenuTextColor,
30	MenuHighlightColor, MenuSelectedColor, ManSectionColor, ManSynopsisColor vt100.AttributeColor
31}
32
33// NewDefaultTheme creates a new default Theme struct
34func NewDefaultTheme() Theme {
35	return Theme{
36		Light:                 false,
37		Foreground:            vt100.LightBlue,
38		Background:            vt100.BackgroundDefault,
39		StatusForeground:      vt100.White,
40		StatusBackground:      vt100.BackgroundBlack,
41		StatusErrorForeground: vt100.LightRed,
42		StatusErrorBackground: vt100.BackgroundDefault,
43		SearchHighlight:       vt100.LightMagenta,
44		MultiLineComment:      vt100.Gray,
45		MultiLineString:       vt100.Magenta,
46		Git:                   vt100.LightGreen,
47		String:                "lightyellow",
48		Keyword:               "lightred",
49		Comment:               "gray",
50		Type:                  "lightblue",
51		Literal:               "lightgreen",
52		Punctuation:           "lightblue",
53		Plaintext:             "lightgreen",
54		Tag:                   "lightgreen",
55		TextTag:               "lightgreen",
56		TextAttrName:          "lightgreen",
57		TextAttrValue:         "lightgreen",
58		Decimal:               "white",
59		AndOr:                 "lightyellow",
60		Dollar:                "lightred",
61		Star:                  "lightyellow",
62		Class:                 "lightred",
63		Private:               "darkred",
64		Protected:             "darkyellow",
65		Public:                "darkgreen",
66		Whitespace:            "",
67		AssemblyEnd:           "cyan",
68		RainbowParenColors:    []vt100.AttributeColor{vt100.LightMagenta, vt100.LightRed, vt100.Yellow, vt100.LightYellow, vt100.LightGreen, vt100.LightBlue, vt100.Red},
69		MarkdownTextColor:     vt100.LightBlue,
70		HeaderBulletColor:     vt100.DarkGray,
71		HeaderTextColor:       vt100.LightGreen,
72		ListBulletColor:       vt100.Red,
73		ListTextColor:         vt100.LightCyan,
74		ListCodeColor:         vt100.Default,
75		CodeColor:             vt100.Default,
76		CodeBlockColor:        vt100.Default,
77		ImageColor:            vt100.LightYellow,
78		LinkColor:             vt100.Magenta,
79		QuoteColor:            vt100.Yellow,
80		QuoteTextColor:        vt100.LightCyan,
81		HTMLColor:             vt100.Default,
82		CommentColor:          vt100.DarkGray,
83		BoldColor:             vt100.LightYellow,
84		ItalicsColor:          vt100.White,
85		StrikeColor:           vt100.DarkGray,
86		TableColor:            vt100.Blue,
87		CheckboxColor:         vt100.Default,
88		XColor:                vt100.LightYellow,
89		TableBackground:       vt100.BackgroundDefault,
90		UnmatchedParenColor:   vt100.White,
91		MenuTitleColor:        vt100.LightYellow,
92		MenuArrowColor:        vt100.Red,
93		MenuTextColor:         vt100.Gray,
94		MenuHighlightColor:    vt100.LightBlue,
95		MenuSelectedColor:     vt100.LightCyan,
96		ManSectionColor:       vt100.LightRed,
97		ManSynopsisColor:      vt100.LightYellow,
98	}
99}
100
101// NewRedBlackTheme creates a new red/black/gray/white Theme struct
102func NewRedBlackTheme() Theme {
103	// NOTE: Dark gray may not be visible with light terminal emulator themes
104	return Theme{
105		Light:                 false,
106		Foreground:            vt100.LightGray,
107		Background:            vt100.BackgroundBlack, // Dark gray background, as opposed to vt100.BackgroundDefault
108		StatusForeground:      vt100.White,
109		StatusBackground:      vt100.BackgroundBlack,
110		StatusErrorForeground: vt100.LightRed,
111		StatusErrorBackground: vt100.BackgroundDefault,
112		SearchHighlight:       vt100.Red,
113		MultiLineComment:      vt100.DarkGray,
114		MultiLineString:       vt100.LightGray,
115		Git:                   vt100.LightGreen,
116		String:                "lightwhite",
117		Keyword:               "darkred",
118		Comment:               "darkgray",
119		Type:                  "white",
120		Literal:               "lightgray",
121		Punctuation:           "darkred",
122		Plaintext:             "lightgray",
123		Tag:                   "darkred",
124		TextTag:               "darkred",
125		TextAttrName:          "darkred",
126		TextAttrValue:         "darkred",
127		Decimal:               "lightwhite",
128		AndOr:                 "darkred",
129		Dollar:                "lightwhite",
130		Star:                  "lightwhite",
131		Class:                 "darkred",
132		Private:               "lightgray",
133		Protected:             "lightgray",
134		Public:                "lightwhite",
135		Whitespace:            "",
136		AssemblyEnd:           "darkred",
137		RainbowParenColors:    []vt100.AttributeColor{vt100.LightGray, vt100.White, vt100.Red},
138		MarkdownTextColor:     vt100.LightGray,
139		HeaderBulletColor:     vt100.DarkGray,
140		HeaderTextColor:       vt100.Red,
141		ListBulletColor:       vt100.Red,
142		ListTextColor:         vt100.LightGray,
143		ListCodeColor:         vt100.Default,
144		CodeColor:             vt100.White,
145		CodeBlockColor:        vt100.White,
146		ImageColor:            vt100.Red,
147		LinkColor:             vt100.Magenta,
148		QuoteColor:            vt100.White,
149		QuoteTextColor:        vt100.LightGray,
150		HTMLColor:             vt100.Default,
151		CommentColor:          vt100.DarkGray,
152		BoldColor:             vt100.Red,
153		ItalicsColor:          vt100.White,
154		StrikeColor:           vt100.DarkGray,
155		TableColor:            vt100.White,
156		CheckboxColor:         vt100.Default,
157		XColor:                vt100.Red,
158		TableBackground:       vt100.BackgroundBlack, // Dark gray background, as opposed to vt100.BackgroundDefault
159		UnmatchedParenColor:   vt100.LightCyan,       // To really stand out
160		MenuTitleColor:        vt100.Red,
161		MenuArrowColor:        vt100.White,
162		MenuTextColor:         vt100.White,
163		MenuHighlightColor:    vt100.Yellow,
164		MenuSelectedColor:     vt100.LightYellow,
165		ManSectionColor:       vt100.Red,
166		ManSynopsisColor:      vt100.White,
167	}
168}
169
170// NewLightTheme creates a theme that is suitable for light xterm terminal emulator sessions
171func NewLightTheme() Theme {
172	return Theme{
173		Light:                 true,
174		Foreground:            vt100.Black,
175		Background:            vt100.BackgroundDefault,
176		StatusForeground:      vt100.White,
177		StatusBackground:      vt100.BackgroundBlack,
178		StatusErrorForeground: vt100.LightRed,
179		StatusErrorBackground: vt100.BackgroundDefault,
180		SearchHighlight:       vt100.Red,
181		MultiLineComment:      vt100.Gray,
182		MultiLineString:       vt100.Red,
183		Git:                   vt100.Blue,
184		String:                "red",
185		Keyword:               "blue",
186		Comment:               "gray",
187		Type:                  "blue",
188		Literal:               "darkcyan",
189		Punctuation:           "black",
190		Plaintext:             "black",
191		Tag:                   "black",
192		TextTag:               "black",
193		TextAttrName:          "black",
194		TextAttrValue:         "black",
195		Decimal:               "darkcyan",
196		AndOr:                 "black",
197		Dollar:                "red",
198		Star:                  "black",
199		Class:                 "blue",
200		Private:               "black",
201		Protected:             "black",
202		Public:                "black",
203		Whitespace:            "",
204		AssemblyEnd:           "red",
205		RainbowParenColors:    []vt100.AttributeColor{vt100.Magenta, vt100.Black, vt100.Blue, vt100.Green},
206		MarkdownTextColor:     vt100.Default,
207		HeaderBulletColor:     vt100.DarkGray,
208		HeaderTextColor:       vt100.Blue,
209		ListBulletColor:       vt100.Red,
210		ListTextColor:         vt100.Default,
211		ListCodeColor:         vt100.Red,
212		CodeColor:             vt100.Red,
213		CodeBlockColor:        vt100.Red,
214		ImageColor:            vt100.Green,
215		LinkColor:             vt100.Magenta,
216		QuoteColor:            vt100.Yellow,
217		QuoteTextColor:        vt100.LightCyan,
218		HTMLColor:             vt100.Default,
219		CommentColor:          vt100.DarkGray,
220		BoldColor:             vt100.Blue,
221		ItalicsColor:          vt100.Blue,
222		StrikeColor:           vt100.DarkGray,
223		TableColor:            vt100.Blue,
224		CheckboxColor:         vt100.Default,
225		XColor:                vt100.Blue,
226		TableBackground:       vt100.BackgroundDefault,
227		UnmatchedParenColor:   vt100.Red,
228		MenuTitleColor:        vt100.Blue,
229		MenuArrowColor:        vt100.Red,
230		MenuTextColor:         vt100.Black,
231		MenuHighlightColor:    vt100.Red,
232		MenuSelectedColor:     vt100.LightRed,
233		ManSectionColor:       vt100.Red,
234		ManSynopsisColor:      vt100.Blue,
235	}
236}
237
238// NewNoColorTheme creates a new theme without colors or syntax highlighting
239func NewNoColorTheme() Theme {
240	return Theme{
241		Light:                 false,
242		Foreground:            vt100.Default,
243		Background:            vt100.BackgroundDefault,
244		StatusForeground:      vt100.White,
245		StatusBackground:      vt100.BackgroundBlack,
246		StatusErrorForeground: vt100.White,
247		StatusErrorBackground: vt100.BackgroundDefault,
248		SearchHighlight:       vt100.Default,
249		MultiLineComment:      vt100.Default,
250		MultiLineString:       vt100.Default,
251		Git:                   vt100.White,
252		String:                "",
253		Keyword:               "",
254		Comment:               "",
255		Type:                  "",
256		Literal:               "",
257		Punctuation:           "",
258		Plaintext:             "",
259		Tag:                   "",
260		TextTag:               "",
261		TextAttrName:          "",
262		TextAttrValue:         "",
263		Decimal:               "",
264		AndOr:                 "",
265		Dollar:                "",
266		Star:                  "",
267		Class:                 "",
268		Private:               "",
269		Protected:             "",
270		Public:                "",
271		Whitespace:            "",
272		AssemblyEnd:           "",
273		RainbowParenColors:    []vt100.AttributeColor{vt100.Gray},
274		MarkdownTextColor:     vt100.Default,
275		HeaderBulletColor:     vt100.Default,
276		HeaderTextColor:       vt100.Default,
277		ListBulletColor:       vt100.Default,
278		ListTextColor:         vt100.Default,
279		ListCodeColor:         vt100.Default,
280		CodeColor:             vt100.Default,
281		CodeBlockColor:        vt100.Default,
282		ImageColor:            vt100.Default,
283		LinkColor:             vt100.Default,
284		QuoteColor:            vt100.Default,
285		QuoteTextColor:        vt100.Default,
286		HTMLColor:             vt100.Default,
287		CommentColor:          vt100.Default,
288		BoldColor:             vt100.Default,
289		ItalicsColor:          vt100.Default,
290		StrikeColor:           vt100.Default,
291		TableColor:            vt100.Default,
292		CheckboxColor:         vt100.Default,
293		XColor:                vt100.White,
294		TableBackground:       vt100.BackgroundDefault,
295		UnmatchedParenColor:   vt100.White,
296		MenuTitleColor:        vt100.White,
297		MenuArrowColor:        vt100.White,
298		MenuTextColor:         vt100.Gray,
299		MenuHighlightColor:    vt100.White,
300		MenuSelectedColor:     vt100.Black,
301		ManSectionColor:       vt100.White,
302		ManSynopsisColor:      vt100.White,
303	}
304}
305
306// TextConfig returns a TextConfig struct that can be used for settings
307// the syntax highlighting colors in the public TextConfig variable that is
308// exported from the syntax package.
309func (t Theme) TextConfig() *syntax.TextConfig {
310	return &syntax.TextConfig{
311		String:        t.String,
312		Keyword:       t.Keyword,
313		Comment:       t.Comment,
314		Type:          t.Type,
315		Literal:       t.Literal,
316		Punctuation:   t.Punctuation,
317		Plaintext:     t.Plaintext,
318		Tag:           t.Tag,
319		TextTag:       t.TextTag,
320		TextAttrName:  t.TextAttrName,
321		TextAttrValue: t.TextAttrValue,
322		Decimal:       t.Decimal,
323		AndOr:         t.AndOr,
324		Dollar:        t.Dollar,
325		Star:          t.Star,
326		Class:         t.Class,
327		Private:       t.Private,
328		Protected:     t.Protected,
329		Public:        t.Public,
330		Whitespace:    t.Whitespace,
331		AssemblyEnd:   t.AssemblyEnd,
332	}
333}
334
335// SetTheme assigns the given theme to the Editor,
336// and also configures syntax highlighting by setting syntax.DefaultTextConfig.
337// Light/dark, syntax highlighting and no color information is also set.
338// Respect the NO_COLOR environment variable. May set e.NoSyntaxHighlight to true.
339func (e *Editor) SetTheme(t Theme) {
340	if envNoColor {
341		t = NewNoColorTheme()
342		e.syntaxHighlight = false
343	}
344	e.Theme = t
345	syntax.DefaultTextConfig = *(t.TextConfig())
346}
347
348// setDefaultTheme sets the default colors
349func (e *Editor) setDefaultTheme() {
350	e.SetTheme(NewDefaultTheme())
351}
352
353// setLightTheme sets the light theme suitable for xterm
354func (e *Editor) setLightTheme() {
355	e.SetTheme(NewLightTheme())
356}
357
358// setRedBlackTheme sets a red/black/gray theme
359func (e *Editor) setRedBlackTheme() {
360	e.SetTheme(NewRedBlackTheme())
361}
362