9 "github.com/zyedidia/tcell/v2"
12 // DefStyle is Micro's default style
13 var DefStyle tcell.Style = tcell.StyleDefault
15 // Colorscheme is the current colorscheme
16 var Colorscheme map[string]tcell.Style
18 // GetColor takes in a syntax group and returns the colorscheme's style for that group
19 func GetColor(color string) tcell.Style {
24 groups := strings.Split(color, ".")
27 for i, g := range groups {
32 if style, ok := Colorscheme[curGroup]; ok {
36 } else if style, ok := Colorscheme[color]; ok {
39 st = StringToStyle(color)
45 // ColorschemeExists checks if a given colorscheme exists
46 func ColorschemeExists(colorschemeName string) bool {
47 return FindRuntimeFile(RTColorscheme, colorschemeName) != nil
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
55 return LoadDefaultColorscheme()
58 // LoadDefaultColorscheme loads the default colorscheme from $(ConfigDir)/colorschemes
59 func LoadDefaultColorscheme() error {
60 return LoadColorscheme(GlobalSettings["colorscheme"].(string))
63 // LoadColorscheme loads the given colorscheme from a directory
64 func LoadColorscheme(colorschemeName string) error {
65 file := FindRuntimeFile(RTColorscheme, colorschemeName)
67 return errors.New(colorschemeName + " is not a valid colorscheme")
69 if data, err := file.Data(); err != nil {
70 return errors.New("Error loading colorscheme: " + err.Error())
72 Colorscheme, err = ParseColorscheme(string(data))
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
84 func ParseColorscheme(text string) (map[string]tcell.Style, error) {
86 parser := regexp.MustCompile(`color-link\s+(\S*)\s+"(.*)"`)
88 lines := strings.Split(text, "\n")
90 c := make(map[string]tcell.Style)
92 for _, line := range lines {
93 if strings.TrimSpace(line) == "" ||
94 strings.TrimSpace(line)[0] == '#' {
99 matches := parser.FindSubmatch([]byte(line))
100 if len(matches) == 3 {
101 link := string(matches[1])
102 colors := string(matches[2])
104 style := StringToStyle(colors)
107 if link == "default" {
111 err = errors.New("Color-link statement is not valid: " + line)
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, italic or underline
121 func StringToStyle(str string) tcell.Style {
123 spaceSplit := strings.Split(str, " ")
124 split := strings.Split(spaceSplit[len(spaceSplit)-1], ",")
126 fg, bg = split[0], split[1]
130 fg = strings.TrimSpace(fg)
131 bg = strings.TrimSpace(bg)
133 var fgColor, bgColor tcell.Color
135 if fg == "" || fg == "default" {
136 fgColor, _, _ = DefStyle.Decompose()
138 fgColor, ok = StringToColor(fg)
140 fgColor, _, _ = DefStyle.Decompose()
143 if bg == "" || bg == "default" {
144 _, bgColor, _ = DefStyle.Decompose()
146 bgColor, ok = StringToColor(bg)
148 _, bgColor, _ = DefStyle.Decompose()
152 style := DefStyle.Foreground(fgColor).Background(bgColor)
153 if strings.Contains(str, "bold") {
154 style = style.Bold(true)
156 if strings.Contains(str, "italic") {
157 style = style.Italic(true)
159 if strings.Contains(str, "reverse") {
160 style = style.Reverse(true)
162 if strings.Contains(str, "underline") {
163 style = style.Underline(true)
168 // StringToColor returns a tcell color from a string representation of a color
169 // We accept either bright... or light... to mean the brighter version of a color
170 func StringToColor(str string) (tcell.Color, bool) {
173 return tcell.ColorBlack, true
175 return tcell.ColorMaroon, true
177 return tcell.ColorGreen, true
179 return tcell.ColorOlive, true
181 return tcell.ColorNavy, true
183 return tcell.ColorPurple, true
185 return tcell.ColorTeal, true
187 return tcell.ColorSilver, true
188 case "brightblack", "lightblack":
189 return tcell.ColorGray, true
190 case "brightred", "lightred":
191 return tcell.ColorRed, true
192 case "brightgreen", "lightgreen":
193 return tcell.ColorLime, true
194 case "brightyellow", "lightyellow":
195 return tcell.ColorYellow, true
196 case "brightblue", "lightblue":
197 return tcell.ColorBlue, true
198 case "brightmagenta", "lightmagenta":
199 return tcell.ColorFuchsia, true
200 case "brightcyan", "lightcyan":
201 return tcell.ColorAqua, true
202 case "brightwhite", "lightwhite":
203 return tcell.ColorWhite, true
205 return tcell.ColorDefault, true
207 // Check if this is a 256 color
208 if num, err := strconv.Atoi(str); err == nil {
209 return GetColor256(num), true
211 // Check if this is a truecolor hex value
212 if len(str) == 7 && str[0] == '#' {
213 return tcell.GetColor(str), true
215 return tcell.ColorDefault, false
219 // GetColor256 returns the tcell color for a number between 0 and 255
220 func GetColor256(color int) tcell.Color {
222 return tcell.ColorDefault
224 return tcell.PaletteColor(color)