################################################################################ #### Unbreak things # Prevent tmux from messing up keybindings and colors. # This is witchcraft, I have no explanation for the following commands. set-option -g xterm-keys on set-window-option -g xterm-keys on set-option -g default-terminal "xterm-256color" # Prevent tmux from waiting half a second before processing the ESC key, see: # http://unix.stackexchange.com/a/25638/176805 set-option -s escape-time 0 # Enable proper mouse support: # http://www.hamvocke.com/blog/a-guide-to-customizing-your-tmux-conf/ set-option -g mouse on bind-key m set-option -g mouse on bind-key M set-option -g mouse off # The following line prevents a weird OS X problem that otherwise # keeps the "open" command from working (and has several other # undesirable properties; see issue #120). For more details on the # issue, see [1]-[5]. # # The exact version of the solution below is the only way I have found # to satisfy all of the following properties: # # * It fixes the problem, i.e. "open" works correctly. # # * When opening a new window in tmux, the window name is correctly # set to zsh initially. It does not briefly flash # "reattach-to-user-namespace", and it does not display # "/usr/local/bin/zsh" either. # # * The "automatic-rename" property is still set to "on" in new tmux # windows, meaning that if you run another program, the window name # will change to reflect that (unless you manually rename the # window). # # * Exiting the shell (e.g. with Control+D) will immediately kill the # tmux window instead of dropping you into another shell. # # * It works for all shells, and doesn't hardcode any particular one. # # * It still works when reattach-to-user-namespace is unavailable. # # Yes, it's horrible. I think we can all agree on that, no need to # point it out. # # Unfortunately, tmux appears to be remarkably unintelligent when it # comes to determining the string to show as the window title. # Basically, about as unintelligent as shebang parsing, and anyone # involved in the virtualenv-can't-handle-spaces fiasco will know # that's pretty darn unintelligent. In particular, it grabs characters # literally from the beginning of the command string until it hits a # space, then discards until the first slash, if there is one. This # means it's impossible to quote the executable name, so if your shell # has spaces in its name, you're screwed. Making this whole fiasco # work for paths with double quotes in it is an exercise in futility, # I think. # # [1]: http://superuser.com/q/834525/326239 # [2]: http://www.economyofeffort.com/2013/07/29/reattach-to-user-namespace-the-fix-for-your-tmux-in-os-x-woes/ # [3]: https://www.elmund.io/osx/2015/07/10/open-command-in-osx-tmux/ # [4]: https://github.com/ChrisJohnsen/tmux-MacOSX-pasteboard # [5]: https://github.com/ChrisJohnsen/tmux-MacOSX-pasteboard/issues/10 run-shell 'command -v reattach-to-user-namespace > /dev/null && tmux set-option -g default-command "$SHELL -c \"reattach-to-user-namespace -l \\\"$(basename "$SHELL")\\\"\"" || true' ################################################################################ #### Keybindings # Use ` instead of C-b as prefix key, see: # http://www.hamvocke.com/blog/a-guide-to-customizing-your-tmux-conf/ unbind-key C-b set-option -g prefix ` bind-key ` send-prefix # Force tmux to use Emacs keybindings, see: # http://stackoverflow.com/q/18240683/3538165 # http://stackoverflow.com/a/18247437/3538165 set-option -g status-keys emacs set-window-option -g mode-keys emacs # Turn off repeatability for moving between panes. Otherwise, if you split # horizontally and switch panes, you will have to wait for the 'repeat period' # to expire before you can use and to page through shell history. # # Doing it this way instead of using 'set-option -g repeat-time 0' makes it # so that Control+Arrows and Meta+Arrows (for resizing panes) are still # repeatable. # # See: http://superuser.com/a/325579/326239 bind-key Up select-pane -U bind-key Down select-pane -D bind-key Left select-pane -L bind-key Right select-pane -R # Keybinding for reloading .tmux.conf. bind-key R source-file ~/.tmux.conf # Keybinding for swapping the current and marked windows. # bind-key \ swap-window # Keybindings for swapping adjacent windows. bind-key < swap-window -t -1 bind-key > swap-window -t +1 # Keybinding for inserting a window. # Adapted from http://superuser.com/a/704551/326239 bind-key I command-prompt -p 'Insert window at:' ' \ run-shell " \ if tmux select-window -t %1; then \ tmux new-window -a; \ tmux swap-window -s %1 -t \$((%1+1)); \ else \ tmux new-window; \ tmux move-window -t %1; \ fi; \ tmux select-window -t #{window_id}; \ tmux select-window -t %1; \ "' ################################################################################ #### Status bar # The following code is adapted from: # https://coderwall.com/p/trgyrq/make-your-tmux-status-bar-responsive # It provides the same appearance as https://github.com/powerline/powerline, # but sidesteps the environment/configuration hell which that project # introduces. # Format to display on the left-hand side of the status bar. # Note that the conditional #{?cond,true,false} operator does not do any # fancy parsing, so you can't have literal commas in the conditions -- # this will cause the conditions to be split up. So we have to use multiple # style #[attr=value] directives. set-option -g status-left '#{?client_prefix,#[fg=colour254]#[bg=colour31],#[fg=colour16]#[bg=colour254]#[bold]} #{=80:session_name} #{?client_prefix,#[fg=colour31],#[fg=colour254]}#[bg=colour234,nobold] ' # Maximum length of the format displayed on the left-hand side. # Since the maximum length of the session name is limited in the above # format string, this number is unimportant -- it just needs to be a # bit larger than what is allocated for the session name, to allow for # the surrounding characters. set-option -g status-left-length 90 # Format to display on the right-hand side of the status bar. set-option -g status-right '#{?mouse,#[fg=colour254]#[bg=colour31],#[fg=colour244,bg=colour234]} Mouse #[fg=colour254,bg=colour234] #H' # Format to display for the current window. set-option -g window-status-current-format '#[fg=colour117,bg=colour31] #{window_index}#{window_flags} #[fg=colour231,bold]#(tmux display-message -p "#{pane_current_path}" | sed "s#$HOME#~#g") #{?#{m:*#{b:SHELL}*, #{pane_current_command}},| #{pane_current_command} }#[fg=colour31,bg=colour234,nobold]' # Format to display for other windows. set-option -g window-status-format '#[fg=colour244,bg=colour234]#{window_index}#{window_flags} #[fg=colour249]#(tmux display-message -p "#{pane_current_path}" | sed "s#$HOME#~#g") #{?#{m:*#{b:SHELL}*, #{pane_current_command}},| #{pane_current_command} }' # Background color for parts of the status bar not specified by the above # formats. For instance, the empty space to the right, and the single # spaces between instances of window-status-format. set-option -g status-bg colour234 # Update the status bar every second, instead of the default 15(!) # seconds. It doesn't look like it's possible to update more than # once per second, unfortunately. set-option -g status-interval 1 ################################################################################ #### Appearance # Attempt to set the title of the terminal emulator. set-option -g set-titles on set-option -g set-titles-string '#{session_name} - #{window_name}' # Show an indicator in the status bar on windows with unseen activity. set-option -g monitor-activity on # Make the borders of the current pane the same color as the borders # of other panes. This is because the borders of the marked pane are # *inverted*, and while different foreground colors in different parts # of the frame are not too objectionable, different background colors # look very bad. set-option -g pane-active-border-style none ################################################################################ #### Miscellaneous # When the current session is killed, switch to another session instead of # detaching. set-option -g detach-on-destroy off # Show messages until they are dismissed, instead of for 750 milliseconds(!). # Actually it is only for an hour, because it doesn't seem like you can turn # off the time limit. set-option -g display-time 36000000 # Open new windows in the same directory as the current pane. bind-key c new-window -c "#{pane_current_path}" # Automatically renumber windows when one is deleted, see: # http://unix.stackexchange.com/a/51879/176805 set-option -g renumber-windows on # Number windows and panes from 1, instead of 0; see: # http://unix.stackexchange.com/a/35932/176805 set-option -g base-index 1 set-window-option -g pane-base-index 1 # Open new panes in the same directory as the current pane. bind-key % split-window -h -c "#{pane_current_path}" bind-key '"' split-window -v -c "#{pane_current_path}" # Increase the scrollback buffer size from 2000 to a larger size, but # not one so large that tmux begins to lag. set-option -g history-limit 10000 ################################################################################ #### Local overrides if-shell "[[ -f ~/.tmux.local.conf ]]" "source ~/.tmux.local.conf"