Open unrealapex opened 6 months ago
What is the difference between wezterm imgcat
and imgcat
? Is there any reason you have to use the former?
I am not sure regarding the technical reasons why they are different, but I believe Wezterm's implementation is done natively in Rust and also renders images with better performance than iTerm2's imgcat
script. You may wish to look at its help page. As for using the former, Wezterm's imgcat
comes out of the box...
So here's what I've found.
The output of imgcat
ends with ^G
as documented in the official specification (See "Protocol" section of https://iterm2.com/documentation-images.html). However, the output of wezterm imgcat
ends with <ESC>\
.
$ imgcat fzf.png | tr -d '\n' | tail -c 1 | ruby -ne 'p $_'
"\a"
$ wezterm imgcat fzf.png | tr -d '\n' | tail -c 2 | ruby -ne 'p $_'
"\e\\"
Is this intentional? Anyway, for some reason, iTerm2 also allows this case and prints the image.
It is trivial for fzf to change its protocol parser to support this alternative sequence.
diff --git a/src/terminal.go b/src/terminal.go
index d267aec..2069571 100644
--- a/src/terminal.go
+++ b/src/terminal.go
@@ -67,7 +67,7 @@ func init() {
// * https://sw.kovidgoyal.net/kitty/graphics-protocol
// * https://en.wikipedia.org/wiki/Sixel
// * https://iterm2.com/documentation-images.html
- passThroughRegex = regexp.MustCompile(`\x1bPtmux;\x1b\x1b.*?[^\x1b]\x1b\\|\x1b(_G|P[0-9;]*q).*?\x1b\\\r?|\x1b]1337;.*?\a`)
+ passThroughRegex = regexp.MustCompile(`\x1bPtmux;\x1b\x1b.*?[^\x1b]\x1b\\|\x1b(_G|P[0-9;]*q).*?\x1b\\\r?|\x1b]1337;.*?(\a|\x1b\\)`)
}
type jumpMode int
I'm going to assume this alternate escape sequence was unintentional. @wez may have a different answer.
OSC sequences are defined as being terminated by the ST sequence, which is ESC \
. They can also be terminated by ^G
. Since the iterm2 protocol is using OSC sequences, parsers must support both of these forms of termination.
Thanks for the comment. I will update the regex.
But,
# Dump the output to a file
wezterm imgcat fzf.png > /tmp/image
# With the updated regex, fzf can render the image in the preview window
fzf --preview 'cat /tmp/image'
# However, this doesn't work. 'wezterm imgcat' process doesn't finish and just hang.
fzf --preview 'wezterm imgcat fzf.png'
hmm, wezterm also tries to query terminal properties via the XTVERSION escape sequence, and then the screen dimensions via a variety of probing escape sequences. Perhaps those also need to be allowed through fzf's processing layer and the responses allowed to be read?
wezterm imgcat
assumes that every terminal will be able to respond to the \u001b[c
sequence, and uses that to avoid waiting forever to receive a response. I think in this case fzf may be preventing that from happening.
Here's a snippet from an ascii-cast showing the probe escapes that are emitted prior to emitting the iterm2 image data OSC sequence:
[9.833448,"o","\u001b[>q\u001b[c"]
[9.837395,"o","\u001b[>q\u001b[c"]
[9.841322,"o","\u001b[18t\u001b[16t\u001b[c"]
Thanks for the pointers.
I've discovered that the hanging has something to do with setpgid
. This is a minimal code to reproduce the problem.
package main
import (
"os/exec"
"syscall"
)
func main() {
cmd := exec.Command("/bin/sh", "-c", "wezterm imgcat ../images/fzf.png")
cmd.SysProcAttr = &syscall.SysProcAttr{Setpgid: true}
cmd.Start()
cmd.Wait()
}
This program hangs, and not setting setpgid
fixes the issue. However, fzf sets the flag so that it can easily kill the preview command and its child processes at once.
Not setting this in fzf, unfortunately, doesn't make wezterm imgcat
work as a preview command. fzf reads the response sequences directly from /dev/tty
as the user input and pastes them on its prompt.
So there doesn't seem to be an easy way to fix it right now, and I recommend using one of the alternatives for now, such as chafa.
# You need to pass the size of the preview window
fzf --preview 'chafa -f iterm -s ${FZF_PREVIEW_COLUMNS}x${FZF_PREVIEW_LINES} {}'
man fzf
)Info
Problem / Steps to reproduce
Is it possible to get Wezterm's implementation of iTerm2's image protocol working in FZF preview? iTerm2 image support integration is available, however, it seems that it does not extend to Wezterm's implementation:
See https://github.com/wez/wezterm/issues/5049