mirror of
https://github.com/jesseduffield/lazygit.git
synced 2025-02-01 13:17:53 +02:00
more efficient
This commit is contained in:
parent
117c0bd4f7
commit
0bc0e4ac88
@ -4,10 +4,33 @@ import (
|
|||||||
"github.com/gookit/color"
|
"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 {
|
type TextStyle struct {
|
||||||
fg *Color
|
fg *Color
|
||||||
bg *Color
|
bg *Color
|
||||||
decoration Decoration
|
decoration Decoration
|
||||||
|
|
||||||
|
style Sprinter
|
||||||
}
|
}
|
||||||
|
|
||||||
type Sprinter interface {
|
type Sprinter interface {
|
||||||
@ -15,74 +38,66 @@ type Sprinter interface {
|
|||||||
Sprintf(format string, a ...interface{}) string
|
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 {
|
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 {
|
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 {
|
func (b TextStyle) SetBold() TextStyle {
|
||||||
b.decoration.SetBold()
|
b.decoration.SetBold()
|
||||||
|
b.style = b.deriveStyle()
|
||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b TextStyle) SetUnderline() TextStyle {
|
func (b TextStyle) SetUnderline() TextStyle {
|
||||||
b.decoration.SetUnderline()
|
b.decoration.SetUnderline()
|
||||||
|
b.style = b.deriveStyle()
|
||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b TextStyle) SetReverse() TextStyle {
|
func (b TextStyle) SetReverse() TextStyle {
|
||||||
b.decoration.SetReverse()
|
b.decoration.SetReverse()
|
||||||
|
b.style = b.deriveStyle()
|
||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b TextStyle) deriveStyle() Sprinter {
|
func (b TextStyle) SetBg(color Color) TextStyle {
|
||||||
// TODO: consider caching
|
b.bg = &color
|
||||||
return deriveStyle(b.fg, b.bg, b.decoration)
|
b.style = b.deriveStyle()
|
||||||
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
func deriveStyle(fg *Color, bg *Color, decoration Decoration) Sprinter {
|
func (b TextStyle) SetFg(color Color) TextStyle {
|
||||||
if fg == nil && bg == nil {
|
b.fg = &color
|
||||||
return color.Style(decoration.ToOpts())
|
b.style = b.deriveStyle()
|
||||||
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
isRgb := (fg != nil && fg.IsRGB()) || (bg != nil && 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
|
|
||||||
}
|
|
||||||
|
|
||||||
style := make([]color.Color, 0, 5)
|
|
||||||
|
|
||||||
if fg != nil {
|
|
||||||
style = append(style, *fg.basic)
|
|
||||||
}
|
|
||||||
|
|
||||||
if bg != nil {
|
|
||||||
style = append(style, *bg.basic)
|
|
||||||
}
|
|
||||||
|
|
||||||
style = append(style, 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) MergeStyle(other TextStyle) TextStyle {
|
func (b TextStyle) MergeStyle(other TextStyle) TextStyle {
|
||||||
b.decoration = b.decoration.Merge(other.decoration)
|
b.decoration = b.decoration.Merge(other.decoration)
|
||||||
|
|
||||||
@ -94,5 +109,52 @@ func (b TextStyle) MergeStyle(other TextStyle) TextStyle {
|
|||||||
b.bg = other.bg
|
b.bg = other.bg
|
||||||
}
|
}
|
||||||
|
|
||||||
|
b.style = b.deriveStyle()
|
||||||
|
|
||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (b TextStyle) deriveStyle() Sprinter {
|
||||||
|
if b.fg == nil && b.bg == nil {
|
||||||
|
return color.Style(b.decoration.ToOpts())
|
||||||
|
}
|
||||||
|
|
||||||
|
isRgb := (b.fg != nil && b.fg.IsRGB()) || (b.bg != nil && b.bg.IsRGB())
|
||||||
|
if isRgb {
|
||||||
|
return b.deriveRGBStyle()
|
||||||
|
}
|
||||||
|
|
||||||
|
return b.deriveBasicStyle()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b TextStyle) deriveBasicStyle() color.Style {
|
||||||
|
style := make([]color.Color, 0, 5)
|
||||||
|
|
||||||
|
if b.fg != nil {
|
||||||
|
style = append(style, *b.fg.basic)
|
||||||
|
}
|
||||||
|
|
||||||
|
if b.bg != nil {
|
||||||
|
style = append(style, *b.bg.basic)
|
||||||
|
}
|
||||||
|
|
||||||
|
style = append(style, b.decoration.ToOpts()...)
|
||||||
|
|
||||||
|
return color.Style(style)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b TextStyle) deriveRGBStyle() *color.RGBStyle {
|
||||||
|
style := &color.RGBStyle{}
|
||||||
|
|
||||||
|
if b.fg != nil {
|
||||||
|
style.SetFg(*b.fg.ToRGB().rgb)
|
||||||
|
}
|
||||||
|
|
||||||
|
if b.bg != nil {
|
||||||
|
style.SetBg(*b.bg.ToRGB().rgb)
|
||||||
|
}
|
||||||
|
|
||||||
|
style.SetOpts(b.decoration.ToOpts())
|
||||||
|
|
||||||
|
return style
|
||||||
|
}
|
||||||
|
@ -19,17 +19,14 @@ func NewBasicColor(cl color.Color) Color {
|
|||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Color) IsRGB() bool {
|
func (c Color) IsRGB() bool {
|
||||||
return c.rgb != nil
|
return c.rgb != nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Color) ToRGB() Color {
|
func (c Color) ToRGB() Color {
|
||||||
if c.IsRGB() {
|
if c.IsRGB() {
|
||||||
return *c
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
rgb := c.basic.RGB()
|
return NewRGBColor(c.basic.RGB())
|
||||||
c.rgb = &rgb
|
|
||||||
|
|
||||||
return NewRGBColor(rgb)
|
|
||||||
}
|
}
|
||||||
|
@ -42,9 +42,11 @@ func (d Decoration) Merge(other Decoration) Decoration {
|
|||||||
if other.bold {
|
if other.bold {
|
||||||
d.bold = true
|
d.bold = true
|
||||||
}
|
}
|
||||||
|
|
||||||
if other.underline {
|
if other.underline {
|
||||||
d.underline = true
|
d.underline = true
|
||||||
}
|
}
|
||||||
|
|
||||||
if other.reverse {
|
if other.reverse {
|
||||||
d.reverse = true
|
d.reverse = true
|
||||||
}
|
}
|
||||||
|
@ -2,11 +2,9 @@ package style
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/gookit/color"
|
"github.com/gookit/color"
|
||||||
"github.com/jesseduffield/lazygit/pkg/utils"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
// FgWhite = New(pointerTo(color.FgWhite), nil)
|
|
||||||
FgWhite = FromBasicFg(color.FgWhite)
|
FgWhite = FromBasicFg(color.FgWhite)
|
||||||
FgLightWhite = FromBasicFg(color.FgLightWhite)
|
FgLightWhite = FromBasicFg(color.FgLightWhite)
|
||||||
FgBlack = FromBasicFg(color.FgBlack)
|
FgBlack = FromBasicFg(color.FgBlack)
|
||||||
@ -30,67 +28,3 @@ var (
|
|||||||
AttrUnderline = New().SetUnderline()
|
AttrUnderline = New().SetUnderline()
|
||||||
AttrBold = New().SetBold()
|
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
|
|
||||||
}
|
|
||||||
|
@ -42,13 +42,13 @@ var (
|
|||||||
|
|
||||||
// UpdateTheme updates all theme variables
|
// UpdateTheme updates all theme variables
|
||||||
func UpdateTheme(themeConfig config.ThemeConfig) {
|
func UpdateTheme(themeConfig config.ThemeConfig) {
|
||||||
ActiveBorderColor = GetGocuiColor(themeConfig.ActiveBorderColor)
|
ActiveBorderColor = GetGocuiStyle(themeConfig.ActiveBorderColor)
|
||||||
InactiveBorderColor = GetGocuiColor(themeConfig.InactiveBorderColor)
|
InactiveBorderColor = GetGocuiStyle(themeConfig.InactiveBorderColor)
|
||||||
SelectedLineBgColor = style.SetConfigStyles(themeConfig.SelectedLineBgColor, true)
|
SelectedLineBgColor = GetTextStyle(themeConfig.SelectedLineBgColor, true)
|
||||||
SelectedRangeBgColor = style.SetConfigStyles(themeConfig.SelectedRangeBgColor, true)
|
SelectedRangeBgColor = GetTextStyle(themeConfig.SelectedRangeBgColor, true)
|
||||||
GocuiSelectedLineBgColor = GetGocuiColor(themeConfig.SelectedLineBgColor)
|
GocuiSelectedLineBgColor = GetGocuiStyle(themeConfig.SelectedLineBgColor)
|
||||||
OptionsColor = GetGocuiColor(themeConfig.OptionsTextColor)
|
OptionsColor = GetGocuiStyle(themeConfig.OptionsTextColor)
|
||||||
OptionsFgColor = style.SetConfigStyles(themeConfig.OptionsTextColor, false)
|
OptionsFgColor = GetTextStyle(themeConfig.OptionsTextColor, false)
|
||||||
|
|
||||||
isLightTheme := themeConfig.LightTheme
|
isLightTheme := themeConfig.LightTheme
|
||||||
if isLightTheme {
|
if isLightTheme {
|
||||||
@ -90,11 +90,61 @@ func GetGocuiAttribute(key string) gocui.Attribute {
|
|||||||
return gocui.ColorWhite
|
return gocui.ColorWhite
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetGocuiColor bitwise OR's a list of attributes obtained via the given keys
|
// GetGocuiStyle bitwise OR's a list of attributes obtained via the given keys
|
||||||
func GetGocuiColor(keys []string) gocui.Attribute {
|
func GetGocuiStyle(keys []string) gocui.Attribute {
|
||||||
var attribute gocui.Attribute
|
var attribute gocui.Attribute
|
||||||
for _, key := range keys {
|
for _, key := range keys {
|
||||||
attribute |= GetGocuiAttribute(key)
|
attribute |= GetGocuiAttribute(key)
|
||||||
}
|
}
|
||||||
return attribute
|
return attribute
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var colorMap = map[string]struct {
|
||||||
|
foreground style.TextStyle
|
||||||
|
background style.TextStyle
|
||||||
|
}{
|
||||||
|
"default": {style.FgWhite, style.BgBlack},
|
||||||
|
"black": {style.FgBlack, style.BgBlack},
|
||||||
|
"red": {style.FgRed, style.BgRed},
|
||||||
|
"green": {style.FgGreen, style.BgGreen},
|
||||||
|
"yellow": {style.FgYellow, style.BgYellow},
|
||||||
|
"blue": {style.FgBlue, style.BgBlue},
|
||||||
|
"magenta": {style.FgMagenta, style.BgMagenta},
|
||||||
|
"cyan": {style.FgCyan, style.BgCyan},
|
||||||
|
"white": {style.FgWhite, style.BgWhite},
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetTextStyle(keys []string, background bool) style.TextStyle {
|
||||||
|
s := style.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 style.TextStyle
|
||||||
|
if background {
|
||||||
|
c = value.background
|
||||||
|
} else {
|
||||||
|
c = value.foreground
|
||||||
|
}
|
||||||
|
s = s.MergeStyle(c)
|
||||||
|
} else if utils.IsValidHexValue(key) {
|
||||||
|
c := style.NewRGBColor(color.HEX(key, background))
|
||||||
|
if background {
|
||||||
|
s.SetBg(c)
|
||||||
|
} else {
|
||||||
|
s.SetFg(c)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user