Make preview renderer suspend early on line wrap

This commit is contained in:
Junegunn Choi 2017-01-11 22:13:40 +09:00
parent f8082bc53a
commit 9977a3e9fc
No known key found for this signature in database
GPG Key ID: 254BC280FEF9C627
5 changed files with 73 additions and 46 deletions

View File

@ -1,8 +1,10 @@
package fzf
import (
"bufio"
"bytes"
"fmt"
"io"
"os"
"os/signal"
"regexp"
@ -852,41 +854,49 @@ func (t *Terminal) printPreview() {
return
}
t.pwindow.Erase()
skip := t.previewer.offset
extractColor(t.previewer.text, nil, func(str string, ansi *ansiState) bool {
if skip > 0 {
newlines := numLinesMax(str, skip)
if skip <= newlines {
for i := 0; i < skip; i++ {
str = str[strings.Index(str, "\n")+1:]
maxWidth := t.pwindow.Width()
if t.tui.DoesAutoWrap() {
maxWidth -= 1
}
reader := bufio.NewReader(strings.NewReader(t.previewer.text))
lineNo := -t.previewer.offset
for {
line, err := reader.ReadString('\n')
eof := err == io.EOF
if !eof {
line = line[:len(line)-1]
}
lineNo++
if lineNo > t.pwindow.Height() {
break
} else if lineNo > 0 {
var fillRet tui.FillReturn
extractColor(line, nil, func(str string, ansi *ansiState) bool {
trimmed := []rune(str)
if !t.preview.wrap {
trimmed, _ = t.trimRight(trimmed, maxWidth-t.pwindow.X())
}
skip = 0
} else {
skip -= newlines
return true
str, _ = t.processTabs(trimmed, 0)
if ansi != nil && ansi.colored() {
fillRet = t.pwindow.CFill(ansi.fg, ansi.bg, ansi.attr, str)
} else {
fillRet = t.pwindow.Fill(str)
}
return fillRet == tui.FillContinue
})
switch fillRet {
case tui.FillNextLine:
continue
case tui.FillSuspend:
break
}
t.pwindow.Fill("\n")
}
lines := strings.Split(str, "\n")
for i, line := range lines {
limit := t.pwindow.Width()
if t.tui.DoesAutoWrap() {
limit -= 1
}
if i == 0 {
limit -= t.pwindow.X()
}
trimmed := []rune(line)
if !t.preview.wrap {
trimmed, _ = t.trimRight(trimmed, limit)
}
lines[i], _ = t.processTabs(trimmed, 0)
str = strings.Join(lines, "\n")
if eof {
break
}
if ansi != nil && ansi.colored() {
return t.pwindow.CFill(ansi.fg, ansi.bg, ansi.attr, str)
}
return t.pwindow.Fill(str)
})
}
t.pwindow.FinishFill()
if t.previewer.lines > t.pwindow.Height() {
offset := fmt.Sprintf("%d/%d", t.previewer.offset+1, t.previewer.lines)

View File

@ -730,23 +730,29 @@ func wrapLine(input string, prefixLength int, max int, tabstop int) []wrappedLin
return lines
}
func (w *LightWindow) fill(str string, onMove func()) bool {
func (w *LightWindow) fill(str string, onMove func()) FillReturn {
allLines := strings.Split(str, "\n")
for i, line := range allLines {
lines := wrapLine(line, w.posx, w.width, w.tabstop)
for j, wl := range lines {
if w.posx >= w.Width()-1 && wl.displayWidth == 0 {
if w.posy < w.height-1 {
w.MoveAndClear(w.posy+1, 0)
}
return FillNextLine
}
w.stderr(wl.text)
w.posx += wl.displayWidth
if j < len(lines)-1 || i < len(allLines)-1 {
if w.posy+1 >= w.height {
return false
return FillSuspend
}
w.MoveAndClear(w.posy+1, 0)
onMove()
}
}
}
return true
return FillContinue
}
func (w *LightWindow) setBg() {
@ -755,13 +761,13 @@ func (w *LightWindow) setBg() {
}
}
func (w *LightWindow) Fill(text string) bool {
func (w *LightWindow) Fill(text string) FillReturn {
w.MoveAndClear(w.posy, w.posx)
w.setBg()
return w.fill(text, w.setBg)
}
func (w *LightWindow) CFill(fg Color, bg Color, attr Attr, text string) bool {
func (w *LightWindow) CFill(fg Color, bg Color, attr Attr, text string) FillReturn {
w.MoveAndClear(w.posy, w.posx)
if bg == colDefault {
bg = w.bg

View File

@ -282,11 +282,14 @@ func (r *FullscreenRenderer) DoesAutoWrap() bool {
return true
}
func (w *CursesWindow) Fill(str string) bool {
return C.waddstr(w.impl, C.CString(str)) == C.OK
func (w *CursesWindow) Fill(str string) FillReturn {
if C.waddstr(w.impl, C.CString(str)) == C.OK {
return FillContinue
}
return FillSuspend
}
func (w *CursesWindow) CFill(fg Color, bg Color, attr Attr, str string) bool {
func (w *CursesWindow) CFill(fg Color, bg Color, attr Attr, str string) FillReturn {
index := ColorPair{fg, bg, -1}.index()
C.wcolor_set(w.impl, C.short(index), nil)
C.wattron(w.impl, C.int(attr))

View File

@ -477,7 +477,7 @@ func (w *TcellWindow) CPrint(pair ColorPair, attr Attr, text string) {
w.printString(text, pair, attr)
}
func (w *TcellWindow) fillString(text string, pair ColorPair, a Attr) bool {
func (w *TcellWindow) fillString(text string, pair ColorPair, a Attr) FillReturn {
lx := 0
var style tcell.Style
@ -511,7 +511,7 @@ func (w *TcellWindow) fillString(text string, pair ColorPair, a Attr) bool {
var yPos = w.top + w.lastY
if yPos >= (w.top + w.height) {
return false
return FillSuspend
}
_screen.SetContent(xPos, yPos, r, nil, style)
@ -520,14 +520,14 @@ func (w *TcellWindow) fillString(text string, pair ColorPair, a Attr) bool {
}
w.lastX += lx
return true
return FillContinue
}
func (w *TcellWindow) Fill(str string) bool {
func (w *TcellWindow) Fill(str string) FillReturn {
return w.fillString(str, ColDefault, 0)
}
func (w *TcellWindow) CFill(fg Color, bg Color, a Attr, str string) bool {
func (w *TcellWindow) CFill(fg Color, bg Color, a Attr, str string) FillReturn {
return w.fillString(str, ColorPair{fg, bg, -1}, a)
}

View File

@ -117,6 +117,14 @@ const (
colWhite
)
type FillReturn int
const (
FillContinue FillReturn = iota
FillNextLine
FillSuspend
)
type ColorPair struct {
fg Color
bg Color
@ -216,8 +224,8 @@ type Window interface {
MoveAndClear(y int, x int)
Print(text string)
CPrint(color ColorPair, attr Attr, text string)
Fill(text string) bool
CFill(fg Color, bg Color, attr Attr, text string) bool
Fill(text string) FillReturn
CFill(fg Color, bg Color, attr Attr, text string) FillReturn
Erase()
}