solarized-emacs

a fork of Bozhidar Batsov's solarized-emacs
git clone https://git.trogloxene.org/solarized-emacs.git
Log | Files | Refs | README

commit a160b9ba9ac4816683aae80168e3e66b0f3d6bfe
parent 4d43e82e8ae99dc4a56fc60ec9c41e1a2b35a545
Author: Thomas Frössman <thomasf@jossystem.se>
Date:   Sun, 17 Nov 2019 20:11:00 +0100

colorlab: split code into multiple go files.

Diffstat:
Mcolorlab/main.go | 531+++++++------------------------------------------------------------------------
Acolorlab/pkg/colorlab/hexcolor.go | 19+++++++++++++++++++
Acolorlab/pkg/colorlab/namedcolors.go | 159+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Acolorlab/pkg/colorlab/solarized.go | 277+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 500 insertions(+), 486 deletions(-)

diff --git a/colorlab/main.go b/colorlab/main.go @@ -3,21 +3,35 @@ package main import ( "bufio" "fmt" - "io" "io/ioutil" "log" "math" "os" - "sort" - "strconv" "strings" "bytes" + "github.com/bbatsov/solarized-emacs/colorlab/pkg/colorlab" "github.com/bbatsov/solarized-emacs/colorlab/pkg/colors" colorful "github.com/lucasb-eyer/go-colorful" ) +func main() { + + for _, pal := range palettes { + fmt.Println(pal.Name) + nc := pal.Generate() + + nc.PrintAlist(os.Stdout, 0) + // nc.FilterPrefix("base").PrintAlist(os.Stdout, 0) + // Merge(nc.FilterSuffix("-d"), oldDarkAccents.NamedColors().WithSuffix("-do")).PrintAlist(os.Stdout, 0) + // Merge(nc.FilterSuffix("-l"), oldLightAccents.NamedColors().WithSuffix("-lo")).PrintAlist(os.Stdout, 0) + + rewriteTheme(nc, pal.Name) + } + fmt.Println("\n-----\n") +} + var palettes = []Palette{ { Name: "solarized-dark", @@ -56,23 +70,7 @@ var palettes = []Palette{ }, } -func main() { - - for _, pal := range palettes { - fmt.Println(pal.Name) - nc := pal.Generate() - - nc.PrintAlist(os.Stdout, 0) - // nc.FilterPrefix("base").PrintAlist(os.Stdout, 0) - // Merge(nc.FilterSuffix("-d"), oldDarkAccents.NamedColors().WithSuffix("-do")).PrintAlist(os.Stdout, 0) - // Merge(nc.FilterSuffix("-l"), oldLightAccents.NamedColors().WithSuffix("-lo")).PrintAlist(os.Stdout, 0) - - rewriteTheme(nc, pal.Name) - } - fmt.Println("\n-----\n") -} - -func (p Palette) Generate() NamedColors { +func (p Palette) Generate() colorlab.NamedColors { pal := p.Solarized @@ -83,7 +81,7 @@ func (p Palette) Generate() NamedColors { bgs, fgs := createComplementaryColors(corrected, 0.85, 0.3, 0.01) hbgs, hfgs := createComplementaryColors(corrected, 0.6, 0.45, 0.04) - cols := Merge( + cols := colorlab.Merge( pal.NamedColors(), fgs.NamedColors().WithSuffix("-1fg"), bgs.NamedColors().WithSuffix("-1bg"), @@ -108,7 +106,7 @@ func (p Palette) Generate() NamedColors { } -func createComplementaryColors(sol Solarized, blendBg, blendFg, gamma float64) (accentBgs, accentFgs Accents) { +func createComplementaryColors(sol colorlab.Solarized, blendBg, blendFg, gamma float64) (accentBgs, accentFgs colorlab.Accents) { lightnessReport := false sol = sol.Clone() cs := sol.Accents.Colors() @@ -223,451 +221,12 @@ func createComplementaryColors(sol Solarized, blendBg, blendFg, gamma float64) ( if lightnessReport { fmt.Println("\n\n") } - return NewAccents(bgs), NewAccents(fgs) -} - -type Solarized struct { - Base - Accents - // AccentsBg Accents - // AccentsFg Accents -} - -func (s Solarized) Clone() Solarized { - return Solarized{ - Base: s.Base.Clone(), - Accents: s.Accents.Clone(), - // AccentsFg: s.AccentsFg, - // AccentsBg: s.AccentsBg, - } -} - -func (s Solarized) Inverse() Solarized { - return Solarized{ - Base: s.Base.Inverse(), - Accents: s.Accents.Clone(), - // AccentsFg: s.AccentsFg, - // AccentsBg: s.AccentsBg, - } -} -func (s Solarized) NamedColors() NamedColors { - return Merge(s.Base.NamedColors(), s.Accents.NamedColors()) - -} - -type HexColor string - -func (h HexColor) Color() colorful.Color { - col, err := colorful.Hex(string(h)) - if err != nil { - panic(err) - } - return col -} - -func (h HexColor) Blend(hc HexColor, t float64) HexColor { - c1 := h.Color() - c2 := hc.Color() - return HexColor(c1.BlendLab(c2, t).Hex()) -} - -type Base struct { - Base03 HexColor - Base02 HexColor - Base01 HexColor - Base00 HexColor - Base0 HexColor - Base1 HexColor - Base2 HexColor - Base3 HexColor -} - -func NewBase(bc [8]colorful.Color) Base { - return Base{ - Base03: HexColor(bc[0].Clamped().Hex()), - Base02: HexColor(bc[1].Clamped().Hex()), - Base01: HexColor(bc[2].Clamped().Hex()), - Base00: HexColor(bc[3].Clamped().Hex()), - Base0: HexColor(bc[4].Clamped().Hex()), - Base1: HexColor(bc[5].Clamped().Hex()), - Base2: HexColor(bc[6].Clamped().Hex()), - Base3: HexColor(bc[7].Clamped().Hex()), - } -} -func (s Base) Clone() Base { - return Base{ - Base03: s.Base03, - Base02: s.Base02, - Base01: s.Base01, - Base00: s.Base00, - Base0: s.Base0, - Base1: s.Base1, - Base2: s.Base2, - Base3: s.Base3, - } -} -func (s Base) NamedColors() NamedColors { - nc := make(NamedColors, 8) - arr := s.colorArray() - for idx, hex := range arr { - nc[baseNames[idx]] = hex - } - return nc -} - -func (s Base) Colors() BaseColors { - a := s.colorArray() - return [8]colorful.Color{ - a[0].Color(), - a[1].Color(), - a[2].Color(), - a[3].Color(), - a[4].Color(), - a[5].Color(), - a[6].Color(), - a[7].Color(), - } -} -func (s Base) colorArray() [8]HexColor { - return [8]HexColor{ - s.Base03, - s.Base02, - s.Base01, - s.Base00, - s.Base0, - s.Base1, - s.Base2, - s.Base3, - } -} - -var baseNames = [8]string{ - 0: "base03", - 1: "base02", - 2: "base01", - 3: "base00", - 4: "base0", - 5: "base1", - 6: "base2", - 7: "base3", -} - -type BaseColors [8]colorful.Color - -func (s Base) Inverse() Base { - return Base{ - Base03: s.Base3, - Base02: s.Base2, - Base01: s.Base1, - Base00: s.Base0, - Base0: s.Base00, - Base1: s.Base01, - Base2: s.Base02, - Base3: s.Base03, - } -} -func (b Base) ChangeLightness(amountFgs, amountBgs float64) Base { - cc := b.Colors() - lightness := func(c colorful.Color, v float64) colorful.Color { - l, a, b := c.Lab() - l = l + v - return colorful.Lab(l, a, b) - } - cc[0] = lightness(cc[0], amountBgs) - cc[1] = lightness(cc[1], amountBgs) - cc[2] = lightness(cc[2], amountFgs) - cc[3] = lightness(cc[3], amountBgs) - cc[4] = lightness(cc[4], amountFgs) - cc[5] = lightness(cc[5], amountFgs) - cc[6] = lightness(cc[6], amountFgs) - cc[7] = lightness(cc[7], amountFgs) - return NewBase(cc) -} - -// Accents . -type Accents struct { - Yellow HexColor - Orange HexColor - Red HexColor - Magenta HexColor - Violet HexColor - Blue HexColor - Cyan HexColor - Green HexColor -} - -func NewAccents(cc [8]colorful.Color) Accents { - return Accents{ - Yellow: HexColor(cc[0].Clamped().Hex()), - Orange: HexColor(cc[1].Clamped().Hex()), - Red: HexColor(cc[2].Clamped().Hex()), - Magenta: HexColor(cc[3].Clamped().Hex()), - Violet: HexColor(cc[4].Clamped().Hex()), - Blue: HexColor(cc[5].Clamped().Hex()), - Cyan: HexColor(cc[6].Clamped().Hex()), - Green: HexColor(cc[7].Clamped().Hex()), - } -} -func (s Accents) Clone() Accents { - return Accents{ - Yellow: s.Yellow, - Orange: s.Orange, - Red: s.Red, - Magenta: s.Magenta, - Violet: s.Violet, - Blue: s.Blue, - Cyan: s.Cyan, - Green: s.Green, - } -} - -func (s Accents) Colors() AccentColors { - a := s.colorArray() - return [8]colorful.Color{ - a[0].Color(), - a[1].Color(), - a[2].Color(), - a[3].Color(), - a[4].Color(), - a[5].Color(), - a[6].Color(), - a[7].Color(), - } -} -func (a Accents) ChangeLightness(amount float64) Accents { - cc := a.Colors() - lightness := func(c colorful.Color, v float64) colorful.Color { - l, a, b := c.Lab() - l = l + v - return colorful.Lab(l, a, b) - } - cc[0] = lightness(cc[0], amount) - cc[1] = lightness(cc[1], amount) - cc[2] = lightness(cc[2], amount) - cc[3] = lightness(cc[3], amount) - cc[4] = lightness(cc[4], amount) - cc[5] = lightness(cc[5], amount) - cc[6] = lightness(cc[6], amount) - cc[7] = lightness(cc[7], amount) - return NewAccents(cc) -} -func (a Accents) ChangeSaturation(amount float64) Accents { - cc := a.Colors() - saturation := func(c colorful.Color, v float64) colorful.Color { - h, s, l := c.Hsl() - // s = math.Min(math.Max(s+v, 0), 1) - s = s + v - return colorful.Hsl(h, s, l) - } - cc[0] = saturation(cc[0], amount) - cc[1] = saturation(cc[1], amount) - cc[2] = saturation(cc[2], amount) - cc[3] = saturation(cc[3], amount) - cc[4] = saturation(cc[4], amount) - cc[5] = saturation(cc[5], amount) - cc[6] = saturation(cc[6], amount) - cc[7] = saturation(cc[7], amount) - return NewAccents(cc) -} - -func (a Accents) Blend(hc HexColor, amount float64) Accents { - c := hc.Color() - cc := a.Colors() - cc[0] = cc[0].BlendLab(c, amount) - cc[1] = cc[1].BlendLab(c, amount) - cc[2] = cc[2].BlendLab(c, amount) - cc[3] = cc[3].BlendLab(c, amount) - cc[4] = cc[4].BlendLab(c, amount) - cc[5] = cc[5].BlendLab(c, amount) - cc[6] = cc[6].BlendLab(c, amount) - cc[7] = cc[7].BlendLab(c, amount) - return NewAccents(cc) -} - -func (ac Accents) NamedColors() NamedColors { - nc := make(NamedColors, 8) - arr := ac.colorArray() - for idx, hex := range arr { - nc[accentNames[idx]] = hex - } - return nc -} - -func (s Accents) colorArray() [8]HexColor { - return [8]HexColor{ - s.Yellow, - s.Orange, - s.Red, - s.Magenta, - s.Violet, - s.Blue, - s.Cyan, - s.Green, - } -} - -var accentNames = [8]string{ - 0: "yellow", - 1: "orange", - 2: "red", - 3: "magenta", - 4: "violet", - 5: "blue", - 6: "cyan", - 7: "green", -} - -type AccentColors [8]colorful.Color - -type NamedColors map[string]HexColor - -func (n NamedColors) WithPrefix(prefix string) NamedColors { - nc := make(NamedColors, len(n)) - for k, v := range n { - nc[fmt.Sprintf("%s%s", prefix, k)] = v - } - return nc -} - -func (n NamedColors) WithSuffix(suffix string) NamedColors { - nc := make(NamedColors, len(n)) - for k, v := range n { - nc[fmt.Sprintf("%s%s", k, suffix)] = v - } - return nc -} - -func (n NamedColors) FilterSuffix(suffix ...string) NamedColors { - nc := make(NamedColors, len(n)) - for k, v := range n { - loop: - for _, s := range suffix { - if strings.HasSuffix(k, s) { - nc[k] = v - break loop - } - } - } - return nc -} - -func (n NamedColors) FilterPrefix(prefix ...string) NamedColors { - nc := make(NamedColors, len(n)) - for k, v := range n { - loop: - for _, p := range prefix { - if strings.HasPrefix(k, p) { - nc[k] = v - break loop - } - } - } - return nc -} - -func (n NamedColors) PrintAlist(w io.Writer, indent int) (int, error) { - keys := n.OrderedKeys() - var longestKey int - for _, n := range keys { - l := len(n) - if l > longestKey { - longestKey = l - } - } - longestKey = longestKey - prefix := "" - for i := 0; i < indent; i++ { - prefix += " " - - } - var nt int - - for _, name := range keys { - n, err := fmt.Fprintf(w, "%s(%-"+strconv.Itoa(longestKey)+"s . \"%s\")\n", prefix, name, n[name]) - n = n + nt - if err != nil { - return nt, err - } - - } - return nt, nil -} - -// Orderedkeys returns the keys in a order that is like how solarized names should be ordered. -// -// primary orer is: -// -// 1. base names -// 2. accent colors -// 3. names that contain base names -// 4. names that contain accent color names -// 5. the rest -// -// secondary sort order is by string comparison. -// -func (n NamedColors) OrderedKeys() []string { - var names []string - for k, _ := range n { - names = append(names, k) - } - sort.Sort(sort.StringSlice(names)) - - var allNames []string - for _, n := range baseNames { - allNames = append(allNames, n) - } - for _, n := range accentNames { - allNames = append(allNames, n) - } - score := func(idx int, exact bool) int { - s := (len(allNames) - idx) + 1 - if exact { - s = s + len(allNames) - } - return s - } - sort.SliceStable(names, func(i int, j int) bool { - var is, js int // scores - in := names[i] - jn := names[j] - scoring: - for sortIdx, sortName := range allNames { - if is == 0 { - // log.Println(in, sortName) - if strings.Contains(in, sortName) { - is = score(sortIdx, in == sortName) - // fmt.Println("score in", in, sortName, is) - } - } - if js == 0 { - if strings.Contains(jn, sortName) { - js = score(sortIdx, jn == sortName) - // fmt.Println("score j", jn, sortName, js) - } - } - if is != 0 && js != 0 { - break scoring - } - } - // log.Println(is, js, in,jn) - return is > js - }) - return names -} - -func Merge(nc ...NamedColors) NamedColors { - res := make(NamedColors) - for _, nc := range nc { - for k, v := range nc { - res[k] = v - } - } - return res + return colorlab.NewAccents(bgs), colorlab.NewAccents(fgs) } var ( // The original solarized color palette - solarized = Solarized{ - Base: Base{ + solarized = colorlab.Solarized{ + Base: colorlab.Base{ Base03: colors.SolarizedBase03, Base02: colors.SolarizedBase02, Base01: colors.SolarizedBase01, @@ -677,7 +236,7 @@ var ( // The original solarized color palette Base2: colors.SolarizedBase2, Base3: colors.SolarizedBase3, }, - Accents: Accents{ + Accents: colorlab.Accents{ Blue: colors.SolarizedBlue, Cyan: colors.SolarizedCyan, Green: colors.SolarizedGreen, @@ -688,17 +247,17 @@ var ( // The original solarized color palette Yellow: colors.SolarizedYellow, }, } - solarizedDarkHighContrast = Solarized{ + solarizedDarkHighContrast = colorlab.Solarized{ Base: solarized.Base.Clone().ChangeLightness(0.04, -0.02), Accents: solarized.Accents.Clone().ChangeLightness(0.05), } - solarizedLightHighContrast = Solarized{ + solarizedLightHighContrast = colorlab.Solarized{ Base: solarized.Base.Clone().ChangeLightness(0.02, -0.05), Accents: solarized.Accents.Clone().ChangeLightness(-0.05), } // the current -d colors in the emacs theme - oldDarkAccents = Accents{ + oldDarkAccents = colorlab.Accents{ Blue: "#00629D", Cyan: "#00736F", Green: "#546E00", @@ -709,7 +268,7 @@ var ( // The original solarized color palette Yellow: "#7B6000", } // the current -l colors in the emacs theme - oldLightAccents = Accents{ + oldLightAccents = colorlab.Accents{ Blue: "#69B7F0", Cyan: "#69CABF", Green: "#B4C342", @@ -719,8 +278,8 @@ var ( // The original solarized color palette Violet: "#9EA0E5", Yellow: "#DEB542", } - gruvboxDark = Solarized{ - Base: Base{ + gruvboxDark = colorlab.Solarized{ + Base: colorlab.Base{ Base03: colors.GruvboxDark0, Base02: colors.GruvboxDark0Soft, Base01: colors.GruvboxDark4, @@ -730,7 +289,7 @@ var ( // The original solarized color palette Base2: colors.GruvboxLight4, Base3: colors.GruvboxLight0, }, - Accents: Accents{ + Accents: colorlab.Accents{ Blue: colors.GruvboxBlue, Cyan: colors.GruvboxAqua, Green: colors.GruvboxGreen, @@ -742,8 +301,8 @@ var ( // The original solarized color palette }, } // note: not inversed here - gruvboxLight = Solarized{ - Base: Base{ + gruvboxLight = colorlab.Solarized{ + Base: colorlab.Base{ Base03: colors.GruvboxDark0, Base02: colors.GruvboxDark0Soft, Base01: colors.GruvboxDark3, @@ -753,7 +312,7 @@ var ( // The original solarized color palette Base2: colors.GruvboxLight1, Base3: colors.GruvboxLight0, }, - Accents: Accents{ + Accents: colorlab.Accents{ Blue: colors.GruvboxDarkBlue, Cyan: colors.GruvboxAqua, Green: colors.GruvboxGreen, @@ -764,31 +323,31 @@ var ( // The original solarized color palette Yellow: colors.GruvboxDarkYellow, }, } - zenburn = Solarized{ - Base: Base{ + zenburn = colorlab.Solarized{ + Base: colorlab.Base{ Base03: colors.ZenburnBg, Base02: colors.ZenburnBgP1, - Base01: HexColor(colors.ZenburnFgM1).Blend(colors.ZenburnFg, 0.3), + Base01: colorlab.HexColor(colors.ZenburnFgM1).Blend(colors.ZenburnFg, 0.3), Base00: colors.ZenburnBgP3, Base0: colors.ZenburnFg, Base1: colors.ZenburnFgP1, - Base2: HexColor(colors.ZenburnFgP1).Blend(colors.ZenburnFgP2, 0.5), + Base2: colorlab.HexColor(colors.ZenburnFgP1).Blend(colors.ZenburnFgP2, 0.5), Base3: colors.ZenburnFgP2, }, - Accents: Accents{ + Accents: colorlab.Accents{ Blue: colors.ZenburnBlue, Cyan: colors.ZenburnCyan, Green: colors.ZenburnGreen, Magenta: colors.ZenburnMagenta, Orange: colors.ZenburnOrange, Red: colors.ZenburnRed, - Violet: HexColor(colors.ZenburnBlue).Blend(colors.ZenburnMagenta, 0.5), + Violet: colorlab.HexColor(colors.ZenburnBlue).Blend(colors.ZenburnMagenta, 0.5), Yellow: colors.ZenburnYellow, }, } - monokai = Solarized{ - Base: Base{ + monokai = colorlab.Solarized{ + Base: colorlab.Base{ Base03: colors.Monokai03, Base02: colors.Monokai02, Base01: colors.Monokai01, @@ -798,7 +357,7 @@ var ( // The original solarized color palette Base2: colors.Monokai0, Base3: colors.Monokai0, }, - Accents: Accents{ + Accents: colorlab.Accents{ Blue: colors.MonokaiBlue, Cyan: colors.MonokaiCyan, Green: colors.MonokaiGreen, @@ -815,10 +374,10 @@ var ( // The original solarized color palette type Palette struct { Name string Inverse bool - Solarized Solarized + Solarized colorlab.Solarized } -func rewriteTheme(nc NamedColors, paletteName string) { +func rewriteTheme(nc colorlab.NamedColors, paletteName string) { var dst bytes.Buffer diff --git a/colorlab/pkg/colorlab/hexcolor.go b/colorlab/pkg/colorlab/hexcolor.go @@ -0,0 +1,19 @@ +package colorlab + +import "github.com/lucasb-eyer/go-colorful" + +type HexColor string + +func (h HexColor) Color() colorful.Color { + col, err := colorful.Hex(string(h)) + if err != nil { + panic(err) + } + return col +} + +func (h HexColor) Blend(hc HexColor, t float64) HexColor { + c1 := h.Color() + c2 := hc.Color() + return HexColor(c1.BlendLab(c2, t).Hex()) +} diff --git a/colorlab/pkg/colorlab/namedcolors.go b/colorlab/pkg/colorlab/namedcolors.go @@ -0,0 +1,159 @@ +package colorlab + +import ( + "fmt" + "io" + "sort" + "strconv" + "strings" +) + +type NamedColors map[string]HexColor + +// WithPrefix returns a copuy of named colors where all keys are prefixed. +func (n NamedColors) WithPrefix(prefix string) NamedColors { + nc := make(NamedColors, len(n)) + for k, v := range n { + nc[fmt.Sprintf("%s%s", prefix, k)] = v + } + return nc +} + +// WithSuffix returns a copuy of named colors where all keys are suffixed. +func (n NamedColors) WithSuffix(suffix string) NamedColors { + nc := make(NamedColors, len(n)) + for k, v := range n { + nc[fmt.Sprintf("%s%s", k, suffix)] = v + } + return nc +} + +func (n NamedColors) FilterSuffix(suffix ...string) NamedColors { + nc := make(NamedColors, len(n)) + for k, v := range n { + loop: + for _, s := range suffix { + if strings.HasSuffix(k, s) { + nc[k] = v + break loop + } + } + } + return nc +} + +func (n NamedColors) FilterPrefix(prefix ...string) NamedColors { + nc := make(NamedColors, len(n)) + for k, v := range n { + loop: + for _, p := range prefix { + if strings.HasPrefix(k, p) { + nc[k] = v + break loop + } + } + } + return nc +} + +// PrintAlist prints the named colors list in a way that is compatible with solarized-palettes.el. +func (n NamedColors) PrintAlist(w io.Writer, indent int) (int, error) { + keys := n.OrderedKeys() + var longestKey int + for _, n := range keys { + l := len(n) + if l > longestKey { + longestKey = l + } + } + longestKey = longestKey + prefix := "" + for i := 0; i < indent; i++ { + prefix += " " + + } + var nt int + + for _, name := range keys { + n, err := fmt.Fprintf(w, "%s(%-"+strconv.Itoa(longestKey)+"s . \"%s\")\n", prefix, name, n[name]) + n = n + nt + if err != nil { + return nt, err + } + + } + return nt, nil +} + +// Orderedkeys returns the keys in a order that is like how solarized names should be ordered. +// +// primary orer is: +// +// 1. base names +// 2. accent colors +// 3. names that contain base names +// 4. names that contain accent color names +// 5. the rest +// +// secondary sort order is by string comparison. +// +func (n NamedColors) OrderedKeys() []string { + var names []string + for k, _ := range n { + names = append(names, k) + } + sort.Sort(sort.StringSlice(names)) + + var allNames []string + for _, n := range baseNames { + allNames = append(allNames, n) + } + for _, n := range accentNames { + allNames = append(allNames, n) + } + score := func(idx int, exact bool) int { + s := (len(allNames) - idx) + 1 + if exact { + s = s + len(allNames) + } + return s + } + sort.SliceStable(names, func(i int, j int) bool { + var is, js int // scores + in := names[i] + jn := names[j] + scoring: + for sortIdx, sortName := range allNames { + if is == 0 { + // log.Println(in, sortName) + if strings.Contains(in, sortName) { + is = score(sortIdx, in == sortName) + // fmt.Println("score in", in, sortName, is) + } + } + if js == 0 { + if strings.Contains(jn, sortName) { + js = score(sortIdx, jn == sortName) + // fmt.Println("score j", jn, sortName, js) + } + } + if is != 0 && js != 0 { + break scoring + } + } + // log.Println(is, js, in,jn) + return is > js + }) + return names +} + +// Merge merges multiple NamedColors +func Merge(nc ...NamedColors) NamedColors { + res := make(NamedColors) + for _, nc := range nc { + for k, v := range nc { + res[k] = v + } + } + return res +} diff --git a/colorlab/pkg/colorlab/solarized.go b/colorlab/pkg/colorlab/solarized.go @@ -0,0 +1,277 @@ +package colorlab + +import ( + "github.com/lucasb-eyer/go-colorful" +) + +type Solarized struct { + Base + Accents +} + +type Base struct { + Base03 HexColor + Base02 HexColor + Base01 HexColor + Base00 HexColor + Base0 HexColor + Base1 HexColor + Base2 HexColor + Base3 HexColor +} + +type BaseColors [8]colorful.Color + +// Accents . +type Accents struct { + Yellow HexColor + Orange HexColor + Red HexColor + Magenta HexColor + Violet HexColor + Blue HexColor + Cyan HexColor + Green HexColor +} + +type AccentColors [8]colorful.Color + +func (s Solarized) Clone() Solarized { + return Solarized{ + Base: s.Base.Clone(), + Accents: s.Accents.Clone(), + } +} + +func (s Solarized) Inverse() Solarized { + return Solarized{ + Base: s.Base.Inverse(), + Accents: s.Accents.Clone(), + } +} + +func (s Solarized) NamedColors() NamedColors { + return Merge(s.Base.NamedColors(), s.Accents.NamedColors()) + +} + +func NewBase(bc [8]colorful.Color) Base { + return Base{ + Base03: HexColor(bc[0].Clamped().Hex()), + Base02: HexColor(bc[1].Clamped().Hex()), + Base01: HexColor(bc[2].Clamped().Hex()), + Base00: HexColor(bc[3].Clamped().Hex()), + Base0: HexColor(bc[4].Clamped().Hex()), + Base1: HexColor(bc[5].Clamped().Hex()), + Base2: HexColor(bc[6].Clamped().Hex()), + Base3: HexColor(bc[7].Clamped().Hex()), + } +} +func (s Base) Clone() Base { + return Base{ + Base03: s.Base03, + Base02: s.Base02, + Base01: s.Base01, + Base00: s.Base00, + Base0: s.Base0, + Base1: s.Base1, + Base2: s.Base2, + Base3: s.Base3, + } +} +func (s Base) NamedColors() NamedColors { + nc := make(NamedColors, 8) + arr := s.colorArray() + for idx, hex := range arr { + nc[baseNames[idx]] = hex + } + return nc +} + +func (s Base) Colors() BaseColors { + a := s.colorArray() + return [8]colorful.Color{ + a[0].Color(), + a[1].Color(), + a[2].Color(), + a[3].Color(), + a[4].Color(), + a[5].Color(), + a[6].Color(), + a[7].Color(), + } +} +func (s Base) colorArray() [8]HexColor { + return [8]HexColor{ + s.Base03, + s.Base02, + s.Base01, + s.Base00, + s.Base0, + s.Base1, + s.Base2, + s.Base3, + } +} + +var baseNames = [8]string{ + 0: "base03", + 1: "base02", + 2: "base01", + 3: "base00", + 4: "base0", + 5: "base1", + 6: "base2", + 7: "base3", +} + +func (s Base) Inverse() Base { + return Base{ + Base03: s.Base3, + Base02: s.Base2, + Base01: s.Base1, + Base00: s.Base0, + Base0: s.Base00, + Base1: s.Base01, + Base2: s.Base02, + Base3: s.Base03, + } +} +func (b Base) ChangeLightness(amountFgs, amountBgs float64) Base { + cc := b.Colors() + lightness := func(c colorful.Color, v float64) colorful.Color { + l, a, b := c.Lab() + l = l + v + return colorful.Lab(l, a, b) + } + cc[0] = lightness(cc[0], amountBgs) + cc[1] = lightness(cc[1], amountBgs) + cc[2] = lightness(cc[2], amountFgs) + cc[3] = lightness(cc[3], amountBgs) + cc[4] = lightness(cc[4], amountFgs) + cc[5] = lightness(cc[5], amountFgs) + cc[6] = lightness(cc[6], amountFgs) + cc[7] = lightness(cc[7], amountFgs) + return NewBase(cc) +} + +func NewAccents(cc [8]colorful.Color) Accents { + return Accents{ + Yellow: HexColor(cc[0].Clamped().Hex()), + Orange: HexColor(cc[1].Clamped().Hex()), + Red: HexColor(cc[2].Clamped().Hex()), + Magenta: HexColor(cc[3].Clamped().Hex()), + Violet: HexColor(cc[4].Clamped().Hex()), + Blue: HexColor(cc[5].Clamped().Hex()), + Cyan: HexColor(cc[6].Clamped().Hex()), + Green: HexColor(cc[7].Clamped().Hex()), + } +} +func (s Accents) Clone() Accents { + return Accents{ + Yellow: s.Yellow, + Orange: s.Orange, + Red: s.Red, + Magenta: s.Magenta, + Violet: s.Violet, + Blue: s.Blue, + Cyan: s.Cyan, + Green: s.Green, + } +} + +func (s Accents) Colors() AccentColors { + a := s.colorArray() + return [8]colorful.Color{ + a[0].Color(), + a[1].Color(), + a[2].Color(), + a[3].Color(), + a[4].Color(), + a[5].Color(), + a[6].Color(), + a[7].Color(), + } +} +func (a Accents) ChangeLightness(amount float64) Accents { + cc := a.Colors() + lightness := func(c colorful.Color, v float64) colorful.Color { + l, a, b := c.Lab() + l = l + v + return colorful.Lab(l, a, b) + } + cc[0] = lightness(cc[0], amount) + cc[1] = lightness(cc[1], amount) + cc[2] = lightness(cc[2], amount) + cc[3] = lightness(cc[3], amount) + cc[4] = lightness(cc[4], amount) + cc[5] = lightness(cc[5], amount) + cc[6] = lightness(cc[6], amount) + cc[7] = lightness(cc[7], amount) + return NewAccents(cc) +} +func (a Accents) ChangeSaturation(amount float64) Accents { + cc := a.Colors() + saturation := func(c colorful.Color, v float64) colorful.Color { + h, s, l := c.Hsl() + // s = math.Min(math.Max(s+v, 0), 1) + s = s + v + return colorful.Hsl(h, s, l) + } + cc[0] = saturation(cc[0], amount) + cc[1] = saturation(cc[1], amount) + cc[2] = saturation(cc[2], amount) + cc[3] = saturation(cc[3], amount) + cc[4] = saturation(cc[4], amount) + cc[5] = saturation(cc[5], amount) + cc[6] = saturation(cc[6], amount) + cc[7] = saturation(cc[7], amount) + return NewAccents(cc) +} + +func (a Accents) Blend(hc HexColor, amount float64) Accents { + c := hc.Color() + cc := a.Colors() + cc[0] = cc[0].BlendLab(c, amount) + cc[1] = cc[1].BlendLab(c, amount) + cc[2] = cc[2].BlendLab(c, amount) + cc[3] = cc[3].BlendLab(c, amount) + cc[4] = cc[4].BlendLab(c, amount) + cc[5] = cc[5].BlendLab(c, amount) + cc[6] = cc[6].BlendLab(c, amount) + cc[7] = cc[7].BlendLab(c, amount) + return NewAccents(cc) +} + +func (ac Accents) NamedColors() NamedColors { + nc := make(NamedColors, 8) + arr := ac.colorArray() + for idx, hex := range arr { + nc[accentNames[idx]] = hex + } + return nc +} + +func (s Accents) colorArray() [8]HexColor { + return [8]HexColor{ + s.Yellow, + s.Orange, + s.Red, + s.Magenta, + s.Violet, + s.Blue, + s.Cyan, + s.Green, + } +} + +var accentNames = [8]string{ + 0: "yellow", + 1: "orange", + 2: "red", + 3: "magenta", + 4: "violet", + 5: "blue", + 6: "cyan", + 7: "green", +}