mirror of
https://github.com/junegunn/fzf.git
synced 2025-05-19 04:40:22 -07:00
Add 'alt-bg' color for striped lines (#4370)
Test cases: 1. 'jump' should show alternating background colors even when 'alt-bg' is not defined as before. go run main.go --bind load:jump Two differences: * The alternating lines will not be in bold (was a bug) * The marker column will not be rendered with alternating background color 2. Use alternating background color when 'alt-bg' is set go run main.go --color bg:238,alt-bg:237 go run main.go --color bg:238,alt-bg:237 --highlight-line 3. 'selected-bg' should take precedence go run main.go --color bg:238,alt-bg:237,selected-bg:232 \ --highlight-line --multi --bind 'load:select+up+select+up' 4. Should work with text with ANSI colors declare -f | perl -0777 -pe 's/^}\n/}\0/gm' | bat --plain --language bash --color always | go run main.go --read0 --ansi --reverse --multi \ --color bg:237,alt-bg:238,current-bg:236 --highlight-line --- Close #4354 Fix #4372
This commit is contained in:
parent
cd6677ba1d
commit
cd9517b679
17
CHANGELOG.md
17
CHANGELOG.md
@ -1,6 +1,23 @@
|
|||||||
CHANGELOG
|
CHANGELOG
|
||||||
=========
|
=========
|
||||||
|
|
||||||
|
0.62.0
|
||||||
|
------
|
||||||
|
- Added `alt-bg` color to create striped lines to visually separate rows
|
||||||
|
```sh
|
||||||
|
fzf --color bg:237,alt-bg:238,current-bg:236 --highlight-line
|
||||||
|
|
||||||
|
declare -f | perl -0777 -pe 's/^}\n/}\0/gm' |
|
||||||
|
bat --plain --language bash --color always |
|
||||||
|
fzf --read0 --ansi --reverse --multi \
|
||||||
|
--color bg:237,alt-bg:238,current-bg:236 --highlight-line
|
||||||
|
```
|
||||||
|
- [fish] Improvements in CTRL-R binding (@bitraid)
|
||||||
|
- You can trigger CTRL-R in the middle of a command to insert the selected item
|
||||||
|
- You can delete history items with SHIFT-DEL
|
||||||
|
- Bug fixes and improvements
|
||||||
|
- Fixed unnecessary 100ms delay after `reload`
|
||||||
|
|
||||||
0.61.3
|
0.61.3
|
||||||
------
|
------
|
||||||
- Reverted #4351 as it caused `tmux run-shell 'fzf --tmux'` to fail (#4559 #4560)
|
- Reverted #4351 as it caused `tmux run-shell 'fzf --tmux'` to fail (#4559 #4560)
|
||||||
|
@ -270,6 +270,7 @@ color mappings.
|
|||||||
\fBcurrent\-bg (bg+) \fRBackground (current line)
|
\fBcurrent\-bg (bg+) \fRBackground (current line)
|
||||||
\fBgutter \fRGutter on the left
|
\fBgutter \fRGutter on the left
|
||||||
\fBcurrent\-hl (hl+) \fRHighlighted substrings (current line)
|
\fBcurrent\-hl (hl+) \fRHighlighted substrings (current line)
|
||||||
|
\fBalt\-bg \fRAlternate background color to create striped lines
|
||||||
\fBquery (input\-fg) \fRQuery string
|
\fBquery (input\-fg) \fRQuery string
|
||||||
\fBdisabled \fRQuery string when search is disabled (\fB\-\-disabled\fR)
|
\fBdisabled \fRQuery string when search is disabled (\fB\-\-disabled\fR)
|
||||||
\fBinfo \fRInfo line (match counters)
|
\fBinfo \fRInfo line (match counters)
|
||||||
|
@ -1295,6 +1295,8 @@ func parseTheme(defaultTheme *tui.ColorTheme, str string) (*tui.ColorTheme, erro
|
|||||||
mergeAttr(&theme.Current)
|
mergeAttr(&theme.Current)
|
||||||
case "current-bg", "bg+":
|
case "current-bg", "bg+":
|
||||||
mergeAttr(&theme.DarkBg)
|
mergeAttr(&theme.DarkBg)
|
||||||
|
case "alt-bg":
|
||||||
|
mergeAttr(&theme.AltBg)
|
||||||
case "selected-fg":
|
case "selected-fg":
|
||||||
mergeAttr(&theme.SelectedFg)
|
mergeAttr(&theme.SelectedFg)
|
||||||
case "selected-bg":
|
case "selected-bg":
|
||||||
|
@ -119,7 +119,7 @@ func minRank() Result {
|
|||||||
return Result{item: &minItem, points: [4]uint16{math.MaxUint16, 0, 0, 0}}
|
return Result{item: &minItem, points: [4]uint16{math.MaxUint16, 0, 0, 0}}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (result *Result) colorOffsets(matchOffsets []Offset, nthOffsets []Offset, theme *tui.ColorTheme, colBase tui.ColorPair, colMatch tui.ColorPair, attrNth tui.Attr, current bool) []colorOffset {
|
func (result *Result) colorOffsets(matchOffsets []Offset, nthOffsets []Offset, theme *tui.ColorTheme, colBase tui.ColorPair, colMatch tui.ColorPair, attrNth tui.Attr) []colorOffset {
|
||||||
itemColors := result.item.Colors()
|
itemColors := result.item.Colors()
|
||||||
|
|
||||||
// No ANSI codes
|
// No ANSI codes
|
||||||
@ -182,18 +182,10 @@ func (result *Result) colorOffsets(matchOffsets []Offset, nthOffsets []Offset, t
|
|||||||
fg := ansi.color.fg
|
fg := ansi.color.fg
|
||||||
bg := ansi.color.bg
|
bg := ansi.color.bg
|
||||||
if fg == -1 {
|
if fg == -1 {
|
||||||
if current {
|
fg = colBase.Fg()
|
||||||
fg = theme.Current.Color
|
|
||||||
} else {
|
|
||||||
fg = theme.Fg.Color
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if bg == -1 {
|
if bg == -1 {
|
||||||
if current {
|
bg = colBase.Bg()
|
||||||
bg = theme.DarkBg.Color
|
|
||||||
} else {
|
|
||||||
bg = theme.Bg.Color
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return tui.NewColorPair(fg, bg, ansi.color.attr).MergeAttr(base)
|
return tui.NewColorPair(fg, bg, ansi.color.attr).MergeAttr(base)
|
||||||
}
|
}
|
||||||
|
@ -131,7 +131,7 @@ func TestColorOffset(t *testing.T) {
|
|||||||
|
|
||||||
colBase := tui.NewColorPair(89, 189, tui.AttrUndefined)
|
colBase := tui.NewColorPair(89, 189, tui.AttrUndefined)
|
||||||
colMatch := tui.NewColorPair(99, 199, tui.AttrUndefined)
|
colMatch := tui.NewColorPair(99, 199, tui.AttrUndefined)
|
||||||
colors := item.colorOffsets(offsets, nil, tui.Dark256, colBase, colMatch, tui.AttrUndefined, true)
|
colors := item.colorOffsets(offsets, nil, tui.Dark256, colBase, colMatch, tui.AttrUndefined)
|
||||||
assert := func(idx int, b int32, e int32, c tui.ColorPair) {
|
assert := func(idx int, b int32, e int32, c tui.ColorPair) {
|
||||||
o := colors[idx]
|
o := colors[idx]
|
||||||
if o.offset[0] != b || o.offset[1] != e || o.color != c {
|
if o.offset[0] != b || o.offset[1] != e || o.color != c {
|
||||||
@ -158,7 +158,7 @@ func TestColorOffset(t *testing.T) {
|
|||||||
|
|
||||||
nthOffsets := []Offset{{37, 39}, {42, 45}}
|
nthOffsets := []Offset{{37, 39}, {42, 45}}
|
||||||
for _, attr := range []tui.Attr{tui.AttrRegular, tui.StrikeThrough} {
|
for _, attr := range []tui.Attr{tui.AttrRegular, tui.StrikeThrough} {
|
||||||
colors = item.colorOffsets(offsets, nthOffsets, tui.Dark256, colRegular, colUnderline, attr, true)
|
colors = item.colorOffsets(offsets, nthOffsets, tui.Dark256, colRegular, colUnderline, attr)
|
||||||
|
|
||||||
// [{[0 5] {1 5 0}} {[5 15] {1 5 8}} {[15 20] {1 5 0}}
|
// [{[0 5] {1 5 0}} {[5 15] {1 5 8}} {[15 20] {1 5 0}}
|
||||||
// {[22 25] {2 6 1}} {[25 27] {2 6 9}} {[27 30] {-1 -1 8}}
|
// {[22 25] {2 6 1}} {[25 27] {2 6 9}} {[27 30] {-1 -1 8}}
|
||||||
|
@ -1258,7 +1258,7 @@ func (t *Terminal) ansiLabelPrinter(str string, color *tui.ColorPair, fill bool)
|
|||||||
printFn := func(window tui.Window, limit int) {
|
printFn := func(window tui.Window, limit int) {
|
||||||
if offsets == nil {
|
if offsets == nil {
|
||||||
// tui.Col* are not initialized until renderer.Init()
|
// tui.Col* are not initialized until renderer.Init()
|
||||||
offsets = result.colorOffsets(nil, nil, t.theme, *color, *color, t.nthAttr, false)
|
offsets = result.colorOffsets(nil, nil, t.theme, *color, *color, t.nthAttr)
|
||||||
}
|
}
|
||||||
for limit > 0 {
|
for limit > 0 {
|
||||||
if length > limit {
|
if length > limit {
|
||||||
@ -2791,17 +2791,28 @@ func (t *Terminal) printItem(result Result, line int, maxLine int, index int, cu
|
|||||||
_, selected := t.selected[item.Index()]
|
_, selected := t.selected[item.Index()]
|
||||||
label := ""
|
label := ""
|
||||||
extraWidth := 0
|
extraWidth := 0
|
||||||
|
alt := false
|
||||||
|
altBg := t.theme.AltBg
|
||||||
|
selectedBg := selected && t.theme.SelectedBg != t.theme.ListBg
|
||||||
if t.jumping != jumpDisabled {
|
if t.jumping != jumpDisabled {
|
||||||
if index < len(t.jumpLabels) {
|
if index < len(t.jumpLabels) {
|
||||||
// Striped
|
// Striped
|
||||||
current = index%2 == 0
|
if !altBg.IsColorDefined() {
|
||||||
|
altBg = t.theme.DarkBg
|
||||||
|
alt = index%2 == 0
|
||||||
|
} else {
|
||||||
|
alt = index%2 == 1
|
||||||
|
}
|
||||||
label = t.jumpLabels[index:index+1] + strings.Repeat(" ", util.Max(0, t.pointerLen-1))
|
label = t.jumpLabels[index:index+1] + strings.Repeat(" ", util.Max(0, t.pointerLen-1))
|
||||||
if t.pointerLen == 0 {
|
if t.pointerLen == 0 {
|
||||||
extraWidth = 1
|
extraWidth = 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if current {
|
} else {
|
||||||
label = t.pointer
|
if current {
|
||||||
|
label = t.pointer
|
||||||
|
}
|
||||||
|
alt = !selectedBg && altBg.IsColorDefined() && index%2 == 1
|
||||||
}
|
}
|
||||||
|
|
||||||
// Avoid unnecessary redraw
|
// Avoid unnecessary redraw
|
||||||
@ -2828,10 +2839,12 @@ func (t *Terminal) printItem(result Result, line int, maxLine int, index int, cu
|
|||||||
maxWidth := t.window.Width() - (t.pointerLen + t.markerLen + 1)
|
maxWidth := t.window.Width() - (t.pointerLen + t.markerLen + 1)
|
||||||
postTask := func(lineNum int, width int, wrapped bool, forceRedraw bool) {
|
postTask := func(lineNum int, width int, wrapped bool, forceRedraw bool) {
|
||||||
width += extraWidth
|
width += extraWidth
|
||||||
if (current || selected) && t.highlightLine {
|
if (current || selected || alt) && t.highlightLine {
|
||||||
color := tui.ColSelected
|
color := tui.ColSelected
|
||||||
if current {
|
if current {
|
||||||
color = tui.ColCurrent
|
color = tui.ColCurrent
|
||||||
|
} else if alt {
|
||||||
|
color = color.WithBg(altBg)
|
||||||
}
|
}
|
||||||
fillSpaces := maxWidth - width
|
fillSpaces := maxWidth - width
|
||||||
if wrapped {
|
if wrapped {
|
||||||
@ -2929,6 +2942,10 @@ func (t *Terminal) printItem(result Result, line int, maxLine int, index int, cu
|
|||||||
base = tui.ColNormal
|
base = tui.ColNormal
|
||||||
match = tui.ColMatch
|
match = tui.ColMatch
|
||||||
}
|
}
|
||||||
|
if alt {
|
||||||
|
base = base.WithBg(altBg)
|
||||||
|
match = match.WithBg(altBg)
|
||||||
|
}
|
||||||
finalLineNum = t.printHighlighted(result, base, match, false, true, line, maxLine, forceRedraw, preTask, postTask)
|
finalLineNum = t.printHighlighted(result, base, match, false, true, line, maxLine, forceRedraw, preTask, postTask)
|
||||||
}
|
}
|
||||||
for i := 0; i < t.gap && finalLineNum < maxLine; i++ {
|
for i := 0; i < t.gap && finalLineNum < maxLine; i++ {
|
||||||
@ -3027,7 +3044,7 @@ func (t *Terminal) printHighlighted(result Result, colBase tui.ColorPair, colMat
|
|||||||
sort.Sort(ByOrder(nthOffsets))
|
sort.Sort(ByOrder(nthOffsets))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
allOffsets := result.colorOffsets(charOffsets, nthOffsets, t.theme, colBase, colMatch, t.nthAttr, current)
|
allOffsets := result.colorOffsets(charOffsets, nthOffsets, t.theme, colBase, colMatch, t.nthAttr)
|
||||||
|
|
||||||
maxLines := 1
|
maxLines := 1
|
||||||
if t.canSpanMultiLines() {
|
if t.canSpanMultiLines() {
|
||||||
|
@ -308,6 +308,12 @@ func (p ColorPair) WithAttr(attr Attr) ColorPair {
|
|||||||
return dup
|
return dup
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p ColorPair) WithBg(bg ColorAttr) ColorPair {
|
||||||
|
dup := p
|
||||||
|
bgPair := ColorPair{colUndefined, bg.Color, bg.Attr}
|
||||||
|
return dup.Merge(bgPair)
|
||||||
|
}
|
||||||
|
|
||||||
func (p ColorPair) MergeAttr(other ColorPair) ColorPair {
|
func (p ColorPair) MergeAttr(other ColorPair) ColorPair {
|
||||||
return p.WithAttr(other.attr)
|
return p.WithAttr(other.attr)
|
||||||
}
|
}
|
||||||
@ -328,6 +334,7 @@ type ColorTheme struct {
|
|||||||
Bg ColorAttr
|
Bg ColorAttr
|
||||||
ListFg ColorAttr
|
ListFg ColorAttr
|
||||||
ListBg ColorAttr
|
ListBg ColorAttr
|
||||||
|
AltBg ColorAttr
|
||||||
Nth ColorAttr
|
Nth ColorAttr
|
||||||
SelectedFg ColorAttr
|
SelectedFg ColorAttr
|
||||||
SelectedBg ColorAttr
|
SelectedBg ColorAttr
|
||||||
@ -735,6 +742,7 @@ func EmptyTheme() *ColorTheme {
|
|||||||
Bg: ColorAttr{colUndefined, AttrUndefined},
|
Bg: ColorAttr{colUndefined, AttrUndefined},
|
||||||
ListFg: ColorAttr{colUndefined, AttrUndefined},
|
ListFg: ColorAttr{colUndefined, AttrUndefined},
|
||||||
ListBg: ColorAttr{colUndefined, AttrUndefined},
|
ListBg: ColorAttr{colUndefined, AttrUndefined},
|
||||||
|
AltBg: ColorAttr{colUndefined, AttrUndefined},
|
||||||
SelectedFg: ColorAttr{colUndefined, AttrUndefined},
|
SelectedFg: ColorAttr{colUndefined, AttrUndefined},
|
||||||
SelectedBg: ColorAttr{colUndefined, AttrUndefined},
|
SelectedBg: ColorAttr{colUndefined, AttrUndefined},
|
||||||
SelectedMatch: ColorAttr{colUndefined, AttrUndefined},
|
SelectedMatch: ColorAttr{colUndefined, AttrUndefined},
|
||||||
@ -780,6 +788,7 @@ func NoColorTheme() *ColorTheme {
|
|||||||
Bg: ColorAttr{colDefault, AttrUndefined},
|
Bg: ColorAttr{colDefault, AttrUndefined},
|
||||||
ListFg: ColorAttr{colDefault, AttrUndefined},
|
ListFg: ColorAttr{colDefault, AttrUndefined},
|
||||||
ListBg: ColorAttr{colDefault, AttrUndefined},
|
ListBg: ColorAttr{colDefault, AttrUndefined},
|
||||||
|
AltBg: ColorAttr{colUndefined, AttrUndefined},
|
||||||
SelectedFg: ColorAttr{colDefault, AttrUndefined},
|
SelectedFg: ColorAttr{colDefault, AttrUndefined},
|
||||||
SelectedBg: ColorAttr{colDefault, AttrUndefined},
|
SelectedBg: ColorAttr{colDefault, AttrUndefined},
|
||||||
SelectedMatch: ColorAttr{colDefault, AttrUndefined},
|
SelectedMatch: ColorAttr{colDefault, AttrUndefined},
|
||||||
@ -825,6 +834,7 @@ func init() {
|
|||||||
Bg: ColorAttr{colDefault, AttrUndefined},
|
Bg: ColorAttr{colDefault, AttrUndefined},
|
||||||
ListFg: ColorAttr{colUndefined, AttrUndefined},
|
ListFg: ColorAttr{colUndefined, AttrUndefined},
|
||||||
ListBg: ColorAttr{colUndefined, AttrUndefined},
|
ListBg: ColorAttr{colUndefined, AttrUndefined},
|
||||||
|
AltBg: ColorAttr{colUndefined, AttrUndefined},
|
||||||
SelectedFg: ColorAttr{colUndefined, AttrUndefined},
|
SelectedFg: ColorAttr{colUndefined, AttrUndefined},
|
||||||
SelectedBg: ColorAttr{colUndefined, AttrUndefined},
|
SelectedBg: ColorAttr{colUndefined, AttrUndefined},
|
||||||
SelectedMatch: ColorAttr{colUndefined, AttrUndefined},
|
SelectedMatch: ColorAttr{colUndefined, AttrUndefined},
|
||||||
@ -864,6 +874,7 @@ func init() {
|
|||||||
Bg: ColorAttr{colDefault, AttrUndefined},
|
Bg: ColorAttr{colDefault, AttrUndefined},
|
||||||
ListFg: ColorAttr{colUndefined, AttrUndefined},
|
ListFg: ColorAttr{colUndefined, AttrUndefined},
|
||||||
ListBg: ColorAttr{colUndefined, AttrUndefined},
|
ListBg: ColorAttr{colUndefined, AttrUndefined},
|
||||||
|
AltBg: ColorAttr{colUndefined, AttrUndefined},
|
||||||
SelectedFg: ColorAttr{colUndefined, AttrUndefined},
|
SelectedFg: ColorAttr{colUndefined, AttrUndefined},
|
||||||
SelectedBg: ColorAttr{colUndefined, AttrUndefined},
|
SelectedBg: ColorAttr{colUndefined, AttrUndefined},
|
||||||
SelectedMatch: ColorAttr{colUndefined, AttrUndefined},
|
SelectedMatch: ColorAttr{colUndefined, AttrUndefined},
|
||||||
@ -903,6 +914,7 @@ func init() {
|
|||||||
Bg: ColorAttr{colDefault, AttrUndefined},
|
Bg: ColorAttr{colDefault, AttrUndefined},
|
||||||
ListFg: ColorAttr{colUndefined, AttrUndefined},
|
ListFg: ColorAttr{colUndefined, AttrUndefined},
|
||||||
ListBg: ColorAttr{colUndefined, AttrUndefined},
|
ListBg: ColorAttr{colUndefined, AttrUndefined},
|
||||||
|
AltBg: ColorAttr{colUndefined, AttrUndefined},
|
||||||
SelectedFg: ColorAttr{colUndefined, AttrUndefined},
|
SelectedFg: ColorAttr{colUndefined, AttrUndefined},
|
||||||
SelectedBg: ColorAttr{colUndefined, AttrUndefined},
|
SelectedBg: ColorAttr{colUndefined, AttrUndefined},
|
||||||
SelectedMatch: ColorAttr{colUndefined, AttrUndefined},
|
SelectedMatch: ColorAttr{colUndefined, AttrUndefined},
|
||||||
|
Loading…
x
Reference in New Issue
Block a user