Add preview-fg and preview-bg for --color

Close #1776
pull/1791/head
Junegunn Choi 5 years ago
parent 8ae96774df
commit 3db6b88d82
No known key found for this signature in database
GPG Key ID: 254BC280FEF9C627

@ -1,8 +1,14 @@
CHANGELOG CHANGELOG
========= =========
0.19.1 (WIP) 0.20.0 (WIP)
------ ------
- Customizable preview window color (`preview-fg` and `preview-bg` for `--color`)
```sh
fzf --preview 'cat {}' \
--color 'fg:#bbccdd,fg+:#ddeeff,bg:#334455,preview-bg:#223344,border:#778899' \
--border --height 20 --layout reverse --info inline
```
- Removed the immediate flicking of the screen on `reload` action. - Removed the immediate flicking of the screen on `reload` action.
```sh ```sh
: | fzf --bind 'change:reload:seq {q}' --phony : | fzf --bind 'change:reload:seq {q}' --phony

@ -21,7 +21,7 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE. THE SOFTWARE.
.. ..
.TH fzf-tmux 1 "Nov 2019" "fzf 0.19.0" "fzf-tmux - open fzf in tmux split pane" .TH fzf-tmux 1 "Dec 2019" "fzf 0.20.0" "fzf-tmux - open fzf in tmux split pane"
.SH NAME .SH NAME
fzf-tmux - open fzf in tmux split pane fzf-tmux - open fzf in tmux split pane

@ -21,7 +21,7 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE. THE SOFTWARE.
.. ..
.TH fzf 1 "Nov 2019" "fzf 0.19.0" "fzf - a command-line fuzzy finder" .TH fzf 1 "Dec 2019" "fzf 0.20.0" "fzf - a command-line fuzzy finder"
.SH NAME .SH NAME
fzf - a command-line fuzzy finder fzf - a command-line fuzzy finder
@ -262,23 +262,25 @@ format.
\fBdark \fRColor scheme for dark 256-color terminal \fBdark \fRColor scheme for dark 256-color terminal
\fBlight \fRColor scheme for light 256-color terminal \fBlight \fRColor scheme for light 256-color terminal
\fB16 \fRColor scheme for 16-color terminal \fB16 \fRColor scheme for 16-color terminal
\fBbw \fRNo colors \fBbw \fRNo colors (equivalent to \fB--no-color\fR)
.B COLOR: .B COLOR:
\fBfg \fRText \fBfg \fRText
\fBbg \fRBackground \fBbg \fRBackground
\fBhl \fRHighlighted substrings \fBpreview-fg \fRPreview window text
\fBfg+ \fRText (current line) \fBpreview-bg \fRPreview window background
\fBbg+ \fRBackground (current line) \fBhl \fRHighlighted substrings
\fBgutter \fRGutter on the left (defaults to \fBbg+\fR) \fBfg+ \fRText (current line)
\fBhl+ \fRHighlighted substrings (current line) \fBbg+ \fRBackground (current line)
\fBinfo \fRInfo \fBgutter \fRGutter on the left (defaults to \fBbg+\fR)
\fBborder \fRBorder of the preview window and horizontal separators (\fB--border\fR) \fBhl+ \fRHighlighted substrings (current line)
\fBprompt \fRPrompt \fBinfo \fRInfo
\fBpointer \fRPointer to the current line \fBborder \fRBorder of the preview window and horizontal separators (\fB--border\fR)
\fBmarker \fRMulti-select marker \fBprompt \fRPrompt
\fBspinner \fRStreaming input indicator \fBpointer \fRPointer to the current line
\fBheader \fRHeader \fBmarker \fRMulti-select marker
\fBspinner \fRStreaming input indicator
\fBheader \fRHeader
.B EXAMPLES: .B EXAMPLES:

@ -597,6 +597,10 @@ func parseTheme(defaultTheme *tui.ColorTheme, str string) *tui.ColorTheme {
theme.Fg = ansi theme.Fg = ansi
case "bg": case "bg":
theme.Bg = ansi theme.Bg = ansi
case "preview-fg":
theme.PreviewFg = ansi
case "preview-bg":
theme.PreviewBg = ansi
case "fg+": case "fg+":
theme.Current = ansi theme.Current = ansi
case "bg+": case "bg+":

@ -624,7 +624,8 @@ func (t *Terminal) resizeWindows() {
marginInt[0]-1, marginInt[0]-1,
marginInt[3], marginInt[3],
width, width,
height+2, tui.MakeBorderStyle(tui.BorderHorizontal, t.unicode)) height+2,
false, tui.MakeBorderStyle(tui.BorderHorizontal, t.unicode))
} }
noBorder := tui.MakeBorderStyle(tui.BorderNone, t.unicode) noBorder := tui.MakeBorderStyle(tui.BorderNone, t.unicode)
if previewVisible { if previewVisible {
@ -633,7 +634,7 @@ func (t *Terminal) resizeWindows() {
if !t.preview.border { if !t.preview.border {
previewBorder = tui.MakeTransparentBorder() previewBorder = tui.MakeTransparentBorder()
} }
t.pborder = t.tui.NewWindow(y, x, w, h, previewBorder) t.pborder = t.tui.NewWindow(y, x, w, h, true, previewBorder)
pwidth := w - 4 pwidth := w - 4
// ncurses auto-wraps the line when the cursor reaches the right-end of // ncurses auto-wraps the line when the cursor reaches the right-end of
// the window. To prevent unintended line-wraps, we use the width one // the window. To prevent unintended line-wraps, we use the width one
@ -641,28 +642,28 @@ func (t *Terminal) resizeWindows() {
if !t.preview.wrap && t.tui.DoesAutoWrap() { if !t.preview.wrap && t.tui.DoesAutoWrap() {
pwidth += 1 pwidth += 1
} }
t.pwindow = t.tui.NewWindow(y+1, x+2, pwidth, h-2, noBorder) t.pwindow = t.tui.NewWindow(y+1, x+2, pwidth, h-2, true, noBorder)
} }
switch t.preview.position { switch t.preview.position {
case posUp: case posUp:
pheight := calculateSize(height, t.preview.size, minHeight, 3) pheight := calculateSize(height, t.preview.size, minHeight, 3)
t.window = t.tui.NewWindow( t.window = t.tui.NewWindow(
marginInt[0]+pheight, marginInt[3], width, height-pheight, noBorder) marginInt[0]+pheight, marginInt[3], width, height-pheight, false, noBorder)
createPreviewWindow(marginInt[0], marginInt[3], width, pheight) createPreviewWindow(marginInt[0], marginInt[3], width, pheight)
case posDown: case posDown:
pheight := calculateSize(height, t.preview.size, minHeight, 3) pheight := calculateSize(height, t.preview.size, minHeight, 3)
t.window = t.tui.NewWindow( t.window = t.tui.NewWindow(
marginInt[0], marginInt[3], width, height-pheight, noBorder) marginInt[0], marginInt[3], width, height-pheight, false, noBorder)
createPreviewWindow(marginInt[0]+height-pheight, marginInt[3], width, pheight) createPreviewWindow(marginInt[0]+height-pheight, marginInt[3], width, pheight)
case posLeft: case posLeft:
pwidth := calculateSize(width, t.preview.size, minWidth, 5) pwidth := calculateSize(width, t.preview.size, minWidth, 5)
t.window = t.tui.NewWindow( t.window = t.tui.NewWindow(
marginInt[0], marginInt[3]+pwidth, width-pwidth, height, noBorder) marginInt[0], marginInt[3]+pwidth, width-pwidth, height, false, noBorder)
createPreviewWindow(marginInt[0], marginInt[3], pwidth, height) createPreviewWindow(marginInt[0], marginInt[3], pwidth, height)
case posRight: case posRight:
pwidth := calculateSize(width, t.preview.size, minWidth, 5) pwidth := calculateSize(width, t.preview.size, minWidth, 5)
t.window = t.tui.NewWindow( t.window = t.tui.NewWindow(
marginInt[0], marginInt[3], width-pwidth, height, noBorder) marginInt[0], marginInt[3], width-pwidth, height, false, noBorder)
createPreviewWindow(marginInt[0], marginInt[3]+width-pwidth, pwidth, height) createPreviewWindow(marginInt[0], marginInt[3]+width-pwidth, pwidth, height)
} }
} else { } else {
@ -670,7 +671,7 @@ func (t *Terminal) resizeWindows() {
marginInt[0], marginInt[0],
marginInt[3], marginInt[3],
width, width,
height, noBorder) height, false, noBorder)
} }
for i := 0; i < t.window.Height(); i++ { for i := 0; i < t.window.Height(); i++ {
t.window.MoveAndClear(i, 0) t.window.MoveAndClear(i, 0)
@ -1071,7 +1072,7 @@ func (t *Terminal) printPreview() {
if t.theme != nil && ansi != nil && ansi.colored() { if t.theme != nil && ansi != nil && ansi.colored() {
fillRet = t.pwindow.CFill(ansi.fg, ansi.bg, ansi.attr, str) fillRet = t.pwindow.CFill(ansi.fg, ansi.bg, ansi.attr, str)
} else { } else {
fillRet = t.pwindow.CFill(tui.ColNormal.Fg(), tui.ColNormal.Bg(), tui.AttrRegular, str) fillRet = t.pwindow.CFill(tui.ColPreview.Fg(), tui.ColPreview.Bg(), tui.AttrRegular, str)
} }
return fillRet == tui.FillContinue return fillRet == tui.FillContinue
}) })

@ -39,6 +39,6 @@ func (r *FullscreenRenderer) MaxY() int { return 0 }
func (r *FullscreenRenderer) RefreshWindows(windows []Window) {} func (r *FullscreenRenderer) RefreshWindows(windows []Window) {}
func (r *FullscreenRenderer) NewWindow(top int, left int, width int, height int, borderStyle BorderStyle) Window { func (r *FullscreenRenderer) NewWindow(top int, left int, width int, height int, preview bool, borderStyle BorderStyle) Window {
return nil return nil
} }

@ -666,7 +666,7 @@ func (r *LightRenderer) DoesAutoWrap() bool {
return false return false
} }
func (r *LightRenderer) NewWindow(top int, left int, width int, height int, borderStyle BorderStyle) Window { func (r *LightRenderer) NewWindow(top int, left int, width int, height int, preview bool, borderStyle BorderStyle) Window {
w := &LightWindow{ w := &LightWindow{
renderer: r, renderer: r,
colored: r.theme != nil, colored: r.theme != nil,
@ -679,8 +679,13 @@ func (r *LightRenderer) NewWindow(top int, left int, width int, height int, bord
fg: colDefault, fg: colDefault,
bg: colDefault} bg: colDefault}
if r.theme != nil { if r.theme != nil {
w.fg = r.theme.Fg if preview {
w.bg = r.theme.Bg w.fg = r.theme.PreviewFg
w.bg = r.theme.PreviewBg
} else {
w.fg = r.theme.Fg
w.bg = r.theme.Bg
}
} }
w.drawBorder() w.drawBorder()
return w return w
@ -704,16 +709,16 @@ func (w *LightWindow) drawBorderHorizontal() {
func (w *LightWindow) drawBorderAround() { func (w *LightWindow) drawBorderAround() {
w.Move(0, 0) w.Move(0, 0)
w.CPrint(ColBorder, AttrRegular, w.CPrint(ColPreviewBorder, AttrRegular,
string(w.border.topLeft)+repeat(w.border.horizontal, w.width-2)+string(w.border.topRight)) string(w.border.topLeft)+repeat(w.border.horizontal, w.width-2)+string(w.border.topRight))
for y := 1; y < w.height-1; y++ { for y := 1; y < w.height-1; y++ {
w.Move(y, 0) w.Move(y, 0)
w.CPrint(ColBorder, AttrRegular, string(w.border.vertical)) w.CPrint(ColPreviewBorder, AttrRegular, string(w.border.vertical))
w.cprint2(colDefault, w.bg, AttrRegular, repeat(' ', w.width-2)) w.CPrint(ColPreviewBorder, AttrRegular, repeat(' ', w.width-2))
w.CPrint(ColBorder, AttrRegular, string(w.border.vertical)) w.CPrint(ColPreviewBorder, AttrRegular, string(w.border.vertical))
} }
w.Move(w.height-1, 0) w.Move(w.height-1, 0)
w.CPrint(ColBorder, AttrRegular, w.CPrint(ColPreviewBorder, AttrRegular,
string(w.border.bottomLeft)+repeat(w.border.horizontal, w.width-2)+string(w.border.bottomRight)) string(w.border.bottomLeft)+repeat(w.border.horizontal, w.width-2)+string(w.border.bottomRight))
} }

@ -32,6 +32,7 @@ type TcellWindow struct {
left int left int
width int width int
height int height int
normal ColorPair
lastX int lastX int
lastY int lastY int
moveCursor bool moveCursor bool
@ -408,14 +409,18 @@ func (r *FullscreenRenderer) RefreshWindows(windows []Window) {
_screen.Show() _screen.Show()
} }
func (r *FullscreenRenderer) NewWindow(top int, left int, width int, height int, borderStyle BorderStyle) Window { func (r *FullscreenRenderer) NewWindow(top int, left int, width int, height int, preview bool, borderStyle BorderStyle) Window {
// TODO normal := ColNormal
if preview {
normal = ColPreview
}
return &TcellWindow{ return &TcellWindow{
color: r.theme != nil, color: r.theme != nil,
top: top, top: top,
left: left, left: left,
width: width, width: width,
height: height, height: height,
normal: normal,
borderStyle: borderStyle} borderStyle: borderStyle}
} }
@ -423,16 +428,16 @@ func (w *TcellWindow) Close() {
// TODO // TODO
} }
func fill(x, y, w, h int, r rune) { func fill(x, y, w, h int, n ColorPair, r rune) {
for ly := 0; ly <= h; ly++ { for ly := 0; ly <= h; ly++ {
for lx := 0; lx <= w; lx++ { for lx := 0; lx <= w; lx++ {
_screen.SetContent(x+lx, y+ly, r, nil, ColNormal.style()) _screen.SetContent(x+lx, y+ly, r, nil, n.style())
} }
} }
} }
func (w *TcellWindow) Erase() { func (w *TcellWindow) Erase() {
fill(w.left-1, w.top, w.width+1, w.height, ' ') fill(w.left-1, w.top, w.width+1, w.height, w.normal, ' ')
} }
func (w *TcellWindow) Enclose(y int, x int) bool { func (w *TcellWindow) Enclose(y int, x int) bool {
@ -449,13 +454,13 @@ func (w *TcellWindow) Move(y int, x int) {
func (w *TcellWindow) MoveAndClear(y int, x int) { func (w *TcellWindow) MoveAndClear(y int, x int) {
w.Move(y, x) w.Move(y, x)
for i := w.lastX; i < w.width; i++ { for i := w.lastX; i < w.width; i++ {
_screen.SetContent(i+w.left, w.lastY+w.top, rune(' '), nil, ColNormal.style()) _screen.SetContent(i+w.left, w.lastY+w.top, rune(' '), nil, w.normal.style())
} }
w.lastX = x w.lastX = x
} }
func (w *TcellWindow) Print(text string) { func (w *TcellWindow) Print(text string) {
w.printString(text, ColNormal, 0) w.printString(text, w.normal, 0)
} }
func (w *TcellWindow) printString(text string, pair ColorPair, a Attr) { func (w *TcellWindow) printString(text string, pair ColorPair, a Attr) {
@ -468,7 +473,7 @@ func (w *TcellWindow) printString(text string, pair ColorPair, a Attr) {
Reverse(a&Attr(tcell.AttrReverse) != 0). Reverse(a&Attr(tcell.AttrReverse) != 0).
Underline(a&Attr(tcell.AttrUnderline) != 0) Underline(a&Attr(tcell.AttrUnderline) != 0)
} else { } else {
style = ColNormal.style(). style = w.normal.style().
Reverse(a&Attr(tcell.AttrReverse) != 0 || pair == ColCurrent || pair == ColCurrentMatch). Reverse(a&Attr(tcell.AttrReverse) != 0 || pair == ColCurrent || pair == ColCurrentMatch).
Underline(a&Attr(tcell.AttrUnderline) != 0 || pair == ColMatch || pair == ColCurrentMatch) Underline(a&Attr(tcell.AttrUnderline) != 0 || pair == ColMatch || pair == ColCurrentMatch)
} }
@ -519,7 +524,7 @@ func (w *TcellWindow) fillString(text string, pair ColorPair, a Attr) FillReturn
if w.color { if w.color {
style = pair.style() style = pair.style()
} else { } else {
style = ColNormal.style() style = w.normal.style()
} }
style = style. style = style.
Blink(a&Attr(tcell.AttrBlink) != 0). Blink(a&Attr(tcell.AttrBlink) != 0).
@ -559,15 +564,15 @@ func (w *TcellWindow) fillString(text string, pair ColorPair, a Attr) FillReturn
} }
func (w *TcellWindow) Fill(str string) FillReturn { func (w *TcellWindow) Fill(str string) FillReturn {
return w.fillString(str, ColNormal, 0) return w.fillString(str, w.normal, 0)
} }
func (w *TcellWindow) CFill(fg Color, bg Color, a Attr, str string) FillReturn { func (w *TcellWindow) CFill(fg Color, bg Color, a Attr, str string) FillReturn {
if fg == colDefault { if fg == colDefault {
fg = ColNormal.Fg() fg = w.normal.Fg()
} }
if bg == colDefault { if bg == colDefault {
bg = ColNormal.Bg() bg = w.normal.Bg()
} }
return w.fillString(str, NewColorPair(fg, bg), a) return w.fillString(str, NewColorPair(fg, bg), a)
} }
@ -584,9 +589,13 @@ func (w *TcellWindow) drawBorder() {
var style tcell.Style var style tcell.Style
if w.color { if w.color {
style = ColBorder.style() if w.borderStyle.shape == BorderAround {
style = ColPreviewBorder.style()
} else {
style = ColBorder.style()
}
} else { } else {
style = ColNormal.style() style = w.normal.style()
} }
for x := left; x < right; x++ { for x := left; x < right; x++ {

@ -173,6 +173,8 @@ func (p ColorPair) Bg() Color {
type ColorTheme struct { type ColorTheme struct {
Fg Color Fg Color
Bg Color Bg Color
PreviewFg Color
PreviewBg Color
DarkBg Color DarkBg Color
Gutter Color Gutter Color
Prompt Color Prompt Color
@ -272,7 +274,7 @@ type Renderer interface {
MaxY() int MaxY() int
DoesAutoWrap() bool DoesAutoWrap() bool
NewWindow(top int, left int, width int, height int, borderStyle BorderStyle) Window NewWindow(top int, left int, width int, height int, preview bool, borderStyle BorderStyle) Window
} }
type Window interface { type Window interface {
@ -334,12 +336,16 @@ var (
ColInfo ColorPair ColInfo ColorPair
ColHeader ColorPair ColHeader ColorPair
ColBorder ColorPair ColBorder ColorPair
ColPreview ColorPair
ColPreviewBorder ColorPair
) )
func EmptyTheme() *ColorTheme { func EmptyTheme() *ColorTheme {
return &ColorTheme{ return &ColorTheme{
Fg: colUndefined, Fg: colUndefined,
Bg: colUndefined, Bg: colUndefined,
PreviewFg: colUndefined,
PreviewBg: colUndefined,
DarkBg: colUndefined, DarkBg: colUndefined,
Gutter: colUndefined, Gutter: colUndefined,
Prompt: colUndefined, Prompt: colUndefined,
@ -363,6 +369,8 @@ func init() {
Default16 = &ColorTheme{ Default16 = &ColorTheme{
Fg: colDefault, Fg: colDefault,
Bg: colDefault, Bg: colDefault,
PreviewFg: colUndefined,
PreviewBg: colUndefined,
DarkBg: colBlack, DarkBg: colBlack,
Gutter: colUndefined, Gutter: colUndefined,
Prompt: colBlue, Prompt: colBlue,
@ -378,6 +386,8 @@ func init() {
Dark256 = &ColorTheme{ Dark256 = &ColorTheme{
Fg: colDefault, Fg: colDefault,
Bg: colDefault, Bg: colDefault,
PreviewFg: colUndefined,
PreviewBg: colUndefined,
DarkBg: 236, DarkBg: 236,
Gutter: colUndefined, Gutter: colUndefined,
Prompt: 110, Prompt: 110,
@ -393,6 +403,8 @@ func init() {
Light256 = &ColorTheme{ Light256 = &ColorTheme{
Fg: colDefault, Fg: colDefault,
Bg: colDefault, Bg: colDefault,
PreviewFg: colUndefined,
PreviewBg: colUndefined,
DarkBg: 251, DarkBg: 251,
Gutter: colUndefined, Gutter: colUndefined,
Prompt: 25, Prompt: 25,
@ -425,6 +437,8 @@ func initTheme(theme *ColorTheme, baseTheme *ColorTheme, forceBlack bool) {
} }
theme.Fg = o(baseTheme.Fg, theme.Fg) theme.Fg = o(baseTheme.Fg, theme.Fg)
theme.Bg = o(baseTheme.Bg, theme.Bg) theme.Bg = o(baseTheme.Bg, theme.Bg)
theme.PreviewFg = o(theme.Fg, o(baseTheme.PreviewFg, theme.PreviewFg))
theme.PreviewBg = o(theme.Bg, o(baseTheme.PreviewBg, theme.PreviewBg))
theme.DarkBg = o(baseTheme.DarkBg, theme.DarkBg) theme.DarkBg = o(baseTheme.DarkBg, theme.DarkBg)
theme.Gutter = o(theme.DarkBg, o(baseTheme.Gutter, theme.Gutter)) theme.Gutter = o(theme.DarkBg, o(baseTheme.Gutter, theme.Gutter))
theme.Prompt = o(baseTheme.Prompt, theme.Prompt) theme.Prompt = o(baseTheme.Prompt, theme.Prompt)
@ -461,6 +475,8 @@ func initPalette(theme *ColorTheme) {
ColInfo = pair(theme.Info, theme.Bg) ColInfo = pair(theme.Info, theme.Bg)
ColHeader = pair(theme.Header, theme.Bg) ColHeader = pair(theme.Header, theme.Bg)
ColBorder = pair(theme.Border, theme.Bg) ColBorder = pair(theme.Border, theme.Bg)
ColPreview = pair(theme.PreviewFg, theme.PreviewBg)
ColPreviewBorder = pair(theme.Border, theme.PreviewBg)
} else { } else {
ColPrompt = pair(colDefault, colDefault) ColPrompt = pair(colDefault, colDefault)
ColNormal = pair(colDefault, colDefault) ColNormal = pair(colDefault, colDefault)
@ -475,6 +491,8 @@ func initPalette(theme *ColorTheme) {
ColInfo = pair(colDefault, colDefault) ColInfo = pair(colDefault, colDefault)
ColHeader = pair(colDefault, colDefault) ColHeader = pair(colDefault, colDefault)
ColBorder = pair(colDefault, colDefault) ColBorder = pair(colDefault, colDefault)
ColPreview = pair(colDefault, colDefault)
ColPreviewBorder = pair(colDefault, colDefault)
} }
} }

Loading…
Cancel
Save