Pass selected text to system commands in Tmux

What I want to achieve is similar to Vim's :'<,'>!some_command. In other words, in Tmux, once some text is selected, I want to press a key that triggers a prompt for me to enter a system command. Then the text will be piped to the command as stdin. The stdout of the command will be displayed in a temporary tmux buffer.

I have answered it here but it's kind of hard to find, so I'll document it here:

1
2
bind-key -T copy-mode   !  command-prompt -p "cmd:" "send-keys -X copy-selection-no-clear \; run-shell \"tmux show-buffer | %1\" "
bind-key -T copy-mode-vi ! command-prompt -p "cmd:" "send-keys -X copy-selection-no-clear \; run-shell \"tmux show-buffer | %1\" "

Several notes:

  • -T copy-mode-vi is essential if you use tmux's vi mode.
  • command-prompt prompts for some user input and run the template as tmux command - it is the core part that makes this run arbitrary user specified commands.
  • tmux show-buffer is for dumping previosly selected text to stdout
  • I could have used pipe-selection which pipes selection to arbitrary command, however, this does not display the command stdout back to tmux. On the contrary, run-shell does this.

KEY BINDING FOR SWAPPING PANES

1
bind-key -T prefix  C-s display-panes \; command-prompt -p "<pane1>:,<pane2>:" "swap-pane -s %1 -t %2"

Press C-b C-s (can hold ctrl) will:

  1. First, display the pane numbers as if you pressed <prefix>q
  2. Prompt for 1st pane to swap
  3. Prompt for 2nd pane to swap

Note:

  • -p "<pane1>:,<pane2>:" the comma seperates two prompts to the user seperately