summaryrefslogtreecommitdiffstats
path: root/pkg/gui/style
diff options
context:
space:
mode:
authorJesse Duffield <jessedduffield@gmail.com>2021-07-31 15:34:45 +1000
committerJesse Duffield <jessedduffield@gmail.com>2021-07-31 17:33:20 +1000
commit0bc0e4ac88f430976e4f2e69285ad6c56d94c137 (patch)
treea317e1f10ccdc111b3e2d71ca87ad47555b6118c /pkg/gui/style
parent117c0bd4f7adea7afb845107623b1b3d9b4e96fa (diff)
more efficient
Diffstat (limited to 'pkg/gui/style')
-rw-r--r--pkg/gui/style/basic.go136
-rw-r--r--pkg/gui/style/color.go11
-rw-r--r--pkg/gui/style/decoration.go2
-rw-r--r--pkg/gui/style/style.go66
4 files changed, 105 insertions, 110 deletions
diff --git a/pkg/gui/style/basic.go b/pkg/gui/style/basic.go
index 5cb1ec8aa..45652097e 100644
--- a/pkg/gui/style/basic.go
+++ b/pkg/gui/style/basic.go
@@ -4,10 +4,33 @@ import (
"github.com/gookit/color"
)
+// A TextStyle contains a foreground color, background color, and
+// decorations (bold/underline/reverse).
+//
+// Colors may each be either 16-bit or 256-bit RGB colors. When
+// we need to produce a string with a TextStyle, if either foreground or
+// background color is RGB, we'll promote the other color component to RGB as well.
+// We could simplify this code by forcing everything to be RGB, but we're not
+// sure how compatible or efficient that would be with various terminals.
+// Lazygit will typically stick to 16-bit colors, but users may configure RGB colors.
+//
+// TextStyles are value objects, not entities, so for example if you want to
+// add the bold decoration to a TextStyle, we'll create a new TextStyle with
+// that decoration applied.
+//
+// Decorations are additive, so when we merge two TextStyles, if either is bold
+// then the resulting style will also be bold.
+//
+// So that we aren't rederiving the underlying style each time we want to print
+// a string, we derive it when a new TextStyle is created and store it in the
+// `style` field.
+
type TextStyle struct {
fg *Color
bg *Color
decoration Decoration
+
+ style Sprinter
}
type Sprinter interface {
@@ -15,84 +38,123 @@ type Sprinter interface {
Sprintf(format string, a ...interface{}) string
}
+func New() TextStyle {
+ s := TextStyle{}
+ s.style = s.deriveStyle()
+ return s
+}
+
+func FromBasicFg(fg color.Color) TextStyle {
+ s := New()
+ c := NewBasicColor(fg)
+ s.fg = &c
+ s.style = s.deriveStyle()
+ return s
+}
+
+func FromBasicBg(bg color.Color) TextStyle {
+ s := New()
+ c := NewBasicColor(bg)
+ s.bg = &c
+ s.style = s.deriveStyle()
+ return s
+}
+
func (b TextStyle) Sprint(a ...interface{}) string {
- return b.deriveStyle().Sprint(a...)
+ return b.style.Sprint(a...)
}
func (b TextStyle) Sprintf(format string, a ...interface{}) string {
- return b.deriveStyle().Sprintf(format, a...)
+ return b.style.Sprintf(format, a...)
}
func (b TextStyle) SetBold() TextStyle {
b.decoration.SetBold()
+ b.style = b.deriveStyle()
return b
}
func (b TextStyle) SetUnderline() TextStyle {
b.decoration.SetUnderline()
+ b.style = b.deriveStyle()
return b
}
func (b TextStyle) SetReverse() TextStyle {
b.decoration.SetReverse()
+ b.style = b.deriveStyle()
return b
}
-func (b TextStyle) deriveStyle() Sprinter {
- // TODO: consider caching
- return deriveStyle(b.fg, b.bg, b.decoration)
+func (b TextStyle) SetBg(color Color) TextStyle {
+ b.bg = &color
+ b.style = b.deriveStyle()
+ return b
+}
+
+func (b TextStyle) SetFg(color Color) TextStyle {
+ b.fg = &color
+ b.style = b.deriveStyle()
+ return b
+}
+
+func (b TextStyle) MergeStyle(other TextStyle) TextStyle {
+ b.decoration = b.decoration.Merge(other.decoration)
+
+ if other.fg != nil {
+ b.fg = other.fg
+ }
+
+ if other.bg != nil {
+ b.bg = other.bg
+ }
+
+ b.style = b.deriveStyle()
+
+ return b
}
-func deriveStyle(fg *Color, bg *Color, decoration Decoration) Sprinter {
- if fg == nil && bg == nil {
- return color.Style(decoration.ToOpts())
+func (b TextStyle) deriveStyle() Sprinter {
+ if b.fg == nil && b.bg == nil {
+ return color.Style(b.decoration.ToOpts())
}
- isRgb := (fg != nil && fg.IsRGB()) || (bg != nil && bg.IsRGB())
+ isRgb := (b.fg != nil && b.fg.IsRGB()) || (b.bg != nil && b.bg.IsRGB())
if isRgb {
- s := &color.RGBStyle{}
- if fg != nil {
- s.SetFg(*fg.ToRGB().rgb)
- }
- if bg != nil {
- s.SetBg(*bg.ToRGB().rgb)
- }
- s.SetOpts(decoration.ToOpts())
- return s
+ return b.deriveRGBStyle()
}
+ return b.deriveBasicStyle()
+}
+
+func (b TextStyle) deriveBasicStyle() color.Style {
style := make([]color.Color, 0, 5)
- if fg != nil {
- style = append(style, *fg.basic)
+ if b.fg != nil {
+ style = append(style, *b.fg.basic)
}
- if bg != nil {
- style = append(style, *bg.basic)
+ if b.bg != nil {
+ style = append(style, *b.bg.basic)
}
- style = append(style, decoration.ToOpts()...)
+ style = append(style, b.decoration.ToOpts()...)
return color.Style(style)
}
-// // Need to convert bg to fg otherwise .RGB wont work
-// // for more info see https://github.com/gookit/color/issues/39
-// rgbBg := (*b.bg - 10).RGB()
-// rgbBg[3] = 1
-// *res.bg = rgbBg
-// res.style = *color.NewRGBStyle(*res.fg, rgbBg)
+func (b TextStyle) deriveRGBStyle() *color.RGBStyle {
+ style := &color.RGBStyle{}
-func (b TextStyle) MergeStyle(other TextStyle) TextStyle {
- b.decoration = b.decoration.Merge(other.decoration)
-
- if other.fg != nil {
- b.fg = other.fg
+ if b.fg != nil {
+ style.SetFg(*b.fg.ToRGB().rgb)
}
- if other.bg != nil {
- b.bg = other.bg
+ if b.bg != nil {
+ style.SetBg(*b.bg.ToRGB().rgb)
}
- return b
+ style.SetOpts(b.decoration.ToOpts())
+
+ return style
}
diff --git a/pkg/gui/style/color.go b/pkg/gui/style/color.go
index ddd8549aa..b2df21bbf 100644
--- a/pkg/gui/style/color.go
+++ b/pkg/gui/style/color.go
@@ -19,17 +19,14 @@ func NewBasicColor(cl color.Color) Color {
return c
}
-func (c *Color) IsRGB() bool {
+func (c Color) IsRGB() bool {
return c.rgb != nil
}
-func (c *Color) ToRGB() Color {
+func (c Color) ToRGB() Color {
if c.IsRGB() {
- return *c
+ return c
}
- rgb := c.basic.RGB()
- c.rgb = &rgb
-
- return NewRGBColor(rgb)
+ return NewRGBColor(c.basic.RGB())
}
diff --git a/pkg/gui/style/decoration.go b/pkg/gui/style/decoration.go
index 165a54084..51887fbdd 100644
--- a/pkg/gui/style/decoration.go
+++ b/pkg/gui/style/decoration.go
@@ -42,9 +42,11 @@ func (d Decoration) Merge(other Decoration) Decoration {
if other.bold {
d.bold = true
}
+
if other.underline {
d.underline = true
}
+
if other.reverse {
d.reverse = true
}
diff --git a/pkg/gui/style/style.go b/pkg/gui/style/style.go
index 5911546c7..d6c8149b2 100644
--- a/pkg/gui/style/style.go
+++ b/pkg/gui/style/style.go
@@ -2,11 +2,9 @@ package style
import (
"github.com/gookit/color"
- "github.com/jesseduffield/lazygit/pkg/utils"
)
var (
- // FgWhite = New(pointerTo(color.FgWhite), nil)
FgWhite = FromBasicFg(color.FgWhite)
FgLightWhite = FromBasicFg(color.FgLightWhite)
FgBlack = FromBasicFg(color.FgBlack)
@@ -30,67 +28,3 @@ var (
AttrUnderline = New().SetUnderline()
AttrBold = New().SetBold()
)
-
-func New() TextStyle {
- return TextStyle{}
-}
-
-func FromBasicFg(fg color.Color) TextStyle {
- s := New()
- c := NewBasicColor(fg)
- s.fg = &c
- return s
-}
-
-func FromBasicBg(bg color.Color) TextStyle {
- s := New()
- c := NewBasicColor(bg)
- s.bg = &c
- return s
-}
-
-var colorMap = map[string]struct {
- forground TextStyle
- background TextStyle
-}{
- "default": {FgWhite, BgBlack},
- "black": {FgBlack, BgBlack},
- "red": {FgRed, BgRed},
- "green": {FgGreen, BgGreen},
- "yellow": {FgYellow, BgYellow},
- "blue": {FgBlue, BgBlue},
- "magenta": {FgMagenta, BgMagenta},
- "cyan": {FgCyan, BgCyan},
- "white": {FgWhite, BgWhite},
-}
-
-func SetConfigStyles(keys []string, background bool) TextStyle {
- s := New()
-
- for _, key := range keys {
- switch key {
- case "bold":
- s = s.SetBold()
- case "reverse":
- s = s.SetReverse()
- case "underline":
- s = s.SetUnderline()
- default:
- value, present := colorMap[key]
- if present {
- var c TextStyle
- if background {
- c = value.background
- } else {
- c = value.forground
- }
- s = s.MergeStyle(c)
- } else if utils.IsValidHexValue(key) {
- c := NewRGBColor(color.HEX(key, background))
- s.bg = &c
- }
- }
- }
-
- return s
-}