スタック・オーバーフローに参加する
687万人以上のプログラマーが集まるスタック・オーバーフローに参加しませんか?
簡単な登録後、すぐにご利用いただけます。
登録

In tmux, the status bar normally shows the current working directory of a pane in the window list. If I have for example two panes in a window, and the two panes have different working directories, is it possible to automatically update the status bar with the current working directory of the pane I’m currently focused on?

To clarify, if I have a window with two panes, and the first pane is in ~ and the second pane is in ~/Sites, I would like the window list in the status bar to say 1:~ when I am focused on the first pane, and 1:~/Sites when I am focused on the second pane.

share|improve this question
up vote 5 down vote accepted

Tmux pane PWD at the prompt

There are several ways that you can do this. I do it myself. The easiest and most customisable way is to set a global variable that tmux can access.

First add this to your .bashrc or .zshrc file, to set the PWD variable after every prompt:

# create a global per-pane variable that holds the pane's PWD
export PS1=$PS1'$( [ -n $TMUX ] && tmux setenv -g TMUX_PWD_$(tmux display -p "#D" | tr -d %) $PWD)'

Now, make a script that displays this variable such as ~/bin/display_tmux_pane_pwd.sh:

#!/bin/bash
tmux showenv -g TMUX_PWD_$(tmux display -p "#D" | tr -d %)  | sed 's/^.*=//'

All that is left is to add this to the satis-bar in .tmux.conf:

set -g status-left '#(~/bin/display_tmux_pane_pwd.sh)'

It may take awhile to update after switching panes, so you can change that with this command. By default it updates every 15 seconds, this will make it 5 seconds. Change it as you like.

set -g status-interval 5

Tmux-pane PWD in other programs

Sometimes it is useful to open up a pane or window and immediately execute a program instead of booting up another shell (e.g. tmux new-window vim). This way, when you close that program you also close the window. Unfortunately, the way I describe above requires a prompt in order to broadcast the status of PWD. However, in many programs, you can work around this fairly easily. Here's an example of what is in my .vimrc file so that vim updates the PWD status whenever it changes buffers.

if exists("$TMUX")
    " Get the environment variable
    let tmux_pane_name_cmd = 'tmux display -p \#D'
    let tmux_pane_name = substitute(system(g:tmux_pane_name_cmd), "\n", "", "")
    let tmux_env_var = "TMUX_PWD_" . substitute(g:tmux_pane_name, "%", "", "")
    unlet tmux_pane_name tmux_pane_name_cmd
    function! BroadcastTmuxCwd()
        let filename = substitute(expand("%:p:h"), $HOME, "~", "")
        let output = system("tmux setenv -g ".g:tmux_env_var." ".l:filename)
    endfunction
    autocmd BufEnter * call BroadcastTmuxCwd()
endif
share|improve this answer
    
This doesn’t seem to be working for me. The status bar doesn’t update until after I do something with the prompt. Is there an event that can be listened to when I switch focus to another pane in tmux? – Jezen Thomas Oct 7 '13 at 9:55
    
Hmm… This might not have worked because there is an unmatched " in that line I placed in my .zshrc. Not exactly sure where I should place it though. – Jezen Thomas Oct 7 '13 at 10:13
    
Oops, the PS1 was a little wonky and had excessive quotation marks. Try it this way, I cannot check it just yet unfortunately. – scicalculator Oct 8 '13 at 1:43
    
Oh, and yes, this requires the prompt to be printed at least once. If you start a pane executing a program and not a prompt then you will not get anything unless you set this variable from that program. I can give my .vimrc that does this if you want. – scicalculator Oct 8 '13 at 1:45
    
@JezenThomas , Just wanted to let you know I finally fixed the PS1 part (should now be compatible with bash and zsh). Also, I added a note about implementing it in other programs and an example for vim – scicalculator Oct 9 '13 at 8:38

In addition to the previous answer, I'd like to add you don't have to rely on the status-interval option. Waiting to see the change isn't really elegant. You can manually update the status bar on events with:

tmux refresh-client -S

I use this option after pane/window/session switching. In my tmux config you will find for instance to switch panes:

bind -r k select-pane -U\; refresh-client -S
bind -r j select-pane -D\; refresh-client -S
bind -r l select-pane -R\; refresh-client -S
bind -r h select-pane -L\; refresh-client -S

I have previously posted on this: manually refresh status bar

share|improve this answer

If you want the current window name to reflect the directory name, here is a modified version of the original answer that does not require calling a script from tmux and updates instantly:

export PS1=$PS1'$( [ -n $TMUX ] && tmux rename-window $(basename $PWD))'

Note that this means that you can't display the current process name any longer. It is of little value for me anyway.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.