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