summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJunegunn Choi <junegunn.c@gmail.com>2025-10-01 00:00:54 +0900
committerJunegunn Choi <junegunn.c@gmail.com>2025-10-09 00:17:00 +0900
commite6ad01fb90df7e324068f61ae96e056f327959c7 (patch)
tree6c909ebfc490bf216f12449b9b3062ee963e7085
parentce2200e9080d84a0e658fd1523f4fac619b58da4 (diff)
downloadfzf-e6ad01fb90df7e324068f61ae96e056f327959c7.tar.gz
Revise color configuration
-rw-r--r--CHANGELOG.md38
-rw-r--r--src/options.go44
-rw-r--r--src/options_test.go15
-rw-r--r--src/terminal.go10
-rw-r--r--src/tui/dummy.go29
-rw-r--r--src/tui/tcell.go19
-rw-r--r--src/tui/tui.go503
7 files changed, 369 insertions, 289 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 89b1fa82..ee88c41f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -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.
```sh
+fzf --raw --color hidden:red
fzf --raw --color hidden:red:strikethrough
-
-# To unset the default 'dim' attribute, prefix the color spec with 'regular'
-fzf --raw --color hidden:regular:red:strikethrough
+fzf --raw --color hidden:red:strikethrough:dim
+fzf --raw --color hidden:red:strikethrough:dim:italic
```
#### 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.
-### 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.
diff --git a/src/options.go b/src/options.go
index d3be6821..79e016b6 100644
--- a/src/options.go
+++ b/src/options.go
@@ -572,6 +572,7 @@ type Options struct {
Multi int
Ansi bool
Mouse bool
+ BaseTheme *tui.ColorTheme
Theme *tui.ColorTheme
Black bool
Bold bool
@@ -672,9 +673,9 @@ func defaultPreviewOpts(command string) previewOpts {
func defaultOptions() *Options {
var theme *tui.ColorTheme
if os.Getenv("NO_COLOR") != "" {
- theme = tui.NoColorTheme()
+ theme = tui.NoColorTheme
} else {
- theme = tui.EmptyTheme()
+ theme = tui.EmptyTheme
}
return &Options{
@@ -1317,8 +1318,9 @@ func dupeTheme(theme *tui.ColorTheme) *tui.ColorTheme {
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 baseTheme *tui.ColorTheme
theme := dupeTheme(defaultTheme)
rrggbb := regexp.MustCompile("^#[0-9a-fA-F]{6}$")
comma := regexp.MustCompile(`[\s,]+`)
@@ -1329,13 +1331,17 @@ func parseTheme(defaultTheme *tui.ColorTheme, str string) (*tui.ColorTheme, erro
}
switch str {
case "dark":
+ baseTheme = tui.Dark256
theme = dupeTheme(tui.Dark256)
case "light":
+ baseTheme = tui.Light256
theme = dupeTheme(tui.Light256)
case "base16", "16":
+ baseTheme = tui.Default16
theme = dupeTheme(tui.Default16)
case "bw", "no":
- theme = tui.NoColorTheme()
+ baseTheme = tui.NoColorTheme
+ theme = dupeTheme(tui.NoColorTheme)
default:
fail := func() {
// 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) {
@@ -2649,11 +2655,15 @@ func parseOptions(index *int, opts *Options, allArgs []string) error {
case "--color":
_, spec := optionalNextString()
if len(spec) == 0 {
- opts.Theme = tui.EmptyTheme()
+ opts.Theme = tui.EmptyTheme
} 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
}
+ if baseTheme != nil {
+ opts.BaseTheme = baseTheme
+ }
}
case "--toggle-sort":
str, err := nextString("key name required")
@@ -2739,7 +2749,8 @@ func parseOptions(index *int, opts *Options, allArgs []string) error {
case "--no-mouse":
opts.Mouse = false
case "+c", "--no-color":
- opts.Theme = tui.NoColorTheme()
+ opts.BaseTheme = tui.NoColorTheme
+ opts.Theme = tui.NoColorTheme
case "+2", "--no-256":
opts.Theme = tui.Default16
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 !tui.IsLightRendererSupported() && opts.Height.size > 0 {
opts.Height = heightSpec{}
diff --git a/src/options_test.go b/src/options_test.go
index 7b152d75..1494d960 100644
--- a/src/options_test.go
+++ b/src/options_test.go
@@ -300,8 +300,12 @@ func TestBind(t *testing.T) {
}
func TestColorSpec(t *testing.T) {
+ var base *tui.ColorTheme
theme := tui.Dark256
- dark, _ := parseTheme(theme, "dark")
+ base, dark, _ := parseTheme(theme, "dark")
+ if *dark != *base {
+ t.Errorf("incorrect base theme returned")
+ }
if *dark != *theme {
t.Errorf("colors should be equivalent")
}
@@ -309,7 +313,10 @@ func TestColorSpec(t *testing.T) {
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 {
t.Errorf("should not be equivalent")
}
@@ -320,7 +327,7 @@ func TestColorSpec(t *testing.T) {
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 {
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)
}
- 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 {
t.Errorf("color not customized")
}
diff --git a/src/terminal.go b/src/terminal.go
index f3b9ccda..5d578540 100644
--- a/src/terminal.go
+++ b/src/terminal.go
@@ -1109,14 +1109,18 @@ func NewTerminal(opts *Options, eventBox *util.EventBox, executor *util.Executor
t.acceptNth = opts.AcceptNth(t.delimiter)
}
+ baseTheme := opts.BaseTheme
+ if baseTheme == nil {
+ baseTheme = renderer.DefaultTheme()
+ }
// 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
var gutterChar, gutterRawChar string
if opts.Gutter != nil {
gutterChar = *opts.Gutter
- } else if t.unicode && !t.theme.Gutter.Color.IsDefault() {
+ } else if t.unicode {
gutterChar = "▌"
} else {
gutterChar = " "
@@ -1125,7 +1129,7 @@ func NewTerminal(opts *Options, eventBox *util.EventBox, executor *util.Executor
if opts.GutterRaw != nil {
gutterRawChar = *opts.GutterRaw
- } else if t.unicode && !t.theme.Gutter.Color.IsDefault() {
+ } else if t.unicode {
gutterRawChar = "▖"
} else {
gutterRawChar = ":"
diff --git a/src/tui/dummy.go b/src/tui/dummy.go
index a9888036..cb0ce0da 100644
--- a/src/tui/dummy.go
+++ b/src/tui/dummy.go
@@ -2,30 +2,7 @@
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 (
- AttrUndefined = Attr(0)
- AttrRegular = Attr(1 << 8)
- AttrClear = Attr(1 << 9)
- BoldForce = Attr(1 << 10)
- FullBg = Attr(1 << 11)
-
Bold = Attr(1)
Dim = Attr(1 << 1)
Italic = Attr(1 << 2)
@@ -36,6 +13,12 @@ const (
StrikeThrough = Attr(1 << 7)
)
+func HasFullscreenRenderer() bool {
+ return false
+}
+
+var DefaultBorderShape = BorderRounded
+
func (r *FullscreenRenderer) Init() error { return nil }
func (r *FullscreenRenderer) DefaultTheme() *ColorTheme { return nil }
func (r *FullscreenRenderer) Resize(maxHeightFunc func(int) int) {}
diff --git a/src/tui/tcell.go b/src/tui/tcell.go
index e4a6a988..f7c6884f 100644
--- a/src/tui/tcell.go
+++ b/src/tui/tcell.go
@@ -36,8 +36,6 @@ func (p ColorPair) style() tcell.Style {
return style.Foreground(asTcellColor(p.Fg())).Background(asTcellColor(p.Bg()))
}
-type Attr int32
-
type TcellWindow struct {
color bool
windowType WindowType
@@ -98,14 +96,6 @@ const (
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() {
_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
// they are declared here to prevent introducing tcell library in non-windows builds
var (
diff --git a/src/tui/tui.go b/src/tui/tui.go
index ae9e8c49..563d3c2a 100644
--- a/src/tui/tui.go
+++ b/src/tui/tui.go
@@ -8,6 +8,25 @@ import (
"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
//
//go:generate stringer -type=EventType
@@ -275,6 +294,13 @@ func (a ColorAttr) IsColorDefined() bool {
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 {
return ColorAttr{Color: colUndefined, Attr: AttrUndefined}
}
@@ -779,9 +805,11 @@ func NewFullscreenRenderer(theme *ColorTheme, forceBlack bool, mouse bool) Rende
}
var (
- Default16 *ColorTheme
- Dark256 *ColorTheme
- Light256 *ColorTheme
+ NoColorTheme *ColorTheme
+ EmptyTheme *ColorTheme
+ Default16 *ColorTheme
+ Dark256 *ColorTheme
+ Light256 *ColorTheme
ColPrompt ColorPair
ColNormal ColorPair
@@ -825,121 +853,120 @@ var (
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 init() {
+ defaultColor := ColorAttr{colDefault, AttrUndefined}
+ undefined := ColorAttr{colUndefined, AttrUndefined}
-func NoColorTheme() *ColorTheme {
- return &ColorTheme{
+ NoColorTheme = &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},
+ 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,
}
-}
-func init() {
Default16 = &ColorTheme{
Colored: true,
- Input: ColorAttr{colDefault, AttrUndefined},
- Fg: ColorAttr{colDefault, AttrUndefined},
- Bg: ColorAttr{colDefault, 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},
+ Input: defaultColor,
+ Fg: defaultColor,
+ Bg: defaultColor,
+ ListFg: undefined,
+ ListBg: undefined,
+ AltBg: undefined,
+ SelectedFg: undefined,
+ SelectedBg: undefined,
+ SelectedMatch: undefined,
DarkBg: ColorAttr{colGrey, AttrUndefined},
Prompt: ColorAttr{colBlue, AttrUndefined},
Match: ColorAttr{colGreen, AttrUndefined},
@@ -951,44 +978,45 @@ func init() {
Marker: ColorAttr{colMagenta, AttrUndefined},
Header: ColorAttr{colCyan, AttrUndefined},
Footer: ColorAttr{colCyan, AttrUndefined},
- Border: ColorAttr{colDefault, Dim},
- BorderLabel: ColorAttr{colDefault, 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},
- ListLabel: ColorAttr{colUndefined, AttrUndefined},
- ListBorder: 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},
+ Border: undefined,
+ BorderLabel: defaultColor,
+ Ghost: undefined,
+ Disabled: undefined,
+ PreviewFg: undefined,
+ PreviewBg: undefined,
+ Gutter: undefined,
+ PreviewBorder: undefined,
+ PreviewScrollbar: undefined,
+ PreviewLabel: undefined,
+ ListLabel: undefined,
+ ListBorder: 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,
}
+
Dark256 = &ColorTheme{
Colored: true,
- Input: ColorAttr{colDefault, AttrUndefined},
- Fg: ColorAttr{colDefault, AttrUndefined},
- Bg: ColorAttr{colDefault, 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},
+ Input: defaultColor,
+ Fg: defaultColor,
+ Bg: defaultColor,
+ ListFg: undefined,
+ ListBg: undefined,
+ AltBg: undefined,
+ SelectedFg: undefined,
+ SelectedBg: undefined,
+ SelectedMatch: undefined,
DarkBg: ColorAttr{236, AttrUndefined},
Prompt: ColorAttr{110, AttrUndefined},
Match: ColorAttr{108, AttrUndefined},
@@ -1002,42 +1030,43 @@ func init() {
Footer: ColorAttr{109, AttrUndefined},
Border: ColorAttr{59, AttrUndefined},
BorderLabel: ColorAttr{145, 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},
- ListLabel: ColorAttr{colUndefined, AttrUndefined},
- ListBorder: 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},
+ Ghost: undefined,
+ Disabled: undefined,
+ PreviewFg: undefined,
+ PreviewBg: undefined,
+ Gutter: undefined,
+ PreviewBorder: undefined,
+ PreviewScrollbar: undefined,
+ PreviewLabel: undefined,
+ ListLabel: undefined,
+ ListBorder: 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,
}
+
Light256 = &ColorTheme{
Colored: true,
- Input: ColorAttr{colDefault, AttrUndefined},
- Fg: ColorAttr{colDefault, AttrUndefined},
- Bg: ColorAttr{colDefault, 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},
+ Input: defaultColor,
+ Fg: defaultColor,
+ Bg: defaultColor,
+ ListFg: undefined,
+ ListBg: undefined,
+ AltBg: undefined,
+ SelectedFg: undefined,
+ SelectedBg: undefined,
+ SelectedMatch: undefined,
DarkBg: ColorAttr{251, AttrUndefined},
Prompt: ColorAttr{25, AttrUndefined},
Match: ColorAttr{66, AttrUndefined},
@@ -1051,34 +1080,34 @@ func init() {
Footer: ColorAttr{31, AttrUndefined},
Border: ColorAttr{145, AttrUndefined},
BorderLabel: ColorAttr{59, 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},
- ListLabel: ColorAttr{colUndefined, AttrUndefined},
- ListBorder: 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},
+ Ghost: undefined,
+ Disabled: undefined,
+ PreviewFg: undefined,
+ PreviewBg: undefined,
+ Gutter: undefined,
+ PreviewBorder: undefined,
+ PreviewScrollbar: undefined,
+ PreviewLabel: undefined,
+ ListLabel: undefined,
+ ListBorder: 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,
}
}
-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 {
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.DarkBg = o(baseTheme.DarkBg, theme.DarkBg)
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'
// e.g. fzf --delimiter / --nth -1 --color fg:dim,nth:regular
- theme.Current = theme.Fg.Merge(o(baseTheme.Current, theme.Current))
- theme.CurrentMatch = o(baseTheme.CurrentMatch, theme.CurrentMatch)
+ current := theme.Current
+ 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.Info = o(baseTheme.Info, theme.Info)
theme.Cursor = o(baseTheme.Cursor, theme.Cursor)
theme.Marker = o(baseTheme.Marker, theme.Marker)
theme.Header = o(baseTheme.Header, theme.Header)
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)
undefined := NewColorAttr()
@@ -1122,9 +1169,23 @@ func InitTheme(theme *ColorTheme, baseTheme *ColorTheme, forceBlack bool, hasInp
theme.SelectedFg = o(theme.ListFg, theme.SelectedFg)
theme.SelectedBg = o(theme.ListBg, theme.SelectedBg)
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.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.PreviewBg = o(theme.Bg, theme.PreviewBg)
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.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)
}