Take the 2-minute tour ×
Unix & Linux Stack Exchange is a question and answer site for users of Linux, FreeBSD and other Un*x-like operating systems.. It's 100% free, no registration required.

I've been experimenting with different tmux keybinding settings and I've noticed the following:

If I reload my tmux config (from within tmux) the keybindings I once had loaded will remain loaded. The only way (I know of) to clean this up is to quit all tmux sessions and restart. So it looks like tmux remembers all previously loaded keybindings and will only remove them on a fresh start or by explicitly unbinding them.

To recreate this:

  • open a terminal (A)
  • start tmux
  • check whether the keybinding shows a clock (press PREFIX C-t)
  • press PREFIX ? to see the keybinding in the list
  • edit ~/.tmux.conf
  • add a keybinding (bind C-t display "Keybinding C-t")
  • reload tmux config (PREFIX : source-file ~/.tmux.conf)
  • check whether the keybinding works (press PREFIX C-t)
  • press PREFIX ? to see the new keybinding in the list
  • edit ~/.tmux.conf again
  • remove the keybinding (so remove bind C-t display "Keybinding C-t")
  • reload tmux config (PREFIX : source-file ~/.tmux.conf)
  • check whether the keybinding works (press PREFIX C-t), it still displays "Keybinding C-t"
  • press PREFIX ? to see that the new keybinding is still in the list
  • exit tmux
  • enter tmux
  • check whether the original keybinding works again (press PREFIX C-t), it should now display a clock again
  • press PREFIX ? to see that the new keybinding has been removed from the list

My question: is there a way to instruct tmux to "forget" all loaded configs and then load .tmux.conf ?

share|improve this question

4 Answers 4

up vote 4 down vote accepted

According to man tmux, unbind-key -a is what you are looking for.

Note that tmux runs a server that will only exit once all sessions are closed, and the key-bindings are per-server. Hence once you create a binding, it will be persistent over all client detaches.

That said, put unbind-key -a at the very top of your configuration file, and on config reload it should do what you want - unbind everything and start binding from scratch.

share|improve this answer
    
Yes and I've stated that in my question already. But instead of "resetting" all possibly binded keys manually I'd like tmux to restart with a "clean slate" and then reload the config file. –  Niels Bom Dec 5 '12 at 14:26
    
@NielsBom check updated answer please –  peterph Dec 5 '12 at 15:01
    
You are correct, the unbind-key -a removes all the keybindings. I'll mark your answer as correct, but for other viewers' sake I'll also add the "hack" I've applied to fix a problem with unbind-key -a. –  Niels Bom Dec 5 '12 at 15:42
    
See my answer for my solution. –  Niels Bom Dec 5 '12 at 15:58

The correct solution (by Peter

So @peterph gave the correct answer which is unbind-key -a which does the following: (man tmux)

If -a is present, all key bindings are removed.

A workable solution

The problem (for me) is that "all" actually means all. Including the keybindings tmux comes with. If you execute the unbind-key -a command tmux instantly doesn't have any keybindings at all anymore so you can't even enter command mode or do anything basically.

My (rather ugly) fix for this is the following:

  • create a .tmux.reset.conf that removes all keybindings and then rebinds all the ones tmux has by default
  • source that reset at the top of your .tmux.conf

My .tmux.conf:

# always load the reset file first
source-file ~/.tmux.reset.conf

My .tmux.reset.conf:

# First remove *all* keybindings
unbind-key -a
# Now reinsert all the regular tmux keys
bind-key C-b send-prefix
bind-key C-o rotate-window
bind-key C-z suspend-client
bind-key Space next-layout
bind-key ! break-pane
bind-key " split-window
bind-key # list-buffers
bind-key $ command-prompt -I #S "rename-session '%%'"
bind-key % split-window -h
bind-key & confirm-before -p "kill-window #W? (y/n)" kill-window
bind-key ' command-prompt -p index "select-window -t ':%%'"
bind-key ( switch-client -p
bind-key ) switch-client -n
bind-key , command-prompt -I #W "rename-window '%%'"
bind-key - delete-buffer
bind-key . command-prompt "move-window -t '%%'"
bind-key 0 select-window -t :0
bind-key 1 select-window -t :1
bind-key 2 select-window -t :2
bind-key 3 select-window -t :3
bind-key 4 select-window -t :4
bind-key 5 select-window -t :5
bind-key 6 select-window -t :6
bind-key 7 select-window -t :7
bind-key 8 select-window -t :8
bind-key 9 select-window -t :9
bind-key : command-prompt
bind-key ; last-pane
bind-key = choose-buffer
bind-key ? list-keys
bind-key D choose-client
bind-key L switch-client -l
bind-key [ copy-mode
bind-key ] paste-buffer
bind-key c new-window
bind-key d detach-client
bind-key f command-prompt "find-window '%%'"
bind-key i display-message
bind-key l last-window
bind-key n next-window
bind-key o select-pane -t :.+
bind-key p previous-window
bind-key q display-panes
bind-key r refresh-client
bind-key s choose-session
bind-key t clock-mode
bind-key w choose-window
bind-key x confirm-before -p "kill-pane #P? (y/n)" kill-pane
bind-key { swap-pane -U
bind-key } swap-pane -D
bind-key ~ show-messages
bind-key PPage copy-mode -u
bind-key -r Up select-pane -U
bind-key -r Down select-pane -D
bind-key -r Left select-pane -L
bind-key -r Right select-pane -R
bind-key -r M-1 select-layout even-horizontal
bind-key -r M-2 select-layout even-vertical
bind-key -r M-3 select-layout main-horizontal
bind-key -r M-4 select-layout main-vertical
bind-key -r M-5 select-layout tiled
bind-key -r M-n next-window -a
bind-key -r M-o rotate-window -D
bind-key -r M-p previous-window -a
bind-key -r M-Up resize-pane -U 5
bind-key -r M-Down resize-pane -D 5
bind-key -r M-Left resize-pane -L 5
bind-key -r M-Right resize-pane -R 5
bind-key -r C-Up resize-pane -U
bind-key -r C-Down resize-pane -D
bind-key -r C-Left resize-pane -L
bind-key -r C-Right resize-pane -R

It kinda looked like this could have worked with tmux key-tables (as far as I can tell) but you can't add new key-tables.

share|improve this answer
1  
It's likely that you can quickly generate the equivalent of your .tmux.reset.conf by running tmux list-keys in a "clean" session. –  jw013 Dec 5 '12 at 23:31
    
tmux -f /dev/null -L temp start-server \; list-keys will effectively generate the defaults (though you need to add a backslash before the semicolon in its binding). –  Chris Johnsen Dec 6 '12 at 5:40
    
@ChrisJohnsen Could you pls elaborate on start-server in a separate answer? –  Niels Bom Dec 6 '12 at 8:57

There is currently no direct way to reset a key’s binding to its default; the initialization of the default bindings (in key_bindings_init()) is done once when the tmux server first starts (in server_start()), and there is no mechanism to reset a single key.

For your desired scenario where you want the act of sourcing your configuration file to reestablish a default binding that was previously overridden by a custom binding that has since been deleted from your configuration file, the method you devised is reasonable (though unfortunately verbose): unbind-key -a, then reestablish all the “default” bindings, then establish your custom bindings (some of which might override a “default” binding).

A server’s current bindings can be extracted with the list-keys command*; this can help generate/maintain your proposed .tmux.reset.conf file, but you need a way to extract the default bindings, not the current bindings.

* There are some situations where the output of list-keys is not currently directly usable: the binding for semicolon needs its semicolon escaped with a backslash to prevent it from being interpreted as a tmux command separator, and any bindings that had arguments that used double quotes inside single quotes (none of the default bindings are like this) will come out as double quotes inside double qoutes.

To get the default bindings you need a temporary server with a minimal configuration (i.e. no custom bindings) so that you can capture its list-keys output. There is no limit to the number of tmux servers you can run, but each one must use a different socket pathname; the -L and -S tmux options can be used to specify a socket name (in $TMPDIR/tmux-$UID or full socket pathname. So, to talk to (or start) a new server on a socket named temp, you would use this:

tmux -L temp …

To make sure it does not use your .tmux.conf, you use -f to tell it to read /dev/null (a special file that is always empty):

tmux -f /dev/null -L temp …

Note: this does not prevent the processing of /etc/tmux.conf, if such a file exists; the path to this “system configuration file” is hard-coded and there is no option to bypass it (short of patching the code).

Normally, you need a new-session command to actually start the server, but we do not want any sessions, just an initialized server to query. The start-server command does just that: starts a server without creating any sessions.

tmux -f /dev/null -L temp start-server …

Now, we just need to append our “query” command (list-keys in this case):

tmux -f /dev/null -L temp start-server \; list-keys

Note: the semicolon needs to be escaped or quoted to prevent the shell from treating it as a shell command separator since we want it to be a tmux command separator.

Since there are no sessions to maintain, the server will exit automatically after it finishes running the list-keys command.

So, you can use a command like this to generate the bulk of your .tmux.reset.conf without having to worry about temporarily removing your .tmux.conf file (to let you see just the default bindings) and without having to shut down any existing servers.


If the run-shell command was synchronous you could embed a call like this in your configuration file (capturing to a temporary file that you would then process with source-file) instead of having a static file (your .tmux.reset.conf). That would let you always use the default bindings from your current version of tmux (the default bindings change occasionally). Alas, the completion of the run-shell command is currently asynchronous with respect to subsequent commands (commands that come after a run-shell command will usually run before the process spawned by run-shell has had a chance to finish).

share|improve this answer

Please also refer to the other answers here, as they do a good job of explaining the situation. I have here my tmux 1.8 compatible tmux.reset.conf, which I had to make several modifications after copying out the tmux -f /dev/null -L temp start-server \; list-keys output. In particular, several things had to be quoted.

# First remove *all* keybindings
unbind-key -a
# Now reinsert all the regular tmux keys
bind-key C-b send-prefix
bind-key C-o rotate-window
bind-key C-z suspend-client
bind-key Space next-layout
bind-key ! break-pane
bind-key '"' split-window
bind-key '#' list-buffers
bind-key '$' command-prompt -I "#S" "rename-session '%%'"
bind-key % split-window -h
bind-key & confirm-before -p "kill-window #W? (y/n)" kill-window
bind-key "'" command-prompt -p index "select-window -t ':%%'"
bind-key ( switch-client -p
bind-key ) switch-client -n
bind-key , command-prompt -I "#W" "rename-window '%%'"
bind-key - delete-buffer
bind-key . command-prompt "move-window -t '%%'"
bind-key 0 select-window -t :0
bind-key 1 select-window -t :1
bind-key 2 select-window -t :2
bind-key 3 select-window -t :3
bind-key 4 select-window -t :4
bind-key 5 select-window -t :5
bind-key 6 select-window -t :6
bind-key 7 select-window -t :7
bind-key 8 select-window -t :8
bind-key 9 select-window -t :9
bind-key : command-prompt
bind-key \; last-pane
bind-key = choose-buffer
bind-key ? list-keys
bind-key D choose-client
bind-key L switch-client -l
bind-key [ copy-mode
bind-key ] paste-buffer
bind-key c new-window
bind-key d detach-client
bind-key f command-prompt "find-window '%%'"
bind-key i display-message
bind-key l last-window
bind-key n next-window
bind-key o select-pane -t :.+
bind-key p previous-window
bind-key q display-panes
bind-key r refresh-client
bind-key s choose-tree
bind-key t clock-mode
bind-key w choose-window
bind-key x confirm-before -p "kill-pane #P? (y/n)" kill-pane
bind-key z resize-pane -Z
bind-key { swap-pane -U
bind-key } swap-pane -D
bind-key '~' show-messages
bind-key PPage copy-mode -u
bind-key -r Up select-pane -U
bind-key -r Down select-pane -D
bind-key -r Left select-pane -L
bind-key -r Right select-pane -R
bind-key M-1 select-layout even-horizontal
bind-key M-2 select-layout even-vertical
bind-key M-3 select-layout main-horizontal
bind-key M-4 select-layout main-vertical
bind-key M-5 select-layout tiled
bind-key M-n next-window -a
bind-key M-o rotate-window -D
bind-key M-p previous-window -a
bind-key -r M-Up resize-pane -U 5
bind-key -r M-Down resize-pane -D 5
bind-key -r M-Left resize-pane -L 5
bind-key -r M-Right resize-pane -R 5
bind-key -r C-Up resize-pane -U
bind-key -r C-Down resize-pane -D
bind-key -r C-Left resize-pane -L
bind-key -r C-Right resize-pane -R
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.