commit 1f8f78f425cc6a2639e9cedd34ac5e420bcf2afc
parent 0f876b04ab4d934ad8f17a57afbd10e7aa5a1c48
Author: Thomas Frössman <thomasf@jossystem.se>
Date: Wed, 20 Nov 2019 15:18:15 +0100
colorlab: refactor
Diffstat:
18 files changed, 508 insertions(+), 479 deletions(-)
diff --git a/colorlab/README.md b/colorlab/README.md
@@ -15,3 +15,6 @@ internal tool under development.
The utility requires at least go 1.13
`go run main.go` will rewrite all palettes in `../solarized-palettes.el` when run.
+
+
+See https://godoc.org/github.com/bbatsov/solarized-emacs/colorlab
diff --git a/colorlab/main.go b/colorlab/main.go
@@ -5,14 +5,17 @@ import (
"bytes"
"flag"
"fmt"
+ "io"
"io/ioutil"
"log"
"os"
+ "strconv"
"strings"
"github.com/bbatsov/solarized-emacs/colorlab/pkg/colorlab"
"github.com/bbatsov/solarized-emacs/colorlab/pkg/colors"
"github.com/bbatsov/solarized-emacs/colorlab/pkg/generator"
+ sol "github.com/bbatsov/solarized-emacs/colorlab/pkg/solarized"
)
// Options are command line flags .
@@ -34,7 +37,7 @@ func main() {
for _, pal := range palettes {
fmt.Println(pal.Name)
nc := pal.Generate()
- nc.PrintAlist(os.Stdout, 0)
+ PrintAlist(os.Stdout, nc, 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)
@@ -51,16 +54,16 @@ var (
BlendForegroundAmout: 0.3,
Gamma: 0.01,
MinimumLightnessDifference: 0.35,
- ForegroundBlendFinder: colorlab.ExtremeColorFgFinder,
- BackgroundBlendFinder: colorlab.ExtremeColorBgFinder,
+ ForegroundBlendFinder: sol.ExtremeColorFgFinder,
+ BackgroundBlendFinder: sol.ExtremeColorBgFinder,
}
default2BgFg = generator.AccentPairGenerator{
BlendBackgroundAmout: 0.6,
BlendForegroundAmout: 0.45,
Gamma: 0.04,
MinimumLightnessDifference: 0.35,
- ForegroundBlendFinder: colorlab.ExtremeColorFgFinder,
- BackgroundBlendFinder: colorlab.ExtremeColorBgFinder,
+ ForegroundBlendFinder: sol.ExtremeColorFgFinder,
+ BackgroundBlendFinder: sol.ExtremeColorBgFinder,
}
palettes = []generator.Palette{
@@ -71,7 +74,7 @@ var (
BlendBackgroundAmout: default1BgFg.BlendBackgroundAmout,
BlendForegroundAmout: default1BgFg.BlendForegroundAmout,
Gamma: default1BgFg.Gamma,
- ForegroundBlendFinder: colorlab.NamedColorFinder("base1"),
+ ForegroundBlendFinder: sol.NamedColorFinder("base1"),
BackgroundBlendFinder: default1BgFg.BackgroundBlendFinder,
MinimumLightnessDifference: 0.4,
},
@@ -79,7 +82,7 @@ var (
BlendBackgroundAmout: default2BgFg.BlendBackgroundAmout,
BlendForegroundAmout: default2BgFg.BlendForegroundAmout,
Gamma: default2BgFg.Gamma,
- ForegroundBlendFinder: colorlab.NamedColorFinder("base1"),
+ ForegroundBlendFinder: sol.NamedColorFinder("base1"),
BackgroundBlendFinder: default2BgFg.BackgroundBlendFinder,
MinimumLightnessDifference: 0.4,
},
@@ -98,7 +101,7 @@ var (
BlendBackgroundAmout: default1BgFg.BlendBackgroundAmout,
BlendForegroundAmout: default1BgFg.BlendForegroundAmout,
Gamma: default1BgFg.Gamma,
- ForegroundBlendFinder: colorlab.NamedColorFinder("base1"),
+ ForegroundBlendFinder: sol.NamedColorFinder("base1"),
BackgroundBlendFinder: default1BgFg.BackgroundBlendFinder,
MinimumLightnessDifference: 0.4,
},
@@ -106,7 +109,7 @@ var (
BlendBackgroundAmout: default2BgFg.BlendBackgroundAmout,
BlendForegroundAmout: default2BgFg.BlendForegroundAmout,
Gamma: default2BgFg.Gamma,
- ForegroundBlendFinder: colorlab.NamedColorFinder("base1"),
+ ForegroundBlendFinder: sol.NamedColorFinder("base1"),
BackgroundBlendFinder: default2BgFg.BackgroundBlendFinder,
MinimumLightnessDifference: 0.4,
},
@@ -146,8 +149,8 @@ var (
}
// The original solarized color palette
- solarized = colorlab.Solarized{
- Base: colorlab.Base{
+ solarized = sol.Solarized{
+ Base: sol.Base{
Base03: colors.SolarizedBase03,
Base02: colors.SolarizedBase02,
Base01: colors.SolarizedBase01,
@@ -157,7 +160,7 @@ var (
Base2: colors.SolarizedBase2,
Base3: colors.SolarizedBase3,
},
- Accents: colorlab.Accents{
+ Accents: sol.Accents{
Blue: colors.SolarizedBlue,
Cyan: colors.SolarizedCyan,
Green: colors.SolarizedGreen,
@@ -168,17 +171,17 @@ var (
Yellow: colors.SolarizedYellow,
},
}
- solarizedDarkHighContrast = colorlab.Solarized{
+ solarizedDarkHighContrast = sol.Solarized{
Base: solarized.Base.Clone().ChangeLightness(0.04, -0.02),
Accents: solarized.Accents.Clone().ChangeLightness(0.05),
}
- solarizedLightHighContrast = colorlab.Solarized{
+ solarizedLightHighContrast = sol.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 = colorlab.Accents{
+ oldDarkAccents = sol.Accents{
Blue: "#00629D",
Cyan: "#00736F",
Green: "#546E00",
@@ -189,7 +192,7 @@ var (
Yellow: "#7B6000",
}
// the current -l colors in the emacs theme
- oldLightAccents = colorlab.Accents{
+ oldLightAccents = sol.Accents{
Blue: "#69B7F0",
Cyan: "#69CABF",
Green: "#B4C342",
@@ -199,8 +202,8 @@ var (
Violet: "#9EA0E5",
Yellow: "#DEB542",
}
- gruvboxDark = colorlab.Solarized{
- Base: colorlab.Base{
+ gruvboxDark = sol.Solarized{
+ Base: sol.Base{
Base03: colors.GruvboxDark0,
Base02: colors.GruvboxDark0Soft,
Base01: colors.GruvboxDark4,
@@ -210,7 +213,7 @@ var (
Base2: colors.GruvboxLight4,
Base3: colors.GruvboxLight0,
},
- Accents: colorlab.Accents{
+ Accents: sol.Accents{
Blue: colors.GruvboxBlue,
Cyan: colors.GruvboxAqua,
Green: colors.GruvboxGreen,
@@ -222,8 +225,8 @@ var (
},
}
// note: not inversed here
- gruvboxLight = colorlab.Solarized{
- Base: colorlab.Base{
+ gruvboxLight = sol.Solarized{
+ Base: sol.Base{
Base03: colors.GruvboxDark0,
Base02: colors.GruvboxDark0Soft,
Base01: colors.GruvboxDark3,
@@ -233,7 +236,7 @@ var (
Base2: colors.GruvboxLight1,
Base3: colors.GruvboxLight0,
},
- Accents: colorlab.Accents{
+ Accents: sol.Accents{
Blue: colors.GruvboxDarkBlue,
Cyan: colors.GruvboxAqua,
Green: colors.GruvboxGreen,
@@ -244,8 +247,8 @@ var (
Yellow: colors.GruvboxDarkYellow,
},
}
- zenburn = colorlab.Solarized{
- Base: colorlab.Base{
+ zenburn = sol.Solarized{
+ Base: sol.Base{
Base03: colors.ZenburnBg,
Base02: colors.ZenburnBgP1,
Base01: colorlab.HexColor(colors.ZenburnFgM1).Blend(colors.ZenburnFg, 0.3),
@@ -255,7 +258,7 @@ var (
Base2: colorlab.HexColor(colors.ZenburnFgP1).Blend(colors.ZenburnFgP2, 0.5),
Base3: colors.ZenburnFgP2,
},
- Accents: colorlab.Accents{
+ Accents: sol.Accents{
Blue: colors.ZenburnBlue,
Cyan: colors.ZenburnCyan,
Green: colors.ZenburnGreen,
@@ -267,8 +270,8 @@ var (
},
}
- monokai = colorlab.Solarized{
- Base: colorlab.Base{
+ monokai = sol.Solarized{
+ Base: sol.Base{
Base03: colors.Monokai03,
Base02: colors.Monokai02,
Base01: colors.Monokai01,
@@ -278,7 +281,7 @@ var (
Base2: colors.Monokai0,
Base3: colors.Monokai0,
},
- Accents: colorlab.Accents{
+ Accents: sol.Accents{
Blue: colors.MonokaiBlue,
Cyan: colors.MonokaiCyan,
Green: colors.MonokaiGreen,
@@ -315,7 +318,7 @@ func rewriteTheme(nc colorlab.NamedColors, paletteName string) {
}
if strings.HasSuffix(txt, fmt.Sprintf(";; %s palette", paletteName)) {
insideReplacement = true
- nc.PrintAlist(&dst, 4)
+ PrintAlist(&dst, nc, 4)
}
}
@@ -328,3 +331,32 @@ func rewriteTheme(nc colorlab.NamedColors, paletteName string) {
ioutil.WriteFile("../solarized-palettes.el", dst.Bytes(), 0x776)
}
+
+// PrintAlist prints the named colors list in a way that is compatible with solarized-palettes.el.
+func PrintAlist(w io.Writer, n colorlab.NamedColors, indent int) (int, error) {
+ keys := sol.OrderedKeys(n)
+ 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
+}
diff --git a/colorlab/pkg/colorlab/accents.go b/colorlab/pkg/colorlab/accents.go
@@ -1,138 +0,0 @@
-package colorlab
-
-import "github.com/lucasb-eyer/go-colorful"
-
-// 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 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",
-}
diff --git a/colorlab/pkg/colorlab/base.go b/colorlab/pkg/colorlab/base.go
@@ -1,137 +0,0 @@
-package colorlab
-
-import (
- "log"
-
- "github.com/lucasb-eyer/go-colorful"
-)
-
-type Base struct {
- Base03 HexColor
- Base02 HexColor
- Base01 HexColor
- Base00 HexColor
- Base0 HexColor
- Base1 HexColor
- Base2 HexColor
- Base3 HexColor
-}
-
-type BaseColors [8]colorful.Color
-
-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,
- }
-}
-
-// Returns true if the LAB lightness of base0 is larger than base03.
-func (b Base) IsDarkOnBright() bool {
- lightness := func(c colorful.Color) float64 {
- l, _, _ := c.Lab()
- return l
- }
- bg := b.Base03
- fg := b.Base0
- bgl := lightness(bg.Color())
- fgl := lightness(fg.Color())
- if fgl == bgl {
- log.Fatalf("bg (%v) and fg (%v) are not supposed to have equal lightness: %v %v", bg, fg, bgl, fgl)
- }
- return fgl > bgl
-}
-
-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)
-}
diff --git a/colorlab/pkg/colorlab/colrofinder.go b/colorlab/pkg/colorlab/colrofinder.go
@@ -1,50 +0,0 @@
-package colorlab
-
-import (
- "log"
-
- "github.com/lucasb-eyer/go-colorful"
-)
-
-// Find a specific color in a Solarized based on some preconditon
-type ColorFinder func(Solarized) colorful.Color
-
-// NamedColorFinder extracts a named color from a palette
-func NamedColorFinder(name string) ColorFinder {
- return func(sol Solarized) colorful.Color {
- colors := sol.NamedColors()
- c, ok := colors[name]
- if !ok {
- log.Fatalf("color %s not in list: %v", name, colors)
- }
- return c.Color()
- }
-}
-
-// BgFinder returns base03 from the input Solarized
-func BgFinder(sol Solarized) colorful.Color {
- return NamedColorFinder("base03")(sol)
-
-}
-
-// FgFinder finds base0 from the input Solarized
-func FgFinder(sol Solarized) colorful.Color {
- return NamedColorFinder("base0")(sol)
-
-}
-
-// ExtremeColorFgFinder finds the darkest base tone for light on dark or the lightest color for dark on light.
-func ExtremeColorFgFinder(sol Solarized) colorful.Color {
- if sol.IsDarkOnBright() {
- return sol.Base.NamedColors().ColorList().ByLightnessDesc()[0]
- }
- return sol.Base.NamedColors().ColorList().ByLightness()[0]
-}
-
-// ExtremeColorFgFinder finds the lightest base tone for light on dark or the darkest color for dark on light.
-func ExtremeColorBgFinder(sol Solarized) colorful.Color {
- if sol.IsDarkOnBright() {
- return sol.Base.NamedColors().ColorList().ByLightness()[0]
- }
- return sol.Base.NamedColors().ColorList().ByLightnessDesc()[0]
-}
diff --git a/colorlab/pkg/colorlab/namedcolors.go b/colorlab/pkg/colorlab/namedcolors.go
@@ -2,9 +2,6 @@ package colorlab
import (
"fmt"
- "io"
- "sort"
- "strconv"
"strings"
)
@@ -56,35 +53,6 @@ func (n NamedColors) FilterPrefix(prefix ...string) NamedColors {
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
-}
-
func (n NamedColors) ColorList() ColorList {
var res ColorList
for _, v := range n {
@@ -94,68 +62,6 @@ func (n NamedColors) ColorList() ColorList {
return res
}
-// 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)
diff --git a/colorlab/pkg/colorlab/package.go b/colorlab/pkg/colorlab/package.go
@@ -0,0 +1,2 @@
+// Package colorlab contains general utulities for working with palette colors
+package colorlab
diff --git a/colorlab/pkg/colorlab/solarized.go b/colorlab/pkg/colorlab/solarized.go
@@ -1,24 +0,0 @@
-package colorlab
-
-type Solarized struct {
- Base
- Accents
-}
-
-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())
-}
diff --git a/colorlab/pkg/colors/package.go b/colorlab/pkg/colors/package.go
@@ -0,0 +1,2 @@
+// Package colors contains color constants for various palettes
+package colors
diff --git a/colorlab/pkg/generator/accentpair.go b/colorlab/pkg/generator/accentpair.go
@@ -4,7 +4,8 @@ import (
"fmt"
"math"
- "github.com/bbatsov/solarized-emacs/colorlab/pkg/colorlab"
+ "github.com/bbatsov/solarized-emacs/colorlab/pkg/solarized"
+
"github.com/lucasb-eyer/go-colorful"
)
@@ -15,11 +16,11 @@ type AccentPairGenerator struct {
Gamma float64
MinimumLightnessDifference float64
- BackgroundBlendFinder colorlab.ColorFinder
- ForegroundBlendFinder colorlab.ColorFinder
+ BackgroundBlendFinder solarized.ColorFinder
+ ForegroundBlendFinder solarized.ColorFinder
}
-func (g *AccentPairGenerator) Generate(sol colorlab.Solarized) (backgrounds, foregrounds colorlab.Accents) {
+func (g *AccentPairGenerator) Generate(sol solarized.Solarized) (backgrounds, foregrounds solarized.Accents) {
lightnessReport := false
sol = sol.Clone()
cs := sol.Accents.Colors()
@@ -111,5 +112,5 @@ func (g *AccentPairGenerator) Generate(sol colorlab.Solarized) (backgrounds, for
if lightnessReport {
fmt.Println("\n\n")
}
- return colorlab.NewAccents(bgs), colorlab.NewAccents(fgs)
+ return solarized.NewAccents(bgs), solarized.NewAccents(fgs)
}
diff --git a/colorlab/pkg/generator/package.go b/colorlab/pkg/generator/package.go
@@ -0,0 +1,2 @@
+// Package generator contains utilities for enhancing a pallete with variations of colors
+package generator
diff --git a/colorlab/pkg/generator/palette.go b/colorlab/pkg/generator/palette.go
@@ -1,12 +1,15 @@
package generator
-import "github.com/bbatsov/solarized-emacs/colorlab/pkg/colorlab"
+import (
+ "github.com/bbatsov/solarized-emacs/colorlab/pkg/colorlab"
+ "github.com/bbatsov/solarized-emacs/colorlab/pkg/solarized"
+)
// Palette .
type Palette struct {
Name string
Inverse bool
- Solarized colorlab.Solarized
+ Solarized solarized.Solarized
Accent1Pair AccentPairGenerator
Accent2Pair AccentPairGenerator
diff --git a/colorlab/pkg/solarized/accents.go b/colorlab/pkg/solarized/accents.go
@@ -0,0 +1,141 @@
+package solarized
+
+import (
+ "github.com/bbatsov/solarized-emacs/colorlab/pkg/colorlab"
+ "github.com/lucasb-eyer/go-colorful"
+)
+
+// Accents .
+type Accents struct {
+ Yellow colorlab.HexColor
+ Orange colorlab.HexColor
+ Red colorlab.HexColor
+ Magenta colorlab.HexColor
+ Violet colorlab.HexColor
+ Blue colorlab.HexColor
+ Cyan colorlab.HexColor
+ Green colorlab.HexColor
+}
+
+type AccentColors [8]colorful.Color
+
+func NewAccents(cc [8]colorful.Color) Accents {
+ return Accents{
+ Yellow: colorlab.HexColor(cc[0].Clamped().Hex()),
+ Orange: colorlab.HexColor(cc[1].Clamped().Hex()),
+ Red: colorlab.HexColor(cc[2].Clamped().Hex()),
+ Magenta: colorlab.HexColor(cc[3].Clamped().Hex()),
+ Violet: colorlab.HexColor(cc[4].Clamped().Hex()),
+ Blue: colorlab.HexColor(cc[5].Clamped().Hex()),
+ Cyan: colorlab.HexColor(cc[6].Clamped().Hex()),
+ Green: colorlab.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 colorlab.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() colorlab.NamedColors {
+ nc := make(colorlab.NamedColors, 8)
+ arr := ac.colorArray()
+ for idx, hex := range arr {
+ nc[accentNames[idx]] = hex
+ }
+ return nc
+}
+
+func (s Accents) colorArray() [8]colorlab.HexColor {
+ return [8]colorlab.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",
+}
diff --git a/colorlab/pkg/solarized/base.go b/colorlab/pkg/solarized/base.go
@@ -0,0 +1,138 @@
+package solarized
+
+import (
+ "log"
+
+ "github.com/bbatsov/solarized-emacs/colorlab/pkg/colorlab"
+ "github.com/lucasb-eyer/go-colorful"
+)
+
+type Base struct {
+ Base03 colorlab.HexColor
+ Base02 colorlab.HexColor
+ Base01 colorlab.HexColor
+ Base00 colorlab.HexColor
+ Base0 colorlab.HexColor
+ Base1 colorlab.HexColor
+ Base2 colorlab.HexColor
+ Base3 colorlab.HexColor
+}
+
+type BaseColors [8]colorful.Color
+
+func NewBase(bc [8]colorful.Color) Base {
+ return Base{
+ Base03: colorlab.HexColor(bc[0].Clamped().Hex()),
+ Base02: colorlab.HexColor(bc[1].Clamped().Hex()),
+ Base01: colorlab.HexColor(bc[2].Clamped().Hex()),
+ Base00: colorlab.HexColor(bc[3].Clamped().Hex()),
+ Base0: colorlab.HexColor(bc[4].Clamped().Hex()),
+ Base1: colorlab.HexColor(bc[5].Clamped().Hex()),
+ Base2: colorlab.HexColor(bc[6].Clamped().Hex()),
+ Base3: colorlab.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() colorlab.NamedColors {
+ nc := make(colorlab.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]colorlab.HexColor {
+ return [8]colorlab.HexColor{
+ s.Base03,
+ s.Base02,
+ s.Base01,
+ s.Base00,
+ s.Base0,
+ s.Base1,
+ s.Base2,
+ s.Base3,
+ }
+}
+
+// Returns true if the LAB lightness of base0 is larger than base03.
+func (b Base) IsDarkOnBright() bool {
+ lightness := func(c colorful.Color) float64 {
+ l, _, _ := c.Lab()
+ return l
+ }
+ bg := b.Base03
+ fg := b.Base0
+ bgl := lightness(bg.Color())
+ fgl := lightness(fg.Color())
+ if fgl == bgl {
+ log.Fatalf("bg (%v) and fg (%v) are not supposed to have equal lightness: %v %v", bg, fg, bgl, fgl)
+ }
+ return fgl > bgl
+}
+
+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)
+}
diff --git a/colorlab/pkg/solarized/colorfinder.go b/colorlab/pkg/solarized/colorfinder.go
@@ -0,0 +1,50 @@
+package solarized
+
+import (
+ "log"
+
+ "github.com/lucasb-eyer/go-colorful"
+)
+
+// Find a specific color in a Solarized based on some preconditon
+type ColorFinder func(Solarized) colorful.Color
+
+// NamedColorFinder extracts a named color from a palette
+func NamedColorFinder(name string) ColorFinder {
+ return func(sol Solarized) colorful.Color {
+ colors := sol.NamedColors()
+ c, ok := colors[name]
+ if !ok {
+ log.Fatalf("color %s not in list: %v", name, colors)
+ }
+ return c.Color()
+ }
+}
+
+// BgFinder returns base03 from the input Solarized
+func BgFinder(sol Solarized) colorful.Color {
+ return NamedColorFinder("base03")(sol)
+
+}
+
+// FgFinder finds base0 from the input Solarized
+func FgFinder(sol Solarized) colorful.Color {
+ return NamedColorFinder("base0")(sol)
+
+}
+
+// ExtremeColorFgFinder finds the darkest base tone for light on dark or the lightest color for dark on light.
+func ExtremeColorFgFinder(sol Solarized) colorful.Color {
+ if sol.IsDarkOnBright() {
+ return sol.Base.NamedColors().ColorList().ByLightnessDesc()[0]
+ }
+ return sol.Base.NamedColors().ColorList().ByLightness()[0]
+}
+
+// ExtremeColorFgFinder finds the lightest base tone for light on dark or the darkest color for dark on light.
+func ExtremeColorBgFinder(sol Solarized) colorful.Color {
+ if sol.IsDarkOnBright() {
+ return sol.Base.NamedColors().ColorList().ByLightness()[0]
+ }
+ return sol.Base.NamedColors().ColorList().ByLightnessDesc()[0]
+}
diff --git a/colorlab/pkg/solarized/package.go b/colorlab/pkg/solarized/package.go
@@ -0,0 +1,2 @@
+// Package solarized contains functionality specific to the structure of a solarize palette
+package solarized
diff --git a/colorlab/pkg/solarized/solarized.go b/colorlab/pkg/solarized/solarized.go
@@ -0,0 +1,26 @@
+package solarized
+
+import "github.com/bbatsov/solarized-emacs/colorlab/pkg/colorlab"
+
+type Solarized struct {
+ Base
+ Accents
+}
+
+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() colorlab.NamedColors {
+ return colorlab.Merge(s.Base.NamedColors(), s.Accents.NamedColors())
+}
diff --git a/colorlab/pkg/solarized/sort.go b/colorlab/pkg/solarized/sort.go
@@ -0,0 +1,70 @@
+package solarized
+
+import (
+ "sort"
+ "strings"
+
+ "github.com/bbatsov/solarized-emacs/colorlab/pkg/colorlab"
+)
+
+// 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 OrderedKeys(n colorlab.NamedColors) []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
+}