diff --git a/CHANGELOG.md b/CHANGELOG.md index 0a041f8d..cc3eb780 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,19 +3,18 @@ CHANGELOG 0.44.0 ------ -- (Experimental) Sixel image support in preview window +- (Experimental) Sixel image support in preview window (not available on Windows) - [bin/fzf-preview.sh](bin/fzf-preview.sh) is added to demonstrate how to display an image using Kitty image protocol or Sixel. You can use it like so: ```sh fzf --preview='fzf-preview.sh {}' ``` -- (Experimental) iTerm2 inline image protocol support in preview window +- (Experimental) iTerm2 inline image protocol support in preview window (not available on Windows) ```sh # Using https://iterm2.com/utilities/imgcat fzf --preview 'imgcat -W $FZF_PREVIEW_COLUMNS -H $FZF_PREVIEW_LINES {}' ``` -- (Experimental) Sixel, Kitty, and iTerm2 image support now also available on Windows - HTTP server can be configured to accept remote connections ```sh # FZF_API_KEY is required for a non-localhost listen address diff --git a/go.mod b/go.mod index 31c33401..e3f1ad9d 100644 --- a/go.mod +++ b/go.mod @@ -1,8 +1,7 @@ module github.com/junegunn/fzf require ( - // go get github.com/gdamore/tcell/v2@8a50441ee1fd29b18a4a7d51e98423a17ec8ef4c - github.com/gdamore/tcell/v2 v2.6.1-0.20231031224054-8a50441ee1fd + github.com/gdamore/tcell/v2 v2.5.4 github.com/mattn/go-isatty v0.0.17 github.com/mattn/go-runewidth v0.0.14 github.com/mattn/go-shellwords v1.0.12 @@ -15,8 +14,8 @@ require ( require ( github.com/gdamore/encoding v1.0.0 // indirect github.com/lucasb-eyer/go-colorful v1.2.0 // indirect - golang.org/x/sync v0.1.0 // indirect - golang.org/x/text v0.12.0 // indirect + golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4 // indirect + golang.org/x/text v0.5.0 // indirect ) go 1.17 diff --git a/go.sum b/go.sum index 3f7ca831..6556c5aa 100644 --- a/go.sum +++ b/go.sum @@ -1,7 +1,7 @@ github.com/gdamore/encoding v1.0.0 h1:+7OoQ1Bc6eTm5niUzBa0Ctsh6JbMW6Ra+YNuAtDBdko= github.com/gdamore/encoding v1.0.0/go.mod h1:alR0ol34c49FCSBLjhosxzcPHQbf2trDkoo5dl+VrEg= -github.com/gdamore/tcell/v2 v2.6.1-0.20231031224054-8a50441ee1fd h1:DzX6TtJGRMP+AMlU+U4JEgoAVR/gwPNrz3JqPnEm3PM= -github.com/gdamore/tcell/v2 v2.6.1-0.20231031224054-8a50441ee1fd/go.mod h1:pwzJMyH4Hd0AZMJkWQ+/g01dDvYWEvmJuaiRU71Xl8k= +github.com/gdamore/tcell/v2 v2.5.4 h1:TGU4tSjD3sCL788vFNeJnTdzpNKIw1H5dgLnJRQVv/k= +github.com/gdamore/tcell/v2 v2.5.4/go.mod h1:dZgRy5v4iMobMEcWNYBtREnDZAT9DYmfqIkrgEMxLyw= github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY= github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng= @@ -11,7 +11,6 @@ github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh github.com/mattn/go-shellwords v1.0.12 h1:M2zGm7EW6UQJvDeQxo4T51eKPurbeFbe8WtebGE2xrk= github.com/mattn/go-shellwords v1.0.12/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= -github.com/rivo/uniseg v0.4.3/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis= github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/saracen/walker v0.1.3 h1:YtcKKmpRPy6XJTHJ75J2QYXXZYWnZNQxPCVqZSHVV/g= @@ -20,42 +19,30 @@ github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5t golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4 h1:uVc8UZUe6tr40fFVnUP5Oj+veunVezqYl9z7DYw9xzw= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= -golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q= golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= -golang.org/x/term v0.9.0/go.mod h1:M6DEAAIenWoTxdKrOltXcmDY3rSplQUkrvaDU5FcQyo= golang.org/x/term v0.13.0 h1:bb+I9cTfFazGW51MZqBVmZy7+JEJMouUHTUSKVQLBek= golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.12.0 h1:k+n5B8goJNdU7hSvEtMUz3d1Q6D/XW4COJSJR6fN0mc= -golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.5.0 h1:OLmvp0KP+FVG99Ct/qFiL/Fhk4zp4QQnZ7b2U+5piUM= +golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/src/terminal.go b/src/terminal.go index f48e5f25..1802e446 100644 --- a/src/terminal.go +++ b/src/terminal.go @@ -1962,8 +1962,6 @@ func (t *Terminal) renderPreviewArea(unchanged bool) { if t.previewed.wipe && t.previewed.version != t.previewer.version { t.previewed.wipe = false t.pwindow.Erase() - // Required for tcell to clear the previous image - t.tui.Sync(true) } else if unchanged { t.pwindow.MoveAndClear(0, 0) // Clear scroll offset display } else { @@ -2094,10 +2092,6 @@ Loop: for i := y + 1; i < height; i++ { t.pwindow.MoveAndClear(i, 0) } - // Required for tcell to clear the previous text - if !t.previewed.image { - t.tui.Sync(false) - } } image = image || isImage if idx == 0 { @@ -2105,7 +2099,7 @@ Loop: } else { t.pwindow.Move(y, x) } - t.tui.PassThrough(t.pwindow.Top()+y, t.pwindow.Left()+x, passThrough) + t.tui.PassThrough(passThrough) if requiredLines > 0 { if y+requiredLines == height { diff --git a/src/tui/dummy.go b/src/tui/dummy.go index d6495816..cceb4478 100644 --- a/src/tui/dummy.go +++ b/src/tui/dummy.go @@ -33,8 +33,7 @@ func (r *FullscreenRenderer) Init() {} func (r *FullscreenRenderer) Resize(maxHeightFunc func(int) int) {} func (r *FullscreenRenderer) Pause(bool) {} func (r *FullscreenRenderer) Resume(bool, bool) {} -func (r *FullscreenRenderer) PassThrough(int, int, string) {} -func (r *FullscreenRenderer) Sync(bool) {} +func (r *FullscreenRenderer) PassThrough(string) {} func (r *FullscreenRenderer) Clear() {} func (r *FullscreenRenderer) NeedScrollbarRedraw() bool { return false } func (r *FullscreenRenderer) Refresh() {} diff --git a/src/tui/light.go b/src/tui/light.go index dd1f9f3d..e5950cde 100644 --- a/src/tui/light.go +++ b/src/tui/light.go @@ -31,12 +31,8 @@ const consoleDevice string = "/dev/tty" var offsetRegexp *regexp.Regexp = regexp.MustCompile("(.*)\x1b\\[([0-9]+);([0-9]+)R") var offsetRegexpBegin *regexp.Regexp = regexp.MustCompile("^\x1b\\[[0-9]+;[0-9]+R") -func (r *LightRenderer) PassThrough(y int, x int, data string) { - r.queued.WriteString("\x1b7" + data + "\x1b8") -} - -func (r *LightRenderer) Sync(bool) { - // No-op +func (r *LightRenderer) PassThrough(str string) { + r.queued.WriteString("\x1b7" + str + "\x1b8") } func (r *LightRenderer) stderr(str string) { diff --git a/src/tui/light_windows.go b/src/tui/light_windows.go index db829d3a..62b10c12 100644 --- a/src/tui/light_windows.go +++ b/src/tui/light_windows.go @@ -110,16 +110,24 @@ func (r *LightRenderer) restoreTerminal() error { return windows.SetConsoleMode(windows.Handle(r.outHandle), r.origStateOutput) } -func (r *LightRenderer) updateTerminalSize() { +func (r *LightRenderer) Size() TermSize { + var w, h int var bufferInfo windows.ConsoleScreenBufferInfo if err := windows.GetConsoleScreenBufferInfo(windows.Handle(r.outHandle), &bufferInfo); err != nil { - r.width = getEnv("COLUMNS", defaultWidth) - r.height = r.maxHeightFunc(getEnv("LINES", defaultHeight)) + w = getEnv("COLUMNS", defaultWidth) + h = r.maxHeightFunc(getEnv("LINES", defaultHeight)) } else { - r.width = int(bufferInfo.Window.Right - bufferInfo.Window.Left) - r.height = r.maxHeightFunc(int(bufferInfo.Window.Bottom - bufferInfo.Window.Top)) + w = int(bufferInfo.Window.Right - bufferInfo.Window.Left) + h = r.maxHeightFunc(int(bufferInfo.Window.Bottom - bufferInfo.Window.Top)) } + return TermSize{h, w, 0, 0} +} + +func (r *LightRenderer) updateTerminalSize() { + size := r.Size() + r.width = size.Columns + r.height = size.Lines } func (r *LightRenderer) findOffset() (row int, col int) { diff --git a/src/tui/tcell.go b/src/tui/tcell.go index bf7b57cb..38641f7a 100644 --- a/src/tui/tcell.go +++ b/src/tui/tcell.go @@ -98,22 +98,9 @@ const ( AttrClear = Attr(1 << 8) ) -func (r *FullscreenRenderer) PassThrough(y int, x int, data string) { - tty, _ := _screen.Tty() - ti, err := tcell.LookupTerminfo(os.Getenv("TERM")) - if err != nil { - return - } - ti.TPuts(tty, ti.TGoto(x, y)) - ti.TPuts(tty, data) -} - -func (r *FullscreenRenderer) Sync(hard bool) { - if hard { - _screen.Sync() - } else { - _screen.Show() - } +func (r *FullscreenRenderer) PassThrough(str string) { + // No-op + // https://github.com/gdamore/tcell/issues/363#issuecomment-680665073 } func (r *FullscreenRenderer) Resize(maxHeightFunc func(int) int) {} @@ -220,10 +207,10 @@ func (r *FullscreenRenderer) Refresh() { // noop } +// TODO: Pixel width and height not implemented func (r *FullscreenRenderer) Size() TermSize { - tty, _ := _screen.Tty() - ws, _ := tty.WindowSize() - return TermSize{ws.Height, ws.Width, ws.PixelWidth, ws.PixelHeight} + cols, lines := _screen.Size() + return TermSize{lines, cols, 0, 0} } func (r *FullscreenRenderer) GetChar() Event { diff --git a/src/tui/tui.go b/src/tui/tui.go index 6834f350..5a5e18d6 100644 --- a/src/tui/tui.go +++ b/src/tui/tui.go @@ -489,8 +489,7 @@ type Renderer interface { RefreshWindows(windows []Window) Refresh() Close() - PassThrough(y int, x int, data string) - Sync(bool) + PassThrough(string) NeedScrollbarRedraw() bool GetChar() Event