]> git.lizzy.rs Git - micro.git/blob - cmd/micro/colorscheme.go
Merge pull request #316 from elopio/snapcraft
[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                         c[link] = StringToStyle(colors)
106                 } else {
107                         fmt.Println("Color-link statement is not valid:", line)
108                 }
109         }
110
111         return c
112 }
113
114 // StringToStyle returns a style from a string
115 // The strings must be in the format "extra foregroundcolor,backgroundcolor"
116 // The 'extra' can be bold, reverse, or underline
117 func StringToStyle(str string) tcell.Style {
118         var fg string
119         bg := "default"
120         split := strings.Split(str, ",")
121         if len(split) > 1 {
122                 fg, bg = split[0], split[1]
123         } else {
124                 fg = split[0]
125         }
126         fg = strings.TrimSpace(fg)
127         bg = strings.TrimSpace(bg)
128
129         style := defStyle.Foreground(StringToColor(fg)).Background(StringToColor(bg))
130         if strings.Contains(str, "bold") {
131                 style = style.Bold(true)
132         }
133         if strings.Contains(str, "reverse") {
134                 style = style.Reverse(true)
135         }
136         if strings.Contains(str, "underline") {
137                 style = style.Underline(true)
138         }
139         return style
140 }
141
142 // StringToColor returns a tcell color from a string representation of a color
143 // We accept either bright... or light... to mean the brighter version of a color
144 func StringToColor(str string) tcell.Color {
145         switch str {
146         case "black":
147                 return tcell.ColorBlack
148         case "red":
149                 return tcell.ColorMaroon
150         case "green":
151                 return tcell.ColorGreen
152         case "yellow":
153                 return tcell.ColorOlive
154         case "blue":
155                 return tcell.ColorNavy
156         case "magenta":
157                 return tcell.ColorPurple
158         case "cyan":
159                 return tcell.ColorTeal
160         case "white":
161                 return tcell.ColorSilver
162         case "brightblack", "lightblack":
163                 return tcell.ColorGray
164         case "brightred", "lightred":
165                 return tcell.ColorRed
166         case "brightgreen", "lightgreen":
167                 return tcell.ColorLime
168         case "brightyellow", "lightyellow":
169                 return tcell.ColorYellow
170         case "brightblue", "lightblue":
171                 return tcell.ColorBlue
172         case "brightmagenta", "lightmagenta":
173                 return tcell.ColorFuchsia
174         case "brightcyan", "lightcyan":
175                 return tcell.ColorAqua
176         case "brightwhite", "lightwhite":
177                 return tcell.ColorWhite
178         case "default":
179                 return tcell.ColorDefault
180         default:
181                 // Check if this is a 256 color
182                 if num, err := strconv.Atoi(str); err == nil {
183                         return GetColor256(num)
184                 }
185                 // Probably a truecolor hex value
186                 return tcell.GetColor(str)
187         }
188 }
189
190 // GetColor256 returns the tcell color for a number between 0 and 255
191 func GetColor256(color int) tcell.Color {
192         colors := []tcell.Color{tcell.ColorBlack, tcell.ColorMaroon, tcell.ColorGreen,
193                 tcell.ColorOlive, tcell.ColorNavy, tcell.ColorPurple,
194                 tcell.ColorTeal, tcell.ColorSilver, tcell.ColorGray,
195                 tcell.ColorRed, tcell.ColorLime, tcell.ColorYellow,
196                 tcell.ColorBlue, tcell.ColorFuchsia, tcell.ColorAqua,
197                 tcell.ColorWhite, tcell.Color16, tcell.Color17, tcell.Color18, tcell.Color19, tcell.Color20,
198                 tcell.Color21, tcell.Color22, tcell.Color23, tcell.Color24, tcell.Color25, tcell.Color26, tcell.Color27, tcell.Color28,
199                 tcell.Color29, tcell.Color30, tcell.Color31, tcell.Color32, tcell.Color33, tcell.Color34, tcell.Color35, tcell.Color36,
200                 tcell.Color37, tcell.Color38, tcell.Color39, tcell.Color40, tcell.Color41, tcell.Color42, tcell.Color43, tcell.Color44,
201                 tcell.Color45, tcell.Color46, tcell.Color47, tcell.Color48, tcell.Color49, tcell.Color50, tcell.Color51, tcell.Color52,
202                 tcell.Color53, tcell.Color54, tcell.Color55, tcell.Color56, tcell.Color57, tcell.Color58, tcell.Color59, tcell.Color60,
203                 tcell.Color61, tcell.Color62, tcell.Color63, tcell.Color64, tcell.Color65, tcell.Color66, tcell.Color67, tcell.Color68,
204                 tcell.Color69, tcell.Color70, tcell.Color71, tcell.Color72, tcell.Color73, tcell.Color74, tcell.Color75, tcell.Color76,
205                 tcell.Color77, tcell.Color78, tcell.Color79, tcell.Color80, tcell.Color81, tcell.Color82, tcell.Color83, tcell.Color84,
206                 tcell.Color85, tcell.Color86, tcell.Color87, tcell.Color88, tcell.Color89, tcell.Color90, tcell.Color91, tcell.Color92,
207                 tcell.Color93, tcell.Color94, tcell.Color95, tcell.Color96, tcell.Color97, tcell.Color98, tcell.Color99, tcell.Color100,
208                 tcell.Color101, tcell.Color102, tcell.Color103, tcell.Color104, tcell.Color105, tcell.Color106, tcell.Color107, tcell.Color108,
209                 tcell.Color109, tcell.Color110, tcell.Color111, tcell.Color112, tcell.Color113, tcell.Color114, tcell.Color115, tcell.Color116,
210                 tcell.Color117, tcell.Color118, tcell.Color119, tcell.Color120, tcell.Color121, tcell.Color122, tcell.Color123, tcell.Color124,
211                 tcell.Color125, tcell.Color126, tcell.Color127, tcell.Color128, tcell.Color129, tcell.Color130, tcell.Color131, tcell.Color132,
212                 tcell.Color133, tcell.Color134, tcell.Color135, tcell.Color136, tcell.Color137, tcell.Color138, tcell.Color139, tcell.Color140,
213                 tcell.Color141, tcell.Color142, tcell.Color143, tcell.Color144, tcell.Color145, tcell.Color146, tcell.Color147, tcell.Color148,
214                 tcell.Color149, tcell.Color150, tcell.Color151, tcell.Color152, tcell.Color153, tcell.Color154, tcell.Color155, tcell.Color156,
215                 tcell.Color157, tcell.Color158, tcell.Color159, tcell.Color160, tcell.Color161, tcell.Color162, tcell.Color163, tcell.Color164,
216                 tcell.Color165, tcell.Color166, tcell.Color167, tcell.Color168, tcell.Color169, tcell.Color170, tcell.Color171, tcell.Color172,
217                 tcell.Color173, tcell.Color174, tcell.Color175, tcell.Color176, tcell.Color177, tcell.Color178, tcell.Color179, tcell.Color180,
218                 tcell.Color181, tcell.Color182, tcell.Color183, tcell.Color184, tcell.Color185, tcell.Color186, tcell.Color187, tcell.Color188,
219                 tcell.Color189, tcell.Color190, tcell.Color191, tcell.Color192, tcell.Color193, tcell.Color194, tcell.Color195, tcell.Color196,
220                 tcell.Color197, tcell.Color198, tcell.Color199, tcell.Color200, tcell.Color201, tcell.Color202, tcell.Color203, tcell.Color204,
221                 tcell.Color205, tcell.Color206, tcell.Color207, tcell.Color208, tcell.Color209, tcell.Color210, tcell.Color211, tcell.Color212,
222                 tcell.Color213, tcell.Color214, tcell.Color215, tcell.Color216, tcell.Color217, tcell.Color218, tcell.Color219, tcell.Color220,
223                 tcell.Color221, tcell.Color222, tcell.Color223, tcell.Color224, tcell.Color225, tcell.Color226, tcell.Color227, tcell.Color228,
224                 tcell.Color229, tcell.Color230, tcell.Color231, tcell.Color232, tcell.Color233, tcell.Color234, tcell.Color235, tcell.Color236,
225                 tcell.Color237, tcell.Color238, tcell.Color239, tcell.Color240, tcell.Color241, tcell.Color242, tcell.Color243, tcell.Color244,
226                 tcell.Color245, tcell.Color246, tcell.Color247, tcell.Color248, tcell.Color249, tcell.Color250, tcell.Color251, tcell.Color252,
227                 tcell.Color253, tcell.Color254, tcell.Color255,
228         }
229
230         return colors[color]
231 }