diff options
| author | Junegunn Choi <junegunn.c@gmail.com> | 2024-12-31 17:03:18 +0900 |
|---|---|---|
| committer | Junegunn Choi <junegunn.c@gmail.com> | 2024-12-31 17:05:14 +0900 |
| commit | 9a2b7f559c88067c25a65a6a34c8e172bdf830dc (patch) | |
| tree | 56bf93324f9096fc6772e64063c5f9ebc803e90a /src/tui | |
| parent | b8d2b0df7e1241c09eff21dbb63ebcc841efc824 (diff) | |
| download | fzf-9a2b7f559c88067c25a65a6a34c8e172bdf830dc.tar.gz | |
Add --list-border for additional border around the list section
Close #4148
Diffstat (limited to 'src/tui')
| -rw-r--r-- | src/tui/dummy.go | 3 | ||||
| -rw-r--r-- | src/tui/light.go | 81 | ||||
| -rw-r--r-- | src/tui/light_unix.go | 2 | ||||
| -rw-r--r-- | src/tui/light_windows.go | 2 | ||||
| -rw-r--r-- | src/tui/tcell.go | 53 | ||||
| -rw-r--r-- | src/tui/tui.go | 83 |
6 files changed, 149 insertions, 75 deletions
diff --git a/src/tui/dummy.go b/src/tui/dummy.go index 1a761460..a49677c6 100644 --- a/src/tui/dummy.go +++ b/src/tui/dummy.go @@ -30,6 +30,7 @@ const ( ) func (r *FullscreenRenderer) Init() error { return nil } +func (r *FullscreenRenderer) DefaultTheme() *ColorTheme { return nil } func (r *FullscreenRenderer) Resize(maxHeightFunc func(int) int) {} func (r *FullscreenRenderer) Pause(bool) {} func (r *FullscreenRenderer) Resume(bool, bool) {} @@ -48,6 +49,6 @@ func (r *FullscreenRenderer) MaxY() int { return 0 } func (r *FullscreenRenderer) RefreshWindows(windows []Window) {} -func (r *FullscreenRenderer) NewWindow(top int, left int, width int, height int, preview bool, borderStyle BorderStyle) Window { +func (r *FullscreenRenderer) NewWindow(top int, left int, width int, height int, windowType WindowType, borderStyle BorderStyle, erase bool) Window { return nil } diff --git a/src/tui/light.go b/src/tui/light.go index 95984542..f0bb2fdf 100644 --- a/src/tui/light.go +++ b/src/tui/light.go @@ -116,19 +116,19 @@ type LightRenderer struct { } type LightWindow struct { - renderer *LightRenderer - colored bool - preview bool - border BorderStyle - top int - left int - width int - height int - posx int - posy int - tabstop int - fg Color - bg Color + renderer *LightRenderer + colored bool + windowType WindowType + border BorderStyle + top int + left int + width int + height int + posx int + posy int + tabstop int + fg Color + bg Color } func NewLightRenderer(ttyin *os.File, theme *ColorTheme, forceBlack bool, mouse bool, tabstop int, clearOnExit bool, fullscreen bool, maxHeightFunc func(int) int) (Renderer, error) { @@ -174,7 +174,6 @@ func (r *LightRenderer) Init() error { return err } r.updateTerminalSize() - initTheme(r.theme, r.defaultTheme(), r.forceBlack) if r.fullscreen { r.smcup() @@ -780,27 +779,32 @@ func (r *LightRenderer) MaxY() int { return r.height } -func (r *LightRenderer) NewWindow(top int, left int, width int, height int, preview bool, borderStyle BorderStyle) Window { +func (r *LightRenderer) NewWindow(top int, left int, width int, height int, windowType WindowType, borderStyle BorderStyle, erase bool) Window { w := &LightWindow{ - renderer: r, - colored: r.theme.Colored, - preview: preview, - border: borderStyle, - top: top, - left: left, - width: width, - height: height, - tabstop: r.tabstop, - fg: colDefault, - bg: colDefault} - if preview { - w.fg = r.theme.PreviewFg.Color - w.bg = r.theme.PreviewBg.Color - } else { + renderer: r, + colored: r.theme.Colored, + windowType: windowType, + border: borderStyle, + top: top, + left: left, + width: width, + height: height, + tabstop: r.tabstop, + fg: colDefault, + bg: colDefault} + switch windowType { + case WindowBase: w.fg = r.theme.Fg.Color w.bg = r.theme.Bg.Color + case WindowList: + w.fg = r.theme.ListFg.Color + w.bg = r.theme.ListBg.Color + case WindowPreview: + w.fg = r.theme.PreviewFg.Color + w.bg = r.theme.PreviewBg.Color } - if !w.bg.IsDefault() && w.border.shape != BorderNone { + if erase && !w.bg.IsDefault() && w.border.shape != BorderNone { + // fzf --color bg:blue --border --padding 1,2 w.Erase() } w.drawBorder(false) @@ -845,7 +849,10 @@ func (w *LightWindow) drawBorder(onlyHorizontal bool) { func (w *LightWindow) drawBorderHorizontal(top, bottom bool) { color := ColBorder - if w.preview { + switch w.windowType { + case WindowList: + color = ColListBorder + case WindowPreview: color = ColPreviewBorder } hw := runeWidth(w.border.top) @@ -863,7 +870,10 @@ func (w *LightWindow) drawBorderHorizontal(top, bottom bool) { func (w *LightWindow) drawBorderVertical(left, right bool) { vw := runeWidth(w.border.left) color := ColBorder - if w.preview { + switch w.windowType { + case WindowList: + color = ColListBorder + case WindowPreview: color = ColPreviewBorder } for y := 0; y < w.height; y++ { @@ -883,7 +893,10 @@ func (w *LightWindow) drawBorderVertical(left, right bool) { func (w *LightWindow) drawBorderAround(onlyHorizontal bool) { w.Move(0, 0) color := ColBorder - if w.preview { + switch w.windowType { + case WindowList: + color = ColListBorder + case WindowPreview: color = ColPreviewBorder } hw := runeWidth(w.border.top) diff --git a/src/tui/light_unix.go b/src/tui/light_unix.go index c2d5612a..76aac2eb 100644 --- a/src/tui/light_unix.go +++ b/src/tui/light_unix.go @@ -18,7 +18,7 @@ func IsLightRendererSupported() bool { return true } -func (r *LightRenderer) defaultTheme() *ColorTheme { +func (r *LightRenderer) DefaultTheme() *ColorTheme { if strings.Contains(os.Getenv("TERM"), "256") { return Dark256 } diff --git a/src/tui/light_windows.go b/src/tui/light_windows.go index e2a2bbfe..cf5126ab 100644 --- a/src/tui/light_windows.go +++ b/src/tui/light_windows.go @@ -39,7 +39,7 @@ func IsLightRendererSupported() bool { return canSetVt100 } -func (r *LightRenderer) defaultTheme() *ColorTheme { +func (r *LightRenderer) DefaultTheme() *ColorTheme { // the getenv check is borrowed from here: https://github.com/gdamore/tcell/commit/0c473b86d82f68226a142e96cc5a34c5a29b3690#diff-b008fcd5e6934bf31bc3d33bf49f47d8R178: if !IsLightRendererSupported() || os.Getenv("ConEmuPID") != "" || os.Getenv("TCELL_TRUECOLOR") == "disable" { return Default16 diff --git a/src/tui/tcell.go b/src/tui/tcell.go index a3ce2cb1..92336cd0 100644 --- a/src/tui/tcell.go +++ b/src/tui/tcell.go @@ -40,7 +40,7 @@ type Attr int32 type TcellWindow struct { color bool - preview bool + windowType WindowType top int left int width int @@ -106,8 +106,12 @@ func (r *FullscreenRenderer) PassThrough(str string) { func (r *FullscreenRenderer) Resize(maxHeightFunc func(int) int) {} -func (r *FullscreenRenderer) defaultTheme() *ColorTheme { - if _screen.Colors() >= 256 { +func (r *FullscreenRenderer) DefaultTheme() *ColorTheme { + s, e := r.getScreen() + if e != nil { + return Default16 + } + if s.Colors() >= 256 { return Dark256 } return Default16 @@ -148,8 +152,19 @@ var ( _initialResize bool = true ) +func (r *FullscreenRenderer) getScreen() (tcell.Screen, error) { + if _screen == nil { + s, e := tcell.NewScreen() + if e != nil { + return nil, e + } + _screen = s + } + return _screen, nil +} + func (r *FullscreenRenderer) initScreen() error { - s, e := tcell.NewScreen() + s, e := r.getScreen() if e != nil { return e } @@ -161,7 +176,6 @@ func (r *FullscreenRenderer) initScreen() error { } else { s.DisableMouse() } - _screen = s return nil } @@ -174,7 +188,6 @@ func (r *FullscreenRenderer) Init() error { if err := r.initScreen(); err != nil { return err } - initTheme(r.theme, r.defaultTheme(), r.forceBlack) return nil } @@ -537,14 +550,17 @@ func (r *FullscreenRenderer) RefreshWindows(windows []Window) { _screen.Show() } -func (r *FullscreenRenderer) NewWindow(top int, left int, width int, height int, preview bool, borderStyle BorderStyle) Window { - normal := ColNormal - if preview { - normal = ColPreview +func (r *FullscreenRenderer) NewWindow(top int, left int, width int, height int, windowType WindowType, borderStyle BorderStyle, erase bool) Window { + normal := ColBorder + switch windowType { + case WindowList: + normal = ColListBorder + case WindowPreview: + normal = ColPreviewBorder } w := &TcellWindow{ color: r.theme.Colored, - preview: preview, + windowType: windowType, top: top, left: left, width: width, @@ -564,11 +580,7 @@ func fill(x, y, w, h int, n ColorPair, r rune) { } func (w *TcellWindow) Erase() { - if w.borderStyle.shape.HasLeft() { - fill(w.left-1, w.top, w.width, w.height-1, w.normal, ' ') - } else { - fill(w.left, w.top, w.width-1, w.height-1, w.normal, ' ') - } + fill(w.left, w.top, w.width-1, w.height-1, w.normal, ' ') w.drawBorder(false) } @@ -768,10 +780,13 @@ func (w *TcellWindow) drawBorder(onlyHorizontal bool) { var style tcell.Style if w.color { - if w.preview { - style = ColPreviewBorder.style() - } else { + switch w.windowType { + case WindowBase: style = ColBorder.style() + case WindowList: + style = ColListBorder.style() + case WindowPreview: + style = ColPreviewBorder.style() } } else { style = w.normal.style() diff --git a/src/tui/tui.go b/src/tui/tui.go index 902d13fe..e2a891d0 100644 --- a/src/tui/tui.go +++ b/src/tui/tui.go @@ -303,6 +303,8 @@ type ColorTheme struct { Disabled ColorAttr Fg ColorAttr Bg ColorAttr + ListFg ColorAttr + ListBg ColorAttr SelectedFg ColorAttr SelectedBg ColorAttr SelectedMatch ColorAttr @@ -323,9 +325,11 @@ type ColorTheme struct { Scrollbar ColorAttr Border ColorAttr PreviewBorder ColorAttr + PreviewLabel ColorAttr PreviewScrollbar ColorAttr BorderLabel ColorAttr - PreviewLabel ColorAttr + ListLabel ColorAttr + ListBorder ColorAttr } type Event struct { @@ -395,6 +399,10 @@ func (s BorderShape) HasBottom() bool { return true } +func (s BorderShape) Visible() bool { + return s != BorderNone +} + type BorderStyle struct { shape BorderShape top rune @@ -525,7 +533,16 @@ type TermSize struct { PxHeight int } +type WindowType int + +const ( + WindowBase WindowType = iota + WindowList + WindowPreview +) + type Renderer interface { + DefaultTheme() *ColorTheme Init() error Resize(maxHeightFunc func(int) int) Pause(clear bool) @@ -546,7 +563,7 @@ type Renderer interface { Size() TermSize - NewWindow(top int, left int, width int, height int, preview bool, borderStyle BorderStyle) Window + NewWindow(top int, left int, width int, height int, windowType WindowType, borderStyle BorderStyle, erase bool) Window } type Window interface { @@ -627,6 +644,8 @@ var ( ColPreviewLabel ColorPair ColPreviewScrollbar ColorPair ColPreviewSpinner ColorPair + ColListBorder ColorPair + ColListLabel ColorPair ) func EmptyTheme() *ColorTheme { @@ -635,6 +654,8 @@ func EmptyTheme() *ColorTheme { Input: ColorAttr{colUndefined, AttrUndefined}, Fg: ColorAttr{colUndefined, AttrUndefined}, Bg: ColorAttr{colUndefined, AttrUndefined}, + ListFg: ColorAttr{colUndefined, AttrUndefined}, + ListBg: ColorAttr{colUndefined, AttrUndefined}, SelectedFg: ColorAttr{colUndefined, AttrUndefined}, SelectedBg: ColorAttr{colUndefined, AttrUndefined}, SelectedMatch: ColorAttr{colUndefined, AttrUndefined}, @@ -650,6 +671,8 @@ func EmptyTheme() *ColorTheme { Header: ColorAttr{colUndefined, AttrUndefined}, Border: ColorAttr{colUndefined, AttrUndefined}, BorderLabel: ColorAttr{colUndefined, AttrUndefined}, + ListLabel: ColorAttr{colUndefined, AttrUndefined}, + ListBorder: ColorAttr{colUndefined, AttrUndefined}, Disabled: ColorAttr{colUndefined, AttrUndefined}, PreviewFg: ColorAttr{colUndefined, AttrUndefined}, PreviewBg: ColorAttr{colUndefined, AttrUndefined}, @@ -668,6 +691,8 @@ func NoColorTheme() *ColorTheme { Input: ColorAttr{colDefault, AttrUndefined}, Fg: ColorAttr{colDefault, AttrUndefined}, Bg: ColorAttr{colDefault, AttrUndefined}, + ListFg: ColorAttr{colDefault, AttrUndefined}, + ListBg: ColorAttr{colDefault, AttrUndefined}, SelectedFg: ColorAttr{colDefault, AttrUndefined}, SelectedBg: ColorAttr{colDefault, AttrUndefined}, SelectedMatch: ColorAttr{colDefault, AttrUndefined}, @@ -690,6 +715,8 @@ func NoColorTheme() *ColorTheme { 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}, } @@ -701,6 +728,8 @@ func init() { Input: ColorAttr{colDefault, AttrUndefined}, Fg: ColorAttr{colDefault, AttrUndefined}, Bg: ColorAttr{colDefault, AttrUndefined}, + ListFg: ColorAttr{colUndefined, AttrUndefined}, + ListBg: ColorAttr{colUndefined, AttrUndefined}, SelectedFg: ColorAttr{colUndefined, AttrUndefined}, SelectedBg: ColorAttr{colUndefined, AttrUndefined}, SelectedMatch: ColorAttr{colUndefined, AttrUndefined}, @@ -723,6 +752,8 @@ func init() { 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}, } @@ -731,6 +762,8 @@ func init() { Input: ColorAttr{colDefault, AttrUndefined}, Fg: ColorAttr{colDefault, AttrUndefined}, Bg: ColorAttr{colDefault, AttrUndefined}, + ListFg: ColorAttr{colUndefined, AttrUndefined}, + ListBg: ColorAttr{colUndefined, AttrUndefined}, SelectedFg: ColorAttr{colUndefined, AttrUndefined}, SelectedBg: ColorAttr{colUndefined, AttrUndefined}, SelectedMatch: ColorAttr{colUndefined, AttrUndefined}, @@ -753,6 +786,8 @@ func init() { 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}, } @@ -761,6 +796,8 @@ func init() { Input: ColorAttr{colDefault, AttrUndefined}, Fg: ColorAttr{colDefault, AttrUndefined}, Bg: ColorAttr{colDefault, AttrUndefined}, + ListFg: ColorAttr{colUndefined, AttrUndefined}, + ListBg: ColorAttr{colUndefined, AttrUndefined}, SelectedFg: ColorAttr{colUndefined, AttrUndefined}, SelectedBg: ColorAttr{colUndefined, AttrUndefined}, SelectedMatch: ColorAttr{colUndefined, AttrUndefined}, @@ -783,12 +820,14 @@ func init() { 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}, } } -func initTheme(theme *ColorTheme, baseTheme *ColorTheme, forceBlack bool) { +func InitTheme(theme *ColorTheme, baseTheme *ColorTheme, forceBlack bool) { if forceBlack { theme.Bg = ColorAttr{colBlack, AttrUndefined} } @@ -820,8 +859,10 @@ func initTheme(theme *ColorTheme, baseTheme *ColorTheme, forceBlack bool) { theme.BorderLabel = o(baseTheme.BorderLabel, theme.BorderLabel) // These colors are not defined in the base themes - theme.SelectedFg = o(theme.Fg, theme.SelectedFg) - theme.SelectedBg = o(theme.Bg, theme.SelectedBg) + theme.ListFg = o(theme.Fg, theme.ListFg) + theme.ListBg = o(theme.Bg, theme.ListBg) + theme.SelectedFg = o(theme.ListFg, theme.SelectedFg) + theme.SelectedBg = o(theme.ListBg, theme.SelectedBg) theme.SelectedMatch = o(theme.Match, theme.SelectedMatch) theme.Disabled = o(theme.Input, theme.Disabled) theme.Gutter = o(theme.DarkBg, theme.Gutter) @@ -829,8 +870,10 @@ func initTheme(theme *ColorTheme, baseTheme *ColorTheme, forceBlack bool) { 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.ListLabel = o(theme.BorderLabel, theme.ListLabel) + theme.ListBorder = o(theme.Border, theme.ListBorder) + theme.Separator = o(theme.ListBorder, theme.Separator) + theme.Scrollbar = o(theme.ListBorder, theme.Scrollbar) theme.PreviewScrollbar = o(theme.PreviewBorder, theme.PreviewScrollbar) initPalette(theme) @@ -843,19 +886,19 @@ func initPalette(theme *ColorTheme) { } return ColorPair{fg.Color, bg.Color, fg.Attr} } - blank := theme.Fg + blank := theme.ListFg blank.Attr = AttrRegular - ColPrompt = pair(theme.Prompt, theme.Bg) - ColNormal = pair(theme.Fg, theme.Bg) + ColPrompt = pair(theme.Prompt, theme.ListBg) + ColNormal = pair(theme.ListFg, theme.ListBg) ColSelected = pair(theme.SelectedFg, theme.SelectedBg) - ColInput = pair(theme.Input, theme.Bg) - ColDisabled = pair(theme.Disabled, theme.Bg) - ColMatch = pair(theme.Match, theme.Bg) + ColInput = pair(theme.Input, theme.ListBg) + ColDisabled = pair(theme.Disabled, theme.ListBg) + ColMatch = pair(theme.Match, theme.ListBg) ColSelectedMatch = pair(theme.SelectedMatch, theme.SelectedBg) ColCursor = pair(theme.Cursor, theme.Gutter) ColCursorEmpty = pair(blank, theme.Gutter) - if theme.SelectedBg.Color != theme.Bg.Color { + if theme.SelectedBg.Color != theme.ListBg.Color { ColMarker = pair(theme.Marker, theme.SelectedBg) } else { ColMarker = pair(theme.Marker, theme.Gutter) @@ -866,11 +909,11 @@ func initPalette(theme *ColorTheme) { ColCurrentCursorEmpty = pair(blank, theme.DarkBg) ColCurrentMarker = pair(theme.Marker, theme.DarkBg) ColCurrentSelectedEmpty = pair(blank, theme.DarkBg) - ColSpinner = pair(theme.Spinner, theme.Bg) - ColInfo = pair(theme.Info, theme.Bg) - ColHeader = pair(theme.Header, theme.Bg) - ColSeparator = pair(theme.Separator, theme.Bg) - ColScrollbar = pair(theme.Scrollbar, theme.Bg) + ColSpinner = pair(theme.Spinner, theme.ListBg) + ColInfo = pair(theme.Info, theme.ListBg) + ColHeader = pair(theme.Header, theme.ListBg) + ColSeparator = pair(theme.Separator, theme.ListBg) + ColScrollbar = pair(theme.Scrollbar, theme.ListBg) ColBorder = pair(theme.Border, theme.Bg) ColBorderLabel = pair(theme.BorderLabel, theme.Bg) ColPreviewLabel = pair(theme.PreviewLabel, theme.PreviewBg) @@ -878,6 +921,8 @@ func initPalette(theme *ColorTheme) { ColPreviewBorder = pair(theme.PreviewBorder, theme.PreviewBg) ColPreviewScrollbar = pair(theme.PreviewScrollbar, theme.PreviewBg) ColPreviewSpinner = pair(theme.Spinner, theme.PreviewBg) + ColListLabel = pair(theme.ListLabel, theme.ListBg) + ColListBorder = pair(theme.ListBorder, theme.ListBg) } func runeWidth(r rune) int { |
