Add a theme package providing all four catppuccin flavors (mocha, frappe, macchiato, latte) mapped to the xterm-256 palette. Themes are selected with -theme or the CTOP_THEME environment variable; -i inverts the flavor. Background slots use the terminal's native color for transparency (opt out with -solid / CTOP_SOLID), and termbox is switched to Output256 so colors render correctly. Replace hardcoded colors in the compact and single views with ctheme portrait slots.
218 lines
4.6 KiB
Go
218 lines
4.6 KiB
Go
package theme
|
|
|
|
import ui "github.com/gizak/termui"
|
|
|
|
type Flavor string
|
|
const (
|
|
Mocha Flavor = "mocha"
|
|
Frappe Flavor = "frappe"
|
|
Macchiato Flavor = "macchiato"
|
|
Latte Flavor = "latte"
|
|
)
|
|
|
|
func Flavors() []string { return []string{"mocha", "frappe", "macchiato", "latte"} }
|
|
|
|
func ParseFlavor(s string) (Flavor, bool) {
|
|
if s == "mocha" { return Mocha, true }
|
|
if s == "frappe" { return Frappe, true }
|
|
if s == "macchiato" { return Macchiato, true }
|
|
if s == "latte" { return Latte, true }
|
|
return "", false
|
|
}
|
|
|
|
var paletteMocha = map[string]int{
|
|
"rosewater": 224,
|
|
"flamingo": 224,
|
|
"pink": 218,
|
|
"mauve": 183,
|
|
"red": 211,
|
|
"maroon": 181,
|
|
"peach": 216,
|
|
"yellow": 223,
|
|
"green": 151,
|
|
"teal": 116,
|
|
"sky": 116,
|
|
"sapphire": 117,
|
|
"blue": 111,
|
|
"lavender": 147,
|
|
"text": 189,
|
|
"subtext1": 146,
|
|
"subtext0": 146,
|
|
"overlay2": 103,
|
|
"overlay1": 103,
|
|
"overlay0": 243,
|
|
"surface2": 241,
|
|
"surface1": 239,
|
|
"surface0": 237,
|
|
"base": 235,
|
|
"mantle": 234,
|
|
"crust": 233,
|
|
}
|
|
|
|
var paletteFrappe = map[string]int{
|
|
"rosewater": 224,
|
|
"flamingo": 217,
|
|
"pink": 218,
|
|
"mauve": 182,
|
|
"red": 174,
|
|
"maroon": 175,
|
|
"peach": 216,
|
|
"yellow": 186,
|
|
"green": 150,
|
|
"teal": 115,
|
|
"sky": 116,
|
|
"sapphire": 110,
|
|
"blue": 111,
|
|
"lavender": 147,
|
|
"text": 189,
|
|
"subtext1": 146,
|
|
"subtext0": 146,
|
|
"overlay2": 109,
|
|
"overlay1": 103,
|
|
"overlay0": 243,
|
|
"surface2": 60,
|
|
"surface1": 59,
|
|
"surface0": 239,
|
|
"base": 237,
|
|
"mantle": 236,
|
|
"crust": 235,
|
|
}
|
|
|
|
var paletteMacchiato = map[string]int{
|
|
"rosewater": 224,
|
|
"flamingo": 224,
|
|
"pink": 218,
|
|
"mauve": 183,
|
|
"red": 210,
|
|
"maroon": 211,
|
|
"peach": 216,
|
|
"yellow": 223,
|
|
"green": 150,
|
|
"teal": 116,
|
|
"sky": 116,
|
|
"sapphire": 116,
|
|
"blue": 111,
|
|
"lavender": 147,
|
|
"text": 189,
|
|
"subtext1": 146,
|
|
"subtext0": 146,
|
|
"overlay2": 103,
|
|
"overlay1": 103,
|
|
"overlay0": 243,
|
|
"surface2": 60,
|
|
"surface1": 240,
|
|
"surface0": 238,
|
|
"base": 236,
|
|
"mantle": 235,
|
|
"crust": 234,
|
|
}
|
|
|
|
var paletteLatte = map[string]int{
|
|
"rosewater": 174,
|
|
"flamingo": 174,
|
|
"pink": 176,
|
|
"mauve": 99,
|
|
"red": 161,
|
|
"maroon": 167,
|
|
"peach": 202,
|
|
"yellow": 172,
|
|
"green": 70,
|
|
"teal": 30,
|
|
"sky": 38,
|
|
"sapphire": 37,
|
|
"blue": 27,
|
|
"lavender": 69,
|
|
"text": 240,
|
|
"subtext1": 60,
|
|
"subtext0": 243,
|
|
"overlay2": 102,
|
|
"overlay1": 246,
|
|
"overlay0": 248,
|
|
"surface2": 249,
|
|
"surface1": 7,
|
|
"surface0": 252,
|
|
"base": 255,
|
|
"mantle": 255,
|
|
"crust": 254,
|
|
}
|
|
|
|
var palettes = map[Flavor]map[string]int{
|
|
Mocha: paletteMocha,
|
|
Frappe: paletteFrappe,
|
|
Macchiato: paletteMacchiato,
|
|
Latte: paletteLatte,
|
|
}
|
|
|
|
var slots = map[string]string{
|
|
"fg": "text",
|
|
"bg": "",
|
|
"block.bg": "",
|
|
"border.bg": "",
|
|
"border.fg": "overlay1",
|
|
"label.fg": "mauve",
|
|
"menu.text.fg": "text",
|
|
"menu.text.bg": "",
|
|
"menu.border.fg": "mauve",
|
|
"menu.label.fg": "mauve",
|
|
"header.fg": "crust",
|
|
"header.bg": "mauve",
|
|
"gauge.bar.bg": "teal",
|
|
"gauge.percent.fg": "text",
|
|
"linechart.axes.fg": "overlay1",
|
|
"linechart.line.fg": "blue",
|
|
"mbarchart.bar.bg": "teal",
|
|
"mbarchart.num.fg": "text",
|
|
"mbarchart.text.fg": "text",
|
|
"par.text.fg": "text",
|
|
"par.text.bg": "",
|
|
"par.text.hi": "crust",
|
|
"sparkline.line.fg": "blue",
|
|
"sparkline.title.fg": "subtext1",
|
|
"status.ok": "green",
|
|
"status.warn": "yellow",
|
|
"status.danger": "red",
|
|
"io.read": "teal",
|
|
"io.write": "peach",
|
|
"net.rx": "teal",
|
|
"net.tx": "peach",
|
|
}
|
|
|
|
var current = Mocha
|
|
var opaque = false
|
|
|
|
func Set(f Flavor) { current = f }
|
|
func Current() Flavor { return current }
|
|
|
|
// SetOpaque toggles whether background slots paint the flavor's base color
|
|
// (opaque) or leave the terminal background untouched (transparent).
|
|
func SetOpaque(v bool) { opaque = v }
|
|
|
|
func Color(name string) ui.Attribute {
|
|
if p, ok := palettes[current]; ok {
|
|
if idx, ok := p[name]; ok {
|
|
return ui.Attribute(idx + 1)
|
|
}
|
|
}
|
|
return ui.ColorDefault
|
|
}
|
|
|
|
func Attr(slot string) ui.Attribute {
|
|
if name, ok := slots[slot]; ok {
|
|
if name == "" && opaque {
|
|
return Color("base")
|
|
}
|
|
return Color(name)
|
|
}
|
|
return ui.ColorDefault
|
|
}
|
|
|
|
func BuildColorMap() map[string]ui.Attribute {
|
|
m := make(map[string]ui.Attribute, len(slots)+4)
|
|
for slot := range slots {
|
|
m[slot] = Attr(slot)
|
|
}
|
|
m["par.fg"] = Color("text")
|
|
m["par.label.bg"] = Color("surface0")
|
|
return m
|
|
}
|