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

View File

@ -282,11 +282,14 @@ func (r *FullscreenRenderer) DoesAutoWrap() bool {
return true return true
} }
func (w *CursesWindow) Fill(str string) bool { func (w *CursesWindow) Fill(str string) FillReturn {
return C.waddstr(w.impl, C.CString(str)) == C.OK 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() index := ColorPair{fg, bg, -1}.index()
C.wcolor_set(w.impl, C.short(index), nil) C.wcolor_set(w.impl, C.short(index), nil)
C.wattron(w.impl, C.int(attr)) 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) 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 lx := 0
var style tcell.Style 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 var yPos = w.top + w.lastY
if yPos >= (w.top + w.height) { if yPos >= (w.top + w.height) {
return false return FillSuspend
} }
_screen.SetContent(xPos, yPos, r, nil, style) _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 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) 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) return w.fillString(str, ColorPair{fg, bg, -1}, a)
} }

View File

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