Tmux key binding to pipe pane contents to program

tmux

I'm trying to get this key binding to work to pipe the contents of the current pane to a program of my choosing:

bind P command-prompt -I "vim -" \
    "capture-pane -eJ -S - -E -; \
    set-buffer -n PIPE; \
    new-window -n '|%1' 'tmux save-buffer -b PIPE - | %1'; \
    delete-buffer -b PIPE"

— but it always results in tmux reporting no buffer PIPE. This text is usually shown and overwritten too quickly for me to even notice it; I managed to elicit it by using sleep 10 as the command name to pipe the output to.

I chose to rename the automatically-named buffer created by capture-pane because otherwise the new-window invocation seemed to reset tmux's current/default buffer to whatever I had last copied in copy mode. As far as I can tell, the new buffer should be renamed PIPE.

I have a similar but simpler binding, which outputs the contents to a file instead of a pipe, working perfectly:

bind H command-prompt -I "tmux_#W.txt" \
    "capture-pane -eJ -S - -E -; \
    save-buffer '%%'; \
    delete-buffer"

If I run the commands in it one by one, the program does receive the text of the pane as it would from any other pipe. What am I doing wrong?

Best Answer

It seems that there is a race between the new-window and the delete-buffer commands: that is, the buffer "PIPE" is deleted before it can be piped into vim or whatever program you want to be executed.

The following ugly hack that sleeps a second before calling delete-buffer fixes the problem for me:

bind P command-prompt -I "vim -" \
    "capture-pane -eJ -S - -E -; \
    set-buffer -n PIPE; \
    new-window -n '|%1' 'tmux save-buffer -b PIPE - | %1'; \
    run-sh 'sleep 1 && tmux delete-buffer -b PIPE'"
Related Question