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