diff --git a/config/tmux/aliases.zsh b/config/tmux/aliases.zsh new file mode 100644 index 00000000..4480414c --- /dev/null +++ b/config/tmux/aliases.zsh @@ -0,0 +1,27 @@ +#!/usr/bin/env zsh + +alias ta='tmux attach' +alias tl='tmux ls' + +if [[ -n $TMUX ]]; then # From inside tmux + alias tf='tmux find-window' + # Detach all other clients to this session + alias mine='tmux detach -a' + # Send command to other tmux window + tt() { + tmux send-keys -t .+ C-u && \ + tmux set-buffer "$*" && \ + tmux paste-buffer -t .+ && \ + tmux send-keys -t .+ Enter; + } + # Create new session (from inside one) + tn() { + local name="${1:-`basename $PWD`}" + TMUX= tmux new-session -d -s "$name" + tmux switch-client -t "$name" + tmux display-message "Session #S created" + } +else # From outside tmux + # Start grouped session so I can be in two different windows in one session + tdup() { tmux new-session -t "${1:-`tmux display-message -p '#S'`}"; } +fi diff --git a/config/tmux/config b/config/tmux/config new file mode 100644 index 00000000..d0742458 --- /dev/null +++ b/config/tmux/config @@ -0,0 +1,118 @@ +# tmux.conf +# By Henrik Lissner +# https://github.com/hlissner/dotfiles +######################################## + +set -g default-terminal "xterm-256color" + +new-session # spawn session if attaching when none are running + +setw -g automatic-rename on # rename window after current program +set -g renumber-windows on # renumber windows when one is closed +# Zero-based indexing is fine in programming languages, but not so much in a +# multiplexer when zero is on the other side of the keyboard. +set -g base-index 1 +setw -g pane-base-index 1 +# display tmux messages longer +set -g display-time 1500 +set -g display-panes-time 800 +# Address vim-mode switching delay (http://superuser.com/a/252717/65504) +set -s escape-time 0 +set -sg repeat-time 600 +set -g history-limit 10000 +# Rather than constraining window size to the maximum size of any client +# connected to the *session*, constrain window size to the maximum size of any +# client connected to *that window*. Much more reasonable. +setw -g aggressive-resize off +# For terminals that support them, propagate these events to programs that +# understand them. +set -s focus-events on + + +######################################## +# Keybinds # +######################################## + +# Rebind prefix to C-c. Press twice to send literal C-c. +unbind C-b +set -g prefix C-c +bind C-c send-prefix + +# Vi-style keybinds +set -g status-keys vi +set -g mode-keys vi + +bind v split-window -h +bind s split-window -v + +bind h select-pane -L +bind j select-pane -D +bind k select-pane -U +bind l select-pane -R +bind H run '$TMUX_HOME/swap-pane.sh left' +bind J run '$TMUX_HOME/swap-pane.sh down' +bind K run '$TMUX_HOME/swap-pane.sh up' +bind L run '$TMUX_HOME/swap-pane.sh right' +bind M run '$TMUX_HOME/swap-pane.sh master' + +bind o resize-pane -Z +bind S choose-session +bind W choose-window +bind / choose-session +bind . choose-window + +# bind = select-layout tiled +bind | select-layout even-horizontal +bind _ select-layout even-vertical + +# Disable confirmation +bind x kill-pane +bind X kill-window +bind q kill-session +bind Q kill-server + +# Smart pane switching with awareness of vim splits +# See: https://github.com/christoomey/vim-tmux-navigator +is_vim='echo "#{pane_current_command}" | grep -iqE "(^|\/)g?(view|n?vim?x?)(diff)?$"' +bind -n C-h if-shell "$is_vim" "send-keys C-h" "select-pane -L" +bind -n C-j if-shell "$is_vim" "send-keys C-j" "select-pane -D" +bind -n C-k if-shell "$is_vim" "send-keys C-k" "select-pane -U" +bind -n C-l if-shell "$is_vim" "send-keys C-l" "select-pane -R" +bind -n C-\ if-shell "$is_vim" "send-keys C-\\" "select-pane -l" +bind C-w last-pane +bind C-n next-window +bind C-p previous-window + +# break pane into a window +bind = select-layout even-vertical +bind + select-layout even-horizontal +bind - break-pane +bind _ join-pane + +# reload config without killing server +bind r source-file $TMUX_HOME/tmux.conf \; display-message " Config reloaded..". +bind ^r refresh-client + + +######################################## +# Copy mode # +######################################## + +bind Enter copy-mode # enter copy mode +bind b list-buffers # list paster buffers +bind p paste-buffer # paste from the top pate buffer +bind P choose-buffer # choose which buffer to paste from + +bind -T copy-mode-vi v send -X begin-selection +bind -T copy-mode-vi C-v send -X rectangle-toggle +bind -T copy-mode-vi y send -X copy-selection +bind -T copy-mode-vi Escape send -X cancel +bind -T copy-mode-vi H send -X start-of-line +bind -T copy-mode-vi L send -X end-of-line + + +######################################## +# Local config # +######################################## +if '[ -f $TMUX_HOME/theme ]' 'source $TMUX_HOME/theme' +if '[ -f ~/.tmux.conf ]' 'source ~/.tmux.conf' diff --git a/config/tmux/swap-pane.sh b/config/tmux/swap-pane.sh new file mode 100755 index 00000000..f5a6e989 --- /dev/null +++ b/config/tmux/swap-pane.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env bash +CONF="$TMUX_PLUGINS_PATH/lastpane" +swap() { tmux swap-pane -s"$1" -t"$2"; } + +target= +case $1 in + up) target="U" ;; + down) target="D" ;; + left) target="L" ;; + right) target="R" ;; + master) target="M" ;; + *) exit 1 ;; +esac + +src_pane=$(tmux display-message -p "#P") +tmux select-pane -${target} + +dst_pane=$(tmux display-message -p "#P") +tmux select-pane -${src_pane} + +[[ "$target" == M ]] && dst_pane=0 +swap "$src_pane" "$dst_pane" +tmux select-pane -t"$dst_pane" diff --git a/modules/shell/tmux.nix b/modules/shell/tmux.nix new file mode 100644 index 00000000..eb647bb8 --- /dev/null +++ b/modules/shell/tmux.nix @@ -0,0 +1,26 @@ +{ config, lib, pkgs, ... }: + +{ + my = { + packages = with pkgs; [ + # The developer of tmux chooses not to add XDG support for religious + # reasons (see tmux/tmux#142). Fortunately, nix offers a simple + # workaround: + (writeScriptBin "tmux" '' + #!${stdenv.shell} + exec ${tmux}/bin/tmux -f "$TMUX_HOME/config" "$@" + '') + ]; + + env.TMUX_HOME = "$XDG_CONFIG_HOME/tmux"; + env.TMUXIFIER = "$XDG_DATA_HOME/tmuxifier"; + env.TMUXIFIER_LAYOUT_PATH = "$XDG_DATA_HOME/tmuxifier"; + env.PATH = [ "$TMUXIFIER/bin" ]; + + zsh.rc = '' + _cache tmuxifier init - + ${lib.readFile } + ''; + home.xdg.configFile."tmux" = { source = ; recursive = true; }; + }; +} diff --git a/modules/shell/zsh.nix b/modules/shell/zsh.nix index b86c941b..e8d7eab1 100644 --- a/modules/shell/zsh.nix +++ b/modules/shell/zsh.nix @@ -1,6 +1,8 @@ { config, pkgs, libs, ... }: { + imports = [ ./tmux.nix ]; + my = { packages = with pkgs; [ zsh