1package cointop 2 3import ( 4 "strconv" 5 6 fcolor "github.com/fatih/color" 7 gocui "github.com/miguelmota/gocui" 8 xtermcolor "github.com/tomnomnom/xtermcolor" 9) 10 11// TODO: fix hex color support 12 13// colorschemeColors is a map of color string names to Attribute types 14type colorschemeColors map[string]interface{} 15 16// ISprintf is a sprintf interface 17type ISprintf func(...interface{}) string 18 19// colorCache is a map of color string names to sprintf functions 20type colorCache map[string]ISprintf 21 22// Colorscheme is the struct for colorscheme 23type Colorscheme struct { 24 colors colorschemeColors 25 cache colorCache 26} 27 28var fgcolorschemeColorsMap = map[string]fcolor.Attribute{ 29 "black": fcolor.FgBlack, 30 "blue": fcolor.FgBlue, 31 "cyan": fcolor.FgCyan, 32 "green": fcolor.FgGreen, 33 "magenta": fcolor.FgMagenta, 34 "red": fcolor.FgRed, 35 "white": fcolor.FgWhite, 36 "yellow": fcolor.FgYellow, 37} 38 39var bgcolorschemeColorsMap = map[string]fcolor.Attribute{ 40 "black": fcolor.BgBlack, 41 "blue": fcolor.BgBlue, 42 "cyan": fcolor.BgCyan, 43 "green": fcolor.BgGreen, 44 "magenta": fcolor.BgMagenta, 45 "red": fcolor.BgRed, 46 "white": fcolor.BgWhite, 47 "yellow": fcolor.BgYellow, 48} 49 50var gocuiColorschemeColorsMap = map[string]gocui.Attribute{ 51 "black": gocui.ColorBlack, 52 "blue": gocui.ColorBlue, 53 "cyan": gocui.ColorCyan, 54 "green": gocui.ColorGreen, 55 "magenta": gocui.ColorMagenta, 56 "red": gocui.ColorRed, 57 "white": gocui.ColorWhite, 58 "yellow": gocui.ColorYellow, 59} 60 61// NewColorscheme ... 62func NewColorscheme(colors colorschemeColors) *Colorscheme { 63 return &Colorscheme{ 64 colors: colors, 65 cache: make(colorCache), 66 } 67} 68 69// BaseFg ... 70func (c *Colorscheme) BaseFg() gocui.Attribute { 71 return c.gocuiFgColor("base") 72} 73 74// BaseBg ... 75func (c *Colorscheme) BaseBg() gocui.Attribute { 76 return c.gocuiBgColor("base") 77} 78 79// Chart ... 80func (c *Colorscheme) Chart(a ...interface{}) string { 81 return c.color("chart", a...) 82} 83 84// Marketbar ... 85func (c *Colorscheme) Marketbar(a ...interface{}) string { 86 return c.color("marketbar", a...) 87} 88 89// MarketbarSprintf ... 90func (c *Colorscheme) MarketbarSprintf() ISprintf { 91 return c.toSprintf("marketbar") 92} 93 94// MarketbarChangeSprintf ... 95func (c *Colorscheme) MarketbarChangeSprintf() ISprintf { 96 // NOTE: reusing table styles 97 return c.toSprintf("table_column_change") 98} 99 100// MarketbarChangeDownSprintf ... 101func (c *Colorscheme) MarketbarChangeDownSprintf() ISprintf { 102 // NOTE: reusing table styles 103 return c.toSprintf("table_column_change_down") 104} 105 106// MarketbarChangeUpSprintf ... 107func (c *Colorscheme) MarketbarChangeUpSprintf() ISprintf { 108 // NOTE: reusing table styles 109 return c.toSprintf("table_column_change_up") 110} 111 112// MarketBarLabelActive ... 113func (c *Colorscheme) MarketBarLabelActive(a ...interface{}) string { 114 return c.color("marketbar_label_active", a...) 115} 116 117// Menu ... 118func (c *Colorscheme) Menu(a ...interface{}) string { 119 return c.color("menu", a...) 120} 121 122// MenuHeader ... 123func (c *Colorscheme) MenuHeader(a ...interface{}) string { 124 return c.color("menu_header", a...) 125} 126 127// MenuLabel ... 128func (c *Colorscheme) MenuLabel(a ...interface{}) string { 129 return c.color("menu_label", a...) 130} 131 132// MenuLabelActive ... 133func (c *Colorscheme) MenuLabelActive(a ...interface{}) string { 134 return c.color("menu_label_active", a...) 135} 136 137// Searchbar ... 138func (c *Colorscheme) Searchbar(a ...interface{}) string { 139 return c.color("searchbar", a...) 140} 141 142// Statusbar ... 143func (c *Colorscheme) Statusbar(a ...interface{}) string { 144 return c.color("statusbar", a...) 145} 146 147// TableColumnPrice ... 148func (c *Colorscheme) TableColumnPrice(a ...interface{}) string { 149 return c.color("table_column_price", a...) 150} 151 152// TableColumnPriceSprintf ... 153func (c *Colorscheme) TableColumnPriceSprintf() ISprintf { 154 return c.toSprintf("table_column_price") 155} 156 157// TableColumnChange ... 158func (c *Colorscheme) TableColumnChange(a ...interface{}) string { 159 return c.color("table_column_change", a...) 160} 161 162// TableColumnChangeSprintf ... 163func (c *Colorscheme) TableColumnChangeSprintf() ISprintf { 164 return c.toSprintf("table_column_change") 165} 166 167// TableColumnChangeDown ... 168func (c *Colorscheme) TableColumnChangeDown(a ...interface{}) string { 169 return c.color("table_column_change_down", a...) 170} 171 172// TableColumnChangeDownSprintf ... 173func (c *Colorscheme) TableColumnChangeDownSprintf() ISprintf { 174 return c.toSprintf("table_column_change_down") 175} 176 177// TableColumnChangeUp ... 178func (c *Colorscheme) TableColumnChangeUp(a ...interface{}) string { 179 return c.color("table_column_change_up", a...) 180} 181 182// TableColumnChangeUpSprintf ... 183func (c *Colorscheme) TableColumnChangeUpSprintf() ISprintf { 184 return c.toSprintf("table_column_change_up") 185} 186 187// TableHeader ... 188func (c *Colorscheme) TableHeader(a ...interface{}) string { 189 return c.color("table_header", a...) 190} 191 192// TableHeaderSprintf ... 193func (c *Colorscheme) TableHeaderSprintf() ISprintf { 194 return c.toSprintf("table_header") 195} 196 197// TableHeaderColumnActive ... 198func (c *Colorscheme) TableHeaderColumnActive(a ...interface{}) string { 199 return c.color("table_header_column_active", a...) 200} 201 202// TableHeaderColumnActiveSprintf ... 203func (c *Colorscheme) TableHeaderColumnActiveSprintf() ISprintf { 204 return c.toSprintf("table_header_column_active") 205} 206 207// TableRow ... 208func (c *Colorscheme) TableRow(a ...interface{}) string { 209 return c.color("table_row", a...) 210} 211 212// TableRowSprintf ... 213func (c *Colorscheme) TableRowSprintf() ISprintf { 214 return c.toSprintf("table_row") 215} 216 217// TableRowActive ... 218func (c *Colorscheme) TableRowActive(a ...interface{}) string { 219 return c.color("table_row_active", a...) 220} 221 222// TableRowFavorite ... 223func (c *Colorscheme) TableRowFavorite(a ...interface{}) string { 224 return c.color("table_row_favorite", a...) 225} 226 227// TableRowFavoriteSprintf ... 228func (c *Colorscheme) TableRowFavoriteSprintf() ISprintf { 229 return c.toSprintf("table_row_favorite") 230} 231 232// SetViewColor ... 233func (c *Colorscheme) SetViewColor(view *gocui.View, name string) { 234 view.FgColor = c.gocuiFgColor(name) 235 view.BgColor = c.gocuiBgColor(name) 236} 237 238// SetViewActiveColor ... 239func (c *Colorscheme) SetViewActiveColor(view *gocui.View, name string) { 240 view.SelFgColor = c.gocuiFgColor(name) 241 view.SelBgColor = c.gocuiBgColor(name) 242} 243 244func (c *Colorscheme) toSprintf(name string) ISprintf { 245 if cached, ok := c.cache[name]; ok { 246 return cached 247 } 248 249 var attrs []fcolor.Attribute 250 if v, ok := c.colors[name+"_fg"].(string); ok { 251 if fg, ok := c.toFgAttr(v); ok { 252 attrs = append(attrs, fg) 253 } 254 } 255 if v, ok := c.colors[name+"_bg"].(string); ok { 256 if bg, ok := c.toBgAttr(v); ok { 257 attrs = append(attrs, bg) 258 } 259 } 260 if v, ok := c.colors[name+"_bold"].(bool); ok { 261 if bold, ok := c.toBoldAttr(v); ok { 262 attrs = append(attrs, bold) 263 } 264 } 265 if v, ok := c.colors[name+"_underline"].(bool); ok { 266 if underline, ok := c.toUnderlineAttr(v); ok { 267 attrs = append(attrs, underline) 268 } 269 } 270 271 c.cache[name] = fcolor.New(attrs...).SprintFunc() 272 return c.cache[name] 273} 274 275func (c *Colorscheme) color(name string, a ...interface{}) string { 276 return c.toSprintf(name)(a...) 277} 278 279func (c *Colorscheme) gocuiFgColor(name string) gocui.Attribute { 280 if v, ok := c.colors[name+"_fg"].(string); ok { 281 if fg, ok := c.toGocuiAttr(v); ok { 282 return fg 283 } 284 } 285 286 return gocui.ColorDefault 287} 288 289func (c *Colorscheme) gocuiBgColor(name string) gocui.Attribute { 290 if v, ok := c.colors[name+"_bg"].(string); ok { 291 if bg, ok := c.toGocuiAttr(v); ok { 292 return bg 293 } 294 } 295 296 return gocui.ColorDefault 297} 298 299func (c *Colorscheme) toFgAttr(v string) (fcolor.Attribute, bool) { 300 if attr, ok := fgcolorschemeColorsMap[v]; ok { 301 return attr, true 302 } 303 304 if code, ok := HexToAnsi(v); ok { 305 return fcolor.Attribute(code), true 306 } 307 308 return 0, false 309} 310 311func (c *Colorscheme) toBgAttr(v string) (fcolor.Attribute, bool) { 312 if attr, ok := bgcolorschemeColorsMap[v]; ok { 313 return attr, true 314 } 315 316 if code, ok := HexToAnsi(v); ok { 317 return fcolor.Attribute(code), true 318 } 319 320 return 0, false 321} 322 323// toBoldAttr converts a boolean to an Attribute type 324func (c *Colorscheme) toBoldAttr(v bool) (fcolor.Attribute, bool) { 325 return fcolor.Bold, v 326} 327 328// toUnderlineAttr converts a boolean to an Attribute type 329func (c *Colorscheme) toUnderlineAttr(v bool) (fcolor.Attribute, bool) { 330 return fcolor.Underline, v 331} 332 333// toGocuiAttr converts a color string name to a gocui Attribute type 334func (c *Colorscheme) toGocuiAttr(v string) (gocui.Attribute, bool) { 335 if attr, ok := gocuiColorschemeColorsMap[v]; ok { 336 return attr, true 337 } 338 339 if code, ok := HexToAnsi(v); ok { 340 return gocui.Attribute(code), true 341 } 342 343 return 0, false 344} 345 346// HexToAnsi converts a hex color string to a uint8 ansi code 347func HexToAnsi(h string) (uint8, bool) { 348 if h == "" { 349 return 0, false 350 } 351 352 n, err := strconv.Atoi(h) 353 if err == nil { 354 if n <= 255 { 355 return uint8(n), true 356 } 357 } 358 359 code, err := xtermcolor.FromHexStr(h) 360 if err != nil { 361 return 0, false 362 } 363 364 return code, true 365} 366 367// gocui can use xterm colors 368