]> git.lizzy.rs Git - micro.git/blob - cmd/micro/colorscheme.go
Update docs and readme
[micro.git] / cmd / micro / colorscheme.go
1 package main
2
3 import (
4         "fmt"
5         "regexp"
6         "strconv"
7         "strings"
8
9         "github.com/zyedidia/tcell"
10 )
11
12 // Colorscheme is a map from string to style -- it represents a colorscheme
13 type Colorscheme map[string]tcell.Style
14
15 // The current colorscheme
16 var colorscheme Colorscheme
17
18 // ColorschemeExists checks if a given colorscheme exists
19 func ColorschemeExists(colorschemeName string) bool {
20         return FindRuntimeFile(RTColorscheme, colorschemeName) != nil
21 }
22
23 // InitColorscheme picks and initializes the colorscheme when micro starts
24 func InitColorscheme() {
25         colorscheme = make(Colorscheme)
26         if screen != nil {
27                 screen.SetStyle(tcell.StyleDefault.
28                         Foreground(tcell.ColorDefault).
29                         Background(tcell.ColorDefault))
30         }
31
32         LoadDefaultColorscheme()
33 }
34
35 // LoadDefaultColorscheme loads the default colorscheme from $(configDir)/colorschemes
36 func LoadDefaultColorscheme() {
37         LoadColorscheme(globalSettings["colorscheme"].(string))
38 }
39
40 // LoadColorscheme loads the given colorscheme from a directory
41 func LoadColorscheme(colorschemeName string) {
42         file := FindRuntimeFile(RTColorscheme, colorschemeName)
43         if file == nil {
44                 TermMessage(colorschemeName, "is not a valid colorscheme")
45         } else {
46                 if data, err := file.Data(); err != nil {
47                         fmt.Println("Error loading colorscheme:", err)
48                 } else {
49                         colorscheme = ParseColorscheme(string(data))
50
51                         // Default style
52                         defStyle = tcell.StyleDefault.
53                                 Foreground(tcell.ColorDefault).
54                                 Background(tcell.ColorDefault)
55
56                         // There may be another default style defined in the colorscheme
57                         // In that case we should use that one
58                         if style, ok := colorscheme["default"]; ok {
59                                 defStyle = style
60                         }
61                         if screen != nil {
62                                 screen.SetStyle(defStyle)
63                         }
64                 }
65         }
66 }
67
68 // ParseColorscheme parses the text definition for a colorscheme and returns the corresponding object
69 // Colorschemes are made up of color-link statements linking a color group to a list of colors
70 // For example, color-link keyword (blue,red) makes all keywords have a blue foreground and
71 // red background
72 func ParseColorscheme(text string) Colorscheme {
73         parser := regexp.MustCompile(`color-link\s+(\S*)\s+"(.*)"`)
74
75         lines := strings.Split(text, "\n")
76
77         c := make(Colorscheme)
78
79         for _, line := range lines {
80                 if strings.TrimSpace(line) == "" ||
81                         strings.TrimSpace(line)[0] == '#' {
82                         // Ignore this line
83                         continue
84                 }
85
86                 matches := parser.FindSubmatch([]byte(line))
87                 if len(matches) == 3 {
88                         link := string(matches[1])
89                         colors := string(matches[2])
90
91                         style := StringToStyle(colors)
92                         c[link] = style
93
94                         if link == "default" {
95                                 defStyle = style
96                         }
97                 } else {
98                         fmt.Println("Color-link statement is not valid:", line)
99                 }
100         }
101
102         return c
103 }
104
105 // StringToStyle returns a style from a string
106 // The strings must be in the format "extra foregroundcolor,backgroundcolor"
107 // The 'extra' can be bold, reverse, or underline
108 func StringToStyle(str string) tcell.Style {
109         var fg, bg string
110         split := strings.Split(str, ",")
111         if len(split) > 1 {
112                 fg, bg = split[0], split[1]
113         } else {
114                 fg = split[0]
115         }
116         fg = strings.TrimSpace(fg)
117         bg = strings.TrimSpace(bg)
118
119         var fgColor, bgColor tcell.Color
120         if fg == "" {
121                 fgColor, _, _ = defStyle.Decompose()
122         } else {
123                 fgColor = StringToColor(fg)
124         }
125         if bg == "" {
126                 _, bgColor, _ = defStyle.Decompose()
127         } else {
128                 bgColor = StringToColor(bg)
129         }
130
131         style := defStyle.Foreground(fgColor).Background(bgColor)
132         if strings.Contains(str, "bold") {
133                 style = style.Bold(true)
134         }
135         if strings.Contains(str, "reverse") {
136                 style = style.Reverse(true)
137         }
138         if strings.Contains(str, "underline") {
139                 style = style.Underline(true)
140         }
141         return style
142 }
143
144 // StringToColor returns a tcell color from a string representation of a color
145 // We accept either bright... or light... to mean the brighter version of a color
146 func StringToColor(str string) tcell.Color {
147         switch str {
148         case "black":
149                 return tcell.ColorBlack
150         case "red":
151                 return tcell.ColorMaroon
152         case "green":
153                 return tcell.ColorGreen
154         case "yellow":
155                 return tcell.ColorOlive
156         case "blue":
157                 return tcell.ColorNavy
158         case "magenta":
159                 return tcell.ColorPurple
160         case "cyan":
161                 return tcell.ColorTeal
162         case "white":
163                 return tcell.ColorSilver
164         case "brightblack", "lightblack":
165                 return tcell.ColorGray
166         case "brightred", "lightred":
167                 return tcell.ColorRed
168         case "brightgreen", "lightgreen":
169                 return tcell.ColorLime
170         case "brightyellow", "lightyellow":
171                 return tcell.ColorYellow
172         case "brightblue", "lightblue":
173                 return tcell.ColorBlue
174         case "brightmagenta", "lightmagenta":
175                 return tcell.ColorFuchsia
176         case "brightcyan", "lightcyan":
177                 return tcell.ColorAqua
178         case "brightwhite", "lightwhite":
179                 return tcell.ColorWhite
180         case "default":
181                 return tcell.ColorDefault
182         default:
183                 // Check if this is a 256 color
184                 if num, err := strconv.Atoi(str); err == nil {
185                         return GetColor256(num)
186                 }
187                 // Probably a truecolor hex value
188                 return tcell.GetColor(str)
189         }
190 }
191
192 // GetColor256 returns the tcell color for a number between 0 and 255
193 func GetColor256(color int) tcell.Color {
194         colors := []tcell.Color{tcell.ColorBlack, tcell.ColorMaroon, tcell.ColorGreen,
195                 tcell.ColorOlive, tcell.ColorNavy, tcell.ColorPurple,
196                 tcell.ColorTeal, tcell.ColorSilver, tcell.ColorGray,
197                 tcell.ColorRed, tcell.ColorLime, tcell.ColorYellow,
198                 tcell.ColorBlue, tcell.ColorFuchsia, tcell.ColorAqua,
199                 tcell.ColorWhite, tcell.Color16, tcell.Color17, tcell.Color18, tcell.Color19, tcell.Color20,
200                 tcell.Color21, tcell.Color22, tcell.Color23, tcell.Color24, tcell.Color25, tcell.Color26, tcell.Color27, tcell.Color28,
201                 tcell.Color29, tcell.Color30, tcell.Color31, tcell.Color32, tcell.Color33, tcell.Color34, tcell.Color35, tcell.Color36,
202                 tcell.Color37, tcell.Color38, tcell.Color39, tcell.Color40, tcell.Color41, tcell.Color42, tcell.Color43, tcell.Color44,
203                 tcell.Color45, tcell.Color46, tcell.Color47, tcell.Color48, tcell.Color49, tcell.Color50, tcell.Color51, tcell.Color52,
204                 tcell.Color53, tcell.Color54, tcell.Color55, tcell.Color56, tcell.Color57, tcell.Color58, tcell.Color59, tcell.Color60,
205                 tcell.Color61, tcell.Color62, tcell.Color63, tcell.Color64, tcell.Color65, tcell.Color66, tcell.Color67, tcell.Color68,
206                 tcell.Color69, tcell.Color70, tcell.Color71, tcell.Color72, tcell.Color73, tcell.Color74, tcell.Color75, tcell.Color76,
207                 tcell.Color77, tcell.Color78, tcell.Color79, tcell.Color80, tcell.Color81, tcell.Color82, tcell.Color83, tcell.Color84,
208                 tcell.Color85, tcell.Color86, tcell.Color87, tcell.Color88, tcell.Color89, tcell.Color90, tcell.Color91, tcell.Color92,
209                 tcell.Color93, tcell.Color94, tcell.Color95, tcell.Color96, tcell.Color97, tcell.Color98, tcell.Color99, tcell.Color100,
210                 tcell.Color101, tcell.Color102, tcell.Color103, tcell.Color104, tcell.Color105, tcell.Color106, tcell.Color107, tcell.Color108,
211                 tcell.Color109, tcell.Color110, tcell.Color111, tcell.Color112, tcell.Color113, tcell.Color114, tcell.Color115, tcell.Color116,
212                 tcell.Color117, tcell.Color118, tcell.Color119, tcell.Color120, tcell.Color121, tcell.Color122, tcell.Color123, tcell.Color124,
213                 tcell.Color125, tcell.Color126, tcell.Color127, tcell.Color128, tcell.Color129, tcell.Color130, tcell.Color131, tcell.Color132,
214                 tcell.Color133, tcell.Color134, tcell.Color135, tcell.Color136, tcell.Color137, tcell.Color138, tcell.Color139, tcell.Color140,
215                 tcell.Color141, tcell.Color142, tcell.Color143, tcell.Color144, tcell.Color145, tcell.Color146, tcell.Color147, tcell.Color148,
216                 tcell.Color149, tcell.Color150, tcell.Color151, tcell.Color152, tcell.Color153, tcell.Color154, tcell.Color155, tcell.Color156,
217                 tcell.Color157, tcell.Color158, tcell.Color159, tcell.Color160, tcell.Color161, tcell.Color162, tcell.Color163, tcell.Color164,
218                 tcell.Color165, tcell.Color166, tcell.Color167, tcell.Color168, tcell.Color169, tcell.Color170, tcell.Color171, tcell.Color172,
219                 tcell.Color173, tcell.Color174, tcell.Color175, tcell.Color176, tcell.Color177, tcell.Color178, tcell.Color179, tcell.Color180,
220                 tcell.Color181, tcell.Color182, tcell.Color183, tcell.Color184, tcell.Color185, tcell.Color186, tcell.Color187, tcell.Color188,
221                 tcell.Color189, tcell.Color190, tcell.Color191, tcell.Color192, tcell.Color193, tcell.Color194, tcell.Color195, tcell.Color196,
222                 tcell.Color197, tcell.Color198, tcell.Color199, tcell.Color200, tcell.Color201, tcell.Color202, tcell.Color203, tcell.Color204,
223                 tcell.Color205, tcell.Color206, tcell.Color207, tcell.Color208, tcell.Color209, tcell.Color210, tcell.Color211, tcell.Color212,
224                 tcell.Color213, tcell.Color214, tcell.Color215, tcell.Color216, tcell.Color217, tcell.Color218, tcell.Color219, tcell.Color220,
225                 tcell.Color221, tcell.Color222, tcell.Color223, tcell.Color224, tcell.Color225, tcell.Color226, tcell.Color227, tcell.Color228,
226                 tcell.Color229, tcell.Color230, tcell.Color231, tcell.Color232, tcell.Color233, tcell.Color234, tcell.Color235, tcell.Color236,
227                 tcell.Color237, tcell.Color238, tcell.Color239, tcell.Color240, tcell.Color241, tcell.Color242, tcell.Color243, tcell.Color244,
228                 tcell.Color245, tcell.Color246, tcell.Color247, tcell.Color248, tcell.Color249, tcell.Color250, tcell.Color251, tcell.Color252,
229                 tcell.Color253, tcell.Color254, tcell.Color255,
230         }
231
232         return colors[color]
233 }