mirror of
https://github.com/junegunn/fzf.git
synced 2025-11-08 11:23:47 -05:00
Add special 'strip' style attribute for stripping colors
Test cases: fd --color always | fzf --ansi --delimiter / fd --color always | fzf --ansi --delimiter / --nth -1 --color fg:dim,nth:regular fd --color always | fzf --ansi --delimiter / --nth -1 --color fg:dim:strip,nth:regular fd --color always | fzf --ansi --delimiter / --nth -1 --color fg:dim:strip,nth:regular --raw fd --color always | fzf --ansi --delimiter / --nth -1 --color fg:dim:strip,nth:regular,hidden:strikethrough --raw fd --color always | fzf --ansi --delimiter / --nth -1 --color fg:dim:strip,nth:regular,hidden:strip:strikethrough --raw fd --color always | fzf --ansi --delimiter / --nth -1 --color fg:dim:strip,nth:regular,hidden:strip:dim:strikethrough --raw
This commit is contained in:
@@ -50,6 +50,14 @@ fzf --raw --color hidden:red:strikethrough:dim
|
||||
fzf --raw --color hidden:red:strikethrough:dim:italic
|
||||
```
|
||||
|
||||
For colored input, dimming alone may not be enough, and you may prefer to remove
|
||||
colors entirely. For that case, a new special style attribute `strip` has been
|
||||
added.
|
||||
|
||||
```sh
|
||||
fd --color always | fzf --ansi --raw --color hidden:dim:strip:strikethrough
|
||||
```
|
||||
|
||||
#### Conditional actions for raw mode
|
||||
|
||||
You may want to perform different actions depending on whether the current item
|
||||
|
||||
@@ -325,7 +325,8 @@ color mappings. Each entry is separated by a comma and/or whitespaces.
|
||||
\fB#rrggbb \fR24-bit colors
|
||||
|
||||
.B ANSI ATTRIBUTES: (Only applies to foreground colors)
|
||||
\fBregular \fRClears previously set attributes; should precede the other ones
|
||||
\fBregular \fRClear previously set attributes; should precede the other ones
|
||||
\fBstrip \fRRemove colors
|
||||
\fBbold\fR
|
||||
\fBunderline\fR
|
||||
\fBreverse\fR
|
||||
|
||||
@@ -1366,6 +1366,8 @@ func parseTheme(defaultTheme *tui.ColorTheme, str string) (*tui.ColorTheme, *tui
|
||||
cattr.Attr |= tui.Bold
|
||||
case "dim":
|
||||
cattr.Attr |= tui.Dim
|
||||
case "strip":
|
||||
cattr.Attr |= tui.Strip
|
||||
case "italic":
|
||||
cattr.Attr |= tui.Italic
|
||||
case "underline":
|
||||
|
||||
@@ -123,7 +123,7 @@ func minRank() Result {
|
||||
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) []colorOffset {
|
||||
func (result *Result) colorOffsets(matchOffsets []Offset, nthOffsets []Offset, theme *tui.ColorTheme, colBase tui.ColorPair, colMatch tui.ColorPair, attrNth tui.Attr, hidden bool) []colorOffset {
|
||||
itemColors := result.item.Colors()
|
||||
|
||||
// No ANSI codes
|
||||
@@ -194,6 +194,10 @@ func (result *Result) colorOffsets(matchOffsets []Offset, nthOffsets []Offset, t
|
||||
if !theme.Colored {
|
||||
return tui.NewColorPair(-1, -1, ansi.color.attr).MergeAttr(base)
|
||||
}
|
||||
// fd --color always | fzf --ansi --delimiter / --nth -1 --color fg:dim:strip,nth:regular
|
||||
if base.ShouldStripColors() {
|
||||
return base
|
||||
}
|
||||
fg := ansi.color.fg
|
||||
bg := ansi.color.bg
|
||||
if fg == -1 {
|
||||
@@ -251,6 +255,9 @@ func (result *Result) colorOffsets(matchOffsets []Offset, nthOffsets []Offset, t
|
||||
if curr.nth {
|
||||
base = base.WithAttr(attrNth)
|
||||
}
|
||||
if hidden {
|
||||
base = base.WithFg(theme.Hidden)
|
||||
}
|
||||
color := ansiToColorPair(ansi, base)
|
||||
colors = append(colors, colorOffset{
|
||||
offset: [2]int32{int32(start), int32(idx)},
|
||||
@@ -258,9 +265,13 @@ func (result *Result) colorOffsets(matchOffsets []Offset, nthOffsets []Offset, t
|
||||
match: false,
|
||||
url: ansi.color.url})
|
||||
} else {
|
||||
color := colBase.WithAttr(attrNth)
|
||||
if hidden {
|
||||
color = color.WithFg(theme.Hidden)
|
||||
}
|
||||
colors = append(colors, colorOffset{
|
||||
offset: [2]int32{int32(start), int32(idx)},
|
||||
color: colBase.WithAttr(attrNth),
|
||||
color: color,
|
||||
match: false,
|
||||
url: nil})
|
||||
}
|
||||
|
||||
@@ -131,7 +131,7 @@ func TestColorOffset(t *testing.T) {
|
||||
|
||||
colBase := tui.NewColorPair(89, 189, tui.AttrUndefined)
|
||||
colMatch := tui.NewColorPair(99, 199, tui.AttrUndefined)
|
||||
colors := item.colorOffsets(offsets, nil, tui.Dark256, colBase, colMatch, tui.AttrUndefined)
|
||||
colors := item.colorOffsets(offsets, nil, tui.Dark256, colBase, colMatch, tui.AttrUndefined, false)
|
||||
assert := func(idx int, b int32, e int32, c tui.ColorPair) {
|
||||
o := colors[idx]
|
||||
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}}
|
||||
for _, attr := range []tui.Attr{tui.AttrRegular, tui.StrikeThrough} {
|
||||
colors = item.colorOffsets(offsets, nthOffsets, tui.Dark256, colRegular, colUnderline, attr)
|
||||
colors = item.colorOffsets(offsets, nthOffsets, tui.Dark256, colRegular, colUnderline, attr, false)
|
||||
|
||||
// [{[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}}
|
||||
|
||||
@@ -1485,7 +1485,7 @@ func (t *Terminal) ansiLabelPrinter(str string, color *tui.ColorPair, fill bool)
|
||||
printFn := func(window tui.Window, limit int) {
|
||||
if offsets == nil {
|
||||
// tui.Col* are not initialized until renderer.Init()
|
||||
offsets = result.colorOffsets(nil, nil, t.theme, *color, *color, t.nthAttr)
|
||||
offsets = result.colorOffsets(nil, nil, t.theme, *color, *color, t.nthAttr, false)
|
||||
}
|
||||
for limit > 0 {
|
||||
if length > limit {
|
||||
@@ -1548,7 +1548,7 @@ func (t *Terminal) parsePrompt(prompt string) (func(), int) {
|
||||
return 1
|
||||
}
|
||||
t.printHighlighted(
|
||||
Result{item: item}, tui.ColPrompt, tui.ColPrompt, false, false, line, line, true, preTask, nil)
|
||||
Result{item: item}, tui.ColPrompt, tui.ColPrompt, false, false, false, line, line, true, preTask, nil)
|
||||
})
|
||||
t.wrap = wrap
|
||||
}
|
||||
@@ -3070,7 +3070,7 @@ func (t *Terminal) printFooter() {
|
||||
colors: colors}
|
||||
|
||||
t.printHighlighted(Result{item: item},
|
||||
tui.ColFooter, tui.ColFooter, false, false, line, line, true,
|
||||
tui.ColFooter, tui.ColFooter, false, false, false, line, line, true,
|
||||
func(markerClass) int {
|
||||
t.footerWindow.Print(indent)
|
||||
return indentSize
|
||||
@@ -3142,7 +3142,7 @@ func (t *Terminal) printHeaderImpl(window tui.Window, borderShape tui.BorderShap
|
||||
colors: colors}
|
||||
|
||||
t.printHighlighted(Result{item: item},
|
||||
tui.ColHeader, tui.ColHeader, false, false, line, line, true,
|
||||
tui.ColHeader, tui.ColHeader, false, false, false, line, line, true,
|
||||
func(markerClass) int {
|
||||
t.window.Print(indent)
|
||||
return indentSize
|
||||
@@ -3378,13 +3378,7 @@ func (t *Terminal) printItem(result Result, line int, maxLine int, index int, cu
|
||||
}
|
||||
return indentSize
|
||||
}
|
||||
base := tui.ColCurrent
|
||||
match := tui.ColCurrentMatch
|
||||
if !matched {
|
||||
base = base.WithFg(t.theme.Hidden)
|
||||
match = match.WithFg(t.theme.Hidden)
|
||||
}
|
||||
finalLineNum = t.printHighlighted(result, base, match, true, true, line, maxLine, forceRedraw, preTask, postTask)
|
||||
finalLineNum = t.printHighlighted(result, tui.ColCurrent, tui.ColCurrentMatch, true, true, !matched, line, maxLine, forceRedraw, preTask, postTask)
|
||||
} else {
|
||||
preTask := func(marker markerClass) int {
|
||||
w := t.window.Width() - t.pointerLen
|
||||
@@ -3418,11 +3412,7 @@ func (t *Terminal) printItem(result Result, line int, maxLine int, index int, cu
|
||||
base = base.WithBg(altBg)
|
||||
match = match.WithBg(altBg)
|
||||
}
|
||||
if !matched {
|
||||
base = base.WithFg(t.theme.Hidden)
|
||||
match = match.WithFg(t.theme.Hidden)
|
||||
}
|
||||
finalLineNum = t.printHighlighted(result, base, match, false, true, line, maxLine, forceRedraw, preTask, postTask)
|
||||
finalLineNum = t.printHighlighted(result, base, match, false, true, !matched, line, maxLine, forceRedraw, preTask, postTask)
|
||||
}
|
||||
for i := 0; i < t.gap && finalLineNum < maxLine; i++ {
|
||||
finalLineNum++
|
||||
@@ -3469,7 +3459,7 @@ func (t *Terminal) overflow(runes []rune, max int) bool {
|
||||
return t.displayWidthWithLimit(runes, 0, max) > max
|
||||
}
|
||||
|
||||
func (t *Terminal) printHighlighted(result Result, colBase tui.ColorPair, colMatch tui.ColorPair, current bool, match bool, lineNum int, maxLineNum int, forceRedraw bool, preTask func(markerClass) int, postTask func(int, int, bool, bool, tui.ColorPair)) int {
|
||||
func (t *Terminal) printHighlighted(result Result, colBase tui.ColorPair, colMatch tui.ColorPair, current bool, match bool, hidden bool, lineNum int, maxLineNum int, forceRedraw bool, preTask func(markerClass) int, postTask func(int, int, bool, bool, tui.ColorPair)) int {
|
||||
var displayWidth int
|
||||
item := result.item
|
||||
matchOffsets := []Offset{}
|
||||
@@ -3521,7 +3511,7 @@ func (t *Terminal) printHighlighted(result Result, colBase tui.ColorPair, colMat
|
||||
sort.Sort(ByOrder(nthOffsets))
|
||||
}
|
||||
}
|
||||
allOffsets := result.colorOffsets(charOffsets, nthOffsets, t.theme, colBase, colMatch, t.nthAttr)
|
||||
allOffsets := result.colorOffsets(charOffsets, nthOffsets, t.theme, colBase, colMatch, t.nthAttr, hidden)
|
||||
|
||||
maxLines := 1
|
||||
if t.canSpanMultiLines() {
|
||||
|
||||
@@ -16,6 +16,7 @@ const (
|
||||
AttrClear = Attr(1 << 9)
|
||||
BoldForce = Attr(1 << 10)
|
||||
FullBg = Attr(1 << 11)
|
||||
Strip = Attr(1 << 12)
|
||||
)
|
||||
|
||||
func (a Attr) Merge(b Attr) Attr {
|
||||
@@ -384,6 +385,10 @@ func (p ColorPair) IsFullBgMarker() bool {
|
||||
return p.attr&FullBg > 0
|
||||
}
|
||||
|
||||
func (p ColorPair) ShouldStripColors() bool {
|
||||
return p.attr&Strip > 0
|
||||
}
|
||||
|
||||
func (p ColorPair) HasBg() bool {
|
||||
return p.attr&Reverse == 0 && p.bg != colDefault ||
|
||||
p.attr&Reverse > 0 && p.fg != colDefault
|
||||
|
||||
Reference in New Issue
Block a user