hpjansson / chafa

📺🗿 Terminal graphics for the 21st century.
https://hpjansson.org/chafa/
GNU Lesser General Public License v3.0
2.88k stars 60 forks source link

kitty with tmux passthrough only works if `kitty +icat` was invoked before #195

Closed ronyclau closed 5 months ago

ronyclau commented 6 months ago

Problem

No image is shown when chafa is called in a tmux pane in which kitty +icat has never been called.

Reproduction steps

Assuming that an image named red.png is in the current directory,

  1. Create a new pane in tmux. You can split an existing window, or create a new window.
  2. Call chafa --passthrough tmux -f kitty red.png. Black space of correct height is printed instead of the image.
  3. Call kitty +icat red.png. (Any image would do actually.)
  4. Call chafa --passthrough tmux -f kitty red.png again. The image would be displayed as expected.
Example image ![red.png](https://github.com/hpjansson/chafa/assets/26790480/0e12cbef-82a9-476e-a6cc-1f8598159b85)

Expected result

The image should be displayed regardless of whether kitty +icat has been invoked before.

Environment

chafa 1.14.0 tmux 3.4 kitty 0.32.2

kovidgoyal commented 6 months ago

This will be because you havent enabled tmux passthrough. icat does that for you if needed, automatically. I am guessing chafa doesnt.

ronyclau commented 6 months ago

Greetings, Kovid. First of all, thank you for bringing kitty and calibre to us!

May I ask whether this is something I have to configure on kitty (generated a default kitty.conf just now, and didn't find anything related) or tmux side, or this is on chafa?

kovidgoyal commented 6 months ago

tmux

ronyclau commented 6 months ago

TL;DR: add set -g allow-passthrough on to tmux.conf.

Thanks for the quick answer. Solved!

Related tmux doc here.

hpjansson commented 6 months ago

Chafa is supposed to set the tmux option automatically. The relevant code is here: https://github.com/hpjansson/chafa/blob/master/tools/chafa/chafa.c#L1818-L1904

It will only do so if it thinks it's not already set, and if it makes any changes, will restore the option to its original value afterwards.

There's likely something going wrong with this code; maybe we're being too conservative when detecting whether it's already set, you're running Chafa in a remote session where it's unable to set the option, or there's a bug. FWIW it works here, so I need some more info.

@ronyclau What's the output if you revert your configuration to the state where Chafa doesn't work, and run tmux show allow-passthrough and tmux set-option allow-passthrough on inside tmux? Does it work afterwards?

ronyclau commented 6 months ago

@hpjansson

Without the config, tmux show allow-passthrough prints nothing (or more precisely, just a new line, such that the next prompt is on the next line).

After tmux set-option allow-passthrough on is ran, it works, so allow-passthrough was indeed not enabled in tmux.


From the code block you linked, some observations:

  1. In my case where tmux show allow-passthrough prints just a new line, standard_output would be "\n", strings would be { "\n", "" }, and thus mode remains NULL. The part of the logic looks fine.

  2. When it does prints something, e.g. allow-passthrough on, due to the trailing new line, standard_output would be "allow-passthrough on\n", which in turn strings would be { "allow-passthrough", "on\n", "" }, and mode becomes "on\n".

    This line at https://github.com/hpjansson/chafa/blob/241b474bfaf3d83807000d59dbdcd6a7f3fe95ec/tools/chafa/chafa.c#L1848

    if (!mode || (strcmp (mode, "on") && strcmp (mode, "all")))

    would evaluate to true. Likely unintentional, but the result would just be that tmux set-option allow-passthrough on always got run. However, this doesn't match what I saw, as it's obvious from the test above that passthrough wasn't enabled when the image was printed, so the root cause likely isn't this.

  3. tmux show allow-passthrough would still print nothing or off even when the option is set globally, as this returns the session option value. From tmux's manpage (emphasis mine):

    Show the pane options (or a single option if option is provided) with -p, the window options with -w, the server options with -s, otherwise the session options.

    In other words, with set -g allow-passthrough on in config, item 1 still applies. Use tmux show -A allow-passthrough to get the effective value.


To dig a bit deeper, I enabled tmux's verbose mode with an empty config file (tmux -f /dev/null -v), and did some more tests:

Test 1

  1. Start a brand new tmux session by calling tmux -f /dev/null -v.
  2. Run tmux show allow-passthrough.
  3. Run tmux set allow-passthrough on.
  4. Quit tmux.
  5. Grep the log for tmux's command line parsing function cmd_unpack_argv.

Result

$ grep cmd_unpack_argv tmux-server-428170.log
1711392694.170651 cmd_unpack_argv: argv[0]=show
1711392694.170654 cmd_unpack_argv: argv[1]=allow-passthrough
1711392702.054822 cmd_unpack_argv: argv[0]=set
1711392702.054826 cmd_unpack_argv: argv[1]=allow-passthrough
1711392702.054829 cmd_unpack_argv: argv[2]=on

Test 2

  1. Start a brand new tmux session by calling tmux -f /dev/null -v.
  2. Run chafa --passthrough=tmux -f kitty red.png.
  3. Quit tmux.
  4. Grep the log for tmux's command line parsing function cmd_unpack_argv.

Result

$ grep cmd_unpack_argv tmux-server-426090.log

No matching line implies that the tmux server didn't receive any command from the tmux command line interface.

I would suggest checking whether apply_passthrough_workarounds_tmux really got called, and whether this call failed for some reason.

hpjansson commented 6 months ago

Thanks for the thorough analysis!

To shed some light on what the exec calls are doing (if anything), could you please run:

strace -f -e trace=execve,read chafa red.png 2>&1 | grep 'allow-passthrough\|exited'

ronyclau commented 6 months ago

Sure thing.

I am running this with the passthrough and format params as chafa couldn't detect kitty over ssh, and fallback to symbol mode.

$ strace -f -e trace=execve,read chafa --passthrough=tmux -f kitty red.png 2>&1 | grep 'allow-passthrough\|exited'
[pid 637726] +++ exited with 0 +++
[pid 637725] +++ exited with 0 +++
[pid 637724] +++ exited with 0 +++
[pid 637723] +++ exited with 0 +++
[pid 637722] +++ exited with 0 +++
[pid 637721] +++ exited with 0 +++
[pid 637720] +++ exited with 0 +++
[pid 637719] +++ exited with 0 +++
[pid 637718] +++ exited with 0 +++
[pid 637717] +++ exited with 0 +++
[pid 637716] +++ exited with 0 +++
[pid 637715] +++ exited with 0 +++
[pid 637714] +++ exited with 0 +++
[pid 637713] +++ exited with 0 +++
[pid 637712] +++ exited with 0 +++
[pid 637711] +++ exited with 0 +++
[pid 637710] +++ exited with 0 +++
[pid 637709] +++ exited with 0 +++
[pid 637708] +++ exited with 0 +++
[pid 637707] +++ exited with 0 +++
[pid 637706] +++ exited with 0 +++
[pid 637705] +++ exited with 0 +++
[pid 637704] +++ exited with 0 +++
[pid 637703] +++ exited with 0 +++
[pid 637702] +++ exited with 0 +++
[pid 637701] +++ exited with 0 +++
[pid 637700] +++ exited with 0 +++
[pid 637699] +++ exited with 0 +++
[pid 637698] +++ exited with 0 +++
[pid 637697] +++ exited with 0 +++
[pid 637696] +++ exited with 0 +++
[pid 637695] +++ exited with 0 +++
+++ exited with 0 +++
hpjansson commented 6 months ago

Are you running the remote ssh session inside tmux, or tmux inside the ssh session? If the former, there are two issues with it:

hpjansson commented 5 months ago

I'll assume this issue resulted from running in an ssh session where tmux could not be detected nor manipulated. In that case there's no more to do in this issue, so I'm closing it. Please correct me if this is wrong.

Thanks for all the feedback!