Skip to content

Instantly share code, notes, and snippets.

@cowens
Created January 5, 2020 07:29
Show Gist options
  • Save cowens/77b28c207508d81c953c42f17a1df842 to your computer and use it in GitHub Desktop.
Save cowens/77b28c207508d81c953c42f17a1df842 to your computer and use it in GitHub Desktop.
tmux.conf
# OS specific changes
# macOS specific commands
if-shell "[[ $(uname) == 'Darwin' ]]" {
# makes pbcopy work from the commandline
set-option -g default-command "reattach-to-user-namespace -l bash"
}
# prefix+t brings up a useless clock, make it look nice
set-option -w -g clock-mode-style 24
set-option -w -g clock-mode-colour green
# vi keybindings forever, when entering copy mode it uses the
# copy-mode-vi keybinding table instead of copy-mode keybinding
# table
set-option -w -g mode-keys vi
# when using the main-horizontal or main-vertical layouts
# sets the width of the main pane
set-option -w -g main-pane-width 120
# tmux waits when it sees an escape character in case it is part
# of a escape sequence. This means hitting escape in vi is painfully
# slow. So make tmux wait less time (default is 500, half a second).
set-option -s escape-time 50
# tmux hides messages a little too fast for me (default is 750)
set-option -g display-time 1500
# You can hit prefix-: and get a prompt to enter tmux commands into.
# This option lets you use vi style keybindings in the prompt
set-option -g status-keys vi
# Normally I like things to be 0 indexed, but since my keyboard's number
# row starts with 1 it makes more sense to have the first pane be 1 as well
# so prefix-1 maps to the first window
set-option -g base-index 1
# Just a big old scroll back limit
set-option -g history-limit 1000000
# green and black is how I roll
set-option -g status-bg green
set-option -g status-fg black
set-option -g message-style fg=black,bg=green # messages and command mode
set-option -g message-command-style fg=black,bg=green # when editing command mode text
set-option -g mode-style bg=green,fg=black # selection should be inverse
# the left side of the status bar gets truncated if it is more than 10
# characters by default. That may have made sense on an 80x25 terminal
# but I have a lot more real estate
set-option -g status-left-length 100
# I don't use #H for the hostname because I prefer to use nicknames and hostnames
# have become monstrosities like sandbox-chas-01.legacy-dev-uw2.zipaws.com
# nested_level is a per-session environment variable I use to keep track
# of how nested my tmux session is (see end of config)
if-shell "[[ $(uname) == 'Darwin' ]]" {
set-option -g status-left '#(cat ~/.hostname) [#{?mouse,on,off}] [#(pbpaste | perl -C -pe "tr/\x0-\x19/\x{2400}-\x{2419}/; \$_ = substr \$_, 0, 10")] [#S] '
} {
set-option -g status-left '#(cat ~/.hostname) [#{?mouse,on,off}] [#S] '
}
set-option -g status-right "%a %m/%d %H:%M:%S"
# eats up more CPU, but I like to see the seconds change for rough timing purposes
set-option -g status-interval 1
# I don't like gaps in the numbering of windows, so when window 4 closes,
# 5 should become 4, 6 should become 5, etc
set-option -g renumber-windows on
set-option -g default-terminal "screen-256color"
# remove default bindings that I don't use
unbind-key C-b
unbind-key M
unbind-key l
unbind-key '"'
unbind-key %
unbind-key -
unbind-key [
unbind-key ]
unbind-key C-Left
unbind-key C-Right
unbind-key C-Up
unbind-key C-Down
# C-a should be the prefix
set-option -g prefix C-a
# changed bindings
bind-key C-a last-window # was l
bind-key - split-window # was "
bind-key | split-window -h # was %
bind-key p run "~/bin/tpaste" # was ]
bind-key Left select-pane -L # no -r so it won't repeat
bind-key Right select-pane -R # no -r so it won't repeat
bind-key Up select-pane -U # no -r so it won't repeat
bind-key Down select-pane -D # no -r so it won't repeat
# new bindings
bind-key P command-prompt -p 'save history to filename:' -I '~/tmux.history' 'capture-pane -S -32768 ; save-buffer %1'
bind-key a send-prefix # a for send the prefix a
bind-key m set-option mouse # m for mouse on/off
bind-key r source-file ~/.tmux.conf \; display-message "sourced conf" # r for reload conf
# simple window navigation, -T root means you don't need to hit prefix first,
# this makes scanning for what you want much faster
bind-key -T root S-left previous-window
bind-key -T root S-right next-window
# bring the current environment when attaching to a session
# note: this does not fix the environment of existing shells
# you need this in the PROMPT_COMMAND environment variable to
# PROMPT_COMMAND='eval $(tmux show-environment |grep -v ^- | perl -pe "s/=(.*)/=\x22\$1\x22/")'
set-option -g update-environment "SSH_AUTH_SOCK SSH_AGENT_PID SSH_ASKPASS SSH_CONNECTION"
# I have my own clipboard solution, so no need to use escape sequences
set-option -s set-clipboard off
# make vi mode more like vim
# I have a TCP server that runs on my macOS machine that exposes my pasteboard
# via an ssh tunnel (it is also authenticating and encrypting the messages), so
# even under Linux I have a version pbcopy.
bind-key Escape copy-mode # was [
bind-key -T copy-mode-vi 'v' send-keys -X begin-selection
bind-key -T copy-mode-vi 'y' send-keys -X copy-pipe-and-cancel "~/bin/pbcopy"
bind-key -T copy-mode-vi 'C-v' send-keys -X rectangle-toggle
bind-key -T copy-mode-vi Escape send-keys -X cancel
# Turning mouse on is only viable because of the TCP server mentioned above.
# Turning it on gives me nice things like handling selections involving split
# panes correctly and the ability to select and resize panes with the mouse
set-option -g -s mouse on
bind-key -T copy-mode-vi MouseDrag1Pane select-pane \; send-keys -X begin-selection
bind-key -T copy-mode-vi MouseDragEnd1Pane send-keys -X copy-pipe-and-cancel "~/bin/pbcopy"
# double click to copy word, this sort of sucks in comparison to not having the
# mouse on there is no obvious indicator what was selected.
bind-key -T root DoubleClick1Pane {
select-pane
copy-mode
send-keys -X select-word
send-keys -X copy-pipe-and-cancel "~/bin/pbcopy"
refresh-client -S # make the status bar catch the updated buffer quick
}
# middle mouse paste, uses the same TCP server from above
bind-key -T root MouseDown2Pane select-pane \; run "~/bin/tpaste"
bind-key -T copy-mode-vi WheelUpPane select-pane \; send-keys -X -N 5 scroll-up
bind-key -T copy-mode-vi WheelDownPane select-pane \; send-keys -X -N 5 scroll-down
# The following insanity is to enable nested instances of tmux. The most
# common case is ssh'ing into a remote host that is running tmux. Hitting
# shift-up will cause (almost) all of the keybindings in the current tmux
# instance to go away letting the nested tmux see the keypresses. Hitting
# shift-down will return control to the parent tmux instance. I am limiting
# this to five levels because two should generally be enough and, since there
# is no math in tmux config, I have had to do addition/subtraction with
# if-shell commands.
# this runs every time a session is created. It creates an environment
# variable named nested_level that keeps track of how deep we have ceded
# control
set-hook -g session-created { set-environment nested_level 0 }
bind-key -T root S-up {
# no need to do math, we have to be going to level one if the root
# keybinding table still has shift-up in it
set-environment nested_level 1
# turn off the prefix so the prefix can go to the deeper tmux instances
set-option prefix None
# set the keybinding table name to "nested", there are only two
# keybindings in that table and they are below
set-option key-table nested
# set inverse the window in the status bar so we know which one we were
# in
set-option window-status-current-style "fg=green,bg=black"
# if for some reason we were in copy mode, cancel it
if-shell -F '#{pane_in_mode}' { send-keys -X cancel }
# might as well update the status bar now instead of in a second
refresh-client -S
}
# since this is in the nested keybinding table, it won't run until unless
# the keybinding above has run. We are just doing some basic addition on
# nested_level and passing the shift-up on to the deeper level of tmux
bind-key -T nested S-up {
if-shell -F '#{==:#{nested_level},1}' {
set-environment nested_level 2
send-keys S-up
} {
if-shell -F '#{==:#{nested_level},2}' {
send-keys S-up
set-environment nested_level 3
} {
if-shell -F '#{==:#{nested_level},3}' {
send-keys S-up
set-environment nested_level 4
}
}
}
}
# same as the two above but in reverse
bind-key -T nested S-down {
if-shell -F '#{==:#{nested_level},4}' {
set-environment nested_level 3
send-keys S-down
} {
if-shell -F '#{==:#{nested_level},3}' {
set-environment nested_level 2
send-keys S-down
} {
if-shell -F '#{==:#{nested_level},2}' {
set-environment nested_level 1
send-keys S-down
} {
if-shell -F '#{==:#{nested_level},1}' {
set-environment nested_level 0
set-option -u prefix
set-option -u key-table
set-option -u window-status-current-style
refresh-client -S
}
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment