summaryrefslogtreecommitdiff
path: root/src/ansi.go
diff options
context:
space:
mode:
authorJunegunn Choi <junegunn.c@gmail.com>2025-06-24 22:50:02 +0900
committerJunegunn Choi <junegunn.c@gmail.com>2025-06-25 02:12:10 +0900
commit4811e52af3ed7f89e82baa908f9a8a25fb593361 (patch)
treeda7d88eadf9a0e8044b4748dd790cd599117b663 /src/ansi.go
parent8d81730ec2855d3d32a171f8b675430ffb4c4d59 (diff)
downloadfzf-4811e52af3ed7f89e82baa908f9a8a25fb593361.tar.gz
Support full-line background color in the list section
Close #4432
Diffstat (limited to 'src/ansi.go')
-rw-r--r--src/ansi.go34
1 files changed, 30 insertions, 4 deletions
diff --git a/src/ansi.go b/src/ansi.go
index 79359d34..cbe73c21 100644
--- a/src/ansi.go
+++ b/src/ansi.go
@@ -156,13 +156,13 @@ func isCtrlSeqStart(c uint8) bool {
// nextAnsiEscapeSequence returns the ANSI escape sequence and is equivalent to
// calling FindStringIndex() on the below regex (which was originally used):
//
-// "(?:\x1b[\\[()][0-9;:?]*[a-zA-Z@]|\x1b][0-9]+[;:][[:print:]]+(?:\x1b\\\\|\x07)|\x1b.|[\x0e\x0f]|.\x08)"
+// "(?:\x1b[\\[()][0-9;:?]*[a-zA-Z@]|\x1b][0-9]+[;:][[:print:]]+(?:\x1b\\\\|\x07)|\x1b.|[\x0e\x0f]|.\x08|\n)"
func nextAnsiEscapeSequence(s string) (int, int) {
// fast check for ANSI escape sequences
i := 0
for ; i < len(s); i++ {
switch s[i] {
- case '\x0e', '\x0f', '\x1b', '\x08':
+ case '\x0e', '\x0f', '\x1b', '\x08', '\n':
// We ignore the fact that '\x08' cannot be the first char
// in the string and be an escape sequence for the sake of
// speed and simplicity.
@@ -174,6 +174,9 @@ func nextAnsiEscapeSequence(s string) (int, int) {
Loop:
for ; i < len(s); i++ {
switch s[i] {
+ case '\n':
+ // match: `\n`
+ return i, i + 1
case '\x08':
// backtrack to match: `.\x08`
if i > 0 && s[i-1] != '\n' {
@@ -265,13 +268,27 @@ func extractColor(str string, state *ansiState, proc func(string, *ansiState) bo
output.WriteString(prev)
}
- newState := interpretCode(str[start:idx], state)
- if !newState.equals(state) {
+ code := str[start:idx]
+ newState := interpretCode(code, state)
+ if code == "\n" || !newState.equals(state) {
if state != nil {
// Update last offset
(&offsets[len(offsets)-1]).offset[1] = int32(runeCount)
}
+ if code == "\n" {
+ output.WriteRune('\n')
+ // Full-background marker
+ if newState.lbg >= 0 {
+ marker := newState
+ marker.attr |= tui.FullBg
+ offsets = append(offsets, ansiOffset{
+ [2]int32{int32(runeCount), int32(runeCount)},
+ marker,
+ })
+ }
+ }
+
if newState.colored() {
// Append new offset
if pstate == nil {
@@ -349,6 +366,13 @@ func parseAnsiCode(s string) (int, string) {
}
func interpretCode(ansiCode string, prevState *ansiState) ansiState {
+ if ansiCode == "\n" {
+ if prevState != nil {
+ return *prevState
+ }
+ return ansiState{-1, -1, 0, -1, nil}
+ }
+
var state ansiState
if prevState == nil {
state = ansiState{-1, -1, 0, -1, nil}
@@ -435,6 +459,7 @@ func interpretCode(ansiCode string, prevState *ansiState) ansiState {
state.fg = -1
state.bg = -1
state.attr = 0
+ state.lbg = -1
state256 = 0
default:
if num >= 30 && num <= 37 {
@@ -477,6 +502,7 @@ func interpretCode(ansiCode string, prevState *ansiState) ansiState {
state.fg = -1
state.bg = -1
state.attr = 0
+ state.lbg = -1
}
if state256 > 0 {