Support ANSI code for clearing the rest of the line (ESC[0K)

Some programs use it to set the background color for the whole line.

  fzf --preview "printf 'normal \x1b[42mgreen\x1b[0K \x1b[43myellow\x1b[m\nnormal again'"

  fzf --preview 'delta <(echo foo) <(echo bar) < /dev/tty'

Fix #2249
This commit is contained in:
Junegunn Choi 2020-11-25 01:40:30 +09:00
parent 3fe8eeedc5
commit 3829eab1cf
No known key found for this signature in database
GPG Key ID: 254BC280FEF9C627
3 changed files with 21 additions and 7 deletions

View File

@ -19,17 +19,18 @@ type ansiState struct {
fg tui.Color
bg tui.Color
attr tui.Attr
lbg tui.Color
}
func (s *ansiState) colored() bool {
return s.fg != -1 || s.bg != -1 || s.attr > 0
return s.fg != -1 || s.bg != -1 || s.attr > 0 || s.lbg >= 0
}
func (s *ansiState) equals(t *ansiState) bool {
if t == nil {
return !s.colored()
}
return s.fg == t.fg && s.bg == t.bg && s.attr == t.attr
return s.fg == t.fg && s.bg == t.bg && s.attr == t.attr && s.lbg == t.lbg
}
func (s *ansiState) ToString() string {
@ -195,11 +196,14 @@ func interpretCode(ansiCode string, prevState *ansiState) *ansiState {
// State
var state *ansiState
if prevState == nil {
state = &ansiState{-1, -1, 0}
state = &ansiState{-1, -1, 0, -1}
} else {
state = &ansiState{prevState.fg, prevState.bg, prevState.attr}
state = &ansiState{prevState.fg, prevState.bg, prevState.attr, prevState.lbg}
}
if ansiCode[0] != '\x1b' || ansiCode[1] != '[' || ansiCode[len(ansiCode)-1] != 'm' {
if strings.HasSuffix(ansiCode, "0K") {
state.lbg = prevState.bg
}
return state
}

View File

@ -525,7 +525,7 @@ func (t *Terminal) parsePrompt(prompt string) (func(), int) {
// // unless the part has a non-default ANSI state
loc := whiteSuffix.FindStringIndex(trimmed)
if loc != nil {
blankState := ansiOffset{[2]int32{int32(loc[0]), int32(loc[1])}, ansiState{-1, -1, tui.AttrClear}}
blankState := ansiOffset{[2]int32{int32(loc[0]), int32(loc[1])}, ansiState{-1, -1, tui.AttrClear, -1}}
if item.colors != nil {
lastColor := (*item.colors)[len(*item.colors)-1]
if lastColor.offset[1] < int32(loc[1]) {
@ -1277,6 +1277,10 @@ func (t *Terminal) renderPreviewText(unchanged bool) {
}
var ansi *ansiState
for _, line := range t.previewer.lines {
var lbg tui.Color = -1
if ansi != nil {
ansi.lbg = -1
}
line = strings.TrimSuffix(line, "\n")
if lineNo >= height || t.pwindow.Y() == height-1 && t.pwindow.X() > 0 {
t.previewed.filled = true
@ -1292,6 +1296,7 @@ func (t *Terminal) renderPreviewText(unchanged bool) {
str, width := t.processTabs(trimmed, prefixWidth)
prefixWidth += width
if t.theme.Colored && ansi != nil && ansi.colored() {
lbg = ansi.lbg
fillRet = t.pwindow.CFill(ansi.fg, ansi.bg, ansi.attr, str)
} else {
fillRet = t.pwindow.CFill(tui.ColPreview.Fg(), tui.ColPreview.Bg(), tui.AttrRegular, str)
@ -1308,7 +1313,12 @@ func (t *Terminal) renderPreviewText(unchanged bool) {
if unchanged && lineNo == 0 {
break
}
t.pwindow.Fill("\n")
if lbg >= 0 {
t.pwindow.CFill(-1, lbg, tui.AttrRegular,
strings.Repeat(" ", t.pwindow.Width()-t.pwindow.X())+"\n")
} else {
t.pwindow.Fill("\n")
}
}
lineNo++
}

View File

@ -4,7 +4,7 @@
package tui
type Attr int
type Attr int32
func HasFullscreenRenderer() bool {
return false