It happened to me multiple times that I closed a pane without actually wanting it via a (too) quick <C-d>. Activate remain-on-exit so that I have to press <C-d> twice before the pane is actually killed. Dead panes can be recovered with `respawn-pane`. Will see how this goes - could be annoying.
337 lines
11 KiB
Bash
337 lines
11 KiB
Bash
set -g default-terminal "tmux-256color"
|
|
set -g mouse on
|
|
set -g mode-keys vi
|
|
set -g extended-keys always
|
|
|
|
set -g prompt-history-limit 999999
|
|
set -g history-file "$XDG_DATA_HOME/tmux/tmux_history"
|
|
run-shell 'mkdir -p "${XDG_DATA_HOME:-$HOME/.local/share}/tmux"'
|
|
|
|
# Better clipboard on mousedrag (https://unix.stackexchange.com/a/349020)
|
|
# Disable xterm escape sequences for setting clipboard
|
|
set -s set-clipboard off
|
|
|
|
set -g copy-command 'xclip -selection clipboard'
|
|
|
|
# https://github.com/neovim/neovim/wiki/FAQ#cursor-shape-doesnt-change-in-tmux
|
|
set -ga terminal-overrides '*:Ss=\E[%p1%d q:Se=\E[ q'
|
|
|
|
# Set C-a as new prefix
|
|
unbind C-b
|
|
set -g prefix C-a
|
|
bind C-a send-prefix
|
|
|
|
# Copy selection into primary selection (without aborting)
|
|
bind -T copy-mode-vi MouseDragEnd1Pane {
|
|
send -X copy-pipe-no-clear "xclip -selection primary"
|
|
}
|
|
|
|
# Select word or line on double or triple click respectively (w/o aborting).
|
|
# (These are the defaults w/o the `run -d 0.3; send -X copy-pipe-and-cancel`)
|
|
bind -T copy-mode-vi SecondClick1Pane {
|
|
select-pane -t=
|
|
send -X select-word
|
|
send -X pipe-no-clear "xclip -selection primary"
|
|
}
|
|
bind -T copy-mode-vi TripleClick1Pane {
|
|
select-pane -t=
|
|
send -X select-line
|
|
send -X pipe-no-clear "xclip -selection primary"
|
|
}
|
|
bind -n SecondClick1Pane {
|
|
select-pane -t=
|
|
if -F "#{||:#{pane_in_mode},#{mouse_any_flag}}" {
|
|
send -M
|
|
} {
|
|
copy-mode
|
|
send -X select-word
|
|
}
|
|
send -X pipe-no-clear "xclip -selection primary"
|
|
}
|
|
bind -n TripleClick1Pane {
|
|
select-pane -t=
|
|
if -F "#{||:#{pane_in_mode},#{mouse_any_flag}}" {
|
|
send -M
|
|
} {
|
|
copy-mode
|
|
send -X select-line
|
|
}
|
|
send -X pipe-no-clear "xclip -selection primary"
|
|
}
|
|
|
|
# Scroll up 5 lines when entering copy-mode through the mouse wheel, send 5x`up`
|
|
# when the current pane is in alternate mode and discard the `-e` flag passed to
|
|
# copy-mode from the default binding (See below)
|
|
# TODO: Do not modify selection when scolling with the wheel
|
|
bind -n WheelUpPane \
|
|
if -F "#{||:#{pane_in_mode},#{mouse_any_flag}}" {
|
|
send -M
|
|
} {
|
|
if -F "#{alternate_on}" {
|
|
send -N5 up
|
|
} {
|
|
copy-mode; send -XN5 scroll-up
|
|
}
|
|
}
|
|
# Scroll without selecting the pane
|
|
bind -T copy-mode-vi WheelUpPane send -XN5 scroll-up
|
|
# Exit copy-mode when at the bottom. This practically mimics `copy-mode -e` but
|
|
# only scrolling with the wheel (`-e` annoys me when scrolling down with `C-d`).
|
|
bind -T copy-mode-vi WheelDownPane \
|
|
if -F "#{==:0,#{scroll_position}}" {
|
|
send -X cancel
|
|
} {
|
|
send -XN5 scroll-down
|
|
}
|
|
|
|
# Split panes with > and <
|
|
unbind %
|
|
bind < splitw -v -c "#{pane_current_path}"
|
|
unbind '"'
|
|
bind > splitw -h -c "#{pane_current_path}"
|
|
|
|
# tmux stopped supporting format string for -t, thus run-shell is
|
|
bind -N "Create a new window behind the current one with the same CWD" \
|
|
c run-shell \
|
|
"tmux neww -at #{active_window_index} -c \"#{pane_current_path}\""
|
|
|
|
bind -N "Break off the current pane to a new window behind the current one" \
|
|
! run-shell "tmux breakp -at #{active_window_index}"
|
|
|
|
bind -N "Source the config file" \
|
|
R \
|
|
source-file "$XDG_CONFIG_HOME/tmux/tmux.conf" \; \
|
|
display "Sourced $XDG_CONFIG_HOME/tmux/tmux.conf"
|
|
|
|
# Fullscreen pane (toggle)
|
|
bind F resizep -Z
|
|
|
|
# Automatically renumber windows when closing one
|
|
set -g renumber-windows on
|
|
# Number windows with 1-based indices
|
|
set -g base-index 1
|
|
|
|
# Enter copy-mode and scroll one page up directly with PageUp without the need
|
|
# of the prefix. (Exists already per default with prefix)
|
|
bind -n PPage copy-mode -u
|
|
|
|
# Repeatable window-navigation bindings
|
|
bind -r n next
|
|
bind -r C-n next
|
|
bind -r p prev
|
|
bind -r C-p prev
|
|
|
|
# Jump back to last focused window
|
|
bind C-o last-window
|
|
|
|
# Swap window with previous/next one
|
|
bind -r N swap-window -d -t :+1
|
|
bind -r P swap-window -d -t :-1
|
|
|
|
# Reorder windows by dragging them in the status line.
|
|
bind -n MouseDrag1Status swap-window -d -t=
|
|
|
|
# TODO: do nothing on drags that don't start on a window name
|
|
bind -n MouseDragEnd1StatusDefault \
|
|
if -F "#{e|>|f|0:#{mouse_x},#{e|/|f:#{window_width},2}}" {
|
|
run-shell "tmux move-window -at #{last_window_index}"
|
|
} {
|
|
move-window -t0
|
|
}
|
|
|
|
# Repeatable window-movement bindings
|
|
bind -r \{ swap-pane -U
|
|
bind -r \} swap-pane -D
|
|
|
|
# Select windows with Alt-[0-9], select last window if target is current
|
|
bind -n M-1 select-window -T -t 1
|
|
bind -n M-2 select-window -T -t 2
|
|
bind -n M-3 select-window -T -t 3
|
|
bind -n M-4 select-window -T -t 4
|
|
bind -n M-5 select-window -T -t 5
|
|
bind -n M-6 select-window -T -t 6
|
|
bind -n M-7 select-window -T -t 7
|
|
bind -n M-8 select-window -T -t 8
|
|
bind -n M-9 select-window -T -t 9
|
|
bind -n M-0 select-window -T -t 10
|
|
|
|
# Vim-bindings
|
|
|
|
# Enter copy-mode with Escape
|
|
# bind Escape copy-mode
|
|
|
|
# Start selection (i.e. visual mode) with `v`, and rectangle selection (i.e.
|
|
# visual block mode) with `C-v`
|
|
# TODO: mimic vims behaviour for visual mode cycling and toggling
|
|
unbind -T copy-mode-vi v
|
|
bind -T copy-mode-vi v send -X begin-selection
|
|
unbind -T copy-mode-vi C-v
|
|
bind -T copy-mode-vi C-v {
|
|
if -F "#{selection_active}" {} { send -X begin-selection }
|
|
send -X rectangle-toggle
|
|
}
|
|
|
|
# Yank into system clipboard with vim-like bindings
|
|
bind -T copy-mode-vi y run-shell '${XDG_CONFIG_HOME:-$HOME/.config}/tmux/yank.sh'
|
|
bind -T copy-mode-vi Y \
|
|
if -F "#{selection_present}" {
|
|
send -X copy-pipe-line
|
|
} {
|
|
send -X copy-pipe-end-of-line
|
|
}
|
|
|
|
# Clear selection or cancel copy-mode when nothing is selected
|
|
bind -T copy-mode-vi Escape \
|
|
if -F "#{selection_present}" {
|
|
send -X clear-selection
|
|
} {
|
|
send -X cancel
|
|
}
|
|
|
|
# Use insert-mode-like bindings to cancel copy-mode
|
|
bind -T copy-mode-vi A send -X cancel
|
|
bind -T copy-mode-vi I send -X cancel
|
|
bind -T copy-mode-vi a send -X cancel
|
|
|
|
# Rudimentary text object simulation
|
|
bind -T copy-mode-vi i run-shell '${XDG_CONFIG_HOME:-$HOME/.config}/tmux/textobjs.sh'
|
|
|
|
# Simulate vim's C-e & C-y (Keep cursor position while scrolling). As tmux
|
|
# cannot scroll past the first and last history line, both bindings stop
|
|
# scrolling when the respective line is visible. This mimics the behaviour of
|
|
# vim's C-y at the top of the file.
|
|
bind -T copy-mode-vi C-e \
|
|
# check that there is still history beneath to scroll to.
|
|
if -F "#{e|>:#{scroll_position},0}" {
|
|
send-keys -X scroll-down
|
|
# check that the cursor is not at the top of the pane
|
|
if -F "#{e|>:#{copy_cursor_y},#{scroll_region_upper}}" {
|
|
send-keys -X cursor-up
|
|
}
|
|
}
|
|
|
|
bind -T copy-mode-vi C-y \
|
|
# check that there is still history above to scroll to.
|
|
if -F "#{e|<:#{scroll_position},#{history_size}}" {
|
|
send-keys -X scroll-up
|
|
# check that the cursor is not at the bottom of the pane
|
|
if -F "#{e|<:#{copy_cursor_y},#{scroll_region_lower}}" {
|
|
send-keys -X cursor-down
|
|
}
|
|
}
|
|
|
|
# Navigate panes with <prefix>-[hjkl]
|
|
# NOTE: C-[hjkl] (w/o prefix) moves through vim splits and tmux panes
|
|
# See vim-tmux-navigator
|
|
unbind l
|
|
bind -r h selectp -L
|
|
bind -r j selectp -D
|
|
bind -r k selectp -U
|
|
bind -r l selectp -R
|
|
|
|
# Resize mode similar to my i3 config
|
|
bind -T resize h resizep -L \; switchc -T resize
|
|
bind -T resize j resizep -D \; switchc -T resize
|
|
bind -T resize k resizep -U \; switchc -T resize
|
|
bind -T resize l resizep -R \; switchc -T resize
|
|
bind -T resize 1 selectl even-horizontal \; switchc -T resize
|
|
bind -T resize 2 selectl even-vertical \; switchc -T resize
|
|
bind -T resize 3 selectl main-horizontal \; switchc -T resize
|
|
bind -T resize 4 selectl main-vertical \; switchc -T resize
|
|
bind -T resize 5 selectl tiled \; switchc -T resize
|
|
bind r switchc -T resize
|
|
|
|
# Make it possible to send keys that are bound in the root key table. (C-h for
|
|
# example is sometimes needed as backspace sequence)
|
|
# TODO: Make repeatable without C-v
|
|
bind -r C-v command-prompt -k -p (selfinsert) { send "%%" }
|
|
|
|
# Synchronize the panes in the current window with `<prefix>S`
|
|
bind S set -w synchronize-panes
|
|
|
|
# Require confirmation before killing a pane
|
|
set -g remain-on-exit on
|
|
bind -n C-d if -F "#{pane_dead}" { kill-pane } { send }
|
|
|
|
# Change installation location of plugins
|
|
setenv -g TMUX_PLUGIN_MANAGER_PATH "$XDG_CONFIG_HOME/tmux/plugins/"
|
|
|
|
## Plugins
|
|
set -g @plugin 'tmux-plugins/tmux-continuum'
|
|
set -g @plugin 'tmux-plugins/tmux-prefix-highlight'
|
|
set -g @plugin 'tmux-plugins/tmux-resurrect'
|
|
set -g @plugin 'tmux-plugins/tmux-sensible'
|
|
set -g @plugin 'tmux-plugins/tpm'
|
|
set -g @plugin 'vim-tmux-navigator'
|
|
|
|
# Capture pane content
|
|
set -g @resurrect-capture-pane-contents 'on'
|
|
# Change keybindings
|
|
set -g @resurrect-save 'C-s'
|
|
set -g @resurrect-restore 'C-r'
|
|
# Save session every 5 min
|
|
set -g @continuum-save-interval '5'
|
|
# Last saved environment is automatically restored when tmux is started.
|
|
set -g @continuum-restore 'on'
|
|
# Restore {,neo}vim sessions with the help of vim-obsession
|
|
# https://github.com/tpope/vim-obsession
|
|
set -g @resurrect-strategy-vim 'session'
|
|
set -g @resurrect-strategy-nvim 'session'
|
|
# Save sessions before detaching
|
|
unbind d
|
|
bind d {
|
|
run -b "$XDG_CONFIG_HOME/tmux/plugins/tmux-resurrect/scripts/save.sh";
|
|
detach
|
|
}
|
|
|
|
## Theming
|
|
set -g @accent_color '#fce94f' # brightyellow
|
|
set -g @ui_color '#757773' # brightblack
|
|
set -g @sync_color '#ef2929' # brightred
|
|
set -g @text_fg '#5e6466' # black
|
|
|
|
set -g status-style bg=default,fg='#d3d7cf' # white
|
|
set -g message-command-style 'bg=default,fg=#{@accent_color}'
|
|
set -g message-style 'bg=#{@accent_color},fg=#{@text_fg}'
|
|
set -g mode-style 'bg=#{@accent_color},fg=#{@text_fg}'
|
|
|
|
# Visually display when a pane is in copy-mode or 'synchronize-panes' is on.
|
|
# Use the pane-borders for tmux >= 3.2 and the "prefix_highlight" plugin
|
|
# otherwise.
|
|
#
|
|
# NOTE: `<` does string comparison with `strcmp()`. This means that the
|
|
# condition will break from a double digit major version (e.g. `10.0`) on.
|
|
# TODO: Use #{e|<|f:, but cut off trailing non-numbers and convert the result
|
|
# (i.e. 1.00 or 0.00) back into an int.
|
|
if -F "#{<:#{version},3.2}" {
|
|
set -g pane-border-style 'bg=default,fg=#{@ui_color}'
|
|
set -g pane-active-border-style 'bg=default,fg=#{@accent_color}'
|
|
|
|
set -g @prefix_highlight_show_copy_mode 'on'
|
|
set -g @prefix_highlight_show_sync_mode 'on'
|
|
set -g @prefix_highlight_copy_mode_attr 'fg=#{@text_fg},bg=#{@accent_color}'
|
|
set -g @prefix_highlight_sync_mode_attr 'fg=#{@text_fg},bg=#{@sync_color}'
|
|
} {
|
|
# From 3.2 on, we can use formats in styles, so that all indicators can be
|
|
# done by the borders.
|
|
set -g pane-border-style "#{?synchronize-panes,fg=#{@sync_color},fg=#{@ui_color}}"
|
|
set -g pane-active-border-style "#{?pane_in_mode,bg=#{@accent_color}#,fg=#{@ui_color},#{?synchronize-panes,fg=#{@sync_color},fg=#{@accent_color}}}"
|
|
}
|
|
|
|
set -g @prefix_highlight_fg '#{@accent_color}'
|
|
set -g @prefix_highlight_bg 'default'
|
|
set -g status-right "#{prefix_highlight}"
|
|
set -g status-left "#{prefix_highlight}"
|
|
|
|
set -g status-justify centre
|
|
|
|
# Display window_index and window_name as status and highlight it when the
|
|
# active pane is zoomed.
|
|
set -g window-status-current-format \
|
|
"#{?window_zoomed_flag,#[fg=#{@text_fg} bg=#{@accent_color} underscore],#[fg=#{@accent_color} bold]}#I #W"
|
|
set -g window-status-format \
|
|
"#[fg=#{@ui_color}]#{?window_zoomed_flag,#[underscore],}#I #W"
|
|
|
|
# Initialize TMUX plugin manager. Keep this line at the very bottom.
|
|
run -b "$XDG_CONFIG_HOME/tmux/plugins/tpm/tpm"
|