aharris88
aharris88

Reputation: 3630

How to automatically rename tmux windows to the current directory

I would like to have tmux to automatically rename the window with the current working directory (cwd). As it is by default, it names the tab/window as the name of the current process, such as zsh or vim.

When I open a new window in tmux, the name is reattach-to-use-namespace and then it immediately switches to zsh.

tmux tabs

I'm on OS X 10.10.2, I use zshell, and I have tmux 1.9a.

To be clear, I don't want the entire path in the name of the window, just the current directory, so for example, I want projectName, not /Users/username/Development/projectName.

If you want to see my current tmux.conf, here it is.

Upvotes: 77

Views: 39921

Answers (12)

Aki K
Aki K

Reputation: 1262

Similar to my answer here, I wanted to truncate instead of removing the directories, similar to how it's done in the Starship prompt which is inspired by the fish shell.

So, paths can look like so:

Original Path Truncated Path
/home/user/adir/bdir/cdir/ddir ~/a/b/c/ddir
/home/user/adir/.bdir/cdir/ddir ~/a/.b/c/ddir
/Users/user/adir/bdir/cdir/ddir ~/a/b/c/ddir
/home /home
/Users /Users
/etc/var/adir/bdir/cdir/ddir /e/v/a/b/c/ddir
/etc /etc

To achieve that, you can write a bash function like so:

~/scripts/functions.sh

#!/usr/bin/env bash

function truncate_path() {
  local path_to_truncate truncation_length truncated_path

  if [ -z "$1" ] || [ -z "$2" ]; then
    echo "Usage: truncate_path <path> <truncation_length>"
    return 1
  fi

  path_to_truncate="$1"
  truncation_length="$2"

  if ! [[ "$truncation_length" =~ ^[0-9]+$ ]]; then
    echo "Error: truncation_length must be a positive integer"
    return 1
  fi

  truncated_path=$(
    echo "$path_to_truncate" |
      sed "s|^$HOME|~|g" |
      awk -F "/" -v OFS="/" -v truncation_length="$truncation_length" '{
        if (NF <= truncation_length) {
          print;
          exit;
        }

        for (i = 2; i <= NF-truncation_length; i++) {
          if (substr($i, 1, 1) == ".") {
            $i = substr($i, 1, 2);
          } else {
            $i = substr($i, 1, 1);
          }
        }
        print;
      }'
  )

  echo "$truncated_path"
}

Source it in your .zshrc (or .bashrc):

~/.zshrc

source ~/scripts/functions.sh

And then in tmux use it like so:

tmux.conf

set-window-option -g window-status-current-format '#(zsh -c "source ~/scripts/functions.sh && truncate_path #{pane_current_path} 1")'
set-window-option -g window-status-format '#(zsh -c "source ~/scripts/functions.sh && truncate_path #{pane_current_path} 1")'

Upvotes: 0

Greg Bell
Greg Bell

Reputation: 2219

To get the best of both worlds - window name is path when you're at a shell prompt, but name of executable when you're running something, try this:

set-option -g status-interval 1
set-option -g automatic-rename on
set-option -g automatic-rename-format "#{?#{==:#{pane_current_command},bash},#{b:pane_current_path},#{pane_current_command}}"

Replace "bash" with whatever shell you're using.

Upvotes: 22

Show the top N components

enter image description here

Showing just the basename generates too much ambiguity, but full paths are too much clutter, so I settled for:

the/last/path

instead of:

/a/very/long/the/last/path

or just:

path

.tmux.conf

set-window-option -g window-status-current-format '#[fg=white,bold]** #{window_index} #[fg=green]#{pane_current_command} #[fg=blue]#(echo "#{pane_current_path}" | rev | cut -d'/' -f-3 | rev) #[fg=white]**|'
set-window-option -g window-status-format '#[fg=white,bold]#{window_index} #[fg=green]#{pane_current_command} #[fg=blue]#(echo "#{pane_current_path}" | rev | cut -d'/' -f-3 | rev) #[fg=white]|'

Trick taken from: Remove part of path on Unix

If that still does not solve ambiguity, I go for:

bind-key -r w choose-window -F '#{window_index} | #{pane_current_command} | #{host} | #{pane_current_path}'

Tested on Tmux 2.1, Ubuntu 16.04.

Upvotes: 26

Rho Phi
Rho Phi

Reputation: 1240

To change what you see in the window list you can specify a format when you define the key-binding for the chose-window function like this:

bind-key '"'  choose-window  -F "#{session_name} | #{window_name} - #{b:pane_current_path} (#{pane_current_command})"

Upvotes: 0

Justin M. Keyes
Justin M. Keyes

Reputation: 6974

With tmux 2.3+, the b: format modifier shows the "basename" (or "tail") of a path.

set-option -g status-interval 5
set-option -g automatic-rename on
set-option -g automatic-rename-format '#{b:pane_current_path}'

The FORMATS section of man tmux describes other modifiers, such as #{d:} and even #{s/foo/bar/:}.


With tmux 2.2 or older, the basename shell command can be used instead.

set-option -g status-interval 5
set-option -g automatic-rename on
set-option -g automatic-rename-format '#(basename "#{pane_current_path}")'

Upvotes: 95

jibancanyang
jibancanyang

Reputation: 14

I am sure that you want use this:

set -g status-left '#{pane_current_path} '

enter image description here

Upvotes: 0

CEL
CEL

Reputation: 878

Expanding on what Josef wrote, you can put the basename of the directory in the status using a shell snippet:

# be sure to see note* below
set -g window-status-format '#I:#(pwd="#{pane_current_path}"; echo ${pwd####*/})#F'
set -g window-status-current-format '#I:#(pwd="#{pane_current_path}"; echo ${pwd####*/})#F'

# status bar updates every 15s by default**, change to 1s here 
# (this step is optional - a lower latency might have negative battery/cpu usage impacts)
set -g status-interval 1

*Note that what would be ${pwd##*/} is escaped to ${pwd####*/} since # has special meaning in the format string.

**See here for an example default tmux config.

Upvotes: 37

FreePender
FreePender

Reputation: 4879

This doesn't strictly answer your question--it doesn't automatically rename an existing tmux session to the current working directory.

Rather, when creating a new session, it names that session after the current working directory.

Here's what I did:

to

~/.aliases

add

alias tm='tmux new -s `basename $PWD`'

Open a new terminal window and type:

tm

This now creates a new tmux session which is named after the current working directory.

Note: This relies on basename which does not exist in Windows.

Upvotes: 0

Harry Mallon
Harry Mallon

Reputation: 915

I use the following in ~/.tmux.conf to achieve this (working on OSX, zsh, tmux-2.3):

set -g automatic-rename-format '#{pane_current_path}'
set -g status-interval 5

You can set status-interval to 1 to make it respond faster to changing directories.

According to the changelog (https://raw.githubusercontent.com/tmux/tmux/master/CHANGES) this should work in tmux 1.9 and up.

Using ssh into a CentOS machine with tmux 2.3 the window name doesn't change until I press return in the new panel, not sure why that is happening.

Upvotes: 3

logcat
logcat

Reputation: 3474

I am using zsh hook for that

Add following in ~/.zshrc

precmd () {
  if [ -n "$TMUX" ]; then
    tmux set-window-option -q window-status-format "#[fg=cyan bg=cyan] | #[fg=white, bg=cyan] #I | ${PWD##/*/} #[fg=cyan, bg=cyan] | "
    tmux set-window-option -q window-status-current-format "#[fg=cyan, bg=cyan] | #[fg=white, bg=cyan] #I | ${PWD##/*/} #[fg=cyan, bg=cyan] | "
  fi
}

Upvotes: 1

JuniorCompressor
JuniorCompressor

Reputation: 20025

Do something like this in a tmux session for zsh shell:

setopt PROMPT_SUBST
export PS1=$'\ek$(basename $(pwd))\e\\> '

If someone uses bash shell:

export PS1="\033k\$(basename \$(pwd))\033\\> "

You can add these commands in the shell initialization file on the condition the $TERM env variable is set to the value "screen"

Upvotes: 0

Josef Cech
Josef Cech

Reputation: 2275

Adding this config to your ~/.tmux.conf file should work:

set-option -g window-status-current-format '#I:#{pane_current_path}#F'
set-option -g window-status-format '#I:#{pane_current_path}#F'
set-option -g status-interval 1

It depends however on your Tmux version. I wasn't able to make it work on 1.9a3 (in Cygwin) - but with Tmux 1.8 on Ubuntu (in Vagrant) it worked fine.

Upvotes: 4

Related Questions