From 5a391024059e055f9e21b997ff77e1b4ba5302c5 Mon Sep 17 00:00:00 2001 From: Junegunn Choi Date: Sun, 14 May 2023 18:28:46 +0900 Subject: [PATCH] Allow customizing the color of preview scrollbar via 'preview-scrollbar' --- man/man1/fzf.1 | 46 ++++---- src/options.go | 4 + src/terminal.go | 6 +- src/tui/tui.go | 294 +++++++++++++++++++++++++----------------------- 4 files changed, 186 insertions(+), 164 deletions(-) diff --git a/man/man1/fzf.1 b/man/man1/fzf.1 index 82a9b6f..1ff1fe0 100644 --- a/man/man1/fzf.1 +++ b/man/man1/fzf.1 @@ -433,28 +433,30 @@ color mappings. \fBbw \fRNo colors (equivalent to \fB--no-color\fR) .B COLOR NAMES: - \fBfg \fRText - \fBpreview-fg \fRPreview window text - \fBbg \fRBackground - \fBpreview-bg \fRPreview window background - \fBhl \fRHighlighted substrings - \fBfg+ \fRText (current line) - \fBbg+ \fRBackground (current line) - \fBgutter \fRGutter on the left - \fBhl+ \fRHighlighted substrings (current line) - \fBquery \fRQuery string - \fBdisabled \fRQuery string when search is disabled (\fB--disabled\fR) - \fBinfo \fRInfo line (match counters) - \fBborder \fRBorder around the window (\fB--border\fR and \fB--preview\fR) - \fBseparator \fRHorizontal separator on info line - \fBscrollbar \fRScrollbar - \fBlabel \fRBorder label (\fB--border-label\fR and \fB--preview-label\fR) - \fBpreview-label \fRBorder label of the preview window (\fB--preview-label\fR) - \fBprompt \fRPrompt - \fBpointer \fRPointer to the current line - \fBmarker \fRMulti-select marker - \fBspinner \fRStreaming input indicator - \fBheader \fRHeader + \fBfg \fRText + \fBpreview-fg \fRPreview window text + \fBbg \fRBackground + \fBpreview-bg \fRPreview window background + \fBhl \fRHighlighted substrings + \fBfg+ \fRText (current line) + \fBbg+ \fRBackground (current line) + \fBgutter \fRGutter on the left + \fBhl+ \fRHighlighted substrings (current line) + \fBquery \fRQuery string + \fBdisabled \fRQuery string when search is disabled (\fB--disabled\fR) + \fBinfo \fRInfo line (match counters) + \fBborder \fRBorder around the window (\fB--border\fR and \fB--preview\fR) + \fBscrollbar \fRScrollbar + \fBpreview-border \fRBorder around the preview window (\fB--preview\fR) + \fBpreview-scrollbar \fRScrollbar + \fBseparator \fRHorizontal separator on info line + \fBlabel \fRBorder label (\fB--border-label\fR and \fB--preview-label\fR) + \fBpreview-label \fRBorder label of the preview window (\fB--preview-label\fR) + \fBprompt \fRPrompt + \fBpointer \fRPointer to the current line + \fBmarker \fRMulti-select marker + \fBspinner \fRStreaming input indicator + \fBheader \fRHeader .B ANSI COLORS: \fB-1 \fRDefault terminal foreground/background color diff --git a/src/options.go b/src/options.go index 27e32d1..ba84c8b 100644 --- a/src/options.go +++ b/src/options.go @@ -888,10 +888,14 @@ func parseTheme(defaultTheme *tui.ColorTheme, str string) *tui.ColorTheme { mergeAttr(&theme.CurrentMatch) case "border": mergeAttr(&theme.Border) + case "preview-border": + mergeAttr(&theme.PreviewBorder) case "separator": mergeAttr(&theme.Separator) case "scrollbar": mergeAttr(&theme.Scrollbar) + case "preview-scrollbar": + mergeAttr(&theme.PreviewScrollbar) case "label": mergeAttr(&theme.BorderLabel) case "preview-label": diff --git a/src/terminal.go b/src/terminal.go index d108bfd..fadfd6c 100644 --- a/src/terminal.go +++ b/src/terminal.go @@ -1930,7 +1930,9 @@ func (t *Terminal) renderPreviewText(height int, lines []string, lineNo int, unc func (t *Terminal) renderPreviewScrollbar(yoff int, barLength int, barStart int) { height := t.pwindow.Height() w := t.pborder.Width() + redraw := false if len(t.previewer.bar) != height { + redraw = true t.previewer.bar = make([]bool, height) } xshift := -1 - t.borderWidth @@ -1947,7 +1949,7 @@ func (t *Terminal) renderPreviewScrollbar(yoff int, barLength int, barStart int) // Avoid unnecessary redraws bar := i >= yoff+barStart && i < yoff+barStart+barLength - if bar == t.previewer.bar[i] && !t.tui.NeedScrollbarRedraw() { + if !redraw && bar == t.previewer.bar[i] && !t.tui.NeedScrollbarRedraw() { continue } @@ -1956,7 +1958,7 @@ func (t *Terminal) renderPreviewScrollbar(yoff int, barLength int, barStart int) if i >= yoff+barStart && i < yoff+barStart+barLength { t.pborder.CPrint(tui.ColPreviewScrollbar, t.scrollbar) } else { - t.pborder.Print(" ") + t.pborder.CPrint(tui.ColPreviewScrollbar, " ") } } } diff --git a/src/tui/tui.go b/src/tui/tui.go index 73ed0c9..5fd27d0 100644 --- a/src/tui/tui.go +++ b/src/tui/tui.go @@ -253,29 +253,31 @@ func (p ColorPair) MergeNonDefault(other ColorPair) ColorPair { } type ColorTheme struct { - Colored bool - Input ColorAttr - Disabled ColorAttr - Fg ColorAttr - Bg ColorAttr - PreviewFg ColorAttr - PreviewBg ColorAttr - DarkBg ColorAttr - Gutter ColorAttr - Prompt ColorAttr - Match ColorAttr - Current ColorAttr - CurrentMatch ColorAttr - Spinner ColorAttr - Info ColorAttr - Cursor ColorAttr - Selected ColorAttr - Header ColorAttr - Separator ColorAttr - Scrollbar ColorAttr - Border ColorAttr - BorderLabel ColorAttr - PreviewLabel ColorAttr + Colored bool + Input ColorAttr + Disabled ColorAttr + Fg ColorAttr + Bg ColorAttr + PreviewFg ColorAttr + PreviewBg ColorAttr + DarkBg ColorAttr + Gutter ColorAttr + Prompt ColorAttr + Match ColorAttr + Current ColorAttr + CurrentMatch ColorAttr + Spinner ColorAttr + Info ColorAttr + Cursor ColorAttr + Selected ColorAttr + Header ColorAttr + Separator ColorAttr + Scrollbar ColorAttr + Border ColorAttr + PreviewBorder ColorAttr + PreviewScrollbar ColorAttr + BorderLabel ColorAttr + PreviewLabel ColorAttr } type Event struct { @@ -508,57 +510,61 @@ var ( func EmptyTheme() *ColorTheme { return &ColorTheme{ - Colored: true, - Input: ColorAttr{colUndefined, AttrUndefined}, - Fg: ColorAttr{colUndefined, AttrUndefined}, - Bg: 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}, - Selected: ColorAttr{colUndefined, AttrUndefined}, - Header: ColorAttr{colUndefined, AttrUndefined}, - Border: ColorAttr{colUndefined, AttrUndefined}, - BorderLabel: ColorAttr{colUndefined, AttrUndefined}, - Disabled: ColorAttr{colUndefined, AttrUndefined}, - PreviewFg: ColorAttr{colUndefined, AttrUndefined}, - PreviewBg: ColorAttr{colUndefined, AttrUndefined}, - Gutter: ColorAttr{colUndefined, AttrUndefined}, - PreviewLabel: ColorAttr{colUndefined, AttrUndefined}, - Separator: ColorAttr{colUndefined, AttrUndefined}, - Scrollbar: ColorAttr{colUndefined, AttrUndefined}, + Colored: true, + Input: ColorAttr{colUndefined, AttrUndefined}, + Fg: ColorAttr{colUndefined, AttrUndefined}, + Bg: 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}, + Selected: ColorAttr{colUndefined, AttrUndefined}, + Header: ColorAttr{colUndefined, AttrUndefined}, + Border: ColorAttr{colUndefined, AttrUndefined}, + BorderLabel: ColorAttr{colUndefined, AttrUndefined}, + 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}, } } func NoColorTheme() *ColorTheme { return &ColorTheme{ - Colored: false, - Input: ColorAttr{colDefault, AttrUndefined}, - Fg: ColorAttr{colDefault, AttrUndefined}, - Bg: 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}, - Selected: ColorAttr{colDefault, AttrUndefined}, - Header: ColorAttr{colDefault, AttrUndefined}, - Border: ColorAttr{colDefault, AttrUndefined}, - BorderLabel: ColorAttr{colDefault, AttrUndefined}, - Disabled: ColorAttr{colDefault, AttrUndefined}, - PreviewFg: ColorAttr{colDefault, AttrUndefined}, - PreviewBg: ColorAttr{colDefault, AttrUndefined}, - Gutter: ColorAttr{colDefault, AttrUndefined}, - PreviewLabel: ColorAttr{colDefault, AttrUndefined}, - Separator: ColorAttr{colDefault, AttrUndefined}, - Scrollbar: ColorAttr{colDefault, AttrUndefined}, + Colored: false, + Input: ColorAttr{colDefault, AttrUndefined}, + Fg: ColorAttr{colDefault, AttrUndefined}, + Bg: 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}, + Selected: ColorAttr{colDefault, AttrUndefined}, + Header: ColorAttr{colDefault, AttrUndefined}, + Border: ColorAttr{colDefault, AttrUndefined}, + BorderLabel: ColorAttr{colDefault, AttrUndefined}, + 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}, + Separator: ColorAttr{colDefault, AttrUndefined}, + Scrollbar: ColorAttr{colDefault, AttrUndefined}, } } @@ -569,79 +575,85 @@ func errorExit(message string) { func init() { Default16 = &ColorTheme{ - Colored: true, - Input: ColorAttr{colDefault, AttrUndefined}, - Fg: ColorAttr{colDefault, AttrUndefined}, - Bg: ColorAttr{colDefault, AttrUndefined}, - DarkBg: ColorAttr{colBlack, AttrUndefined}, - Prompt: ColorAttr{colBlue, AttrUndefined}, - Match: ColorAttr{colGreen, AttrUndefined}, - Current: ColorAttr{colYellow, AttrUndefined}, - CurrentMatch: ColorAttr{colGreen, AttrUndefined}, - Spinner: ColorAttr{colGreen, AttrUndefined}, - Info: ColorAttr{colWhite, AttrUndefined}, - Cursor: ColorAttr{colRed, AttrUndefined}, - Selected: ColorAttr{colMagenta, AttrUndefined}, - Header: ColorAttr{colCyan, AttrUndefined}, - Border: ColorAttr{colBlack, AttrUndefined}, - BorderLabel: ColorAttr{colWhite, AttrUndefined}, - Disabled: ColorAttr{colUndefined, AttrUndefined}, - PreviewFg: ColorAttr{colUndefined, AttrUndefined}, - PreviewBg: ColorAttr{colUndefined, AttrUndefined}, - Gutter: ColorAttr{colUndefined, AttrUndefined}, - PreviewLabel: ColorAttr{colUndefined, AttrUndefined}, - Separator: ColorAttr{colUndefined, AttrUndefined}, - Scrollbar: ColorAttr{colUndefined, AttrUndefined}, + Colored: true, + Input: ColorAttr{colDefault, AttrUndefined}, + Fg: ColorAttr{colDefault, AttrUndefined}, + Bg: ColorAttr{colDefault, AttrUndefined}, + DarkBg: ColorAttr{colBlack, AttrUndefined}, + Prompt: ColorAttr{colBlue, AttrUndefined}, + Match: ColorAttr{colGreen, AttrUndefined}, + Current: ColorAttr{colYellow, AttrUndefined}, + CurrentMatch: ColorAttr{colGreen, AttrUndefined}, + Spinner: ColorAttr{colGreen, AttrUndefined}, + Info: ColorAttr{colWhite, AttrUndefined}, + Cursor: ColorAttr{colRed, AttrUndefined}, + Selected: ColorAttr{colMagenta, AttrUndefined}, + Header: ColorAttr{colCyan, AttrUndefined}, + Border: ColorAttr{colBlack, AttrUndefined}, + BorderLabel: ColorAttr{colWhite, AttrUndefined}, + 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}, } Dark256 = &ColorTheme{ - Colored: true, - Input: ColorAttr{colDefault, AttrUndefined}, - Fg: ColorAttr{colDefault, AttrUndefined}, - Bg: ColorAttr{colDefault, AttrUndefined}, - DarkBg: ColorAttr{236, AttrUndefined}, - Prompt: ColorAttr{110, AttrUndefined}, - Match: ColorAttr{108, AttrUndefined}, - Current: ColorAttr{254, AttrUndefined}, - CurrentMatch: ColorAttr{151, AttrUndefined}, - Spinner: ColorAttr{148, AttrUndefined}, - Info: ColorAttr{144, AttrUndefined}, - Cursor: ColorAttr{161, AttrUndefined}, - Selected: ColorAttr{168, AttrUndefined}, - Header: ColorAttr{109, AttrUndefined}, - Border: ColorAttr{59, AttrUndefined}, - BorderLabel: ColorAttr{145, AttrUndefined}, - Disabled: ColorAttr{colUndefined, AttrUndefined}, - PreviewFg: ColorAttr{colUndefined, AttrUndefined}, - PreviewBg: ColorAttr{colUndefined, AttrUndefined}, - Gutter: ColorAttr{colUndefined, AttrUndefined}, - PreviewLabel: ColorAttr{colUndefined, AttrUndefined}, - Separator: ColorAttr{colUndefined, AttrUndefined}, - Scrollbar: ColorAttr{colUndefined, AttrUndefined}, + Colored: true, + Input: ColorAttr{colDefault, AttrUndefined}, + Fg: ColorAttr{colDefault, AttrUndefined}, + Bg: ColorAttr{colDefault, AttrUndefined}, + DarkBg: ColorAttr{236, AttrUndefined}, + Prompt: ColorAttr{110, AttrUndefined}, + Match: ColorAttr{108, AttrUndefined}, + Current: ColorAttr{254, AttrUndefined}, + CurrentMatch: ColorAttr{151, AttrUndefined}, + Spinner: ColorAttr{148, AttrUndefined}, + Info: ColorAttr{144, AttrUndefined}, + Cursor: ColorAttr{161, AttrUndefined}, + Selected: ColorAttr{168, AttrUndefined}, + Header: ColorAttr{109, AttrUndefined}, + Border: ColorAttr{59, AttrUndefined}, + BorderLabel: ColorAttr{145, AttrUndefined}, + 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}, } Light256 = &ColorTheme{ - Colored: true, - Input: ColorAttr{colDefault, AttrUndefined}, - Fg: ColorAttr{colDefault, AttrUndefined}, - Bg: ColorAttr{colDefault, AttrUndefined}, - DarkBg: ColorAttr{251, AttrUndefined}, - Prompt: ColorAttr{25, AttrUndefined}, - Match: ColorAttr{66, AttrUndefined}, - Current: ColorAttr{237, AttrUndefined}, - CurrentMatch: ColorAttr{23, AttrUndefined}, - Spinner: ColorAttr{65, AttrUndefined}, - Info: ColorAttr{101, AttrUndefined}, - Cursor: ColorAttr{161, AttrUndefined}, - Selected: ColorAttr{168, AttrUndefined}, - Header: ColorAttr{31, AttrUndefined}, - Border: ColorAttr{145, AttrUndefined}, - BorderLabel: ColorAttr{59, AttrUndefined}, - Disabled: ColorAttr{colUndefined, AttrUndefined}, - PreviewFg: ColorAttr{colUndefined, AttrUndefined}, - PreviewBg: ColorAttr{colUndefined, AttrUndefined}, - Gutter: ColorAttr{colUndefined, AttrUndefined}, - PreviewLabel: ColorAttr{colUndefined, AttrUndefined}, - Separator: ColorAttr{colUndefined, AttrUndefined}, - Scrollbar: ColorAttr{colUndefined, AttrUndefined}, + Colored: true, + Input: ColorAttr{colDefault, AttrUndefined}, + Fg: ColorAttr{colDefault, AttrUndefined}, + Bg: ColorAttr{colDefault, AttrUndefined}, + DarkBg: ColorAttr{251, AttrUndefined}, + Prompt: ColorAttr{25, AttrUndefined}, + Match: ColorAttr{66, AttrUndefined}, + Current: ColorAttr{237, AttrUndefined}, + CurrentMatch: ColorAttr{23, AttrUndefined}, + Spinner: ColorAttr{65, AttrUndefined}, + Info: ColorAttr{101, AttrUndefined}, + Cursor: ColorAttr{161, AttrUndefined}, + Selected: ColorAttr{168, AttrUndefined}, + Header: ColorAttr{31, AttrUndefined}, + Border: ColorAttr{145, AttrUndefined}, + BorderLabel: ColorAttr{59, AttrUndefined}, + 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}, } } @@ -682,8 +694,10 @@ func initTheme(theme *ColorTheme, baseTheme *ColorTheme, forceBlack bool) { theme.PreviewFg = o(theme.Fg, theme.PreviewFg) theme.PreviewBg = o(theme.Bg, theme.PreviewBg) theme.PreviewLabel = o(theme.BorderLabel, theme.PreviewLabel) + theme.PreviewBorder = o(theme.Border, theme.PreviewBorder) theme.Separator = o(theme.Border, theme.Separator) theme.Scrollbar = o(theme.Border, theme.Scrollbar) + theme.PreviewScrollbar = o(theme.PreviewBorder, theme.PreviewScrollbar) initPalette(theme) } @@ -721,6 +735,6 @@ func initPalette(theme *ColorTheme) { ColBorderLabel = pair(theme.BorderLabel, theme.Bg) ColPreviewLabel = pair(theme.PreviewLabel, theme.PreviewBg) ColPreview = pair(theme.PreviewFg, theme.PreviewBg) - ColPreviewBorder = pair(theme.Border, theme.PreviewBg) - ColPreviewScrollbar = pair(theme.Scrollbar, theme.PreviewBg) + ColPreviewBorder = pair(theme.PreviewBorder, theme.PreviewBg) + ColPreviewScrollbar = pair(theme.PreviewScrollbar, theme.PreviewBg) }