m/fzf
1
0
mirror of https://github.com/junegunn/fzf.git synced 2025-11-17 15:53:39 -05:00

Fix $FZF_CLICK_{HEADER,FOOTER}_WORD with ANSI colors and tabs

This commit is contained in:
Junegunn Choi
2025-08-02 16:00:28 +09:00
parent 04c4269db3
commit da3d995709
2 changed files with 23 additions and 6 deletions

View File

@@ -1,6 +1,10 @@
CHANGELOG CHANGELOG
========= =========
0.65.1
------
- Fixed incorrect `$FZF_CLICK_HEADER_WORD` and `$FZF_CLICK_FOOTER_WORD` when the header or footer contains ANSI escape sequences and tab characters.
0.65.0 0.65.0
------ ------
- Added `click-footer` event that is triggered when the footer section is clicked. When the event is triggered, the following environment variables are set: - Added `click-footer` event that is triggered when the footer section is clicked. When the event is triggered, the following environment variables are set:

View File

@@ -1801,6 +1801,11 @@ func (t *Terminal) displayWidth(runes []rune) int {
return width return width
} }
func (t *Terminal) displayWidthWithPrefix(str string, prefixWidth int) int {
width, _ := util.RunesWidth([]rune(str), prefixWidth, t.tabstop, math.MaxInt32)
return width
}
const ( const (
minWidth = 4 minWidth = 4
minHeight = 3 minHeight = 3
@@ -4767,6 +4772,7 @@ func (t *Terminal) addClickHeaderWord(env []string) []string {
if t.layout == layoutReverse { if t.layout == layoutReverse {
headers[0], headers[1] = headers[1], headers[0] headers[0], headers[1] = headers[1], headers[0]
} }
var trimmedLine string
var words []Token var words []Token
var lineNum int var lineNum int
for lineNum = 0; lineNum <= clickHeaderLine; lineNum++ { for lineNum = 0; lineNum <= clickHeaderLine; lineNum++ {
@@ -4785,7 +4791,9 @@ func (t *Terminal) addClickHeaderWord(env []string) []string {
return env return env
} }
words = Tokenize(line, t.delimiter) // NOTE: We can't expand tabs here because the delimiter can contain tabs.
trimmedLine, _, _ = extractColor(line, nil, nil)
words = Tokenize(trimmedLine, t.delimiter)
if currentLine { if currentLine {
break break
} else { } else {
@@ -4796,11 +4804,14 @@ func (t *Terminal) addClickHeaderWord(env []string) []string {
} }
colNum := t.clickHeaderColumn - 1 colNum := t.clickHeaderColumn - 1
prefixWidth, prefixLength := 0, 0
for idx, token := range words { for idx, token := range words {
prefixWidth := int(token.prefixLength) prefixWidth += t.displayWidthWithPrefix(trimmedLine[prefixLength:token.prefixLength], prefixWidth)
word := token.text.ToString() prefixLength = int(token.prefixLength)
word, _ := t.processTabs(token.text.ToRunes(), prefixWidth)
trimmed := strings.TrimRightFunc(word, unicode.IsSpace) trimmed := strings.TrimRightFunc(word, unicode.IsSpace)
trimWidth, _ := util.RunesWidth([]rune(trimmed), prefixWidth, t.tabstop, math.MaxInt32) trimWidth := t.displayWidthWithPrefix(trimmed, prefixWidth)
// Find the position of the first non-space character in the word // Find the position of the first non-space character in the word
minPos := strings.IndexFunc(trimmed, func(r rune) bool { minPos := strings.IndexFunc(trimmed, func(r rune) bool {
@@ -4828,13 +4839,15 @@ func (t *Terminal) addClickFooterWord(env []string) []string {
// NOTE: Unlike in click-header, we don't use --delimiter here, since we're // NOTE: Unlike in click-header, we don't use --delimiter here, since we're
// only interested in the word, not nth. Does this make sense? // only interested in the word, not nth. Does this make sense?
words := Tokenize(t.footer[clickFooterLine], Delimiter{}) trimmed, _, _ := extractColor(t.footer[clickFooterLine], nil, nil)
trimmed, _ = t.processTabs([]rune(trimmed), 0)
words := Tokenize(trimmed, Delimiter{})
colNum := t.clickFooterColumn - 1 colNum := t.clickFooterColumn - 1
for _, token := range words { for _, token := range words {
prefixWidth := int(token.prefixLength) prefixWidth := int(token.prefixLength)
word := token.text.ToString() word := token.text.ToString()
trimmed := strings.TrimRightFunc(word, unicode.IsSpace) trimmed := strings.TrimRightFunc(word, unicode.IsSpace)
trimWidth, _ := util.RunesWidth([]rune(trimmed), prefixWidth, t.tabstop, math.MaxInt32) trimWidth := t.displayWidthWithPrefix(trimmed, prefixWidth)
// Find the position of the first non-space character in the word // Find the position of the first non-space character in the word
minPos := strings.IndexFunc(trimmed, func(r rune) bool { minPos := strings.IndexFunc(trimmed, func(r rune) bool {