summaryrefslogtreecommitdiffstats
path: root/src/terminal.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/terminal.go')
-rw-r--r--src/terminal.go58
1 files changed, 26 insertions, 32 deletions
diff --git a/src/terminal.go b/src/terminal.go
index 54f96675..aabeb07c 100644
--- a/src/terminal.go
+++ b/src/terminal.go
@@ -2,7 +2,6 @@ package fzf
import (
"bufio"
- "bytes"
"fmt"
"io/ioutil"
"os"
@@ -15,6 +14,9 @@ import (
"syscall"
"time"
+ "github.com/mattn/go-runewidth"
+ "github.com/rivo/uniseg"
+
"github.com/junegunn/fzf/src/tui"
"github.com/junegunn/fzf/src/util"
)
@@ -673,11 +675,8 @@ func (t *Terminal) sortSelected() []selectedItem {
}
func (t *Terminal) displayWidth(runes []rune) int {
- l := 0
- for _, r := range runes {
- l += util.RuneWidth(r, l, t.tabstop)
- }
- return l
+ width, _ := util.RunesWidth(runes, 0, t.tabstop, 0)
+ return width
}
const (
@@ -1141,28 +1140,18 @@ func (t *Terminal) printItem(result Result, line int, i int, current bool) {
t.prevLines[i] = newLine
}
-func (t *Terminal) trimRight(runes []rune, width int) ([]rune, int) {
+func (t *Terminal) trimRight(runes []rune, width int) ([]rune, bool) {
// We start from the beginning to handle tab characters
- l := 0
- for idx, r := range runes {
- l += util.RuneWidth(r, l, t.tabstop)
- if l > width {
- return runes[:idx], len(runes) - idx
- }
+ width, overflowIdx := util.RunesWidth(runes, 0, t.tabstop, width)
+ if overflowIdx >= 0 {
+ return runes[:overflowIdx], true
}
- return runes, 0
+ return runes, false
}
func (t *Terminal) displayWidthWithLimit(runes []rune, prefixWidth int, limit int) int {
- l := 0
- for _, r := range runes {
- l += util.RuneWidth(r, l+prefixWidth, t.tabstop)
- if l > limit {
- // Early exit
- return l
- }
- }
- return l
+ width, _ := util.RunesWidth(runes, prefixWidth, t.tabstop, limit)
+ return width
}
func (t *Terminal) trimLeft(runes []rune, width int) ([]rune, int32) {
@@ -1362,9 +1351,9 @@ func (t *Terminal) renderPreviewText(height int, lines []string, lineNo int, unc
prefixWidth := 0
_, _, ansi = extractColor(line, ansi, func(str string, ansi *ansiState) bool {
trimmed := []rune(str)
- trimmedLen := 0
+ isTrimmed := false
if !t.previewOpts.wrap {
- trimmed, trimmedLen = t.trimRight(trimmed, maxWidth-t.pwindow.X())
+ trimmed, isTrimmed = t.trimRight(trimmed, maxWidth-t.pwindow.X())
}
str, width := t.processTabs(trimmed, prefixWidth)
prefixWidth += width
@@ -1374,7 +1363,7 @@ func (t *Terminal) renderPreviewText(height int, lines []string, lineNo int, unc
} else {
fillRet = t.pwindow.CFill(tui.ColPreview.Fg(), tui.ColPreview.Bg(), tui.AttrRegular, str)
}
- return trimmedLen == 0 &&
+ return !isTrimmed &&
(fillRet == tui.FillContinue || t.previewOpts.wrap && fillRet == tui.FillNextLine)
})
t.previewer.scrollable = t.previewer.scrollable || t.pwindow.Y() == height-1 && t.pwindow.X() == t.pwindow.Width()
@@ -1430,16 +1419,21 @@ func (t *Terminal) printPreviewDelayed() {
}
func (t *Terminal) processTabs(runes []rune, prefixWidth int) (string, int) {
- var strbuf bytes.Buffer
+ var strbuf strings.Builder
l := prefixWidth
- for _, r := range runes {
- w := util.RuneWidth(r, l, t.tabstop)
- l += w
- if r == '\t' {
+ gr := uniseg.NewGraphemes(string(runes))
+ for gr.Next() {
+ rs := gr.Runes()
+ str := string(rs)
+ var w int
+ if len(rs) == 1 && rs[0] == '\t' {
+ w = t.tabstop - l%t.tabstop
strbuf.WriteString(strings.Repeat(" ", w))
} else {
- strbuf.WriteRune(r)
+ w = runewidth.StringWidth(str)
+ strbuf.WriteString(str)
}
+ l += w
}
return strbuf.String(), l
}