m/fzf
1
0
mirror of https://github.com/junegunn/fzf.git synced 2025-11-15 06:43:47 -05:00

Revise color configuration

This commit is contained in:
Junegunn Choi
2025-10-01 00:00:54 +09:00
parent ce2200e908
commit e6ad01fb90
7 changed files with 372 additions and 292 deletions

View File

@@ -44,10 +44,10 @@ Non-matching items are displayed in a dimmed color by default, but you can
change it with the `--color hidden:...` option. change it with the `--color hidden:...` option.
```sh ```sh
fzf --raw --color hidden:red
fzf --raw --color hidden:red:strikethrough fzf --raw --color hidden:red:strikethrough
fzf --raw --color hidden:red:strikethrough:dim
# To unset the default 'dim' attribute, prefix the color spec with 'regular' fzf --raw --color hidden:red:strikethrough:dim:italic
fzf --raw --color hidden:regular:red:strikethrough
``` ```
#### Conditional actions for raw mode #### Conditional actions for raw mode
@@ -104,7 +104,37 @@ fzf --gutter ' ' --color gutter:reverse
As noted above, the `--gutter-raw CHAR` option was also added for customizing the gutter column in raw mode. As noted above, the `--gutter-raw CHAR` option was also added for customizing the gutter column in raw mode.
### Compatibility changes ### Breaking changes
#### Hiding the gutter column
In the previous versions, the recommended way to hide the gutter column was to
set `--color gutter:-1`. That's because the gutter column was just a space
character, reversed. But now that it's using a visible character (`▌`), applying
the default color is no longer enough to hide it. Instead, you can set it to
a space character.
```sh
# Hide the gutter column
fzf --gutter ' '
# Classic style
fzf --gutter ' ' --color gutter:reverse
```
#### `--color` option
In the previous versions, some elements had default style attributes applied and
you would have to explicitly unset them with `regular` attribute if you wanted
to reset them. This is no longer needed now, as the default style attributes
are applied only when you do not specify any color or style for that element.
```sh
# No 'dim', just red and italic.
fzf --ghost 'Type to search' --color ghost:red:italic
```
#### Compatibility changes
Starting with this release, fzf is built with Go 1.23. Support for some old OS versions has been dropped. Starting with this release, fzf is built with Go 1.23. Support for some old OS versions has been dropped.

View File

@@ -572,6 +572,7 @@ type Options struct {
Multi int Multi int
Ansi bool Ansi bool
Mouse bool Mouse bool
BaseTheme *tui.ColorTheme
Theme *tui.ColorTheme Theme *tui.ColorTheme
Black bool Black bool
Bold bool Bold bool
@@ -672,9 +673,9 @@ func defaultPreviewOpts(command string) previewOpts {
func defaultOptions() *Options { func defaultOptions() *Options {
var theme *tui.ColorTheme var theme *tui.ColorTheme
if os.Getenv("NO_COLOR") != "" { if os.Getenv("NO_COLOR") != "" {
theme = tui.NoColorTheme() theme = tui.NoColorTheme
} else { } else {
theme = tui.EmptyTheme() theme = tui.EmptyTheme
} }
return &Options{ return &Options{
@@ -1317,8 +1318,9 @@ func dupeTheme(theme *tui.ColorTheme) *tui.ColorTheme {
return &dupe return &dupe
} }
func parseTheme(defaultTheme *tui.ColorTheme, str string) (*tui.ColorTheme, error) { func parseTheme(defaultTheme *tui.ColorTheme, str string) (*tui.ColorTheme, *tui.ColorTheme, error) {
var err error var err error
var baseTheme *tui.ColorTheme
theme := dupeTheme(defaultTheme) theme := dupeTheme(defaultTheme)
rrggbb := regexp.MustCompile("^#[0-9a-fA-F]{6}$") rrggbb := regexp.MustCompile("^#[0-9a-fA-F]{6}$")
comma := regexp.MustCompile(`[\s,]+`) comma := regexp.MustCompile(`[\s,]+`)
@@ -1329,13 +1331,17 @@ func parseTheme(defaultTheme *tui.ColorTheme, str string) (*tui.ColorTheme, erro
} }
switch str { switch str {
case "dark": case "dark":
baseTheme = tui.Dark256
theme = dupeTheme(tui.Dark256) theme = dupeTheme(tui.Dark256)
case "light": case "light":
baseTheme = tui.Light256
theme = dupeTheme(tui.Light256) theme = dupeTheme(tui.Light256)
case "base16", "16": case "base16", "16":
baseTheme = tui.Default16
theme = dupeTheme(tui.Default16) theme = dupeTheme(tui.Default16)
case "bw", "no": case "bw", "no":
theme = tui.NoColorTheme() baseTheme = tui.NoColorTheme
theme = dupeTheme(tui.NoColorTheme)
default: default:
fail := func() { fail := func() {
// Let the code proceed to simplify the error handling // Let the code proceed to simplify the error handling
@@ -1514,7 +1520,7 @@ func parseTheme(defaultTheme *tui.ColorTheme, str string) (*tui.ColorTheme, erro
} }
} }
} }
return theme, err return baseTheme, theme, err
} }
func parseWalkerOpts(str string) (walkerOpts, error) { func parseWalkerOpts(str string) (walkerOpts, error) {
@@ -2649,11 +2655,15 @@ func parseOptions(index *int, opts *Options, allArgs []string) error {
case "--color": case "--color":
_, spec := optionalNextString() _, spec := optionalNextString()
if len(spec) == 0 { if len(spec) == 0 {
opts.Theme = tui.EmptyTheme() opts.Theme = tui.EmptyTheme
} else { } else {
if opts.Theme, err = parseTheme(opts.Theme, spec); err != nil { var baseTheme *tui.ColorTheme
if baseTheme, opts.Theme, err = parseTheme(opts.Theme, spec); err != nil {
return err return err
} }
if baseTheme != nil {
opts.BaseTheme = baseTheme
}
} }
case "--toggle-sort": case "--toggle-sort":
str, err := nextString("key name required") str, err := nextString("key name required")
@@ -2739,7 +2749,8 @@ func parseOptions(index *int, opts *Options, allArgs []string) error {
case "--no-mouse": case "--no-mouse":
opts.Mouse = false opts.Mouse = false
case "+c", "--no-color": case "+c", "--no-color":
opts.Theme = tui.NoColorTheme() opts.BaseTheme = tui.NoColorTheme
opts.Theme = tui.NoColorTheme
case "+2", "--no-256": case "+2", "--no-256":
opts.Theme = tui.Default16 opts.Theme = tui.Default16
case "--black": case "--black":
@@ -3616,23 +3627,6 @@ func postProcessOptions(opts *Options) error {
} }
} }
if opts.Bold {
theme := opts.Theme
boldify := func(c tui.ColorAttr) tui.ColorAttr {
dup := c
if (c.Attr & tui.AttrRegular) == 0 {
dup.Attr |= tui.BoldForce
}
return dup
}
theme.Current = boldify(theme.Current)
theme.CurrentMatch = boldify(theme.CurrentMatch)
theme.Prompt = boldify(theme.Prompt)
theme.Input = boldify(theme.Input)
theme.Cursor = boldify(theme.Cursor)
theme.Spinner = boldify(theme.Spinner)
}
// If --height option is not supported on the platform, just ignore it // If --height option is not supported on the platform, just ignore it
if !tui.IsLightRendererSupported() && opts.Height.size > 0 { if !tui.IsLightRendererSupported() && opts.Height.size > 0 {
opts.Height = heightSpec{} opts.Height = heightSpec{}

View File

@@ -300,8 +300,12 @@ func TestBind(t *testing.T) {
} }
func TestColorSpec(t *testing.T) { func TestColorSpec(t *testing.T) {
var base *tui.ColorTheme
theme := tui.Dark256 theme := tui.Dark256
dark, _ := parseTheme(theme, "dark") base, dark, _ := parseTheme(theme, "dark")
if *dark != *base {
t.Errorf("incorrect base theme returned")
}
if *dark != *theme { if *dark != *theme {
t.Errorf("colors should be equivalent") t.Errorf("colors should be equivalent")
} }
@@ -309,7 +313,10 @@ func TestColorSpec(t *testing.T) {
t.Errorf("point should not be equivalent") t.Errorf("point should not be equivalent")
} }
light, _ := parseTheme(theme, "dark,light") base, light, _ := parseTheme(theme, "dark,light")
if *light != *base {
t.Errorf("incorrect base theme returned")
}
if *light == *theme { if *light == *theme {
t.Errorf("should not be equivalent") t.Errorf("should not be equivalent")
} }
@@ -320,7 +327,7 @@ func TestColorSpec(t *testing.T) {
t.Errorf("point should not be equivalent") t.Errorf("point should not be equivalent")
} }
customized, _ := parseTheme(theme, "fg:231,bg:232") _, customized, _ := parseTheme(theme, "fg:231,bg:232")
if customized.Fg.Color != 231 || customized.Bg.Color != 232 { if customized.Fg.Color != 231 || customized.Bg.Color != 232 {
t.Errorf("color not customized") t.Errorf("color not customized")
} }
@@ -333,7 +340,7 @@ func TestColorSpec(t *testing.T) {
t.Errorf("colors should now be equivalent: %v, %v", tui.Dark256, customized) t.Errorf("colors should now be equivalent: %v, %v", tui.Dark256, customized)
} }
customized, _ = parseTheme(theme, "fg:231,dark bg:232") _, customized, _ = parseTheme(theme, "fg:231,dark bg:232")
if customized.Fg != tui.Dark256.Fg || customized.Bg == tui.Dark256.Bg { if customized.Fg != tui.Dark256.Fg || customized.Bg == tui.Dark256.Bg {
t.Errorf("color not customized") t.Errorf("color not customized")
} }

View File

@@ -1109,14 +1109,18 @@ func NewTerminal(opts *Options, eventBox *util.EventBox, executor *util.Executor
t.acceptNth = opts.AcceptNth(t.delimiter) t.acceptNth = opts.AcceptNth(t.delimiter)
} }
baseTheme := opts.BaseTheme
if baseTheme == nil {
baseTheme = renderer.DefaultTheme()
}
// This should be called before accessing tui.Color* // This should be called before accessing tui.Color*
tui.InitTheme(opts.Theme, renderer.DefaultTheme(), opts.Black, opts.InputBorderShape.Visible(), opts.HeaderBorderShape.Visible()) tui.InitTheme(opts.Theme, baseTheme, opts.Bold, opts.Black, opts.InputBorderShape.Visible(), opts.HeaderBorderShape.Visible())
// Gutter character // Gutter character
var gutterChar, gutterRawChar string var gutterChar, gutterRawChar string
if opts.Gutter != nil { if opts.Gutter != nil {
gutterChar = *opts.Gutter gutterChar = *opts.Gutter
} else if t.unicode && !t.theme.Gutter.Color.IsDefault() { } else if t.unicode {
gutterChar = "▌" gutterChar = "▌"
} else { } else {
gutterChar = " " gutterChar = " "
@@ -1125,7 +1129,7 @@ func NewTerminal(opts *Options, eventBox *util.EventBox, executor *util.Executor
if opts.GutterRaw != nil { if opts.GutterRaw != nil {
gutterRawChar = *opts.GutterRaw gutterRawChar = *opts.GutterRaw
} else if t.unicode && !t.theme.Gutter.Color.IsDefault() { } else if t.unicode {
gutterRawChar = "▖" gutterRawChar = "▖"
} else { } else {
gutterRawChar = ":" gutterRawChar = ":"

View File

@@ -2,30 +2,7 @@
package tui package tui
type Attr int32
func HasFullscreenRenderer() bool {
return false
}
var DefaultBorderShape = BorderRounded
func (a Attr) Merge(b Attr) Attr {
if b&AttrRegular > 0 {
// Only keep bold attribute set by the system
return (b &^ AttrRegular) | (a & BoldForce)
}
return (a &^ AttrRegular) | b
}
const ( const (
AttrUndefined = Attr(0)
AttrRegular = Attr(1 << 8)
AttrClear = Attr(1 << 9)
BoldForce = Attr(1 << 10)
FullBg = Attr(1 << 11)
Bold = Attr(1) Bold = Attr(1)
Dim = Attr(1 << 1) Dim = Attr(1 << 1)
Italic = Attr(1 << 2) Italic = Attr(1 << 2)
@@ -36,6 +13,12 @@ const (
StrikeThrough = Attr(1 << 7) StrikeThrough = Attr(1 << 7)
) )
func HasFullscreenRenderer() bool {
return false
}
var DefaultBorderShape = BorderRounded
func (r *FullscreenRenderer) Init() error { return nil } func (r *FullscreenRenderer) Init() error { return nil }
func (r *FullscreenRenderer) DefaultTheme() *ColorTheme { return nil } func (r *FullscreenRenderer) DefaultTheme() *ColorTheme { return nil }
func (r *FullscreenRenderer) Resize(maxHeightFunc func(int) int) {} func (r *FullscreenRenderer) Resize(maxHeightFunc func(int) int) {}

View File

@@ -36,8 +36,6 @@ func (p ColorPair) style() tcell.Style {
return style.Foreground(asTcellColor(p.Fg())).Background(asTcellColor(p.Bg())) return style.Foreground(asTcellColor(p.Fg())).Background(asTcellColor(p.Bg()))
} }
type Attr int32
type TcellWindow struct { type TcellWindow struct {
color bool color bool
windowType WindowType windowType WindowType
@@ -98,14 +96,6 @@ const (
Italic = Attr(tcell.AttrItalic) Italic = Attr(tcell.AttrItalic)
) )
const (
AttrUndefined = Attr(0)
AttrRegular = Attr(1 << 7)
AttrClear = Attr(1 << 8)
BoldForce = Attr(1 << 10)
FullBg = Attr(1 << 11)
)
func (r *FullscreenRenderer) Bell() { func (r *FullscreenRenderer) Bell() {
_screen.Beep() _screen.Beep()
} }
@@ -159,15 +149,6 @@ func (c Color) Style() tcell.Color {
} }
} }
func (a Attr) Merge(b Attr) Attr {
if b&AttrRegular > 0 {
// Only keep bold attribute set by the system
return (b &^ AttrRegular) | (a & BoldForce)
}
return (a &^ AttrRegular) | b
}
// handle the following as private members of FullscreenRenderer instance // handle the following as private members of FullscreenRenderer instance
// they are declared here to prevent introducing tcell library in non-windows builds // they are declared here to prevent introducing tcell library in non-windows builds
var ( var (

View File

@@ -8,6 +8,25 @@ import (
"github.com/rivo/uniseg" "github.com/rivo/uniseg"
) )
type Attr int32
const (
AttrUndefined = Attr(0)
AttrRegular = Attr(1 << 8)
AttrClear = Attr(1 << 9)
BoldForce = Attr(1 << 10)
FullBg = Attr(1 << 11)
)
func (a Attr) Merge(b Attr) Attr {
if b&AttrRegular > 0 {
// Only keep bold attribute set by the system
return (b &^ AttrRegular) | (a & BoldForce)
}
return (a &^ AttrRegular) | b
}
// Types of user action // Types of user action
// //
//go:generate stringer -type=EventType //go:generate stringer -type=EventType
@@ -275,6 +294,13 @@ func (a ColorAttr) IsColorDefined() bool {
return a.Color != colUndefined return a.Color != colUndefined
} }
func (a ColorAttr) IsAttrDefined() bool {
return a.Attr != AttrUndefined
}
func (a ColorAttr) IsUndefined() bool {
return !a.IsColorDefined() && !a.IsAttrDefined()
}
func NewColorAttr() ColorAttr { func NewColorAttr() ColorAttr {
return ColorAttr{Color: colUndefined, Attr: AttrUndefined} return ColorAttr{Color: colUndefined, Attr: AttrUndefined}
} }
@@ -779,9 +805,11 @@ func NewFullscreenRenderer(theme *ColorTheme, forceBlack bool, mouse bool) Rende
} }
var ( var (
Default16 *ColorTheme NoColorTheme *ColorTheme
Dark256 *ColorTheme EmptyTheme *ColorTheme
Light256 *ColorTheme Default16 *ColorTheme
Dark256 *ColorTheme
Light256 *ColorTheme
ColPrompt ColorPair ColPrompt ColorPair
ColNormal ColorPair ColNormal ColorPair
@@ -825,121 +853,120 @@ var (
ColInputLabel ColorPair ColInputLabel ColorPair
) )
func EmptyTheme() *ColorTheme {
return &ColorTheme{
Colored: true,
Input: ColorAttr{colUndefined, AttrUndefined},
Fg: ColorAttr{colUndefined, AttrUndefined},
Bg: ColorAttr{colUndefined, AttrUndefined},
ListFg: ColorAttr{colUndefined, AttrUndefined},
ListBg: ColorAttr{colUndefined, AttrUndefined},
AltBg: ColorAttr{colUndefined, AttrUndefined},
SelectedFg: ColorAttr{colUndefined, AttrUndefined},
SelectedBg: ColorAttr{colUndefined, AttrUndefined},
SelectedMatch: ColorAttr{colUndefined, AttrUndefined},
DarkBg: ColorAttr{colUndefined, AttrUndefined},
Prompt: ColorAttr{colUndefined, AttrUndefined},
Match: ColorAttr{colUndefined, AttrUndefined},
Current: ColorAttr{colUndefined, AttrUndefined},
CurrentMatch: ColorAttr{colUndefined, AttrUndefined},
Spinner: ColorAttr{colUndefined, AttrUndefined},
Info: ColorAttr{colUndefined, AttrUndefined},
Cursor: ColorAttr{colUndefined, AttrUndefined},
Marker: ColorAttr{colUndefined, AttrUndefined},
Header: ColorAttr{colUndefined, AttrUndefined},
Footer: ColorAttr{colUndefined, AttrUndefined},
Border: ColorAttr{colUndefined, AttrUndefined},
BorderLabel: ColorAttr{colUndefined, AttrUndefined},
ListLabel: ColorAttr{colUndefined, AttrUndefined},
ListBorder: ColorAttr{colUndefined, AttrUndefined},
Ghost: ColorAttr{colUndefined, Dim},
Disabled: ColorAttr{colUndefined, AttrUndefined},
PreviewFg: ColorAttr{colUndefined, AttrUndefined},
PreviewBg: ColorAttr{colUndefined, AttrUndefined},
Gutter: ColorAttr{colUndefined, AttrUndefined},
PreviewBorder: ColorAttr{colUndefined, AttrUndefined},
PreviewScrollbar: ColorAttr{colUndefined, AttrUndefined},
PreviewLabel: ColorAttr{colUndefined, AttrUndefined},
Separator: ColorAttr{colUndefined, AttrUndefined},
Scrollbar: ColorAttr{colUndefined, AttrUndefined},
InputBg: ColorAttr{colUndefined, AttrUndefined},
InputBorder: ColorAttr{colUndefined, AttrUndefined},
InputLabel: ColorAttr{colUndefined, AttrUndefined},
HeaderBg: ColorAttr{colUndefined, AttrUndefined},
HeaderBorder: ColorAttr{colUndefined, AttrUndefined},
HeaderLabel: ColorAttr{colUndefined, AttrUndefined},
FooterBg: ColorAttr{colUndefined, AttrUndefined},
FooterBorder: ColorAttr{colUndefined, AttrUndefined},
FooterLabel: ColorAttr{colUndefined, AttrUndefined},
GapLine: ColorAttr{colUndefined, AttrUndefined},
Nth: ColorAttr{colUndefined, AttrUndefined},
Hidden: ColorAttr{colUndefined, Dim},
}
}
func NoColorTheme() *ColorTheme {
return &ColorTheme{
Colored: false,
Input: ColorAttr{colDefault, AttrUndefined},
Fg: ColorAttr{colDefault, AttrUndefined},
Bg: ColorAttr{colDefault, AttrUndefined},
ListFg: ColorAttr{colDefault, AttrUndefined},
ListBg: ColorAttr{colDefault, AttrUndefined},
AltBg: ColorAttr{colUndefined, AttrUndefined},
SelectedFg: ColorAttr{colDefault, AttrUndefined},
SelectedBg: ColorAttr{colDefault, AttrUndefined},
SelectedMatch: ColorAttr{colDefault, AttrUndefined},
DarkBg: ColorAttr{colDefault, AttrUndefined},
Prompt: ColorAttr{colDefault, AttrUndefined},
Match: ColorAttr{colDefault, Underline},
Current: ColorAttr{colDefault, Reverse},
CurrentMatch: ColorAttr{colDefault, Reverse | Underline},
Spinner: ColorAttr{colDefault, AttrUndefined},
Info: ColorAttr{colDefault, AttrUndefined},
Cursor: ColorAttr{colDefault, AttrUndefined},
Marker: ColorAttr{colDefault, AttrUndefined},
Header: ColorAttr{colDefault, AttrUndefined},
Border: ColorAttr{colDefault, AttrUndefined},
BorderLabel: ColorAttr{colDefault, AttrUndefined},
Ghost: ColorAttr{colDefault, Dim},
Disabled: ColorAttr{colDefault, AttrUndefined},
PreviewFg: ColorAttr{colDefault, AttrUndefined},
PreviewBg: ColorAttr{colDefault, AttrUndefined},
Gutter: ColorAttr{colDefault, AttrUndefined},
PreviewBorder: ColorAttr{colDefault, AttrUndefined},
PreviewScrollbar: ColorAttr{colDefault, AttrUndefined},
PreviewLabel: ColorAttr{colDefault, AttrUndefined},
ListLabel: ColorAttr{colDefault, AttrUndefined},
ListBorder: ColorAttr{colDefault, AttrUndefined},
Separator: ColorAttr{colDefault, AttrUndefined},
Scrollbar: ColorAttr{colDefault, AttrUndefined},
InputBg: ColorAttr{colDefault, AttrUndefined},
InputBorder: ColorAttr{colDefault, AttrUndefined},
InputLabel: ColorAttr{colDefault, AttrUndefined},
HeaderBg: ColorAttr{colDefault, AttrUndefined},
HeaderBorder: ColorAttr{colDefault, AttrUndefined},
HeaderLabel: ColorAttr{colDefault, AttrUndefined},
FooterBg: ColorAttr{colDefault, AttrUndefined},
FooterBorder: ColorAttr{colDefault, AttrUndefined},
FooterLabel: ColorAttr{colDefault, AttrUndefined},
GapLine: ColorAttr{colDefault, AttrUndefined},
Nth: ColorAttr{colUndefined, AttrUndefined},
Hidden: ColorAttr{colUndefined, Dim},
}
}
func init() { func init() {
defaultColor := ColorAttr{colDefault, AttrUndefined}
undefined := ColorAttr{colUndefined, AttrUndefined}
NoColorTheme = &ColorTheme{
Colored: false,
Input: defaultColor,
Fg: defaultColor,
Bg: defaultColor,
ListFg: defaultColor,
ListBg: defaultColor,
AltBg: undefined,
SelectedFg: defaultColor,
SelectedBg: defaultColor,
SelectedMatch: defaultColor,
DarkBg: defaultColor,
Prompt: defaultColor,
Match: defaultColor,
Current: undefined,
CurrentMatch: undefined,
Spinner: defaultColor,
Info: defaultColor,
Cursor: defaultColor,
Marker: defaultColor,
Header: defaultColor,
Border: undefined,
BorderLabel: defaultColor,
Ghost: undefined,
Disabled: defaultColor,
PreviewFg: defaultColor,
PreviewBg: defaultColor,
Gutter: undefined,
PreviewBorder: defaultColor,
PreviewScrollbar: defaultColor,
PreviewLabel: defaultColor,
ListLabel: defaultColor,
ListBorder: defaultColor,
Separator: defaultColor,
Scrollbar: defaultColor,
InputBg: defaultColor,
InputBorder: defaultColor,
InputLabel: defaultColor,
HeaderBg: defaultColor,
HeaderBorder: defaultColor,
HeaderLabel: defaultColor,
FooterBg: defaultColor,
FooterBorder: defaultColor,
FooterLabel: defaultColor,
GapLine: defaultColor,
Nth: undefined,
Hidden: undefined,
}
EmptyTheme = &ColorTheme{
Colored: true,
Input: undefined,
Fg: undefined,
Bg: undefined,
ListFg: undefined,
ListBg: undefined,
AltBg: undefined,
SelectedFg: undefined,
SelectedBg: undefined,
SelectedMatch: undefined,
DarkBg: undefined,
Prompt: undefined,
Match: undefined,
Current: undefined,
CurrentMatch: undefined,
Spinner: undefined,
Info: undefined,
Cursor: undefined,
Marker: undefined,
Header: undefined,
Footer: undefined,
Border: undefined,
BorderLabel: undefined,
ListLabel: undefined,
ListBorder: undefined,
Ghost: undefined,
Disabled: undefined,
PreviewFg: undefined,
PreviewBg: undefined,
Gutter: undefined,
PreviewBorder: undefined,
PreviewScrollbar: undefined,
PreviewLabel: undefined,
Separator: undefined,
Scrollbar: undefined,
InputBg: undefined,
InputBorder: undefined,
InputLabel: undefined,
HeaderBg: undefined,
HeaderBorder: undefined,
HeaderLabel: undefined,
FooterBg: undefined,
FooterBorder: undefined,
FooterLabel: undefined,
GapLine: undefined,
Nth: undefined,
Hidden: undefined,
}
Default16 = &ColorTheme{ Default16 = &ColorTheme{
Colored: true, Colored: true,
Input: ColorAttr{colDefault, AttrUndefined}, Input: defaultColor,
Fg: ColorAttr{colDefault, AttrUndefined}, Fg: defaultColor,
Bg: ColorAttr{colDefault, AttrUndefined}, Bg: defaultColor,
ListFg: ColorAttr{colUndefined, AttrUndefined}, ListFg: undefined,
ListBg: ColorAttr{colUndefined, AttrUndefined}, ListBg: undefined,
AltBg: ColorAttr{colUndefined, AttrUndefined}, AltBg: undefined,
SelectedFg: ColorAttr{colUndefined, AttrUndefined}, SelectedFg: undefined,
SelectedBg: ColorAttr{colUndefined, AttrUndefined}, SelectedBg: undefined,
SelectedMatch: ColorAttr{colUndefined, AttrUndefined}, SelectedMatch: undefined,
DarkBg: ColorAttr{colGrey, AttrUndefined}, DarkBg: ColorAttr{colGrey, AttrUndefined},
Prompt: ColorAttr{colBlue, AttrUndefined}, Prompt: ColorAttr{colBlue, AttrUndefined},
Match: ColorAttr{colGreen, AttrUndefined}, Match: ColorAttr{colGreen, AttrUndefined},
@@ -951,44 +978,45 @@ func init() {
Marker: ColorAttr{colMagenta, AttrUndefined}, Marker: ColorAttr{colMagenta, AttrUndefined},
Header: ColorAttr{colCyan, AttrUndefined}, Header: ColorAttr{colCyan, AttrUndefined},
Footer: ColorAttr{colCyan, AttrUndefined}, Footer: ColorAttr{colCyan, AttrUndefined},
Border: ColorAttr{colDefault, Dim}, Border: undefined,
BorderLabel: ColorAttr{colDefault, AttrUndefined}, BorderLabel: defaultColor,
Ghost: ColorAttr{colUndefined, Dim}, Ghost: undefined,
Disabled: ColorAttr{colUndefined, AttrUndefined}, Disabled: undefined,
PreviewFg: ColorAttr{colUndefined, AttrUndefined}, PreviewFg: undefined,
PreviewBg: ColorAttr{colUndefined, AttrUndefined}, PreviewBg: undefined,
Gutter: ColorAttr{colUndefined, AttrUndefined}, Gutter: undefined,
PreviewBorder: ColorAttr{colUndefined, AttrUndefined}, PreviewBorder: undefined,
PreviewScrollbar: ColorAttr{colUndefined, AttrUndefined}, PreviewScrollbar: undefined,
PreviewLabel: ColorAttr{colUndefined, AttrUndefined}, PreviewLabel: undefined,
ListLabel: ColorAttr{colUndefined, AttrUndefined}, ListLabel: undefined,
ListBorder: ColorAttr{colUndefined, AttrUndefined}, ListBorder: undefined,
Separator: ColorAttr{colUndefined, AttrUndefined}, Separator: undefined,
Scrollbar: ColorAttr{colUndefined, AttrUndefined}, Scrollbar: undefined,
InputBg: ColorAttr{colUndefined, AttrUndefined}, InputBg: undefined,
InputBorder: ColorAttr{colUndefined, AttrUndefined}, InputBorder: undefined,
InputLabel: ColorAttr{colUndefined, AttrUndefined}, InputLabel: undefined,
HeaderBg: ColorAttr{colUndefined, AttrUndefined}, HeaderBg: undefined,
HeaderBorder: ColorAttr{colUndefined, AttrUndefined}, HeaderBorder: undefined,
HeaderLabel: ColorAttr{colUndefined, AttrUndefined}, HeaderLabel: undefined,
FooterBg: ColorAttr{colUndefined, AttrUndefined}, FooterBg: undefined,
FooterBorder: ColorAttr{colUndefined, AttrUndefined}, FooterBorder: undefined,
FooterLabel: ColorAttr{colUndefined, AttrUndefined}, FooterLabel: undefined,
GapLine: ColorAttr{colUndefined, AttrUndefined}, GapLine: undefined,
Nth: ColorAttr{colUndefined, AttrUndefined}, Nth: undefined,
Hidden: ColorAttr{colUndefined, Dim}, Hidden: undefined,
} }
Dark256 = &ColorTheme{ Dark256 = &ColorTheme{
Colored: true, Colored: true,
Input: ColorAttr{colDefault, AttrUndefined}, Input: defaultColor,
Fg: ColorAttr{colDefault, AttrUndefined}, Fg: defaultColor,
Bg: ColorAttr{colDefault, AttrUndefined}, Bg: defaultColor,
ListFg: ColorAttr{colUndefined, AttrUndefined}, ListFg: undefined,
ListBg: ColorAttr{colUndefined, AttrUndefined}, ListBg: undefined,
AltBg: ColorAttr{colUndefined, AttrUndefined}, AltBg: undefined,
SelectedFg: ColorAttr{colUndefined, AttrUndefined}, SelectedFg: undefined,
SelectedBg: ColorAttr{colUndefined, AttrUndefined}, SelectedBg: undefined,
SelectedMatch: ColorAttr{colUndefined, AttrUndefined}, SelectedMatch: undefined,
DarkBg: ColorAttr{236, AttrUndefined}, DarkBg: ColorAttr{236, AttrUndefined},
Prompt: ColorAttr{110, AttrUndefined}, Prompt: ColorAttr{110, AttrUndefined},
Match: ColorAttr{108, AttrUndefined}, Match: ColorAttr{108, AttrUndefined},
@@ -1002,42 +1030,43 @@ func init() {
Footer: ColorAttr{109, AttrUndefined}, Footer: ColorAttr{109, AttrUndefined},
Border: ColorAttr{59, AttrUndefined}, Border: ColorAttr{59, AttrUndefined},
BorderLabel: ColorAttr{145, AttrUndefined}, BorderLabel: ColorAttr{145, AttrUndefined},
Ghost: ColorAttr{colUndefined, Dim}, Ghost: undefined,
Disabled: ColorAttr{colUndefined, AttrUndefined}, Disabled: undefined,
PreviewFg: ColorAttr{colUndefined, AttrUndefined}, PreviewFg: undefined,
PreviewBg: ColorAttr{colUndefined, AttrUndefined}, PreviewBg: undefined,
Gutter: ColorAttr{colUndefined, AttrUndefined}, Gutter: undefined,
PreviewBorder: ColorAttr{colUndefined, AttrUndefined}, PreviewBorder: undefined,
PreviewScrollbar: ColorAttr{colUndefined, AttrUndefined}, PreviewScrollbar: undefined,
PreviewLabel: ColorAttr{colUndefined, AttrUndefined}, PreviewLabel: undefined,
ListLabel: ColorAttr{colUndefined, AttrUndefined}, ListLabel: undefined,
ListBorder: ColorAttr{colUndefined, AttrUndefined}, ListBorder: undefined,
Separator: ColorAttr{colUndefined, AttrUndefined}, Separator: undefined,
Scrollbar: ColorAttr{colUndefined, AttrUndefined}, Scrollbar: undefined,
InputBg: ColorAttr{colUndefined, AttrUndefined}, InputBg: undefined,
InputBorder: ColorAttr{colUndefined, AttrUndefined}, InputBorder: undefined,
InputLabel: ColorAttr{colUndefined, AttrUndefined}, InputLabel: undefined,
HeaderBg: ColorAttr{colUndefined, AttrUndefined}, HeaderBg: undefined,
HeaderBorder: ColorAttr{colUndefined, AttrUndefined}, HeaderBorder: undefined,
HeaderLabel: ColorAttr{colUndefined, AttrUndefined}, HeaderLabel: undefined,
FooterBg: ColorAttr{colUndefined, AttrUndefined}, FooterBg: undefined,
FooterBorder: ColorAttr{colUndefined, AttrUndefined}, FooterBorder: undefined,
FooterLabel: ColorAttr{colUndefined, AttrUndefined}, FooterLabel: undefined,
GapLine: ColorAttr{colUndefined, AttrUndefined}, GapLine: undefined,
Nth: ColorAttr{colUndefined, AttrUndefined}, Nth: undefined,
Hidden: ColorAttr{colUndefined, Dim}, Hidden: undefined,
} }
Light256 = &ColorTheme{ Light256 = &ColorTheme{
Colored: true, Colored: true,
Input: ColorAttr{colDefault, AttrUndefined}, Input: defaultColor,
Fg: ColorAttr{colDefault, AttrUndefined}, Fg: defaultColor,
Bg: ColorAttr{colDefault, AttrUndefined}, Bg: defaultColor,
ListFg: ColorAttr{colUndefined, AttrUndefined}, ListFg: undefined,
ListBg: ColorAttr{colUndefined, AttrUndefined}, ListBg: undefined,
AltBg: ColorAttr{colUndefined, AttrUndefined}, AltBg: undefined,
SelectedFg: ColorAttr{colUndefined, AttrUndefined}, SelectedFg: undefined,
SelectedBg: ColorAttr{colUndefined, AttrUndefined}, SelectedBg: undefined,
SelectedMatch: ColorAttr{colUndefined, AttrUndefined}, SelectedMatch: undefined,
DarkBg: ColorAttr{251, AttrUndefined}, DarkBg: ColorAttr{251, AttrUndefined},
Prompt: ColorAttr{25, AttrUndefined}, Prompt: ColorAttr{25, AttrUndefined},
Match: ColorAttr{66, AttrUndefined}, Match: ColorAttr{66, AttrUndefined},
@@ -1051,34 +1080,34 @@ func init() {
Footer: ColorAttr{31, AttrUndefined}, Footer: ColorAttr{31, AttrUndefined},
Border: ColorAttr{145, AttrUndefined}, Border: ColorAttr{145, AttrUndefined},
BorderLabel: ColorAttr{59, AttrUndefined}, BorderLabel: ColorAttr{59, AttrUndefined},
Ghost: ColorAttr{colUndefined, Dim}, Ghost: undefined,
Disabled: ColorAttr{colUndefined, AttrUndefined}, Disabled: undefined,
PreviewFg: ColorAttr{colUndefined, AttrUndefined}, PreviewFg: undefined,
PreviewBg: ColorAttr{colUndefined, AttrUndefined}, PreviewBg: undefined,
Gutter: ColorAttr{colUndefined, AttrUndefined}, Gutter: undefined,
PreviewBorder: ColorAttr{colUndefined, AttrUndefined}, PreviewBorder: undefined,
PreviewScrollbar: ColorAttr{colUndefined, AttrUndefined}, PreviewScrollbar: undefined,
PreviewLabel: ColorAttr{colUndefined, AttrUndefined}, PreviewLabel: undefined,
ListLabel: ColorAttr{colUndefined, AttrUndefined}, ListLabel: undefined,
ListBorder: ColorAttr{colUndefined, AttrUndefined}, ListBorder: undefined,
Separator: ColorAttr{colUndefined, AttrUndefined}, Separator: undefined,
Scrollbar: ColorAttr{colUndefined, AttrUndefined}, Scrollbar: undefined,
InputBg: ColorAttr{colUndefined, AttrUndefined}, InputBg: undefined,
InputBorder: ColorAttr{colUndefined, AttrUndefined}, InputBorder: undefined,
InputLabel: ColorAttr{colUndefined, AttrUndefined}, InputLabel: undefined,
HeaderBg: ColorAttr{colUndefined, AttrUndefined}, HeaderBg: undefined,
HeaderBorder: ColorAttr{colUndefined, AttrUndefined}, HeaderBorder: undefined,
HeaderLabel: ColorAttr{colUndefined, AttrUndefined}, HeaderLabel: undefined,
FooterBg: ColorAttr{colUndefined, AttrUndefined}, FooterBg: undefined,
FooterBorder: ColorAttr{colUndefined, AttrUndefined}, FooterBorder: undefined,
FooterLabel: ColorAttr{colUndefined, AttrUndefined}, FooterLabel: undefined,
GapLine: ColorAttr{colUndefined, AttrUndefined}, GapLine: undefined,
Nth: ColorAttr{colUndefined, AttrUndefined}, Nth: undefined,
Hidden: ColorAttr{colUndefined, Dim}, Hidden: undefined,
} }
} }
func InitTheme(theme *ColorTheme, baseTheme *ColorTheme, forceBlack bool, hasInputWindow bool, hasHeaderWindow bool) { func InitTheme(theme *ColorTheme, baseTheme *ColorTheme, boldify bool, forceBlack bool, hasInputWindow bool, hasHeaderWindow bool) {
if forceBlack { if forceBlack {
theme.Bg = ColorAttr{colBlack, AttrUndefined} theme.Bg = ColorAttr{colBlack, AttrUndefined}
} }
@@ -1098,18 +1127,36 @@ func InitTheme(theme *ColorTheme, baseTheme *ColorTheme, forceBlack bool, hasInp
theme.Bg = o(baseTheme.Bg, theme.Bg) theme.Bg = o(baseTheme.Bg, theme.Bg)
theme.DarkBg = o(baseTheme.DarkBg, theme.DarkBg) theme.DarkBg = o(baseTheme.DarkBg, theme.DarkBg)
theme.Prompt = o(baseTheme.Prompt, theme.Prompt) theme.Prompt = o(baseTheme.Prompt, theme.Prompt)
theme.Match = o(baseTheme.Match, theme.Match) match := theme.Match
if !baseTheme.Colored && match.IsUndefined() {
match.Attr = Underline
}
theme.Match = o(baseTheme.Match, match)
// Inherit from 'fg', so that we don't have to write 'current-fg:dim' // Inherit from 'fg', so that we don't have to write 'current-fg:dim'
// e.g. fzf --delimiter / --nth -1 --color fg:dim,nth:regular // e.g. fzf --delimiter / --nth -1 --color fg:dim,nth:regular
theme.Current = theme.Fg.Merge(o(baseTheme.Current, theme.Current)) current := theme.Current
theme.CurrentMatch = o(baseTheme.CurrentMatch, theme.CurrentMatch) if !baseTheme.Colored && current.IsUndefined() {
current.Attr = Reverse
}
theme.Current = theme.Fg.Merge(o(baseTheme.Current, current))
currentMatch := theme.CurrentMatch
if !baseTheme.Colored && currentMatch.IsUndefined() {
currentMatch.Attr = Reverse | Underline
}
theme.CurrentMatch = o(baseTheme.CurrentMatch, currentMatch)
theme.Spinner = o(baseTheme.Spinner, theme.Spinner) theme.Spinner = o(baseTheme.Spinner, theme.Spinner)
theme.Info = o(baseTheme.Info, theme.Info) theme.Info = o(baseTheme.Info, theme.Info)
theme.Cursor = o(baseTheme.Cursor, theme.Cursor) theme.Cursor = o(baseTheme.Cursor, theme.Cursor)
theme.Marker = o(baseTheme.Marker, theme.Marker) theme.Marker = o(baseTheme.Marker, theme.Marker)
theme.Header = o(baseTheme.Header, theme.Header) theme.Header = o(baseTheme.Header, theme.Header)
theme.Footer = o(baseTheme.Footer, theme.Footer) theme.Footer = o(baseTheme.Footer, theme.Footer)
theme.Border = o(baseTheme.Border, theme.Border)
// If border color is undefined, set it to default color with dim attribute.
border := theme.Border
if baseTheme.Border.IsUndefined() && border.IsUndefined() {
border.Attr = Dim
}
theme.Border = o(baseTheme.Border, border)
theme.BorderLabel = o(baseTheme.BorderLabel, theme.BorderLabel) theme.BorderLabel = o(baseTheme.BorderLabel, theme.BorderLabel)
undefined := NewColorAttr() undefined := NewColorAttr()
@@ -1122,9 +1169,23 @@ func InitTheme(theme *ColorTheme, baseTheme *ColorTheme, forceBlack bool, hasInp
theme.SelectedFg = o(theme.ListFg, theme.SelectedFg) theme.SelectedFg = o(theme.ListFg, theme.SelectedFg)
theme.SelectedBg = o(theme.ListBg, theme.SelectedBg) theme.SelectedBg = o(theme.ListBg, theme.SelectedBg)
theme.SelectedMatch = o(theme.Match, theme.SelectedMatch) theme.SelectedMatch = o(theme.Match, theme.SelectedMatch)
theme.Ghost = o(theme.Input, theme.Ghost)
ghost := theme.Ghost
if ghost.IsUndefined() {
ghost.Attr = Dim
} else if ghost.IsColorDefined() && !ghost.IsAttrDefined() {
// Don't want to inherit 'bold' from 'input'
ghost.Attr = AttrRegular
}
theme.Ghost = o(theme.Input, ghost)
theme.Disabled = o(theme.Input, theme.Disabled) theme.Disabled = o(theme.Input, theme.Disabled)
theme.Gutter = o(theme.DarkBg, theme.Gutter)
// Use dim gutter on non-colored themes if undefined
gutter := theme.Gutter
if !baseTheme.Colored && gutter.IsUndefined() {
gutter.Attr = Dim
}
theme.Gutter = o(theme.DarkBg, gutter)
theme.PreviewFg = o(theme.Fg, theme.PreviewFg) theme.PreviewFg = o(theme.Fg, theme.PreviewFg)
theme.PreviewBg = o(theme.Bg, theme.PreviewBg) theme.PreviewBg = o(theme.Bg, theme.PreviewBg)
theme.PreviewLabel = o(theme.BorderLabel, theme.PreviewLabel) theme.PreviewLabel = o(theme.BorderLabel, theme.PreviewLabel)
@@ -1166,6 +1227,26 @@ func InitTheme(theme *ColorTheme, baseTheme *ColorTheme, forceBlack bool, hasInp
theme.FooterBorder = o(theme.Border, theme.FooterBorder) theme.FooterBorder = o(theme.Border, theme.FooterBorder)
theme.FooterLabel = o(theme.BorderLabel, theme.FooterLabel) theme.FooterLabel = o(theme.BorderLabel, theme.FooterLabel)
if boldify {
boldify := func(c ColorAttr) ColorAttr {
dup := c
if (c.Attr & AttrRegular) == 0 {
dup.Attr |= BoldForce
}
return dup
}
theme.Current = boldify(theme.Current)
theme.CurrentMatch = boldify(theme.CurrentMatch)
theme.Prompt = boldify(theme.Prompt)
theme.Input = boldify(theme.Input)
theme.Cursor = boldify(theme.Cursor)
theme.Spinner = boldify(theme.Spinner)
}
if theme.Hidden.IsUndefined() {
theme.Hidden.Attr = Dim
}
initPalette(theme) initPalette(theme)
} }