8

I've written the following which allows me to switch tmux window with fzf:

tmux list-windows -F "#I:#W" | fzf-tmux | cut -d ":" -f 1 | xargs tmux select-window -t

When I run this in a shell it works perfectly, giving me an fzf list of windows which I can search through and switch to.

I bound it to the f key in tmux:

# fast window switching
unbind f
bind-key f run "tmux list-windows -F \"#I:#W\" | fzf-tmux | cut -d \":\" -f 1 | xargs tmux select-window -t"

But when I run it, it displays the same window N times (where N is the number of windows I have open).

So if I have 3 windows open, running the script in zsh gives me:

1. first window
2. second window
3. third window

where the tmux key binding gives me

1. first window
1. first window
1. first window

I haven't written tmux scripts before, so perhaps there's a better way of getting the windows than what I am doing here? Otherwise, I don't understand why I get different options when run from tmux and run in a shell.

Update:

it seems that run-shell "tmux list-windows" correctly outputs the different windows (but with a load of layout info that I don't want), whereas run-shell "tmux list-windows -F '#I:#W'" gives me the original problem of the same window repeating for each window entry.

I think that the problem is that tmux is expanding #I:#W for the current window, instead of passing it to the list-windows command, so I need to escape them. Any ideas on how to do that?

Update 2:

Answer is to double hash the variables (##I:##W instead of #I:#W).

GTF
  • 8,031
  • 5
  • 36
  • 59

2 Answers2

7

Thanks for sharing your solution! Helped me a lot :)

For people who come across this post and wonder how this command can be used to switch between tmux sessions:

bind-key C-f run-shell "tmux list-sessions -F \"##S\" | fzf-tmux | xargs tmux switch -t"

peterfication
  • 428
  • 5
  • 12
5

In case anyone wants to use this script in the future, the correct version this:

# fast window switching
bind -n C-f run-shell "tmux list-windows -F \"##I:##W\" | fzf-tmux | cut -d \":\" -f 1 | xargs tmux select-window -t"
GTF
  • 8,031
  • 5
  • 36
  • 59
  • How does this work for you? When I run the command, I get `'tmux list-windows -F "#I:#W" | fzf-tmux | cut -d ":" -f 1 | xargs tmux select-window -t' returned 123` back. – Ikke Oct 02 '17 at 09:15
  • Is an issue with tput that is failing: https://github.com/junegunn/fzf/issues/1032 – Ikke Oct 02 '17 at 09:23
  • 4
    as of tmux 3.0a the -b flag is required. see: https://github.com/junegunn/fzf/issues/1841#issuecomment-580975759. So all together that's now: `bind -n C-f run-shell -b "tmux list-windows -F \"##I:##W\" | fzf-tmux | cut -d \":\" -f 1 | xargs tmux select-window -t"` – AustinC Mar 05 '20 at 00:48
  • 1
    @AustinC or @GTF, escaping-out doesn't go cleanly. It opens the command in a full-screen pane that has to be `q`'d out-of. Do you know how to make it just return to the previous view? – PeterM May 06 '22 at 19:18
  • 1
    Based on https://waylonwalker.com/tmux-fzf-session-jump, I came up with this: `bind -n C-w display-popup -E "tmux list-windows | grep -v \"^$(tmux display-message -p '#S')\$\" | fzf --reverse | cut -d \":\" -f 1 | xargs tmux select-window -t"`. Note that it requires recent tmux - I'm using next-3.4. – PeterM May 06 '22 at 21:07