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:
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",
+}