├── tmux ├── renew_env.sh ├── tmux.remote.conf ├── yank.sh └── tmux.conf ├── .gitignore ├── .gitattributes ├── install.sh ├── Dockerfile └── readme.md /tmux/renew_env.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -eu 4 | 5 | pane_fmt="#{pane_id} #{pane_in_mode} #{pane_input_off} #{pane_dead} #{pane_current_command}" 6 | tmux list-panes -s -F "$pane_fmt" | awk ' 7 | $2 == 0 && $3 == 0 && $4 == 0 && $5 ~ /(bash|zsh|ksh|fish)/ { print $1 } 8 | ' | while read -r pane_id; do 9 | # renew environment variables according to update-environment tmux option 10 | # also clear screen 11 | tmux send-keys -t "$pane_id" 'Enter' 'eval "$(tmux show-env -s)"' 'Enter' 'C-l' 12 | done; -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ### https://raw.github.com/github/gitignore/8ab86f6bb71e85b5046f1d921bbbe5ceec9063ba/Global/OSX.gitignore 2 | 3 | .DS_Store 4 | .AppleDouble 5 | .LSOverride 6 | 7 | # Icon must end with two \r 8 | Icon 9 | 10 | # Thumbnails 11 | ._* 12 | 13 | # Files that might appear in the root of a volume 14 | .DocumentRevisions-V100 15 | .fseventsd 16 | .Spotlight-V100 17 | .TemporaryItems 18 | .Trashes 19 | .VolumeIcon.icns 20 | 21 | # Directories potentially created on remote AFP share 22 | .AppleDB 23 | .AppleDesktop 24 | Network Trash Folder 25 | Temporary Items 26 | .apdisk 27 | 28 | 29 | -------------------------------------------------------------------------------- /tmux/tmux.remote.conf: -------------------------------------------------------------------------------- 1 | # show status bar at bottom for remote session, 2 | # so it do not stack together with local session's one 3 | set -g status-position bottom 4 | 5 | # Set port of SSH remote tunnel, where tmux will pipe buffers to transfer on local machine for copy 6 | set -g @copy_backend_remote_tunnel_port 11988 7 | 8 | # In remote mode we don't show "clock" and "battery status" widgets 9 | set -g status-left "$wg_session" 10 | set -g status-right "#{prefix_highlight} $wg_is_keys_off $wg_is_zoomed #{sysstat_cpu} | #{sysstat_mem} | #{sysstat_loadavg} | $wg_user_host | #{online_status}" 11 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # common settings that generally should always be used with your language specific settings 2 | 3 | # Auto detect text files and perform LF normalization 4 | # http://davidlaing.com/2012/09/19/customise-your-gitattributes-to-become-a-git-ninja/ 5 | * text=auto 6 | 7 | # 8 | # The above will handle all files NOT found below 9 | # 10 | 11 | # Documents 12 | *.doc diff=astextplain 13 | *.DOC diff=astextplain 14 | *.docx diff=astextplain 15 | *.DOCX diff=astextplain 16 | *.dot diff=astextplain 17 | *.DOT diff=astextplain 18 | *.pdf diff=astextplain 19 | *.PDF diff=astextplain 20 | *.rtf diff=astextplain 21 | *.RTF diff=astextplain 22 | *.md text 23 | *.adoc text 24 | *.textile text 25 | *.mustache text 26 | *.csv text 27 | *.tab text 28 | *.tsv text 29 | *.sql text 30 | 31 | # Graphics 32 | *.png binary 33 | *.jpg binary 34 | *.jpeg binary 35 | *.gif binary 36 | *.tif binary 37 | *.tiff binary 38 | *.ico binary 39 | # SVG treated as an asset (binary) by default. If you want to treat it as text, 40 | # comment-out the following line and uncomment the line after. 41 | *.svg binary 42 | #*.svg text 43 | *.eps binary -------------------------------------------------------------------------------- /install.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | set -u 5 | set -o pipefail 6 | 7 | is_app_installed() { 8 | type "$1" &>/dev/null 9 | } 10 | 11 | REPODIR="$(cd "$(dirname "$0")"; pwd -P)" 12 | cd "$REPODIR"; 13 | 14 | if ! is_app_installed tmux; then 15 | printf "WARNING: \"tmux\" command is not found. \ 16 | Install it first\n" 17 | exit 1 18 | fi 19 | 20 | if [ ! -e "$HOME/.tmux/plugins/tpm" ]; then 21 | printf "WARNING: Cannot found TPM (Tmux Plugin Manager) \ 22 | at default location: \$HOME/.tmux/plugins/tpm.\n" 23 | git clone https://github.com/tmux-plugins/tpm ~/.tmux/plugins/tpm 24 | fi 25 | 26 | if [ -e "$HOME/.tmux.conf" ]; then 27 | printf "Found existing .tmux.conf in your \$HOME directory. Will create a backup at $HOME/.tmux.conf.bak\n" 28 | fi 29 | 30 | cp -f "$HOME/.tmux.conf" "$HOME/.tmux.conf.bak" 2>/dev/null || true 31 | cp -a ./tmux/. "$HOME"/.tmux/ 32 | ln -sf .tmux/tmux.conf "$HOME"/.tmux.conf; 33 | 34 | # Install TPM plugins. 35 | # TPM requires running tmux server, as soon as `tmux start-server` does not work 36 | # create dump __noop session in detached mode, and kill it when plugins are installed 37 | printf "Install TPM plugins\n" 38 | tmux new -d -s __noop >/dev/null 2>&1 || true 39 | tmux set-environment -g TMUX_PLUGIN_MANAGER_PATH "~/.tmux/plugins" 40 | "$HOME"/.tmux/plugins/tpm/bin/install_plugins || true 41 | tmux kill-session -t __noop >/dev/null 2>&1 || true 42 | 43 | printf "OK: Completed\n" 44 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM debian:stretch-slim 2 | 3 | RUN apt-get update \ 4 | && apt-get install -y --no-install-recommends \ 5 | ca-certificates \ 6 | fontconfig \ 7 | git \ 8 | gcc \ 9 | iputils-ping \ 10 | libevent-dev \ 11 | libncurses-dev \ 12 | locales \ 13 | make \ 14 | procps \ 15 | wget \ 16 | && wget -O - https://github.com/tmux/tmux/releases/download/2.6/tmux-2.6.tar.gz | tar xzf - \ 17 | && cd tmux-2.6 \ 18 | && LDFLAGS="-L/usr/local/lib -Wl,-rpath=/usr/local/lib" ./configure --prefix=/usr/local \ 19 | && make \ 20 | && make install \ 21 | && cd .. \ 22 | && rm -rf tmux-2.6 \ 23 | && apt-get purge -y gcc make \ 24 | && apt-get -y autoremove \ 25 | && apt-get clean \ 26 | && rm -rf /var/lib/apt/lists/* 27 | 28 | RUN sed -i -e 's/# en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/' /etc/locale.gen \ 29 | && locale-gen 30 | ENV LC_ALL=en_US.UTF-8 31 | ENV LANG=en_US.UTF-8 32 | 33 | RUN mkdir -p $HOME/.fonts $HOME/.config/fontconfig/conf.d \ 34 | && wget -P $HOME/.fonts https://github.com/powerline/powerline/raw/develop/font/PowerlineSymbols.otf \ 35 | && wget -P $HOME/.config/fontconfig/conf.d/ https://github.com/powerline/powerline/raw/develop/font/10-powerline-symbols.conf \ 36 | && fc-cache -vf $HOME/.fonts/ 37 | 38 | WORKDIR /root 39 | 40 | RUN git clone https://github.com/samoshkin/tmux-config \ 41 | && ./tmux-config/install.sh \ 42 | && rm -rf ./tmux-config 43 | 44 | ENV TERM=xterm-256color 45 | 46 | 47 | -------------------------------------------------------------------------------- /tmux/yank.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -eu 4 | 5 | is_app_installed() { 6 | type "$1" &>/dev/null 7 | } 8 | 9 | # get data either form stdin or from file 10 | buf=$(cat "$@") 11 | 12 | copy_backend_remote_tunnel_port=$(tmux show-option -gvq "@copy_backend_remote_tunnel_port") 13 | copy_use_osc52_fallback=$(tmux show-option -gvq "@copy_use_osc52_fallback") 14 | 15 | # Resolve copy backend: pbcopy (OSX), reattach-to-user-namespace (OSX), xclip/xsel (Linux) 16 | copy_backend="" 17 | if is_app_installed pbcopy; then 18 | copy_backend="pbcopy" 19 | elif is_app_installed reattach-to-user-namespace; then 20 | copy_backend="reattach-to-user-namespace pbcopy" 21 | elif [ -n "${DISPLAY-}" ] && is_app_installed xsel; then 22 | copy_backend="xsel -i --clipboard" 23 | elif [ -n "${DISPLAY-}" ] && is_app_installed xclip; then 24 | copy_backend="xclip -i -f -selection primary | xclip -i -selection clipboard" 25 | elif [ -n "${copy_backend_remote_tunnel_port-}" ] \ 26 | && (netstat -f inet -nl 2>/dev/null || netstat -4 -nl 2>/dev/null) \ 27 | | grep -q "[.:]$copy_backend_remote_tunnel_port"; then 28 | copy_backend="nc localhost $copy_backend_remote_tunnel_port" 29 | fi 30 | 31 | # if copy backend is resolved, copy and exit 32 | if [ -n "$copy_backend" ]; then 33 | printf "%s" "$buf" | eval "$copy_backend" 34 | exit; 35 | fi 36 | 37 | 38 | # If no copy backends were eligible, decide to fallback to OSC 52 escape sequences 39 | # Note, most terminals do not handle OSC 40 | if [ "$copy_use_osc52_fallback" == "off" ]; then 41 | exit; 42 | fi 43 | 44 | # Copy via OSC 52 ANSI escape sequence to controlling terminal 45 | buflen=$( printf %s "$buf" | wc -c ) 46 | 47 | # https://sunaku.github.io/tmux-yank-osc52.html 48 | # The maximum length of an OSC 52 escape sequence is 100_000 bytes, of which 49 | # 7 bytes are occupied by a "\033]52;c;" header, 1 byte by a "\a" footer, and 50 | # 99_992 bytes by the base64-encoded result of 74_994 bytes of copyable text 51 | maxlen=74994 52 | 53 | # warn if exceeds maxlen 54 | if [ "$buflen" -gt "$maxlen" ]; then 55 | printf "input is %d bytes too long" "$(( buflen - maxlen ))" >&2 56 | fi 57 | 58 | # build up OSC 52 ANSI escape sequence 59 | esc="\033]52;c;$( printf %s "$buf" | head -c $maxlen | base64 | tr -d '\r\n' )\a" 60 | esc="\033Ptmux;\033$esc\033\\" 61 | 62 | # resolve target terminal to send escape sequence 63 | # if we are on remote machine, send directly to SSH_TTY to transport escape sequence 64 | # to terminal on local machine, so data lands in clipboard on our local machine 65 | pane_active_tty=$(tmux list-panes -F "#{pane_active} #{pane_tty}" | awk '$1=="1" { print $2 }') 66 | target_tty="${SSH_TTY:-$pane_active_tty}" 67 | 68 | printf "$esc" > "$target_tty" 69 | -------------------------------------------------------------------------------- /tmux/tmux.conf: -------------------------------------------------------------------------------- 1 | # ========================== 2 | # === General settings === 3 | # ========================== 4 | 5 | set -g default-terminal "screen-256color" 6 | set -g history-limit 20000 7 | set -g buffer-limit 20 8 | set -sg escape-time 0 9 | set -g display-time 1500 10 | set -g remain-on-exit off 11 | set -g repeat-time 300 12 | setw -g allow-rename off 13 | setw -g automatic-rename off 14 | setw -g aggressive-resize on 15 | 16 | # Change prefix key to C-a, easier to type, same to "screen" 17 | unbind C-b 18 | set -g prefix C-a 19 | 20 | # Set parent terminal title to reflect current window in tmux session 21 | set -g set-titles on 22 | set -g set-titles-string "#I:#W" 23 | 24 | # Start index of window/pane with 1, because we're humans, not computers 25 | set -g base-index 1 26 | setw -g pane-base-index 1 27 | 28 | # Enable mouse support 29 | set -g mouse on 30 | 31 | 32 | # ========================== 33 | # === Key bindings === 34 | # ========================== 35 | 36 | # Unbind default key bindings, we're going to override 37 | unbind "\$" # rename-session 38 | unbind , # rename-window 39 | unbind % # split-window -h 40 | unbind '"' # split-window 41 | unbind } # swap-pane -D 42 | unbind { # swap-pane -U 43 | unbind [ # paste-buffer 44 | unbind ] 45 | unbind "'" # select-window 46 | unbind n # next-window 47 | unbind p # previous-window 48 | unbind l # last-window 49 | unbind M-n # next window with alert 50 | unbind M-p # next window with alert 51 | unbind o # focus thru panes 52 | unbind & # kill-window 53 | unbind "#" # list-buffer 54 | unbind = # choose-buffer 55 | unbind z # zoom-pane 56 | unbind M-Up # resize 5 rows up 57 | unbind M-Down # resize 5 rows down 58 | unbind M-Right # resize 5 rows right 59 | unbind M-Left # resize 5 rows left 60 | 61 | 62 | # Edit configuration and reload 63 | bind C-e new-window -n 'tmux.conf' "sh -c '\${EDITOR:-vim} ~/.tmux.conf && tmux source ~/.tmux.conf && tmux display \"Config reloaded\"'" 64 | 65 | # Reload tmux configuration 66 | bind C-r source-file ~/.tmux.conf \; display "Config reloaded" 67 | 68 | # new window and retain cwd 69 | bind c new-window -c "#{pane_current_path}" 70 | 71 | # Prompt to rename window right after it's created 72 | set-hook -g after-new-window 'command-prompt -I "#{window_name}" "rename-window '%%'"' 73 | 74 | # Rename session and window 75 | bind r command-prompt -I "#{window_name}" "rename-window '%%'" 76 | bind R command-prompt -I "#{session_name}" "rename-session '%%'" 77 | 78 | # Split panes 79 | bind | split-window -h -c "#{pane_current_path}" 80 | bind _ split-window -v -c "#{pane_current_path}" 81 | 82 | # Select pane and windows 83 | bind -r C-[ previous-window 84 | bind -r C-] next-window 85 | bind -r [ select-pane -t :.- 86 | bind -r ] select-pane -t :.+ 87 | bind -r Tab last-window # cycle thru MRU tabs 88 | bind -r C-o swap-pane -D 89 | 90 | # Zoom pane 91 | bind + resize-pane -Z 92 | 93 | # Link window 94 | bind L command-prompt -p "Link window from (session:window): " "link-window -s %% -a" 95 | 96 | # Swap panes back and forth with 1st pane 97 | # When in main-(horizontal|vertical) layouts, the biggest/widest panel is always @1 98 | bind \ if '[ #{pane_index} -eq 1 ]' \ 99 | 'swap-pane -s "!"' \ 100 | 'select-pane -t:.1 ; swap-pane -d -t 1 -s "!"' 101 | 102 | # Kill pane/window/session shortcuts 103 | bind x kill-pane 104 | bind X kill-window 105 | bind C-x confirm-before -p "kill other windows? (y/n)" "kill-window -a" 106 | bind Q confirm-before -p "kill-session #S? (y/n)" kill-session 107 | 108 | # Merge session with another one (e.g. move all windows) 109 | # If you use adhoc 1-window sessions, and you want to preserve session upon exit 110 | # but don't want to create a lot of small unnamed 1-window sessions around 111 | # move all windows from current session to main named one (dev, work, etc) 112 | bind C-u command-prompt -p "Session to merge with: " \ 113 | "run-shell 'yes | head -n #{session_windows} | xargs -I {} -n 1 tmux movew -t %%'" 114 | 115 | # Detach from session 116 | bind d detach 117 | bind D if -F '#{session_many_attached}' \ 118 | 'confirm-before -p "Detach other clients? (y/n)" "detach -a"' \ 119 | 'display "Session has only 1 client attached"' 120 | 121 | # Hide status bar on demand 122 | bind C-s if -F '#{s/off//:status}' 'set status off' 'set status on' 123 | 124 | 125 | 126 | # ================================================== 127 | # === Window monitoring for activity and silence === 128 | # ================================================== 129 | bind m setw monitor-activity \; display-message 'Monitor window activity [#{?monitor-activity,ON,OFF}]' 130 | bind M if -F '#{monitor-silence}' \ 131 | 'setw monitor-silence 0 ; display-message "Monitor window silence [OFF]"' \ 132 | 'command-prompt -p "Monitor silence: interval (s)" "setw monitor-silence %%"' 133 | 134 | # Activity bell and whistles 135 | set -g visual-activity on 136 | 137 | # TODO: Does not work as well, check on newer versions 138 | # set -g visual-silence on 139 | 140 | # BUG: bell-action other ignored · Issue #1027 · tmux/tmux · GitHub - https://github.com/tmux/tmux/issues/1027 141 | # set -g visual-bell on 142 | # setw -g bell-action other 143 | 144 | # ================================================ 145 | # === Copy mode, scroll and clipboard === 146 | # ================================================ 147 | set -g @copy_use_osc52_fallback on 148 | 149 | # Prefer vi style key table 150 | setw -g mode-keys vi 151 | 152 | bind p paste-buffer 153 | bind C-p choose-buffer 154 | 155 | # trigger copy mode by 156 | bind -n M-Up copy-mode 157 | 158 | # Scroll up/down by 1 line, half screen, whole screen 159 | bind -T copy-mode-vi M-Up send-keys -X scroll-up 160 | bind -T copy-mode-vi M-Down send-keys -X scroll-down 161 | bind -T copy-mode-vi M-PageUp send-keys -X halfpage-up 162 | bind -T copy-mode-vi M-PageDown send-keys -X halfpage-down 163 | bind -T copy-mode-vi PageDown send-keys -X page-down 164 | bind -T copy-mode-vi PageUp send-keys -X page-up 165 | 166 | # When scrolling with mouse wheel, reduce number of scrolled rows per tick to "2" (default is 5) 167 | bind -T copy-mode-vi WheelUpPane select-pane \; send-keys -X -N 2 scroll-up 168 | bind -T copy-mode-vi WheelDownPane select-pane \; send-keys -X -N 2 scroll-down 169 | 170 | # wrap default shell in reattach-to-user-namespace if available 171 | # there is some hack with `exec & reattach`, credits to "https://github.com/gpakosz/.tmux" 172 | # don't really understand how it works, but at least window are not renamed to "reattach-to-user-namespace" 173 | if -b "command -v reattach-to-user-namespace > /dev/null 2>&1" \ 174 | "run 'tmux set -g default-command \"exec $(tmux show -gv default-shell) 2>/dev/null & reattach-to-user-namespace -l $(tmux show -gv default-shell)\"'" 175 | 176 | yank="~/.tmux/yank.sh" 177 | 178 | # Copy selected text 179 | bind -T copy-mode-vi Enter send-keys -X copy-pipe-and-cancel "$yank" 180 | bind -T copy-mode-vi y send-keys -X copy-pipe-and-cancel "$yank" 181 | bind -T copy-mode-vi Y send-keys -X copy-line \;\ 182 | run "tmux save-buffer - | $yank" 183 | bind-key -T copy-mode-vi D send-keys -X copy-end-of-line \;\ 184 | run "tmux save-buffer - | $yank" 185 | bind -T copy-mode-vi C-j send-keys -X copy-pipe-and-cancel "$yank" 186 | bind-key -T copy-mode-vi A send-keys -X append-selection-and-cancel \;\ 187 | run "tmux save-buffer - | $yank" 188 | 189 | # Copy selection on drag end event, but do not cancel copy mode and do not clear selection 190 | # clear select on subsequence mouse click 191 | bind -T copy-mode-vi MouseDragEnd1Pane \ 192 | send-keys -X copy-pipe "$yank" 193 | bind -T copy-mode-vi MouseDown1Pane select-pane \;\ 194 | send-keys -X clear-selection 195 | 196 | # iTerm2 works with clipboard out of the box, set-clipboard already set to "external" 197 | # tmux show-options -g -s set-clipboard 198 | # set-clipboard on|external 199 | 200 | # ===================================== 201 | # === Theme === 202 | # ===================================== 203 | 204 | # Feel free to NOT use this variables at all (remove, rename) 205 | # this are named colors, just for convenience 206 | color_orange="colour166" # 208, 166 207 | color_purple="colour134" # 135, 134 208 | color_green="colour076" # 070 209 | color_blue="colour39" 210 | color_yellow="colour220" 211 | color_red="colour160" 212 | color_black="colour232" 213 | color_white="white" # 015 214 | 215 | # This is a theme CONTRACT, you are required to define variables below 216 | # Change values, but not remove/rename variables itself 217 | color_dark="$color_black" 218 | color_light="$color_white" 219 | color_session_text="$color_blue" 220 | color_status_text="colour245" 221 | color_main="$color_orange" 222 | color_secondary="$color_purple" 223 | color_level_ok="$color_green" 224 | color_level_warn="$color_yellow" 225 | color_level_stress="$color_red" 226 | color_window_off_indicator="colour088" 227 | color_window_off_status_bg="colour238" 228 | color_window_off_status_current_bg="colour254" 229 | 230 | # ===================================== 231 | # === Appearence and status bar === 232 | # ====================================== 233 | 234 | set -g mode-style "fg=default,bg=$color_main" 235 | 236 | # command line style 237 | set -g message-style "fg=$color_main,bg=$color_dark" 238 | 239 | # status line style 240 | set -g status-style "fg=$color_status_text,bg=$color_dark" 241 | 242 | # window segments in status line 243 | set -g window-status-separator "" 244 | separator_powerline_left="" 245 | separator_powerline_right="" 246 | 247 | # setw -g window-status-style "fg=$color_status_text,bg=$color_dark" 248 | setw -g window-status-format " #I:#W " 249 | setw -g window-status-current-style "fg=$color_light,bold,bg=$color_main" 250 | setw -g window-status-current-format "#[fg=$color_dark,bg=$color_main]$separator_powerline_right#[default] #I:#W# #[fg=$color_main,bg=$color_dark]$separator_powerline_right#[default]" 251 | 252 | # when window has monitoring notification 253 | setw -g window-status-activity-style "fg=$color_main" 254 | 255 | # outline for active pane 256 | setw -g pane-active-border-style "fg=$color_main" 257 | 258 | # general status bar settings 259 | set -g status on 260 | set -g status-interval 5 261 | set -g status-position top 262 | set -g status-justify left 263 | set -g status-right-length 100 264 | 265 | # define widgets we're going to use in status bar 266 | # note, that this is not the complete list, some of them are loaded from plugins 267 | wg_session="#[fg=$color_session_text] #S #[default]" 268 | wg_battery="#{battery_status_fg} #{battery_icon} #{battery_percentage}" 269 | wg_date="#[fg=$color_secondary]%h %d %H:%M#[default]" 270 | wg_user_host="#[fg=$color_secondary]#(whoami)#[default]@#H" 271 | wg_is_zoomed="#[fg=$color_dark,bg=$color_secondary]#{?window_zoomed_flag,[Z],}#[default]" 272 | # TODO: highlighted for nested local session as well 273 | wg_is_keys_off="#[fg=$color_light,bg=$color_window_off_indicator]#([ $(tmux show-option -qv key-table) = 'off' ] && echo 'OFF')#[default]" 274 | 275 | set -g status-left "$wg_session" 276 | set -g status-right "#{prefix_highlight} $wg_is_keys_off $wg_is_zoomed #{sysstat_cpu} | #{sysstat_mem} | #{sysstat_loadavg} | $wg_user_host | $wg_date $wg_battery #{online_status}" 277 | 278 | # online and offline icon for tmux-online-status 279 | set -g @online_icon "#[fg=$color_level_ok]●#[default]" 280 | set -g @offline_icon "#[fg=$color_level_stress]●#[default]" 281 | 282 | # Configure view templates for tmux-plugin-sysstat "MEM" and "CPU" widget 283 | set -g @sysstat_mem_view_tmpl 'MEM:#[fg=#{mem.color}]#{mem.pused}#[default] #{mem.used}' 284 | 285 | # Configure colors for tmux-plugin-sysstat "MEM" and "CPU" widget 286 | set -g @sysstat_cpu_color_low "$color_level_ok" 287 | set -g @sysstat_cpu_color_medium "$color_level_warn" 288 | set -g @sysstat_cpu_color_stress "$color_level_stress" 289 | 290 | set -g @sysstat_mem_color_low "$color_level_ok" 291 | set -g @sysstat_mem_color_medium "$color_level_warn" 292 | set -g @sysstat_mem_color_stress "$color_level_stress" 293 | 294 | set -g @sysstat_swap_color_low "$color_level_ok" 295 | set -g @sysstat_swap_color_medium "$color_level_warn" 296 | set -g @sysstat_swap_color_stress "$color_level_stress" 297 | 298 | 299 | # Configure tmux-battery widget colors 300 | set -g @batt_color_full_charge "#[fg=$color_level_ok]" 301 | set -g @batt_color_high_charge "#[fg=$color_level_ok]" 302 | set -g @batt_color_medium_charge "#[fg=$color_level_warn]" 303 | set -g @batt_color_low_charge "#[fg=$color_level_stress]" 304 | 305 | # Configure tmux-prefix-highlight colors 306 | set -g @prefix_highlight_output_prefix '[' 307 | set -g @prefix_highlight_output_suffix ']' 308 | set -g @prefix_highlight_fg "$color_dark" 309 | set -g @prefix_highlight_bg "$color_secondary" 310 | set -g @prefix_highlight_show_copy_mode 'on' 311 | set -g @prefix_highlight_copy_mode_attr "fg=$color_dark,bg=$color_secondary" 312 | 313 | 314 | # ===================================== 315 | # === Renew environment === 316 | # ===================================== 317 | set -g update-environment \ 318 | "DISPLAY\ 319 | SSH_ASKPASS\ 320 | SSH_AUTH_SOCK\ 321 | SSH_AGENT_PID\ 322 | SSH_CONNECTION\ 323 | SSH_TTY\ 324 | WINDOWID\ 325 | XAUTHORITY" 326 | 327 | bind '$' run "~/.tmux/renew_env.sh" 328 | 329 | 330 | # ============================ 331 | # === Plugins === 332 | # ============================ 333 | set -g @plugin 'tmux-plugins/tpm' 334 | set -g @plugin 'tmux-plugins/tmux-battery' 335 | set -g @plugin 'tmux-plugins/tmux-prefix-highlight' 336 | set -g @plugin 'tmux-plugins/tmux-online-status' 337 | set -g @plugin 'tmux-plugins/tmux-sidebar' 338 | set -g @plugin 'tmux-plugins/tmux-copycat' 339 | set -g @plugin 'tmux-plugins/tmux-open' 340 | set -g @plugin 'samoshkin/tmux-plugin-sysstat' 341 | 342 | # Plugin properties 343 | set -g @sidebar-tree 't' 344 | set -g @sidebar-tree-focus 'T' 345 | set -g @sidebar-tree-command 'tree -C' 346 | 347 | set -g @open-S 'https://www.google.com/search?q=' 348 | 349 | 350 | # ============================================== 351 | # === Nesting local and remote sessions === 352 | # ============================================== 353 | 354 | # Session is considered to be remote when we ssh into host 355 | if-shell 'test -n "$SSH_CLIENT"' \ 356 | 'source-file ~/.tmux/tmux.remote.conf' 357 | 358 | # We want to have single prefix key "C-a", usable both for local and remote session 359 | # we don't want to "C-a" + "a" approach either 360 | # Idea is to turn off all key bindings and prefix handling on local session, 361 | # so that all keystrokes are passed to inner/remote session 362 | 363 | # see: toggle on/off all keybindings · Issue #237 · tmux/tmux - https://github.com/tmux/tmux/issues/237 364 | 365 | # Also, change some visual styles when window keys are off 366 | bind -T root F12 \ 367 | set prefix None \;\ 368 | set key-table off \;\ 369 | set status-style "fg=$color_status_text,bg=$color_window_off_status_bg" \;\ 370 | set window-status-current-format "#[fg=$color_window_off_status_bg,bg=$color_window_off_status_current_bg]$separator_powerline_right#[default] #I:#W# #[fg=$color_window_off_status_current_bg,bg=$color_window_off_status_bg]$separator_powerline_right#[default]" \;\ 371 | set window-status-current-style "fg=$color_dark,bold,bg=$color_window_off_status_current_bg" \;\ 372 | if -F '#{pane_in_mode}' 'send-keys -X cancel' \;\ 373 | refresh-client -S \;\ 374 | 375 | bind -T off F12 \ 376 | set -u prefix \;\ 377 | set -u key-table \;\ 378 | set -u status-style \;\ 379 | set -u window-status-current-style \;\ 380 | set -u window-status-current-format \;\ 381 | refresh-client -S 382 | 383 | # Run all plugins' scripts 384 | run '~/.tmux/plugins/tpm/tpm' 385 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | Tmux Configuration 2 | ===================== 3 | Tmux configuration, that supercharges your [tmux](https://tmux.github.io/) and builds cozy and cool terminal environment. 4 | 5 |  6 | 7 | Table of contents 8 | ----------------- 9 | 10 | 1. [Features](#features) 11 | 1. [Installation](#installation) 12 | 1. [General settings](#general-settings) 13 | 1. [Key bindings](#key-bindings) 14 | 1. [Status line](#status-line) 15 | 1. [Nested tmux sessions](#nested-tmux-sessions) 16 | 1. [Copy mode](#copy-mode) 17 | 1. [Clipboard integration](#clipboard-integration) 18 | 1. [Themes and customization](#themes-and-customization) 19 | 1. [iTerm2 and tmux integration](#iterm2-and-tmux-integration) 20 | 21 | Features 22 | --------- 23 | 24 | - "C-a" prefix instead of "C-b" (screen like) 25 | - support for nested tmux sessions 26 | - local vs remote specific session configuration 27 | - scroll and copy mode improvements 28 | - integration with OSX or Linux clipboard (works for local, remote, and local+remote nested session scenario) 29 | - supercharged status line 30 | - renew tmux and shell environment (SSH_AUTH_SOCK, DISPLAY, SSH_TTY) when reattaching back to old session 31 | - prompt to rename window right after it's created 32 | - newly created windows and panes retain current working directory 33 | - monitor windows for activity/silence 34 | - highlight focused pane 35 | - merge current session with existing one (move all windows) 36 | - configurable visual theme/colors, with some elements borrowed from [Powerline](https://github.com/powerline/powerline) 37 | - integration with 3rd party plugins: [tmux-sidebar](https://github.com/tmux-plugins/tmux-sidebar), [tmux-copycat](https://github.com/tmux-plugins/tmux-copycat), [tmux-open](https://github.com/tmux-plugins/tmux-open), [tmux-plugin-sysstat](https://github.com/samoshkin/tmux-plugin-sysstat) 38 | 39 | **Status line widgets**: 40 | 41 | - CPU, memory usage, system load average metrics 42 | - username and hostname, current date time 43 | - battery information in status line 44 | - visual indicator when you press `prefix` 45 | - visual indicator when you're in `Copy` mode 46 | - visual indicator when pane is zoomed 47 | - online/offline visual indicator 48 | - toggle visibility of status line 49 | 50 | 51 | Installation 52 | ------------- 53 | Prerequisites: 54 | - tmux >= "v2.4" 55 | - OSX, Linux (tested on Ubuntu 14 and CentOS7), FreeBSD (tested on 11.1) 56 | 57 | Personally, I use it on OSX 10.11.5 El Capitan through iTerm2. 58 | 59 | On OSX you can install latest 2.6 version with `brew install tmux`. On Linux it's better to install from source, because official repositories usually contain outdated version. For example, CentOS7 - v1.8 from base repo, Ubuntu 14 - v1.8 from trusty/main. For how to install from source, see this [gist](https://gist.github.com/P7h/91e14096374075f5316e) or just google it. 60 | 61 | 62 | To install tmux-config: 63 | ``` 64 | $ git clone https://github.com/samoshkin/tmux-config.git 65 | $ ./tmux-config/install.sh 66 | ``` 67 | 68 | `install.sh` script does following: 69 | - copies files to `~/.tmux` directory 70 | - symlink tmux config file at `~/.tmux.conf`, existing `~/.tmux.conf` will be backed up 71 | - [Tmux Plugin Manager](https://github.com/tmux-plugins/tpm) will be installed at default location `~/.tmux/plugins/tpm`, unless already presemt 72 | - required tmux plugins will be installed 73 | 74 | Finally, you can jump into a new tmux session: 75 | 76 | ``` 77 | $ tmux new 78 | ``` 79 | 80 | 81 | General settings 82 | ---------------- 83 | Windows and pane indexing starts from `1` rather than `0`. Scrollback history limit is set to `20000`. Automatic window renameing is turned off. Aggresive resizing is on. Message line display timeout is `1.5s`. Mouse support in `on`. 84 | 85 | 256 color palette support is turned on, make sure that your parent terminal is configured propertly. See [here](https://unix.stackexchange.com/questions/1045/getting-256-colors-to-work-in-tmux) and [there](https://github.com/tmux/tmux/wiki/FAQ) 86 | 87 | ``` 88 | # parent terminal 89 | $ echo $TERM 90 | xterm-256color 91 | 92 | # jump into a tmux session 93 | $ tmux new 94 | $ echo $TERM 95 | screen-256color 96 | ``` 97 | 98 | Key bindings 99 | ----------- 100 | So `~/.tmux.conf` overrides default key bindings for many action, to make them more reasonable, easy to recall and comforable to type. 101 | 102 | Let's go through them. 103 | 104 | If you are an iTerm2 user, third column describes the keybinding of similar "action" in iTerm2. It's possible to reuse very same keys you already get used to and tell iTerm2 to execute analogous tmux actions. See [iTerm2 and tmux integration](#iterm2-and-tmux-integration) section below. 105 | 106 |
| tmux key | 109 |Description | 110 |iTerm2 key | 111 |
C-a |
114 | Default prefix, used instead of "C-b". Same prefix is used in screen program, and it's easy to type. The only drawback of "C-a" is that underlying shell does not receive the keystroke to move to the beginning of the line. 115 | | 116 |- | 117 |
<prefix> C-e |
120 | Open ~/.tmux.conf file in your $EDITOR | 121 |- | 122 |
<prefix> C-r |
125 | Reload tmux configuration from ~/.tmux.conf file | 126 |- | 127 |
<prefix> r |
130 | Rename current window | 131 |- | 132 |
<prefix> R |
135 | Rename current session | 136 |- | 137 |
<prefix> _ |
140 | Split new pane horizontally | 141 |⌘⇧D | 142 |
<prefix> | |
145 | Split new pane vertically | 146 |⌘D | 147 |
<prefix> < |
150 | Select next pane | 151 |⌘[ | 152 |
<prefix> > |
155 | Select previous pane | 156 |⌘] | 157 |
<prefix> ← |
160 | Select pane on the left | 161 |⌘⌥← | 162 |
<prefix> → |
165 | Select pane on the right | 166 |⌘⌥→ | 167 |
<prefix> ↑ |
170 | Select pane on the top | 171 |⌘⌥↑ | 172 |
<prefix> ↓ |
175 | Select pane on the bottom | 176 |⌘⌥↓ | 177 |
<prefix> C-← |
180 | Resize pane to the left | 181 |^⌘← | 182 |
<prefix> C-→ |
185 | Resize pane to the right | 186 |^⌘→ | 187 |
<prefix> C-↑ |
190 | Resize pane to the top | 191 |^⌘↑ | 192 |
<prefix> C-↓ |
195 | Resize pane to the bottom | 196 |^⌘↓ | 197 |
<prefix> > |
200 | Move to next window | 201 |⌘⇧] | 202 |
<prefix> < |
205 | Move to previous window | 206 |⌘⇧[ | 207 |
<prefix> Tab |
210 | Switch to most recently used window | 211 |^Tab | 212 |
<prefix> L |
215 | Link window from another session by entering target session and window reference | 216 |- | 217 |
<prefix> \ |
220 | Swap panes back and forth with 1st pane. When in main-horizontal or main-vertical layout, the main panel is always at index 1. This keybinding let you swap secondary pane with main one, and do the opposite. | 221 |⌘\ | 222 |
<prefix> C-o |
225 | Swap current active pane with next one | 226 |- | 227 |
<prefix> + |
230 | Toggle zoom for current pane | 231 |⌘⇧Enter | 232 | 233 |
<prefix> x |
235 | Kill current pane | 236 |⌘W | 237 |
<prefix> X |
240 | Kill current window | 241 |⌘⌥W | 242 |
<prefix> C-x |
245 | Kill other windows but current one (with confirmation) | 246 |- | 247 |
<prefix> Q |
250 | Kill current session (with confirmation) | 251 |- | 252 |
<prefix> C-u |
255 | Merge current session with another. Essentially, this moves all windows from current session to another one | 256 |- | 257 |
<prefix> d |
260 | Detach from session | 261 |- | 262 |
<prefix> D |
265 | Detach other clients except current one from session | 266 |- | 267 |
<prefix> C-s |
270 | Toggle status bar visibility | 271 |- | 272 |
<prefix> m |
275 | Monitor current window for activity | 276 |- | 277 |
<prefix> M |
280 | Monitor current window for silence by entering silence period | 281 |- | 282 |
<prefix> F12 |
285 | Switch off all key binding and prefix hanling in current window. See "Nested sessions" paragraph for more info | 286 |- | 287 |