m/fzf
1
0
mirror of https://github.com/junegunn/fzf.git synced 2025-11-14 06:13:47 -05:00

Print --wrap-sign in preview window

Close #4233
This commit is contained in:
Junegunn Choi
2025-02-10 23:58:23 +09:00
parent bfea9e53a6
commit 19ef8891e3
5 changed files with 66 additions and 34 deletions

View File

@@ -1936,6 +1936,7 @@ func (t *Terminal) resizeWindows(forcePreview bool, redrawBorder bool) {
pwidth -= 1 pwidth -= 1
} }
t.pwindow = t.tui.NewWindow(y, x, pwidth, pheight, tui.WindowPreview, noBorder, true) t.pwindow = t.tui.NewWindow(y, x, pwidth, pheight, tui.WindowPreview, noBorder, true)
t.pwindow.SetWrapSign(t.wrapSign, t.wrapSignWidth)
if !hadPreviewWindow { if !hadPreviewWindow {
t.pwindow.Erase() t.pwindow.Erase()
} }

View File

@@ -44,8 +44,9 @@ func (r *LightRenderer) stderr(str string) {
r.stderrInternal(str, true, "") r.stderrInternal(str, true, "")
} }
const CR string = "\x1b[2m" const DIM string = "\x1b[2m"
const LF string = "\x1b[2m␊" const CR string = DIM + "␍"
const LF string = DIM + "␊"
func (r *LightRenderer) stderrInternal(str string, allowNLCR bool, resetCode string) { func (r *LightRenderer) stderrInternal(str string, allowNLCR bool, resetCode string) {
bytes := []byte(str) bytes := []byte(str)
@@ -127,19 +128,21 @@ type LightRenderer struct {
} }
type LightWindow struct { type LightWindow struct {
renderer *LightRenderer renderer *LightRenderer
colored bool colored bool
windowType WindowType windowType WindowType
border BorderStyle border BorderStyle
top int top int
left int left int
width int width int
height int height int
posx int posx int
posy int posy int
tabstop int tabstop int
fg Color fg Color
bg Color bg Color
wrapSign string
wrapSignWidth int
} }
func NewLightRenderer(ttyin *os.File, theme *ColorTheme, forceBlack bool, mouse bool, tabstop int, clearOnExit bool, fullscreen bool, maxHeightFunc func(int) int) (Renderer, error) { func NewLightRenderer(ttyin *os.File, theme *ColorTheme, forceBlack bool, mouse bool, tabstop int, clearOnExit bool, fullscreen bool, maxHeightFunc func(int) int) (Renderer, error) {
@@ -1105,11 +1108,12 @@ type wrappedLine struct {
displayWidth int displayWidth int
} }
func wrapLine(input string, prefixLength int, max int, tabstop int) []wrappedLine { func wrapLine(input string, prefixLength int, initialMax int, tabstop int, wrapSignWidth int) []wrappedLine {
lines := []wrappedLine{} lines := []wrappedLine{}
width := 0 width := 0
line := "" line := ""
gr := uniseg.NewGraphemes(input) gr := uniseg.NewGraphemes(input)
max := initialMax
for gr.Next() { for gr.Next() {
rs := gr.Runes() rs := gr.Runes()
str := string(rs) str := string(rs)
@@ -1131,6 +1135,7 @@ func wrapLine(input string, prefixLength int, max int, tabstop int) []wrappedLin
line = str line = str
prefixLength = 0 prefixLength = 0
width = w width = w
max = initialMax - wrapSignWidth
} }
} }
lines = append(lines, wrappedLine{string(line), width}) lines = append(lines, wrappedLine{string(line), width})
@@ -1140,7 +1145,7 @@ func wrapLine(input string, prefixLength int, max int, tabstop int) []wrappedLin
func (w *LightWindow) fill(str string, resetCode string) FillReturn { func (w *LightWindow) fill(str string, resetCode string) 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, w.wrapSignWidth)
for j, wl := range lines { for j, wl := range lines {
w.stderrInternal(wl.text, false, resetCode) w.stderrInternal(wl.text, false, resetCode)
w.posx += wl.displayWidth w.posx += wl.displayWidth
@@ -1153,6 +1158,11 @@ func (w *LightWindow) fill(str string, resetCode string) FillReturn {
w.MoveAndClear(w.posy, w.posx) w.MoveAndClear(w.posy, w.posx)
w.Move(w.posy+1, 0) w.Move(w.posy+1, 0)
w.renderer.stderr(resetCode) w.renderer.stderr(resetCode)
if len(lines) > 1 {
w.stderrInternal(DIM+w.wrapSign, false, resetCode)
w.renderer.stderr(resetCode)
w.Move(w.posy, w.wrapSignWidth)
}
} }
} }
} }
@@ -1226,6 +1236,11 @@ func (w *LightWindow) EraseMaybe() bool {
return false return false
} }
func (w *LightWindow) SetWrapSign(sign string, width int) {
w.wrapSign = sign
w.wrapSignWidth = width
}
func (r *LightRenderer) HideCursor() { func (r *LightRenderer) HideCursor() {
r.showCursor = false r.showCursor = false
r.csi("?25l") r.csi("?25l")

View File

@@ -39,20 +39,22 @@ func (p ColorPair) style() tcell.Style {
type Attr int32 type Attr int32
type TcellWindow struct { type TcellWindow struct {
color bool color bool
windowType WindowType windowType WindowType
top int top int
left int left int
width int width int
height int height int
normal ColorPair normal ColorPair
lastX int lastX int
lastY int lastY int
moveCursor bool moveCursor bool
borderStyle BorderStyle borderStyle BorderStyle
uri *string uri *string
params *string params *string
showCursor bool showCursor bool
wrapSign string
wrapSignWidth int
} }
func (w *TcellWindow) Top() int { func (w *TcellWindow) Top() int {
@@ -629,6 +631,11 @@ func (w *TcellWindow) EraseMaybe() bool {
return true return true
} }
func (w *TcellWindow) SetWrapSign(sign string, width int) {
w.wrapSign = sign
w.wrapSignWidth = width
}
func (w *TcellWindow) EncloseX(x int) bool { func (w *TcellWindow) EncloseX(x int) bool {
return x >= w.left && x < (w.left+w.width) return x >= w.left && x < (w.left+w.width)
} }
@@ -757,11 +764,18 @@ Loop:
// word wrap: // word wrap:
xPos := w.left + w.lastX + lx xPos := w.left + w.lastX + lx
if xPos >= (w.left + w.width) { if xPos >= w.left+w.width {
w.lastY++ w.lastY++
w.lastX = 0 w.lastX = 0
lx = 0 lx = 0
xPos = w.left xPos = w.left
wgr := uniseg.NewGraphemes(w.wrapSign)
for wgr.Next() {
rs := wgr.Runes()
_screen.SetContent(w.left+lx, w.top+w.lastY, rs[0], rs[1:], style.Dim(true))
lx += uniseg.StringWidth(string(rs))
}
xPos = w.left + lx
} }
yPos := w.top + w.lastY yPos := w.top + w.lastY

View File

@@ -659,6 +659,8 @@ type Window interface {
LinkEnd() LinkEnd()
Erase() Erase()
EraseMaybe() bool EraseMaybe() bool
SetWrapSign(string, int)
} }
type FullscreenRenderer struct { type FullscreenRenderer struct {

View File

@@ -453,7 +453,7 @@ class TestPreview < TestInteractive
tmux.send_keys 'f' tmux.send_keys 'f'
tmux.until do |lines| tmux.until do |lines|
assert_equal '::', lines[0] assert_equal '::', lines[0]
assert_equal ' 3', lines[1] assert_equal ' 3', lines[1]
end end
end end
@@ -527,7 +527,7 @@ class TestPreview < TestInteractive
tmux.send_keys "seq 10 | #{FZF} --preview-border rounded --preview-window '~5,2,+0,<100000(~0,+100,wrap,noinfo)' --preview 'seq 1000'", :Enter tmux.send_keys "seq 10 | #{FZF} --preview-border rounded --preview-window '~5,2,+0,<100000(~0,+100,wrap,noinfo)' --preview 'seq 1000'", :Enter
tmux.until { |lines| assert_equal 10, lines.match_count } tmux.until { |lines| assert_equal 10, lines.match_count }
tmux.until do |lines| tmux.until do |lines|
assert_equal ['╭────╮', '│ 10 │', '│ 0 │', '│ 10 │', '│ 1 │'], lines.take(5).map(&:strip) assert_equal ['╭────╮', '│ 10 │', '│ ↳ 0│', '│ 10 │', '│ ↳ 1│'], lines.take(5).map(&:strip)
end end
end end