mirror of
https://github.com/fscotto/infra.git
synced 2026-05-30 15:39:58 +00:00
Simplify tmux config and bootstrap plugins with TPM
This commit is contained in:
@@ -21,7 +21,7 @@ Ansible-driven personal infrastructure repo for Void desktops, Linux workstation
|
|||||||
- Prefer minimal, targeted edits. Preserve idempotency and existing ordering.
|
- Prefer minimal, targeted edits. Preserve idempotency and existing ordering.
|
||||||
- Most hosts use `ansible_connection: local`; Windows host is the exception.
|
- Most hosts use `ansible_connection: local`; Windows host is the exception.
|
||||||
- Treat `secrets/` as sensitive. Never print secret values.
|
- Treat `secrets/` as sensitive. Never print secret values.
|
||||||
- Do not edit vendored tmux plugins under `dotfiles/desktop/.tmux/plugins/` unless explicitly asked.
|
- Tmux plugins are bootstrapped by TPM on the host; the repo only keeps tmux config and custom helper scripts.
|
||||||
- Read the relevant role tasks, templates, vars, and deployed dotfiles before editing.
|
- Read the relevant role tasks, templates, vars, and deployed dotfiles before editing.
|
||||||
|
|
||||||
## Validation
|
## Validation
|
||||||
|
|||||||
@@ -88,6 +88,7 @@ Lo stato attuale del profilo desktop include, tra le altre cose:
|
|||||||
- `turnstile` per i servizi utente, inclusi `emacs` e `ssh-agent`
|
- `turnstile` per i servizi utente, inclusi `emacs` e `ssh-agent`
|
||||||
- `ssh-agent` con socket stabile condiviso tra shell, SSH ed Emacs in `~/.local/state/ssh-agent/socket`
|
- `ssh-agent` con socket stabile condiviso tra shell, SSH ed Emacs in `~/.local/state/ssh-agent/socket`
|
||||||
- `ollama` eseguito via container Podman
|
- `ollama` eseguito via container Podman
|
||||||
|
- `tmux` con plugin gestiti da TPM al bootstrap del profilo desktop
|
||||||
- Flatpak con remoto Flathub
|
- Flatpak con remoto Flathub
|
||||||
- GNOME Keyring e bootstrap della posta via script dedicato
|
- GNOME Keyring e bootstrap della posta via script dedicato
|
||||||
- `Waybar` per Sway con `style.css` condiviso
|
- `Waybar` per Sway con `style.css` condiviso
|
||||||
|
|||||||
@@ -193,9 +193,9 @@ desktop_common_dotfiles:
|
|||||||
src: .tmux.conf
|
src: .tmux.conf
|
||||||
dest: .tmux.conf
|
dest: .tmux.conf
|
||||||
mode: "0644"
|
mode: "0644"
|
||||||
- name: tmux config directory
|
- name: tmux helper scripts
|
||||||
src: .tmux/
|
src: .tmux/bin/
|
||||||
dest: .tmux/
|
dest: .tmux/bin/
|
||||||
mode: preserve
|
mode: preserve
|
||||||
- name: Emacs config
|
- name: Emacs config
|
||||||
src: .emacs.d/
|
src: .emacs.d/
|
||||||
|
|||||||
@@ -22,6 +22,9 @@
|
|||||||
- "{{ user_home }}/.config/alacritty"
|
- "{{ user_home }}/.config/alacritty"
|
||||||
- "{{ user_home }}/.config/Thunar"
|
- "{{ user_home }}/.config/Thunar"
|
||||||
- "{{ user_home }}/.config/rofi"
|
- "{{ user_home }}/.config/rofi"
|
||||||
|
- "{{ user_home }}/.tmux"
|
||||||
|
- "{{ user_home }}/.tmux/bin"
|
||||||
|
- "{{ user_home }}/.tmux/plugins"
|
||||||
|
|
||||||
- name: Ensure user local bin directory exists
|
- name: Ensure user local bin directory exists
|
||||||
tags: [dotfiles, dotfiles:desktop, dotfiles:host]
|
tags: [dotfiles, dotfiles:desktop, dotfiles:host]
|
||||||
@@ -285,6 +288,59 @@
|
|||||||
loop_control:
|
loop_control:
|
||||||
label: "{{ item.dest }}"
|
label: "{{ item.dest }}"
|
||||||
|
|
||||||
|
- name: Define managed tmux plugin directories
|
||||||
|
tags: [dotfiles, dotfiles:desktop, tmux]
|
||||||
|
ansible.builtin.set_fact:
|
||||||
|
tmux_managed_plugin_names:
|
||||||
|
- tpm
|
||||||
|
- tmux-sensible
|
||||||
|
- tmux-autoreload
|
||||||
|
- tmux-resurrect
|
||||||
|
- tmux-continuum
|
||||||
|
|
||||||
|
- name: Check whether tmux plugin directories are git checkouts
|
||||||
|
tags: [dotfiles, dotfiles:desktop, tmux]
|
||||||
|
ansible.builtin.stat:
|
||||||
|
path: "{{ user_home }}/.tmux/plugins/{{ item }}/.git"
|
||||||
|
loop: "{{ tmux_managed_plugin_names }}"
|
||||||
|
loop_control:
|
||||||
|
label: "{{ item }}"
|
||||||
|
register: tmux_plugin_git_state
|
||||||
|
|
||||||
|
- name: Remove stale vendored tmux plugin directories
|
||||||
|
tags: [dotfiles, dotfiles:desktop, tmux]
|
||||||
|
ansible.builtin.file:
|
||||||
|
path: "{{ user_home }}/.tmux/plugins/{{ item.item }}"
|
||||||
|
state: absent
|
||||||
|
loop: "{{ tmux_plugin_git_state.results }}"
|
||||||
|
loop_control:
|
||||||
|
label: "{{ item.item }}"
|
||||||
|
when:
|
||||||
|
- item.stat.exists == false
|
||||||
|
|
||||||
|
- name: Bootstrap tmux plugin manager checkout
|
||||||
|
tags: [dotfiles, dotfiles:desktop, tmux]
|
||||||
|
ansible.builtin.git:
|
||||||
|
repo: https://github.com/tmux-plugins/tpm
|
||||||
|
dest: "{{ user_home }}/.tmux/plugins/tpm"
|
||||||
|
version: master
|
||||||
|
update: true
|
||||||
|
become_user: "{{ username }}"
|
||||||
|
environment:
|
||||||
|
HOME: "{{ user_home }}"
|
||||||
|
|
||||||
|
- name: Install tmux plugins through TPM
|
||||||
|
tags: [dotfiles, dotfiles:desktop, tmux]
|
||||||
|
ansible.builtin.command:
|
||||||
|
cmd: "{{ user_home }}/.tmux/plugins/tpm/bin/install_plugins"
|
||||||
|
become_user: "{{ username }}"
|
||||||
|
environment:
|
||||||
|
HOME: "{{ user_home }}"
|
||||||
|
register: tmux_plugin_install
|
||||||
|
changed_when: >-
|
||||||
|
(tmux_plugin_install.stdout | default('')) is search('download success') or
|
||||||
|
(tmux_plugin_install.stderr | default('')) is search('download success')
|
||||||
|
|
||||||
- name: Refresh user font cache
|
- name: Refresh user font cache
|
||||||
tags: [dotfiles, dotfiles:desktop]
|
tags: [dotfiles, dotfiles:desktop]
|
||||||
ansible.builtin.command: fc-cache -f
|
ansible.builtin.command: fc-cache -f
|
||||||
@@ -382,24 +438,12 @@
|
|||||||
desktop_tools_tmp_dir: /tmp/desktop-tools
|
desktop_tools_tmp_dir: /tmp/desktop-tools
|
||||||
st_repo: https://codeberg.org/fscotto/st
|
st_repo: https://codeberg.org/fscotto/st
|
||||||
st_src_dir: "{{ user_home }}/.local/src/st"
|
st_src_dir: "{{ user_home }}/.local/src/st"
|
||||||
gitmux_version: v0.11.5
|
|
||||||
opencode_asset_name: >-
|
opencode_asset_name: >-
|
||||||
{{
|
{{
|
||||||
'opencode-linux-x64-baseline.tar.gz' if ansible_facts['architecture'] == 'x86_64'
|
'opencode-linux-x64-baseline.tar.gz' if ansible_facts['architecture'] == 'x86_64'
|
||||||
else 'opencode-linux-arm64.tar.gz' if ansible_facts['architecture'] in ['aarch64', 'arm64']
|
else 'opencode-linux-arm64.tar.gz' if ansible_facts['architecture'] in ['aarch64', 'arm64']
|
||||||
else ''
|
else ''
|
||||||
}}
|
}}
|
||||||
gitmux_arch: >-
|
|
||||||
{{
|
|
||||||
'amd64' if ansible_facts['architecture'] == 'x86_64'
|
|
||||||
else 'arm64' if ansible_facts['architecture'] in ['aarch64', 'arm64']
|
|
||||||
else ''
|
|
||||||
}}
|
|
||||||
|
|
||||||
- name: Set derived desktop external tool asset metadata
|
|
||||||
tags: [packages]
|
|
||||||
ansible.builtin.set_fact:
|
|
||||||
gitmux_asset: "gitmux_{{ gitmux_version }}_linux_{{ gitmux_arch }}.tar.gz"
|
|
||||||
|
|
||||||
- name: Ensure architecture is supported for OpenCode binary
|
- name: Ensure architecture is supported for OpenCode binary
|
||||||
tags: [packages]
|
tags: [packages]
|
||||||
@@ -407,12 +451,6 @@
|
|||||||
msg: "Unsupported architecture {{ ansible_facts['architecture'] }} for OpenCode release binary"
|
msg: "Unsupported architecture {{ ansible_facts['architecture'] }} for OpenCode release binary"
|
||||||
when: opencode_asset_name == ''
|
when: opencode_asset_name == ''
|
||||||
|
|
||||||
- name: Ensure architecture is supported for gitmux binary
|
|
||||||
tags: [packages]
|
|
||||||
ansible.builtin.fail:
|
|
||||||
msg: "Unsupported architecture {{ ansible_facts['architecture'] }} for gitmux release binary"
|
|
||||||
when: gitmux_arch == ''
|
|
||||||
|
|
||||||
- name: Ensure temporary directory exists for external tools
|
- name: Ensure temporary directory exists for external tools
|
||||||
tags: [packages]
|
tags: [packages]
|
||||||
ansible.builtin.file:
|
ansible.builtin.file:
|
||||||
@@ -457,12 +495,6 @@
|
|||||||
checksum: "{{ opencode_asset.digest | default(omit) }}"
|
checksum: "{{ opencode_asset.digest | default(omit) }}"
|
||||||
extracted_binary: opencode
|
extracted_binary: opencode
|
||||||
install_dest: /usr/local/bin/opencode
|
install_dest: /usr/local/bin/opencode
|
||||||
- name: gitmux
|
|
||||||
asset_name: "{{ gitmux_asset }}"
|
|
||||||
url: "https://github.com/arl/gitmux/releases/download/{{ gitmux_version }}/{{ gitmux_asset }}"
|
|
||||||
checksum: "sha256:https://github.com/arl/gitmux/releases/download/{{ gitmux_version }}/checksums.txt"
|
|
||||||
extracted_binary: gitmux
|
|
||||||
install_dest: /usr/local/bin/gitmux
|
|
||||||
|
|
||||||
- name: Download desktop online archive binary releases
|
- name: Download desktop online archive binary releases
|
||||||
tags: [packages]
|
tags: [packages]
|
||||||
|
|||||||
@@ -1,44 +1,21 @@
|
|||||||
#=== KEYBINDINGS ====#
|
#=== BEHAVIOR ===#
|
||||||
|
|
||||||
# change prefix
|
|
||||||
unbind C-b
|
|
||||||
set -g prefix C-a
|
|
||||||
bind C-a send-prefix
|
|
||||||
|
|
||||||
# split panes using | and -
|
|
||||||
bind | split-window -h
|
|
||||||
bind - split-window -v
|
|
||||||
unbind '"'
|
|
||||||
unbind %
|
|
||||||
|
|
||||||
# switch panes using Alt-arrow without prefix
|
|
||||||
bind -n M-Left select-pane -L
|
|
||||||
bind -n M-Right select-pane -R
|
|
||||||
bind -n M-Up select-pane -U
|
|
||||||
bind -n M-Down select-pane -D
|
|
||||||
|
|
||||||
# switch windows using Alt-<number> without prefix
|
|
||||||
bind-key -n M-1 select-window -t 1
|
|
||||||
bind-key -n M-2 select-window -t 2
|
|
||||||
bind-key -n M-3 select-window -t 3
|
|
||||||
bind-key -n M-4 select-window -t 4
|
|
||||||
bind-key -n M-5 select-window -t 5
|
|
||||||
|
|
||||||
# Other session shortcuts
|
|
||||||
bind S command-prompt -p "New Session:" "new-session -A -s '%%'"
|
|
||||||
bind K confirm kill-session
|
|
||||||
set-option -g detach-on-destroy off
|
|
||||||
|
|
||||||
#=== LAYOUT ====#
|
|
||||||
set -g renumber-window on
|
set -g renumber-window on
|
||||||
set -g base-index 1
|
set -g base-index 1
|
||||||
setw -g pane-base-index 1
|
setw -g pane-base-index 1
|
||||||
bind c new-window -c '#{pane_current_path}'
|
|
||||||
|
|
||||||
# Enable mouse control (clickable windows, panes, resizable panes)
|
|
||||||
set -g mouse on
|
set -g mouse on
|
||||||
|
|
||||||
# Fix Tmux for colors
|
bind-key c new-window -c '#{pane_current_path}'
|
||||||
|
bind-key -n M-Left select-pane -L
|
||||||
|
bind-key -n M-Right select-pane -R
|
||||||
|
bind-key -n M-Up select-pane -U
|
||||||
|
bind-key -n M-Down select-pane -D
|
||||||
|
|
||||||
|
# Session popup: Enter switches, Ctrl-k kills, Ctrl-n creates.
|
||||||
|
bind-key S display-popup -E -w 80% -h 80% "~/.tmux/bin/session-popup '#{pane_current_path}'"
|
||||||
|
|
||||||
|
#=== TERMINAL ===#
|
||||||
|
|
||||||
set -g default-terminal "screen-256color"
|
set -g default-terminal "screen-256color"
|
||||||
set -ag terminal-features ',screen-256color:RGB,tmux*:RGB,alacritty:RGB,foot:RGB,xterm-256color:RGB,gnome*:RGB'
|
set -ag terminal-features ',screen-256color:RGB,tmux*:RGB,alacritty:RGB,foot:RGB,xterm-256color:RGB,gnome*:RGB'
|
||||||
set -g allow-passthrough on
|
set -g allow-passthrough on
|
||||||
@@ -46,15 +23,15 @@ set -ga update-environment TERM
|
|||||||
set -ga update-environment TERM_PROGRAM
|
set -ga update-environment TERM_PROGRAM
|
||||||
|
|
||||||
#=== PLUGINS ===#
|
#=== PLUGINS ===#
|
||||||
|
|
||||||
set -g @plugin 'tmux-plugins/tpm'
|
set -g @plugin 'tmux-plugins/tpm'
|
||||||
set -g @plugin 'tmux-plugins/tmux-sensible'
|
set -g @plugin 'tmux-plugins/tmux-sensible'
|
||||||
set -g @plugin 'sei40kr/tmux-project'
|
set -g @plugin 'b0o/tmux-autoreload'
|
||||||
set-option -g @plugin 'b0o/tmux-autoreload'
|
|
||||||
set -g @plugin 'tmux-plugins/tmux-resurrect'
|
set -g @plugin 'tmux-plugins/tmux-resurrect'
|
||||||
set -g @plugin 'tmux-plugins/tmux-continuum'
|
set -g @plugin 'tmux-plugins/tmux-continuum'
|
||||||
|
|
||||||
#=== THEME: Yaru Blue Dark ===#
|
#=== THEME: Yaru Blue Dark ===#
|
||||||
# palette
|
|
||||||
set -g @yaru_bg "#2b2b2e"
|
set -g @yaru_bg "#2b2b2e"
|
||||||
set -g @yaru_bg_light "#3b3b3e"
|
set -g @yaru_bg_light "#3b3b3e"
|
||||||
set -g @yaru_fg "#e0e0e0"
|
set -g @yaru_fg "#e0e0e0"
|
||||||
@@ -66,11 +43,10 @@ set -g @yaru_sep "#4a4a52"
|
|||||||
set -g @yaru_red "#c7162b"
|
set -g @yaru_red "#c7162b"
|
||||||
set -g @yaru_green "#4caf50"
|
set -g @yaru_green "#4caf50"
|
||||||
|
|
||||||
# status bar
|
|
||||||
set -g status-position top
|
set -g status-position top
|
||||||
set -g status-style "bg=#{@yaru_bg}"
|
set -g status-style "bg=#{@yaru_bg}"
|
||||||
set -g status-left-length 120
|
set -g status-left-length 120
|
||||||
set -g status-right-length 120
|
set -g status-right-length 80
|
||||||
|
|
||||||
set -g status-left ""
|
set -g status-left ""
|
||||||
set -ga status-left "#[bg=#{@yaru_bg},fg=#{@yaru_blue},bold] #S "
|
set -ga status-left "#[bg=#{@yaru_bg},fg=#{@yaru_blue},bold] #S "
|
||||||
@@ -82,22 +58,18 @@ set -ga status-left "#[bg=#{@yaru_bg},fg=#{@yaru_sep}]#{?window_zoomed_flag,│,
|
|||||||
set -ga status-left "#[bg=#{@yaru_bg},fg=#{@yaru_orange}]#{?window_zoomed_flag, zoom ,}"
|
set -ga status-left "#[bg=#{@yaru_bg},fg=#{@yaru_orange}]#{?window_zoomed_flag, zoom ,}"
|
||||||
|
|
||||||
set -g status-right ""
|
set -g status-right ""
|
||||||
set -g status-right '#(gitmux "#{pane_current_path}") '
|
|
||||||
set -ga status-right "#[bg=#{@yaru_bg},fg=#{@yaru_sep}]│"
|
set -ga status-right "#[bg=#{@yaru_bg},fg=#{@yaru_sep}]│"
|
||||||
set -ga status-right "#[bg=#{@yaru_bg},fg=#{@yaru_blue_b}] #H"
|
set -ga status-right "#[bg=#{@yaru_bg},fg=#{@yaru_blue_b}] #H"
|
||||||
|
|
||||||
# pane borders
|
|
||||||
setw -g pane-border-status off
|
setw -g pane-border-status off
|
||||||
setw -g pane-active-border-style "fg=#{@yaru_blue}"
|
setw -g pane-active-border-style "fg=#{@yaru_blue}"
|
||||||
setw -g pane-border-style "fg=#{@yaru_sep}"
|
setw -g pane-border-style "fg=#{@yaru_sep}"
|
||||||
setw -g pane-border-lines single
|
setw -g pane-border-lines single
|
||||||
|
|
||||||
# message and mode
|
|
||||||
set -g message-style "bg=#{@yaru_blue},fg=#{@yaru_bg},bold"
|
set -g message-style "bg=#{@yaru_blue},fg=#{@yaru_bg},bold"
|
||||||
set -g message-command-style "bg=#{@yaru_blue},fg=#{@yaru_bg},bold"
|
set -g message-command-style "bg=#{@yaru_blue},fg=#{@yaru_bg},bold"
|
||||||
set -g mode-style "bg=#{@yaru_orange},fg=#{@yaru_bg},bold"
|
set -g mode-style "bg=#{@yaru_orange},fg=#{@yaru_bg},bold"
|
||||||
|
|
||||||
# window status
|
|
||||||
set -g window-status-format " #I:#{?#{!=:#{window_name},Window},#W,} "
|
set -g window-status-format " #I:#{?#{!=:#{window_name},Window},#W,} "
|
||||||
set -g window-status-style "bg=#{@yaru_bg},fg=#{@yaru_fg_dim}"
|
set -g window-status-style "bg=#{@yaru_bg},fg=#{@yaru_fg_dim}"
|
||||||
set -g window-status-last-style "bg=#{@yaru_bg},fg=#{@yaru_fg}"
|
set -g window-status-last-style "bg=#{@yaru_bg},fg=#{@yaru_fg}"
|
||||||
@@ -107,11 +79,10 @@ set -gF window-status-separator "#[bg=#{@yaru_bg},fg=#{@yaru_sep}]│"
|
|||||||
set -g window-status-current-format " #I:#{?#{!=:#{window_name},Window},#W,} "
|
set -g window-status-current-format " #I:#{?#{!=:#{window_name},Window},#W,} "
|
||||||
set -g window-status-current-style "bg=#{@yaru_blue},fg=#{@yaru_bg},bold"
|
set -g window-status-current-style "bg=#{@yaru_blue},fg=#{@yaru_bg},bold"
|
||||||
|
|
||||||
# Continuum options
|
#=== SESSION RESTORE ===#
|
||||||
set -g @continuum-restore 'on'
|
|
||||||
|
|
||||||
# Project options
|
set -g @continuum-restore 'on'
|
||||||
set -ag @project-base-dirs ,"${HOME}/.dotfiles","${HOME}/Projects:0:2"
|
set -g @continuum-save-interval '15'
|
||||||
|
|
||||||
# Initialize TMUX plugin manager (keep this line at the very bottom of tmux.conf)
|
# Initialize TMUX plugin manager (keep this line at the very bottom of tmux.conf)
|
||||||
run '~/.tmux/plugins/tpm/tpm'
|
run '~/.tmux/plugins/tpm/tpm'
|
||||||
|
|||||||
55
dotfiles/desktop/.tmux/bin/session-popup
Executable file
55
dotfiles/desktop/.tmux/bin/session-popup
Executable file
@@ -0,0 +1,55 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
set -eu
|
||||||
|
|
||||||
|
default_dir=${1:-$HOME}
|
||||||
|
|
||||||
|
new_session() {
|
||||||
|
printf 'New session name: '
|
||||||
|
IFS= read -r session_name
|
||||||
|
|
||||||
|
[ -n "$session_name" ] || return 0
|
||||||
|
|
||||||
|
if ! tmux has-session -t "$session_name" 2>/dev/null; then
|
||||||
|
tmux new-session -d -s "$session_name" -c "$default_dir"
|
||||||
|
fi
|
||||||
|
|
||||||
|
tmux switch-client -t "$session_name"
|
||||||
|
exit 0
|
||||||
|
}
|
||||||
|
|
||||||
|
while :; do
|
||||||
|
selection=$(
|
||||||
|
tmux list-sessions -F '#{session_name}' |
|
||||||
|
fzf \
|
||||||
|
--layout=reverse \
|
||||||
|
--height=100% \
|
||||||
|
--border \
|
||||||
|
--prompt='sessions> ' \
|
||||||
|
--header='Enter switch Ctrl-n new Ctrl-k kill' \
|
||||||
|
--preview 'tmux list-windows -t {} -F "#{window_index}: #{window_name}#{?window_active, [active],}"' \
|
||||||
|
--preview-window='right,60%' \
|
||||||
|
--expect=ctrl-k,ctrl-n
|
||||||
|
) || exit 0
|
||||||
|
|
||||||
|
key=$(printf '%s\n' "$selection" | sed -n '1p')
|
||||||
|
session_name=$(printf '%s\n' "$selection" | sed -n '2p')
|
||||||
|
|
||||||
|
case "$key" in
|
||||||
|
ctrl-n)
|
||||||
|
new_session
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
[ -n "$session_name" ] || exit 0
|
||||||
|
|
||||||
|
case "$key" in
|
||||||
|
ctrl-k)
|
||||||
|
tmux kill-session -t "$session_name"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
tmux switch-client -t "$session_name"
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
@@ -1,139 +0,0 @@
|
|||||||
|
|
||||||
# Created by https://www.toptal.com/developers/gitignore/api/linux,macos,windows,vim,git,zsh
|
|
||||||
# Edit at https://www.toptal.com/developers/gitignore?templates=linux,macos,windows,vim,git,zsh
|
|
||||||
|
|
||||||
### Git ###
|
|
||||||
# Created by git for backups. To disable backups in Git:
|
|
||||||
# $ git config --global mergetool.keepBackup false
|
|
||||||
*.orig
|
|
||||||
|
|
||||||
# Created by git when using merge tools for conflicts
|
|
||||||
*.BACKUP.*
|
|
||||||
*.BASE.*
|
|
||||||
*.LOCAL.*
|
|
||||||
*.REMOTE.*
|
|
||||||
*_BACKUP_*.txt
|
|
||||||
*_BASE_*.txt
|
|
||||||
*_LOCAL_*.txt
|
|
||||||
*_REMOTE_*.txt
|
|
||||||
|
|
||||||
### Linux ###
|
|
||||||
*~
|
|
||||||
|
|
||||||
# temporary files which can be created if a process still has a handle open of a deleted file
|
|
||||||
.fuse_hidden*
|
|
||||||
|
|
||||||
# KDE directory preferences
|
|
||||||
.directory
|
|
||||||
|
|
||||||
# Linux trash folder which might appear on any partition or disk
|
|
||||||
.Trash-*
|
|
||||||
|
|
||||||
# .nfs files are created when an open file is removed but is still being accessed
|
|
||||||
.nfs*
|
|
||||||
|
|
||||||
### macOS ###
|
|
||||||
# General
|
|
||||||
.DS_Store
|
|
||||||
.AppleDouble
|
|
||||||
.LSOverride
|
|
||||||
|
|
||||||
# Icon must end with two
|
|
||||||
Icon
|
|
||||||
|
|
||||||
|
|
||||||
# Thumbnails
|
|
||||||
._*
|
|
||||||
|
|
||||||
# Files that might appear in the root of a volume
|
|
||||||
.DocumentRevisions-V100
|
|
||||||
.fseventsd
|
|
||||||
.Spotlight-V100
|
|
||||||
.TemporaryItems
|
|
||||||
.Trashes
|
|
||||||
.VolumeIcon.icns
|
|
||||||
.com.apple.timemachine.donotpresent
|
|
||||||
|
|
||||||
# Directories potentially created on remote AFP share
|
|
||||||
.AppleDB
|
|
||||||
.AppleDesktop
|
|
||||||
Network Trash Folder
|
|
||||||
Temporary Items
|
|
||||||
.apdisk
|
|
||||||
|
|
||||||
### Vim ###
|
|
||||||
# Swap
|
|
||||||
[._]*.s[a-v][a-z]
|
|
||||||
!*.svg # comment out if you don't need vector files
|
|
||||||
[._]*.sw[a-p]
|
|
||||||
[._]s[a-rt-v][a-z]
|
|
||||||
[._]ss[a-gi-z]
|
|
||||||
[._]sw[a-p]
|
|
||||||
|
|
||||||
# Session
|
|
||||||
Session.vim
|
|
||||||
Sessionx.vim
|
|
||||||
|
|
||||||
# Temporary
|
|
||||||
.netrwhist
|
|
||||||
# Auto-generated tag files
|
|
||||||
tags
|
|
||||||
# Persistent undo
|
|
||||||
[._]*.un~
|
|
||||||
|
|
||||||
### Windows ###
|
|
||||||
# Windows thumbnail cache files
|
|
||||||
Thumbs.db
|
|
||||||
Thumbs.db:encryptable
|
|
||||||
ehthumbs.db
|
|
||||||
ehthumbs_vista.db
|
|
||||||
|
|
||||||
# Dump file
|
|
||||||
*.stackdump
|
|
||||||
|
|
||||||
# Folder config file
|
|
||||||
[Dd]esktop.ini
|
|
||||||
|
|
||||||
# Recycle Bin used on file shares
|
|
||||||
$RECYCLE.BIN/
|
|
||||||
|
|
||||||
# Windows Installer files
|
|
||||||
*.cab
|
|
||||||
*.msi
|
|
||||||
*.msix
|
|
||||||
*.msm
|
|
||||||
*.msp
|
|
||||||
|
|
||||||
# Windows shortcuts
|
|
||||||
*.lnk
|
|
||||||
|
|
||||||
### Zsh ###
|
|
||||||
# Zsh compiled script + zrecompile backup
|
|
||||||
*.zwc
|
|
||||||
*.zwc.old
|
|
||||||
|
|
||||||
# Zsh completion-optimization dumpfile
|
|
||||||
*zcompdump*
|
|
||||||
|
|
||||||
# Zsh zcalc history
|
|
||||||
.zcalc_history
|
|
||||||
|
|
||||||
# A popular plugin manager's files
|
|
||||||
._zinit
|
|
||||||
.zinit_lstupd
|
|
||||||
|
|
||||||
# zdharma/zshelldoc tool's files
|
|
||||||
zsdoc/data
|
|
||||||
|
|
||||||
# robbyrussell/oh-my-zsh/plugins/per-directory-history plugin's files
|
|
||||||
# (when set-up to store the history in the local directory)
|
|
||||||
.directory_history
|
|
||||||
|
|
||||||
# MichaelAquilina/zsh-autoswitch-virtualenv plugin's files
|
|
||||||
# (for Zsh plugins using Python)
|
|
||||||
.venv
|
|
||||||
|
|
||||||
# Zunit tests' output
|
|
||||||
/tests/_output/*
|
|
||||||
!/tests/_output/.gitkeep
|
|
||||||
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
MIT License
|
|
||||||
|
|
||||||
Copyright (c) 2021 Maddison Hellstrom
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
|
||||||
copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
SOFTWARE.
|
|
||||||
@@ -1,166 +0,0 @@
|
|||||||
# tmux-autoreload [](https://github.com/b0o/tmux-autoreload/releases) [](https://mit-license.org)
|
|
||||||
|
|
||||||
tmux-autoreload watches your tmux configuration file and automatically reloads
|
|
||||||
it on change.
|
|
||||||
|
|
||||||
## Install
|
|
||||||
|
|
||||||
#### Dependencies
|
|
||||||
|
|
||||||
- [entr](https://github.com/eradman/entr)
|
|
||||||
|
|
||||||
## Installation
|
|
||||||
|
|
||||||
To install tmux-autoreload with TPM (https://github.com/tmux-plugins/tpm), add the
|
|
||||||
following line to the end of your tmux configuration file:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
set-option -g @plugin 'b0o/tmux-autoreload'
|
|
||||||
```
|
|
||||||
|
|
||||||
Then, inside tmux, press `prefix + I` to fetch the plugin.
|
|
||||||
|
|
||||||
If you don't use a plugin manager, git clone tmux-autoreload to the location of your
|
|
||||||
choice and run it directly:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
run-shell "/path/to/tmux-autoreload/tmux-autoreload.tmux"
|
|
||||||
```
|
|
||||||
|
|
||||||
## Setup
|
|
||||||
|
|
||||||
Once installed, you should be good to go unless you use non-standard
|
|
||||||
configuration file paths or want to customize how tmux-autoreload behaves.
|
|
||||||
|
|
||||||
### Configuration file paths
|
|
||||||
|
|
||||||
If your tmux config file is at a non-standard location or if you have multiple,
|
|
||||||
specify them in `@tmux-autoreload-configs`, separated by commas:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
set-option -g @tmux-autoreload-configs '/path/to/configs/a.conf,/path/to/configs/b.conf'
|
|
||||||
```
|
|
||||||
|
|
||||||
### Entrypoints
|
|
||||||
|
|
||||||
Normally, tmux-autoreload will source whichever file changed. If you wish to
|
|
||||||
source a specific set of files when any configuration file changes, use
|
|
||||||
`@tmux-autoreload-entrypoints`:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
set-option -g @tmux-autoreload-entrypoints '/path/to/entrypoint.conf'
|
|
||||||
```
|
|
||||||
|
|
||||||
You can specify multiple entrypoints separated by commas. All entrypoints
|
|
||||||
will be sourced when any watched file changes.
|
|
||||||
|
|
||||||
Set `@tmux-autoreload-entrypoints` to 1 to use the standard tmux configuration
|
|
||||||
files as entrypoints, usually `/etc/tmux.conf` and `~/.tmux.conf.` You can see
|
|
||||||
these files with:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
tmux display-message -p "#{config_files}"
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Entrypoint Notes
|
|
||||||
|
|
||||||
- If entrypoints are configured, a changed file itself will not necessarily
|
|
||||||
be reloaded unless it's an entrypoint or is sourced by an entrypoint.
|
|
||||||
|
|
||||||
- Entrypoints will not be watched unless they're a standard tmux
|
|
||||||
configuration file like `~/.tmux.conf` or are included in `@tmux-autoreload-configs.`
|
|
||||||
|
|
||||||
### All Options
|
|
||||||
|
|
||||||
```
|
|
||||||
@tmux-autoreload-configs (Default: unset)
|
|
||||||
A comma-delimited list of paths to configuration files which should be
|
|
||||||
watched in addition to the base tmux configuration files.
|
|
||||||
|
|
||||||
@tmux-autoreload-entrypoints (Default: unset)
|
|
||||||
A comma-delimited list of paths to configuration files which should be
|
|
||||||
reloaded when any watched configuration file changes. If unset, the changed
|
|
||||||
file itself will be reloaded.
|
|
||||||
|
|
||||||
If set, only the entrypoints will be reloaded, not necessarily the changed
|
|
||||||
file.
|
|
||||||
|
|
||||||
If set to 1, the base tmux configuration files are used as the entrypoints
|
|
||||||
(you can see the base configuration files with the command tmux
|
|
||||||
display-message -p "#{config_files}").
|
|
||||||
|
|
||||||
@tmux-autoreload-quiet 0|1 (Default: 0)
|
|
||||||
If set to 1, tmux-autoreload will not display status messages.
|
|
||||||
```
|
|
||||||
|
|
||||||
## Advanced Usage
|
|
||||||
|
|
||||||
<!-- USAGE -->
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
||||||
Usage: tmux-autoreload.tmux [-f] [OPT...]
|
|
||||||
Automatically reloads your tmux configuration files on change.
|
|
||||||
|
|
||||||
Options
|
|
||||||
-h Display usage information.
|
|
||||||
-v Display tmux-autoreload version and copyright information.
|
|
||||||
-f Run in foreground (do not fork).
|
|
||||||
-k Kill the running tmux-autoreload instance.
|
|
||||||
-s Show tmux-autoreload status
|
|
||||||
|
|
||||||
Installation
|
|
||||||
To install tmux-autoreload with TPM (https://github.com/tmux-plugins/tpm), add the
|
|
||||||
following line to the end of your tmux configuration file:
|
|
||||||
set-option -g @plugin 'b0o/tmux-autoreload'
|
|
||||||
|
|
||||||
If you don't use a plugin manager, git clone tmux-autoreload to the location of your
|
|
||||||
choice and run it directly:
|
|
||||||
run-shell "/path/to/tmux-autoreload/tmux-autoreload.tmux"
|
|
||||||
|
|
||||||
Once installed, you should be good to go unless you use non-standard
|
|
||||||
configuration file paths or want to customize how tmux-autoreload behaves.
|
|
||||||
|
|
||||||
Configuration file paths
|
|
||||||
If your config file is at a non-standard location or if you have multiple,
|
|
||||||
specify them in @tmux-autoreload-configs, separated by commas:
|
|
||||||
set-option -g @tmux-autoreload-configs '/path/to/configs/a.conf,/path/to/configs/b.conf'
|
|
||||||
|
|
||||||
Entrypoints
|
|
||||||
Normally, tmux-autoreload will source whichever file changed. If you wish to
|
|
||||||
source a specific set of files when any configuration file changes, use
|
|
||||||
@tmux-autoreload-entrypoints:
|
|
||||||
set-option -g @tmux-autoreload-entrypoints '/path/to/entrypoint.conf'
|
|
||||||
|
|
||||||
You can specify multiple entrypoints separated by commas. All entrypoints
|
|
||||||
will be sourced when any watched file changes.
|
|
||||||
|
|
||||||
Set @tmux-autoreload-entrypoints to 1 to use the standard tmux configuration
|
|
||||||
files as entrypoints, usually /etc/tmux.conf and ~/.tmux.conf. You can see
|
|
||||||
these files with:
|
|
||||||
tmux display-message -p "#{config_files}".
|
|
||||||
|
|
||||||
Entrypoint Notes:
|
|
||||||
- If entrypoints are configured, a changed file itself will not necessarily
|
|
||||||
be reloaded unless it's an entrypoint or is sourced by an entrypoint.
|
|
||||||
|
|
||||||
- Entrypoints will not be watched unless they're a standard tmux
|
|
||||||
configuration file like ~/.tmux.conf or are included in @tmux-autoreload-configs.
|
|
||||||
|
|
||||||
Other Options
|
|
||||||
@tmux-autoreload-quiet 0|1 (Default: 0)
|
|
||||||
If set to 1, tmux-autoreload will not display messages
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
||||||
<!-- /USAGE -->
|
|
||||||
|
|
||||||
## License
|
|
||||||
|
|
||||||
<!-- LICENSE -->
|
|
||||||
|
|
||||||
© 2021 Maddison Hellstrom
|
|
||||||
|
|
||||||
Released under the MIT License.
|
|
||||||
|
|
||||||
<!-- /LICENSE -->
|
|
||||||
@@ -1,154 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# Copyright (C) 2020-2021 Maddison Hellstrom <https://github.com/b0o>, MIT License.
|
|
||||||
|
|
||||||
set -Eeuo pipefail
|
|
||||||
if [[ ${BASH_VERSINFO[0]} -ge 5 || (${BASH_VERSINFO[0]} -eq 4 && ${BASH_VERSINFO[1]} -ge 4) ]]; then
|
|
||||||
shopt -s inherit_errexit
|
|
||||||
fi
|
|
||||||
|
|
||||||
declare -g self prog basedir reporoot
|
|
||||||
self="$(readlink -e "${BASH_SOURCE[0]}")"
|
|
||||||
prog="$(basename "$self")"
|
|
||||||
basedir="$(realpath -m "$self/..")"
|
|
||||||
reporoot="$(realpath -m "$basedir/..")"
|
|
||||||
|
|
||||||
# gendocs configuration {{{
|
|
||||||
|
|
||||||
declare -g main="${reporoot}/tmux-autoreload.tmux"
|
|
||||||
|
|
||||||
declare -gA targets=(
|
|
||||||
[readme]="$reporoot/README.md"
|
|
||||||
)
|
|
||||||
|
|
||||||
declare -gi copyright_start=2021
|
|
||||||
|
|
||||||
function target_readme() {
|
|
||||||
section -s USAGE -c <<< "$("$main" -h 2>&1)"
|
|
||||||
section -s LICENSE << EOF
|
|
||||||
© ${copyright_start}$( (($(date +%Y) == copyright_start)) || date +-%Y) Maddison Hellstrom
|
|
||||||
|
|
||||||
Released under the MIT License.
|
|
||||||
EOF
|
|
||||||
}
|
|
||||||
|
|
||||||
# }}}
|
|
||||||
|
|
||||||
declare -gA sections
|
|
||||||
|
|
||||||
function section() {
|
|
||||||
local section
|
|
||||||
local -i code=0
|
|
||||||
local lang
|
|
||||||
|
|
||||||
local opt OPTARG
|
|
||||||
local -i OPTIND
|
|
||||||
while getopts "s:cC:" opt "$@"; do
|
|
||||||
case "$opt" in
|
|
||||||
s)
|
|
||||||
section="$OPTARG"
|
|
||||||
;;
|
|
||||||
c)
|
|
||||||
code=1
|
|
||||||
;;
|
|
||||||
C)
|
|
||||||
code=1
|
|
||||||
lang="$OPTARG"
|
|
||||||
;;
|
|
||||||
\?)
|
|
||||||
return 1
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
done
|
|
||||||
shift $((OPTIND - 1))
|
|
||||||
|
|
||||||
local -a lines=('')
|
|
||||||
|
|
||||||
if [[ $code -eq 1 ]]; then
|
|
||||||
lines+=('```'"${lang:-}" '')
|
|
||||||
fi
|
|
||||||
|
|
||||||
mapfile -tO ${#lines[@]} lines
|
|
||||||
|
|
||||||
if [[ $code -eq 1 ]]; then
|
|
||||||
lines+=('' '```')
|
|
||||||
fi
|
|
||||||
|
|
||||||
sections["$section"]="$(printf '%s\n' "${lines[@]}")\n"
|
|
||||||
}
|
|
||||||
|
|
||||||
function regen_section() {
|
|
||||||
local section="$1"
|
|
||||||
local content="${sections[$section]}"
|
|
||||||
awk < "$target" -v "section=$section" -v "content=$content" '
|
|
||||||
BEGIN {
|
|
||||||
d = 0
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
if (match($0, "^<!-- " section " -->$")) {
|
|
||||||
d = 1
|
|
||||||
print $0
|
|
||||||
print content
|
|
||||||
next
|
|
||||||
}
|
|
||||||
if (match($0, "^<!-- /" section " -->$")) {
|
|
||||||
d = 0
|
|
||||||
print $0
|
|
||||||
next
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
d == 0 {
|
|
||||||
print $0
|
|
||||||
}
|
|
||||||
'
|
|
||||||
}
|
|
||||||
|
|
||||||
function main() {
|
|
||||||
local opt OPTARG
|
|
||||||
local -i OPTIND
|
|
||||||
while getopts "h" opt "$@"; do
|
|
||||||
case "$opt" in
|
|
||||||
h)
|
|
||||||
echo "usage: $prog [opt].. [target].." >&2
|
|
||||||
return 0
|
|
||||||
;;
|
|
||||||
\?)
|
|
||||||
return 1
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
done
|
|
||||||
shift $((OPTIND - 1))
|
|
||||||
|
|
||||||
local -a targets_selected=("${!targets[@]}")
|
|
||||||
|
|
||||||
if [[ $# -gt 0 ]]; then
|
|
||||||
targets_selected=("$@")
|
|
||||||
fi
|
|
||||||
|
|
||||||
local t target
|
|
||||||
for t in "${targets_selected[@]}"; do
|
|
||||||
[[ -v "targets[$t]" ]] || {
|
|
||||||
echo "unknown target: $t" >&2
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
target="${targets["$t"]}"
|
|
||||||
[[ -e "$target" ]] || {
|
|
||||||
echo "target file not found: $target" >&2
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
sections=()
|
|
||||||
"target_${t}" || {
|
|
||||||
echo "unknown target: $t"
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
local s
|
|
||||||
for s in "${!sections[@]}"; do
|
|
||||||
regen_section "$s" > "${target}_"
|
|
||||||
mv "${target}_" "$target"
|
|
||||||
done
|
|
||||||
done
|
|
||||||
}
|
|
||||||
|
|
||||||
main "$@"
|
|
||||||
@@ -1,258 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
# Automatically reloads your tmux configuration files on change.
|
|
||||||
#
|
|
||||||
# Copyright 2021 Maddison Hellstrom <github.com/b0o>, MIT License.
|
|
||||||
|
|
||||||
set -Eeuo pipefail
|
|
||||||
if [[ ${BASH_VERSINFO[0]} -ge 5 || (${BASH_VERSINFO[0]} -eq 4 && ${BASH_VERSINFO[1]} -ge 4) ]]; then
|
|
||||||
shopt -s inherit_errexit
|
|
||||||
fi
|
|
||||||
|
|
||||||
function years_from() {
|
|
||||||
local from="$1" to
|
|
||||||
to="${2:-$(date +%Y)}"
|
|
||||||
if [[ "$from" == "$to" ]]; then
|
|
||||||
echo "$from"
|
|
||||||
else
|
|
||||||
echo "$from-$to"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
declare -g self prog name
|
|
||||||
self="$(realpath -e "${BASH_SOURCE[0]}")"
|
|
||||||
prog="$(basename "$self")"
|
|
||||||
name="${prog%.tmux}"
|
|
||||||
|
|
||||||
declare -gr version="0.0.1"
|
|
||||||
declare -gr authors=("$(years_from 2021) Maddison Hellstrom <github.com/b0o>")
|
|
||||||
declare -gr repo_short="b0o/$name"
|
|
||||||
declare -gr repository="https://github.com/$repo_short"
|
|
||||||
declare -gr issues="https://github.com/$repo_short/issues"
|
|
||||||
declare -gr license="MIT"
|
|
||||||
declare -gr license_url="https://mit-license.org"
|
|
||||||
|
|
||||||
function usage() {
|
|
||||||
cat <<EOF
|
|
||||||
Usage: $prog [-f] [OPT...]
|
|
||||||
Automatically reloads your tmux configuration files on change.
|
|
||||||
|
|
||||||
Options
|
|
||||||
-h Display usage information.
|
|
||||||
-v Display $name version and copyright information.
|
|
||||||
-f Run in foreground (do not fork).
|
|
||||||
-k Kill the running $name instance.
|
|
||||||
-s Show $name status
|
|
||||||
|
|
||||||
Installation
|
|
||||||
To install $name with TPM (https://github.com/tmux-plugins/tpm), add the
|
|
||||||
following line to the end of your tmux configuration file:
|
|
||||||
set-option -g @plugin '$repo_short'
|
|
||||||
|
|
||||||
If you don't use a plugin manager, git clone $name to the location of your
|
|
||||||
choice and run it directly:
|
|
||||||
run-shell "/path/to/$name/$prog"
|
|
||||||
|
|
||||||
Once installed, you should be good to go unless you use non-standard
|
|
||||||
configuration file paths or want to customize how $name behaves.
|
|
||||||
|
|
||||||
Configuration file paths
|
|
||||||
If your config file is at a non-standard location or if you have multiple,
|
|
||||||
specify them in @$name-configs, separated by commas:
|
|
||||||
set-option -g @$name-configs '/path/to/configs/a.conf,/path/to/configs/b.conf'
|
|
||||||
|
|
||||||
Entrypoints
|
|
||||||
Normally, $name will source whichever file changed. If you wish to
|
|
||||||
source a specific set of files when any configuration file changes, use
|
|
||||||
@$name-entrypoints:
|
|
||||||
set-option -g @$name-entrypoints '/path/to/entrypoint.conf'
|
|
||||||
|
|
||||||
You can specify multiple entrypoints separated by commas. All entrypoints
|
|
||||||
will be sourced when any watched file changes.
|
|
||||||
|
|
||||||
Set @$name-entrypoints to 1 to use the standard tmux configuration
|
|
||||||
files as entrypoints, usually /etc/tmux.conf and ~/.tmux.conf. You can see
|
|
||||||
these files with:
|
|
||||||
tmux display-message -p "#{config_files}".
|
|
||||||
|
|
||||||
Entrypoint Notes:
|
|
||||||
- If entrypoints are configured, a changed file itself will not necessarily
|
|
||||||
be reloaded unless it's an entrypoint or is sourced by an entrypoint.
|
|
||||||
|
|
||||||
- Entrypoints will not be watched unless they're a standard tmux
|
|
||||||
configuration file like ~/.tmux.conf or are included in @$name-configs.
|
|
||||||
|
|
||||||
Other Options
|
|
||||||
@$name-quiet 0|1 (Default: 0)
|
|
||||||
If set to 1, $name will not display messages
|
|
||||||
|
|
||||||
EOF
|
|
||||||
}
|
|
||||||
|
|
||||||
function usage_version() {
|
|
||||||
cat <<EOF
|
|
||||||
$name v$version
|
|
||||||
|
|
||||||
Repository: $repository
|
|
||||||
Issues: $issues
|
|
||||||
License: $license ($license_url)
|
|
||||||
Copyright: ${authors[0]}
|
|
||||||
EOF
|
|
||||||
if [[ ${#authors[@]} -gt 1 ]]; then
|
|
||||||
printf ' %s\n' "${authors[@]:1}"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
function display_message() {
|
|
||||||
if [[ "$(tmux show-option -gv "@$name-quiet")" == "1" ]]; then
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
# `tmux display-message -c` is broken in v3.2a
|
|
||||||
# https://github.com/tmux/tmux/issues/2737#issuecomment-898861216
|
|
||||||
if [[ "$(tmux display-message -p "#{version}")" == "3.2a" ]]; then
|
|
||||||
tmux display-message "$@"
|
|
||||||
else
|
|
||||||
while read -r client; do
|
|
||||||
tmux display-message -c "$client" "$@"
|
|
||||||
done < <(tmux list-clients -F '#{client_name}')
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
function get_base_configs() {
|
|
||||||
tmux display-message -p "#{config_files}" | tr ',' '\n' | sort -u
|
|
||||||
}
|
|
||||||
|
|
||||||
function get_user_configs() {
|
|
||||||
tmux show-option -gv "@$name-configs" | tr ',' '\n' | sort -u
|
|
||||||
}
|
|
||||||
|
|
||||||
function get_entrypoints() {
|
|
||||||
local entrypoints
|
|
||||||
entrypoints="$(tmux show-option -gv "@$name-entrypoints")"
|
|
||||||
if [[ -z "$entrypoints" || "$entrypoints" == "0" ]]; then
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
if [[ "$entrypoints" == "1" ]]; then
|
|
||||||
get_base_configs
|
|
||||||
else
|
|
||||||
echo "$entrypoints" | tr ',' '\n'
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
function get_instance() {
|
|
||||||
local -i instance_pid
|
|
||||||
instance_pid="$(tmux show-options -gv "@$name-pid")"
|
|
||||||
if [[ "$instance_pid" -gt 0 ]] && ps "$instance_pid" &>/dev/null; then
|
|
||||||
echo "$instance_pid"
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
|
|
||||||
function reload() {
|
|
||||||
local -a entrypoints
|
|
||||||
mapfile -t entrypoints < <(get_entrypoints)
|
|
||||||
if [[ ${#entrypoints[@]} -eq 0 ]]; then
|
|
||||||
entrypoints=("$@")
|
|
||||||
fi
|
|
||||||
if msg="$(tmux source-file "${entrypoints[@]}")"; then
|
|
||||||
display_message "Reloaded $(
|
|
||||||
printf '%s\n' "${entrypoints[@]}" | xargs -n1 basename | tr '\n' ',' | sed 's/,$/\n/; s/,/, /g'
|
|
||||||
)"
|
|
||||||
else
|
|
||||||
display_message -d 0 "#[fg=white,bg=red,bold]ERROR: $msg"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
function onexit() {
|
|
||||||
local -i code=$?
|
|
||||||
local -i entr_pid=$1
|
|
||||||
display_message "$name exited with code $code" || true
|
|
||||||
if [[ -v entr_pid && $entr_pid -gt 1 ]] && ps "$entr_pid" &>/dev/null; then
|
|
||||||
kill "$entr_pid" || true
|
|
||||||
fi
|
|
||||||
tmux set-option -gu "@$name-pid" &
|
|
||||||
return "$code"
|
|
||||||
}
|
|
||||||
|
|
||||||
function kill_instance() {
|
|
||||||
local -i instance_pid
|
|
||||||
if instance_pid="$(get_instance)"; then
|
|
||||||
kill "$instance_pid"
|
|
||||||
return $?
|
|
||||||
fi
|
|
||||||
echo "$name -k: kill failed: no instance found" >&2
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
|
|
||||||
function get_status() {
|
|
||||||
local -i instance_pid
|
|
||||||
if instance_pid="$(get_instance)"; then
|
|
||||||
echo "running: $instance_pid"
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
echo "not running"
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
|
|
||||||
function main() {
|
|
||||||
if ! [[ "${1:-}" =~ ^-[hvfksr]$ ]]; then
|
|
||||||
"$self" -f "$@" &>/dev/null &
|
|
||||||
disown
|
|
||||||
exit $?
|
|
||||||
fi
|
|
||||||
|
|
||||||
local opt OPTARG
|
|
||||||
local -i OPTIND
|
|
||||||
while getopts "hvfksr:" opt "$@"; do
|
|
||||||
case "$opt" in
|
|
||||||
h)
|
|
||||||
usage
|
|
||||||
return 0
|
|
||||||
;;
|
|
||||||
v)
|
|
||||||
usage_version
|
|
||||||
return 0
|
|
||||||
;;
|
|
||||||
f)
|
|
||||||
# Silently ignore -f
|
|
||||||
;;
|
|
||||||
k)
|
|
||||||
kill_instance
|
|
||||||
return
|
|
||||||
;;
|
|
||||||
s)
|
|
||||||
get_status
|
|
||||||
return
|
|
||||||
;;
|
|
||||||
r)
|
|
||||||
reload "$OPTARG"
|
|
||||||
return
|
|
||||||
;;
|
|
||||||
\?)
|
|
||||||
return 1
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
done
|
|
||||||
shift $((OPTIND - 1))
|
|
||||||
|
|
||||||
if get_instance &>/dev/null; then
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
command -v entr &>/dev/null || {
|
|
||||||
echo "Command not found: entr" >&2
|
|
||||||
display_message -d 0 "Failed to start $name: Command not found: entr"
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
|
|
||||||
tmux set-option -g "@$name-pid" $$
|
|
||||||
|
|
||||||
# shellcheck disable=2016
|
|
||||||
entr -np sh -c '"$0" -r "$1"' "$self" /_ <<<"$(printf '%s\n' "$(get_base_configs)" "$(get_user_configs)")" &
|
|
||||||
# shellcheck disable=2064
|
|
||||||
trap "onexit $!" EXIT
|
|
||||||
wait
|
|
||||||
}
|
|
||||||
|
|
||||||
main "$@"
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
# Force text files to have unix eols, so Windows/Cygwin does not break them
|
|
||||||
*.* eol=lf
|
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
# Changelog
|
|
||||||
|
|
||||||
### master
|
|
||||||
- bugfix: "auto restore" feature stopped working
|
|
||||||
- bugfix: prevent race condition when auto-saving with locks (@v9v)
|
|
||||||
- Multiple users on a system can now each run continuum on their own.
|
|
||||||
|
|
||||||
### v3.1.0, 2015-03-14
|
|
||||||
- properly quote scripts
|
|
||||||
- bugfix: "auto restore" feature does not work on tmux `1.9a`
|
|
||||||
- bugfix: do not count `tmux source-file .tmux.conf` as a tmux process (when
|
|
||||||
checking if other tmux server is running). Previously, this caused
|
|
||||||
interpolation command not to be inserted into `status-right` because `tmux
|
|
||||||
source-file` was falsely detected as another tmux server.
|
|
||||||
- add `#{continuum_status}` status line interpolation
|
|
||||||
|
|
||||||
### v3.0.0, 2015-02-20
|
|
||||||
- rename the plugin from `tmux-resurrect-auto` to `tmux-continuum`
|
|
||||||
|
|
||||||
### v2.2.0, 2015-02-20
|
|
||||||
- document tmux multi-server behavior in the readme
|
|
||||||
- do not auto-restore tmux environment if another tmux server is already running
|
|
||||||
(we don't want to duplicate stuff)
|
|
||||||
- bugfixes for 'tmux auto start' OS X Terminal.app and iTerm scripts
|
|
||||||
- prevent saving for the first 15 minutes only when plugin is sourced the first
|
|
||||||
time (not on subsequent sources or tmux.conf reloads)
|
|
||||||
- do not start auto-saving if there's another tmux server running (we don't want
|
|
||||||
for save files from various tmux environments to override each other)
|
|
||||||
|
|
||||||
### v2.1.0, 2015-02-18
|
|
||||||
- enable "tmux auto start" for OS X
|
|
||||||
- enable customizing "tmux auto start" for OS X
|
|
||||||
- fix errors when creating a launchd plist file for auto-start on OS X
|
|
||||||
|
|
||||||
### v2.0.0, 2015-02-15
|
|
||||||
- enable automatic environment restore when tmux is started
|
|
||||||
|
|
||||||
### v1.0.0, 2015-02-12
|
|
||||||
- first working version
|
|
||||||
- run the save script in the background
|
|
||||||
- do not start saving right after tmux is started
|
|
||||||
- add a check for tmux version to the initializer script
|
|
||||||
- when interval is set to '0' autosave is disabled
|
|
||||||
- bugfix: helper files not loaded
|
|
||||||
- update readme with the instructions how to disable auto saving
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
### Contributing
|
|
||||||
|
|
||||||
Code contributions are welcome!
|
|
||||||
|
|
||||||
If you wanna contribute a bigger feature, please open a github issue so we can
|
|
||||||
discuss it together first.
|
|
||||||
|
|
||||||
### Reporting a bug
|
|
||||||
|
|
||||||
If you find a bug please report it in the issues. When reporting a bug please
|
|
||||||
attach:
|
|
||||||
- a file symlinked to `~/.tmux/resurrect/last`.
|
|
||||||
- your `.tmux.conf`
|
|
||||||
- if you're getting an error paste it to a [gist](https://gist.github.com/) and
|
|
||||||
link it in the issue
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
Copyright (C) Bruno Sutic
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
a copy of this software and associated documentation files (the "Software"),
|
|
||||||
to deal in the Software without restriction, including without limitation
|
|
||||||
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
Software is furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included
|
|
||||||
in all copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
||||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
|
||||||
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
||||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
|
||||||
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
|
||||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
|
|
||||||
OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
@@ -1,103 +0,0 @@
|
|||||||
# tmux-continuum
|
|
||||||
|
|
||||||
Features:
|
|
||||||
|
|
||||||
- continuous saving of tmux environment
|
|
||||||
- automatic tmux start when computer/server is turned on
|
|
||||||
- automatic restore when tmux is started
|
|
||||||
|
|
||||||
Together, these features enable uninterrupted tmux usage. No matter the computer
|
|
||||||
or server restarts, if the machine is on, tmux will be there how you left it off
|
|
||||||
the last time it was used.
|
|
||||||
|
|
||||||
Tested and working on Linux, OSX and Cygwin.
|
|
||||||
|
|
||||||
#### Continuous saving
|
|
||||||
|
|
||||||
Tmux environment will be saved at an interval of 15 minutes. All the saving
|
|
||||||
happens in the background without impact to your workflow.
|
|
||||||
|
|
||||||
This action starts automatically when the plugin is installed. Note it requires
|
|
||||||
the status line to be `on` to run (since it uses a hook in status-right to run).
|
|
||||||
|
|
||||||
#### Automatic tmux start
|
|
||||||
|
|
||||||
Tmux is automatically started after the computer/server is turned on.
|
|
||||||
|
|
||||||
See the [instructions](docs/automatic_start.md) on how to enable this for your
|
|
||||||
system.
|
|
||||||
|
|
||||||
#### Automatic restore
|
|
||||||
|
|
||||||
Last saved environment is automatically restored when tmux is started.
|
|
||||||
|
|
||||||
Put `set -g @continuum-restore 'on'` in `.tmux.conf` to enable this.
|
|
||||||
|
|
||||||
Note: automatic restore happens **exclusively** on tmux server start. No other
|
|
||||||
action (e.g. sourcing `.tmux.conf`) triggers this.
|
|
||||||
|
|
||||||
#### Dependencies
|
|
||||||
|
|
||||||
`tmux 1.9` or higher, `bash`,
|
|
||||||
[tmux-resurrect](https://github.com/tmux-plugins/tmux-resurrect) plugin.
|
|
||||||
|
|
||||||
### Installation with [Tmux Plugin Manager](https://github.com/tmux-plugins/tpm) (recommended)
|
|
||||||
|
|
||||||
Please make sure you have
|
|
||||||
[tmux-resurrect](https://github.com/tmux-plugins/tmux-resurrect) installed.
|
|
||||||
|
|
||||||
Add plugin to the list of TPM plugins in `.tmux.conf`:
|
|
||||||
|
|
||||||
set -g @plugin 'tmux-plugins/tmux-resurrect'
|
|
||||||
set -g @plugin 'tmux-plugins/tmux-continuum'
|
|
||||||
|
|
||||||
Hit `prefix + I` to fetch the plugin and source it. The plugin will
|
|
||||||
automatically start "working" in the background, no action required.
|
|
||||||
|
|
||||||
### Manual Installation
|
|
||||||
|
|
||||||
Please make sure you have
|
|
||||||
[tmux-resurrect](https://github.com/tmux-plugins/tmux-resurrect) installed.
|
|
||||||
|
|
||||||
Clone the repo:
|
|
||||||
|
|
||||||
$ git clone https://github.com/tmux-plugins/tmux-continuum ~/clone/path
|
|
||||||
|
|
||||||
Add this line to the bottom of `.tmux.conf`:
|
|
||||||
|
|
||||||
run-shell ~/clone/path/continuum.tmux
|
|
||||||
|
|
||||||
Reload TMUX environment with: `$ tmux source-file ~/.tmux.conf`
|
|
||||||
|
|
||||||
The plugin will automatically start "working" in the background, no action
|
|
||||||
required.
|
|
||||||
|
|
||||||
### Docs
|
|
||||||
|
|
||||||
- [frequently asked questions](docs/faq.md)
|
|
||||||
- [behavior when running multiple tmux servers](docs/multiple_tmux_servers.md) -
|
|
||||||
this doc is safe to skip, but you might want to read it if you're using tmux
|
|
||||||
with `-L` or `-S` flags
|
|
||||||
- [automatically start tmux after the computer is turned on](docs/automatic_start.md)
|
|
||||||
- [continuum status in tmux status line](docs/continuum_status.md)
|
|
||||||
|
|
||||||
### Other goodies
|
|
||||||
|
|
||||||
- [tmux-copycat](https://github.com/tmux-plugins/tmux-copycat) - a plugin for
|
|
||||||
regex searches in tmux and fast match selection
|
|
||||||
- [tmux-yank](https://github.com/tmux-plugins/tmux-yank) - enables copying
|
|
||||||
highlighted text to system clipboard
|
|
||||||
- [tmux-open](https://github.com/tmux-plugins/tmux-open) - a plugin for quickly
|
|
||||||
opening highlighted file or a url
|
|
||||||
|
|
||||||
### Known Issues
|
|
||||||
|
|
||||||
- In order to be executed periodically, the plugin updates the `status-right` tmux variable. In case some plugin (usually themes) overwrites the `status-right` variable, the autosave feature stops working. To fix this issue, place the plugin last in the TPM plugins list.
|
|
||||||
|
|
||||||
### Reporting bugs and contributing
|
|
||||||
|
|
||||||
Both contributing and bug reports are welcome. Please check out
|
|
||||||
[contributing guidelines](CONTRIBUTING.md).
|
|
||||||
|
|
||||||
### License
|
|
||||||
[MIT](LICENSE.md)
|
|
||||||
@@ -1,89 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
set -x
|
|
||||||
|
|
||||||
CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
|
||||||
|
|
||||||
source "$CURRENT_DIR/scripts/helpers.sh"
|
|
||||||
source "$CURRENT_DIR/scripts/variables.sh"
|
|
||||||
source "$CURRENT_DIR/scripts/shared.sh"
|
|
||||||
|
|
||||||
save_command_interpolation="#($CURRENT_DIR/scripts/continuum_save.sh)"
|
|
||||||
|
|
||||||
supported_tmux_version_ok() {
|
|
||||||
"$CURRENT_DIR/scripts/check_tmux_version.sh" "$SUPPORTED_VERSION"
|
|
||||||
}
|
|
||||||
|
|
||||||
handle_tmux_automatic_start() {
|
|
||||||
"$CURRENT_DIR/scripts/handle_tmux_automatic_start.sh"
|
|
||||||
}
|
|
||||||
|
|
||||||
another_tmux_server_running() {
|
|
||||||
if just_started_tmux_server; then
|
|
||||||
another_tmux_server_running_on_startup
|
|
||||||
else
|
|
||||||
# script loaded after tmux server start can have multiple clients attached
|
|
||||||
[ "$(number_tmux_processes_except_current_server)" -gt "$(number_current_server_client_processes)" ]
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
delay_saving_environment_on_first_plugin_load() {
|
|
||||||
if [ -z "$(get_tmux_option "$last_auto_save_option" "")" ]; then
|
|
||||||
# last save option not set, this is first time plugin load
|
|
||||||
set_last_save_timestamp
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
add_resurrect_save_interpolation() {
|
|
||||||
local status_right_value="$(get_tmux_option "status-right" "")"
|
|
||||||
# check interpolation not already added
|
|
||||||
if ! [[ "$status_right_value" == *"$save_command_interpolation"* ]]; then
|
|
||||||
local new_value="${save_command_interpolation}${status_right_value}"
|
|
||||||
set_tmux_option "status-right" "$new_value"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
just_started_tmux_server() {
|
|
||||||
local tmux_start_time
|
|
||||||
tmux_start_time="$(tmux display-message -p -F '#{start_time}')"
|
|
||||||
local restore_max_delay
|
|
||||||
restore_max_delay="$(get_tmux_option "$auto_restore_max_delay_option" "${auto_restore_max_delay_default}")"
|
|
||||||
[ "$tmux_start_time" == "" ] || [ "$tmux_start_time" -gt "$(($(date +%s)-${restore_max_delay}))" ]
|
|
||||||
}
|
|
||||||
|
|
||||||
start_auto_restore_in_background() {
|
|
||||||
"$CURRENT_DIR/scripts/continuum_restore.sh" &
|
|
||||||
}
|
|
||||||
|
|
||||||
update_tmux_option() {
|
|
||||||
local option="$1"
|
|
||||||
local option_value="$(get_tmux_option "$option")"
|
|
||||||
# replace interpolation string with a script to execute
|
|
||||||
local new_option_value="${option_value/$status_interpolation_string/$status_script}"
|
|
||||||
set_tmux_option "$option" "$new_option_value"
|
|
||||||
}
|
|
||||||
|
|
||||||
main() {
|
|
||||||
if supported_tmux_version_ok; then
|
|
||||||
handle_tmux_automatic_start
|
|
||||||
|
|
||||||
# Advanced edge case handling: start auto-saving only if this is the
|
|
||||||
# only tmux server. We don't want saved files from more environments to
|
|
||||||
# overwrite each other.
|
|
||||||
if ! another_tmux_server_running; then
|
|
||||||
# give user a chance to restore previously saved session
|
|
||||||
delay_saving_environment_on_first_plugin_load
|
|
||||||
add_resurrect_save_interpolation
|
|
||||||
fi
|
|
||||||
|
|
||||||
if just_started_tmux_server; then
|
|
||||||
start_auto_restore_in_background
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Put "#{continuum_status}" interpolation in status-right or
|
|
||||||
# status-left tmux option to get current tmux continuum status.
|
|
||||||
update_tmux_option "status-right"
|
|
||||||
update_tmux_option "status-left"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
main
|
|
||||||
@@ -1,47 +0,0 @@
|
|||||||
# Automatic Tmux start
|
|
||||||
|
|
||||||
Tmux is automatically started after the computer/server is turned on.
|
|
||||||
|
|
||||||
### OS X
|
|
||||||
|
|
||||||
To enable this feature:
|
|
||||||
- put `set -g @continuum-boot 'on'` in `.tmux.conf`
|
|
||||||
- reload tmux config with this shell command: `$ tmux source-file ~/.tmux.conf`
|
|
||||||
|
|
||||||
Next time the computer is started:
|
|
||||||
- `Terminal.app` window will open and resize to maximum size
|
|
||||||
- `tmux` command will be executed in the terminal window
|
|
||||||
- if "auto restore" feature is enabled, tmux will start restoring previous env
|
|
||||||
|
|
||||||
Config options:
|
|
||||||
- `set -g @continuum-boot-options 'fullscreen'` - terminal window
|
|
||||||
will go fullscreen
|
|
||||||
- `set -g @continuum-boot-options 'iterm'` - start [iTerm](https://www.iterm2.com) instead
|
|
||||||
of `Terminal.app`
|
|
||||||
- `set -g @continuum-boot-options 'iterm,fullscreen'` - start `iTerm`
|
|
||||||
in fullscreen
|
|
||||||
- `set -g @continuum-boot-options 'kitty'` - start [kitty](https://sw.kovidgoyal.net/kitty) instead
|
|
||||||
of `Terminal.app`
|
|
||||||
- `set -g @continuum-boot-options 'kitty,fullscreen'` - start `kitty`
|
|
||||||
in fullscreen
|
|
||||||
- `set -g @continuum-boot-options 'alacritty'` - start [alacritty](https://github.com/alacritty/alacritty) instead of `Terminal.app`
|
|
||||||
- `set -g @continuum-boot-options 'alacritty,fullscreen'` - start `alacritty`
|
|
||||||
in fullscreen
|
|
||||||
|
|
||||||
Note: The first time you reboot your machine and activate this feature you may be prompted about a script requiring
|
|
||||||
access to a system program (i.e. - System Events). If this happens tmux will not start automatically and you will need
|
|
||||||
to go to `System Preferences -> Security & Privacy -> Accessability` and add the script to the list of apps that are
|
|
||||||
allowed to control your computer.
|
|
||||||
|
|
||||||
### Linux
|
|
||||||
|
|
||||||
Help with this would be greatly appreciated. Please get in touch.
|
|
||||||
|
|
||||||
#### Systemd
|
|
||||||
|
|
||||||
##### this will only start the tmux server, it will *not* start any terminal emulator
|
|
||||||
|
|
||||||
To enable automatic start with systemd:
|
|
||||||
- Put `set -g @continuum-boot 'on'` in `.tmux.conf`
|
|
||||||
- reload tmux config with this shell command: `$ tmux source-file ~/.tmux.conf`
|
|
||||||
- see [systemd](/docs/systemd_details.md) for more details about how this is implemented
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
## Continuum status in tmux status line
|
|
||||||
|
|
||||||
There is an option to display current status of tmux continuum in tmux status
|
|
||||||
line. This is done via `#{continuum_status}` interpolation and it works with
|
|
||||||
both `status-right` and `status-left` tmux native options.
|
|
||||||
|
|
||||||
Example usage:
|
|
||||||
|
|
||||||
set -g status-right 'Continuum status: #{continuum_status}'
|
|
||||||
|
|
||||||
When running, `#{continuum_status}` will show continuum save interval:
|
|
||||||
|
|
||||||
Continuum status: 15
|
|
||||||
|
|
||||||
or if continuous saving is disabled:
|
|
||||||
|
|
||||||
Continuum status: off
|
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
### FAQ
|
|
||||||
|
|
||||||
> Will a previous save be overwritten immediately after I start tmux?
|
|
||||||
|
|
||||||
No, first automatic save starts 15 minutes after tmux is started. If automatic
|
|
||||||
restore is not enabled, that gives you enough time to manually restore from a
|
|
||||||
previous save.
|
|
||||||
|
|
||||||
> I want to make a restore to a previous point in time, but it seems that save
|
|
||||||
is now overwritten?
|
|
||||||
|
|
||||||
Read how to [restore a previously saved environment](https://github.com/tmux-plugins/tmux-resurrect/blob/master/docs/restoring_previously_saved_environment.md)
|
|
||||||
|
|
||||||
> Will this plugin fill my hard disk?
|
|
||||||
|
|
||||||
Most likely no. A regular save file is in the range of 5Kb. And `tmux-resurrect` already has a `remove_old_backups()` routine that will ["remove resurrect files older than 30 days, but keep at least 5 copies of backup."](https://github.com/tmux-plugins/tmux-resurrect/blob/da1a7558024b8552f7262b39ed22e3d679304f99/scripts/save.sh#L271-L277)
|
|
||||||
|
|
||||||
> How do I change the save interval to i.e. 1 hour?
|
|
||||||
|
|
||||||
The interval is always measured in minutes. So setting the interval to `60`
|
|
||||||
(minutes) will do the trick. Put this in `.tmux.conf`:
|
|
||||||
|
|
||||||
set -g @continuum-save-interval '60'
|
|
||||||
|
|
||||||
and then source `tmux.conf` by executing this command in the shell
|
|
||||||
`$ tmux source-file ~/.tmux.conf`.
|
|
||||||
|
|
||||||
> How do I stop automatic saving?
|
|
||||||
|
|
||||||
Just set the save interval to `0`. Put this in `.tmux.conf`
|
|
||||||
|
|
||||||
set -g @continuum-save-interval '0'
|
|
||||||
|
|
||||||
and then source `tmux.conf` by executing this command in the shell
|
|
||||||
`$ tmux source-file ~/.tmux.conf`.
|
|
||||||
|
|
||||||
> I had automatic restore turned on, how do I disable it now?
|
|
||||||
|
|
||||||
Just remove `set -g @continuum-restore 'on'` from `tmux.conf`.
|
|
||||||
|
|
||||||
To be absolutely sure automatic restore doesn't happen, create a
|
|
||||||
`tmux_no_auto_restore` file in your home directory (command:
|
|
||||||
`$ touch ~/tmux_no_auto_restore`). Automatic restore won't happen if this file
|
|
||||||
exists.
|
|
||||||
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
### Behavior when running multiple tmux servers
|
|
||||||
|
|
||||||
(This is safe to skip if you're always running a single tmux server.)
|
|
||||||
|
|
||||||
If you're an advanced tmux user, you might be running multiple tmux servers at
|
|
||||||
the same time. Maybe you start the first tmux server with `$ tmux` and then
|
|
||||||
later another one with e.g. `$ tmux -S/tmp/foo`.
|
|
||||||
|
|
||||||
You probably don't want to "auto restore" the same environment in the second
|
|
||||||
tmux that uses `/tmp/foo` socket. You also probably don't want two tmux
|
|
||||||
environments both having "auto save" feature on (think about overwrites).
|
|
||||||
|
|
||||||
This plugin handles multi-server scenario by giving precedence to the tmux
|
|
||||||
server that was first started.
|
|
||||||
|
|
||||||
In the above example, the server started with `$ tmux` will do "auto
|
|
||||||
restore" (if enabled) and will start "auto saving".
|
|
||||||
"Auto restore" or "auto saving" **will not** happen for the second server that
|
|
||||||
was started later with the `$ tmux -S/tmp/foo` command. The plugin will
|
|
||||||
detect the presence of another server (`$ tmux`) and give it precedence.
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
# Systemd automatic start for tmux
|
|
||||||
|
|
||||||
The first time tmux starts when `@continuum-boot` is set to 'on' tmux-continuum will generate a user level systemd unit file which it will save to `${HOME}/.config/systemd/user/tmux.service` and enable it. From then on when that user logs in, either through a GUI session or on the console or via ssh, Systemd will start the tmux server.
|
|
||||||
|
|
||||||
The command used to start the tmux server is determined via the `@continuum-systemd-start-cmd` option that can be set in .tmux.conf. (Remember to reload your configuration with `tmux source ~/.tmux.conf` afterwards.
|
|
||||||
|
|
||||||
The default command to use is `new-session -d`. If you want more control over what sessions get started then you should set up your sessions in tmux.conf and set `@continuum-systemd-start-cmd = 'start-server'`. As this will be executed as part of systemd's ExecStart statement there will be no shell parsing. See [Systemd manual](http://www.freedesktop.org/software/systemd/man/systemd.service.html#Command%20lines) for more details.
|
|
||||||
|
|
||||||
To control the tmux service you can use all the standard `systemctl` commands using the `--user` argument. eg to see if the tmux server has started:
|
|
||||||
|
|
||||||
systemctl --user status tmux.service
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
VERSION="$1"
|
|
||||||
UNSUPPORTED_MSG="$2"
|
|
||||||
|
|
||||||
# this is used to get "clean" integer version number. Examples:
|
|
||||||
# `tmux 1.9` => `19`
|
|
||||||
# `1.9a` => `19`
|
|
||||||
get_digits_from_string() {
|
|
||||||
local string="$1"
|
|
||||||
local only_digits="$(echo "$string" | tr -dC '[:digit:]')"
|
|
||||||
echo "$only_digits"
|
|
||||||
}
|
|
||||||
|
|
||||||
tmux_version_int() {
|
|
||||||
local tmux_version_string=$(tmux -V)
|
|
||||||
echo "$(get_digits_from_string "$tmux_version_string")"
|
|
||||||
}
|
|
||||||
|
|
||||||
exit_if_unsupported_version() {
|
|
||||||
local current_version="$1"
|
|
||||||
local supported_version="$2"
|
|
||||||
if [ "$current_version" -lt "$supported_version" ]; then
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
main() {
|
|
||||||
local supported_version_int="$(get_digits_from_string "$VERSION")"
|
|
||||||
local current_version_int="$(tmux_version_int)"
|
|
||||||
exit_if_unsupported_version "$current_version_int" "$supported_version_int"
|
|
||||||
}
|
|
||||||
main
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
|
||||||
|
|
||||||
source "$CURRENT_DIR/helpers.sh"
|
|
||||||
source "$CURRENT_DIR/variables.sh"
|
|
||||||
|
|
||||||
auto_restore_enabled() {
|
|
||||||
local auto_restore_value="$(get_tmux_option "$auto_restore_option" "$auto_restore_default")"
|
|
||||||
[ "$auto_restore_value" == "on" ] && [ ! -f "$auto_restore_halt_file" ]
|
|
||||||
}
|
|
||||||
|
|
||||||
fetch_and_run_tmux_resurrect_restore_script() {
|
|
||||||
# give tmux some time to start and source all the plugins
|
|
||||||
sleep 1
|
|
||||||
local resurrect_restore_script_path="$(get_tmux_option "$resurrect_restore_path_option" "")"
|
|
||||||
if [ -n "$resurrect_restore_script_path" ]; then
|
|
||||||
"$resurrect_restore_script_path"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
main() {
|
|
||||||
# Advanced edge case handling: auto restore only if this is the only tmux
|
|
||||||
# server. If another tmux server exists, it is assumed auto-restore is not wanted.
|
|
||||||
if auto_restore_enabled && ! another_tmux_server_running_on_startup; then
|
|
||||||
fetch_and_run_tmux_resurrect_restore_script
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
main
|
|
||||||
@@ -1,60 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
|
||||||
|
|
||||||
source "$CURRENT_DIR/helpers.sh"
|
|
||||||
source "$CURRENT_DIR/variables.sh"
|
|
||||||
source "$CURRENT_DIR/shared.sh"
|
|
||||||
|
|
||||||
supported_tmux_version_ok() {
|
|
||||||
"$CURRENT_DIR/check_tmux_version.sh" "$SUPPORTED_VERSION"
|
|
||||||
}
|
|
||||||
|
|
||||||
get_interval() {
|
|
||||||
get_tmux_option "$auto_save_interval_option" "$auto_save_interval_default"
|
|
||||||
}
|
|
||||||
|
|
||||||
auto_save_not_disabled() {
|
|
||||||
[ "$(get_interval)" -gt 0 ]
|
|
||||||
}
|
|
||||||
|
|
||||||
enough_time_since_last_run_passed() {
|
|
||||||
local last_saved_timestamp="$(get_tmux_option "$last_auto_save_option" "0")"
|
|
||||||
local interval_minutes="$(get_interval)"
|
|
||||||
local interval_seconds="$((interval_minutes * 60))"
|
|
||||||
local next_run="$((last_saved_timestamp + $interval_seconds))"
|
|
||||||
[ "$(current_timestamp)" -ge "$next_run" ]
|
|
||||||
}
|
|
||||||
|
|
||||||
fetch_and_run_tmux_resurrect_save_script() {
|
|
||||||
local resurrect_save_script_path="$(get_tmux_option "$resurrect_save_path_option" "")"
|
|
||||||
if [ -n "$resurrect_save_script_path" ]; then
|
|
||||||
"$resurrect_save_script_path" "quiet" >/dev/null 2>&1 &
|
|
||||||
set_last_save_timestamp
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
acquire_lock() {
|
|
||||||
# Sometimes tmux starts multiple saves in parallel. We want only one
|
|
||||||
# save to be running, otherwise we can get corrupted saved state.
|
|
||||||
local lockdir_prefix="/tmp/tmux-continuum-$(current_tmux_server_pid)-lock-"
|
|
||||||
# The following implements a lock that auto-expires after 100...200s.
|
|
||||||
local lock_generation=$((`date +%s` / 100))
|
|
||||||
local lockdir1="${lockdir_prefix}${lock_generation}"
|
|
||||||
local lockdir2="${lockdir_prefix}$(($lock_generation + 1))"
|
|
||||||
if mkdir "$lockdir1"; then
|
|
||||||
trap "rmdir "$lockdir1"" EXIT
|
|
||||||
if mkdir "$lockdir2"; then
|
|
||||||
trap "rmdir "$lockdir1" "$lockdir2"" EXIT
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
return 1 # Someone else has the lock.
|
|
||||||
}
|
|
||||||
|
|
||||||
main() {
|
|
||||||
if supported_tmux_version_ok && auto_save_not_disabled && enough_time_since_last_run_passed && acquire_lock; then
|
|
||||||
fetch_and_run_tmux_resurrect_save_script
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
main
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
|
||||||
|
|
||||||
source "$CURRENT_DIR/helpers.sh"
|
|
||||||
source "$CURRENT_DIR/variables.sh"
|
|
||||||
|
|
||||||
print_status() {
|
|
||||||
local save_int="$(get_tmux_option "$auto_save_interval_option")"
|
|
||||||
local status=""
|
|
||||||
local style_wrap
|
|
||||||
if [ $save_int -gt 0 ]; then
|
|
||||||
style_wrap="$(get_tmux_option "$status_on_style_wrap_option" "")"
|
|
||||||
status="$save_int"
|
|
||||||
else
|
|
||||||
style_wrap="$(get_tmux_option "$status_off_style_wrap_option" "")"
|
|
||||||
status="off"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -n "$style_wrap" ]; then
|
|
||||||
status="${style_wrap/$status_wrap_string/$status}"
|
|
||||||
fi
|
|
||||||
echo "$status"
|
|
||||||
}
|
|
||||||
print_status
|
|
||||||
@@ -1,36 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
|
||||||
|
|
||||||
source "$CURRENT_DIR/helpers.sh"
|
|
||||||
source "$CURRENT_DIR/variables.sh"
|
|
||||||
|
|
||||||
is_tmux_automatic_start_enabled() {
|
|
||||||
local auto_start_value="$(get_tmux_option "$auto_start_option" "$auto_start_default")"
|
|
||||||
[ "$auto_start_value" == "on" ]
|
|
||||||
}
|
|
||||||
|
|
||||||
is_osx() {
|
|
||||||
[ $(uname) == "Darwin" ]
|
|
||||||
}
|
|
||||||
|
|
||||||
is_systemd() {
|
|
||||||
[ $(ps -o comm= -p1) == 'systemd' ]
|
|
||||||
}
|
|
||||||
|
|
||||||
main() {
|
|
||||||
if is_tmux_automatic_start_enabled; then
|
|
||||||
if is_osx; then
|
|
||||||
"$CURRENT_DIR/handle_tmux_automatic_start/osx_enable.sh"
|
|
||||||
elif is_systemd; then
|
|
||||||
"$CURRENT_DIR/handle_tmux_automatic_start/systemd_enable.sh"
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
if is_osx; then
|
|
||||||
"$CURRENT_DIR/handle_tmux_automatic_start/osx_disable.sh"
|
|
||||||
elif is_systemd; then
|
|
||||||
"$CURRENT_DIR/handle_tmux_automatic_start/systemd_disable.sh"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
main
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
../../docs/automatic_start.md
|
|
||||||
@@ -1,68 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
# for "true full screen" call the script with "fullscreen" as the first argument
|
|
||||||
TRUE_FULL_SCREEN="$1"
|
|
||||||
|
|
||||||
start_terminal_and_run_tmux() {
|
|
||||||
osascript <<-EOF
|
|
||||||
tell application "alacritty"
|
|
||||||
activate
|
|
||||||
delay 0.5
|
|
||||||
tell application "System Events" to tell process "alacritty"
|
|
||||||
set frontmost to true
|
|
||||||
keystroke "tmux"
|
|
||||||
key code 36
|
|
||||||
end tell
|
|
||||||
end tell
|
|
||||||
EOF
|
|
||||||
}
|
|
||||||
|
|
||||||
resize_window_to_full_screen() {
|
|
||||||
osascript <<-EOF
|
|
||||||
tell application "alacritty"
|
|
||||||
activate
|
|
||||||
tell application "System Events"
|
|
||||||
if (every window of process "alacritty") is {} then
|
|
||||||
keystroke "n" using command down
|
|
||||||
end if
|
|
||||||
|
|
||||||
tell application "Finder"
|
|
||||||
set desktopSize to bounds of window of desktop
|
|
||||||
end tell
|
|
||||||
|
|
||||||
set position of front window of process "alacritty" to {0, 0}
|
|
||||||
set size of front window of process "alacritty" to {item 3 of desktopSize, item 4 of desktopSize}
|
|
||||||
end tell
|
|
||||||
end tell
|
|
||||||
EOF
|
|
||||||
}
|
|
||||||
|
|
||||||
resize_to_true_full_screen() {
|
|
||||||
osascript <<-EOF
|
|
||||||
tell application "Alacritty"
|
|
||||||
activate
|
|
||||||
delay 0.5
|
|
||||||
tell application "System Events" to tell process "Alacritty"
|
|
||||||
if front window exists then
|
|
||||||
tell front window
|
|
||||||
if value of attribute "AXFullScreen" then
|
|
||||||
set value of attribute "AXFullScreen" to false
|
|
||||||
else
|
|
||||||
set value of attribute "AXFullScreen" to true
|
|
||||||
end if
|
|
||||||
end tell
|
|
||||||
end if
|
|
||||||
end tell
|
|
||||||
end tell
|
|
||||||
EOF
|
|
||||||
}
|
|
||||||
|
|
||||||
main() {
|
|
||||||
start_terminal_and_run_tmux
|
|
||||||
if [ "$TRUE_FULL_SCREEN" == "fullscreen" ]; then
|
|
||||||
resize_to_true_full_screen
|
|
||||||
else
|
|
||||||
resize_window_to_full_screen
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
main
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
|
||||||
|
|
||||||
source "$CURRENT_DIR/../variables.sh"
|
|
||||||
|
|
||||||
main() {
|
|
||||||
rm "$osx_auto_start_file_path" > /dev/null 2>&1
|
|
||||||
}
|
|
||||||
main
|
|
||||||
@@ -1,72 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
|
||||||
|
|
||||||
source "$CURRENT_DIR/../helpers.sh"
|
|
||||||
source "$CURRENT_DIR/../variables.sh"
|
|
||||||
|
|
||||||
template() {
|
|
||||||
local tmux_start_script="$1"
|
|
||||||
local is_fullscreen="$2"
|
|
||||||
|
|
||||||
local fullscreen_tag=""
|
|
||||||
if [ "$is_fullscreen" == "true" ]; then
|
|
||||||
# newline and spacing so tag is aligned with other tags in template
|
|
||||||
fullscreen_tag=$'\n <string>fullscreen</string>'
|
|
||||||
fi
|
|
||||||
|
|
||||||
local content
|
|
||||||
read -r -d '' content <<-EOF
|
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
||||||
<plist version="1.0">
|
|
||||||
<dict>
|
|
||||||
<key>Label</key>
|
|
||||||
<string>${osx_auto_start_file_name}</string>
|
|
||||||
<key>ProgramArguments</key>
|
|
||||||
<array>
|
|
||||||
<string>${tmux_start_script}</string>$fullscreen_tag
|
|
||||||
</array>
|
|
||||||
<key>RunAtLoad</key>
|
|
||||||
<true/>
|
|
||||||
</dict>
|
|
||||||
</plist>
|
|
||||||
EOF
|
|
||||||
echo "$content"
|
|
||||||
}
|
|
||||||
|
|
||||||
get_strategy() {
|
|
||||||
local options="$1"
|
|
||||||
if [[ "$options" =~ "iterm" ]]; then
|
|
||||||
echo "iterm"
|
|
||||||
elif [[ "$options" =~ "kitty" ]]; then
|
|
||||||
echo "kitty"
|
|
||||||
elif [[ "$options" =~ "alacritty" ]]; then
|
|
||||||
echo "alacritty"
|
|
||||||
else
|
|
||||||
# Terminal.app is the default console app
|
|
||||||
echo "terminal"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
get_fullscreen_option_value() {
|
|
||||||
local options="$1"
|
|
||||||
if [[ "$options" =~ "fullscreen" ]]; then
|
|
||||||
echo "true"
|
|
||||||
else
|
|
||||||
echo "false"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
main() {
|
|
||||||
local options="$(get_tmux_option "$auto_start_config_option" "$auto_start_config_default")"
|
|
||||||
local strategy="$(get_strategy "$options")"
|
|
||||||
local fullscreen_option_value="$(get_fullscreen_option_value "$options")"
|
|
||||||
local tmux_start_script_path="${CURRENT_DIR}/osx_${strategy}_start_tmux.sh"
|
|
||||||
|
|
||||||
local launchd_plist_file_content="$(template "$tmux_start_script_path" "$fullscreen_option_value")"
|
|
||||||
if ! diff "$osx_auto_start_file_path" <(echo "$launchd_plist_file_content") &>/dev/null ; then
|
|
||||||
echo "$launchd_plist_file_content" > "$osx_auto_start_file_path"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
main
|
|
||||||
@@ -1,66 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
# for "true full screen" call the script with "fullscreen" as the first argument
|
|
||||||
TRUE_FULL_SCREEN="$1"
|
|
||||||
|
|
||||||
start_iterm_and_run_tmux() {
|
|
||||||
osascript <<-EOF
|
|
||||||
tell application "iTerm"
|
|
||||||
activate
|
|
||||||
|
|
||||||
# open iterm window
|
|
||||||
try
|
|
||||||
set _session to current session of current window
|
|
||||||
on error
|
|
||||||
set _term to (make new terminal)
|
|
||||||
tell _term
|
|
||||||
launch session "Tmux"
|
|
||||||
set _session to current session
|
|
||||||
end tell
|
|
||||||
end try
|
|
||||||
|
|
||||||
# start tmux
|
|
||||||
tell _session
|
|
||||||
write text "tmux"
|
|
||||||
end tell
|
|
||||||
end tell
|
|
||||||
EOF
|
|
||||||
}
|
|
||||||
|
|
||||||
resize_window_to_full_screen() {
|
|
||||||
osascript <<-EOF
|
|
||||||
tell application "iTerm"
|
|
||||||
set winID to id of window 1
|
|
||||||
tell application "Finder"
|
|
||||||
set desktopSize to bounds of window of desktop
|
|
||||||
end tell
|
|
||||||
set bounds of window id winID to desktopSize
|
|
||||||
end tell
|
|
||||||
EOF
|
|
||||||
}
|
|
||||||
|
|
||||||
resize_to_true_full_screen() {
|
|
||||||
osascript <<-EOF
|
|
||||||
tell application "iTerm"
|
|
||||||
# wait for iTerm to start
|
|
||||||
delay 1
|
|
||||||
activate
|
|
||||||
# short wait for iTerm to gain focus
|
|
||||||
delay 0.1
|
|
||||||
# Command + Enter for fullscreen
|
|
||||||
tell application "System Events"
|
|
||||||
key code 36 using {command down}
|
|
||||||
end tell
|
|
||||||
end tell
|
|
||||||
EOF
|
|
||||||
}
|
|
||||||
|
|
||||||
main() {
|
|
||||||
start_iterm_and_run_tmux
|
|
||||||
if [ "$TRUE_FULL_SCREEN" == "fullscreen" ]; then
|
|
||||||
resize_to_true_full_screen
|
|
||||||
else
|
|
||||||
resize_window_to_full_screen
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
main
|
|
||||||
@@ -1,60 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
# for "true full screen" call the script with "fullscreen" as the first argument
|
|
||||||
TRUE_FULL_SCREEN="$1"
|
|
||||||
|
|
||||||
start_terminal_and_run_tmux() {
|
|
||||||
osascript <<-EOF
|
|
||||||
tell application "kitty"
|
|
||||||
activate
|
|
||||||
delay 5
|
|
||||||
tell application "System Events" to tell process "kitty"
|
|
||||||
set frontmost to true
|
|
||||||
keystroke "tmux"
|
|
||||||
key code 36
|
|
||||||
end tell
|
|
||||||
end tell
|
|
||||||
EOF
|
|
||||||
}
|
|
||||||
|
|
||||||
resize_window_to_full_screen() {
|
|
||||||
osascript <<-EOF
|
|
||||||
tell application "kitty"
|
|
||||||
activate
|
|
||||||
tell application "System Events"
|
|
||||||
if (every window of process "kitty") is {} then
|
|
||||||
keystroke "n" using command down
|
|
||||||
end if
|
|
||||||
|
|
||||||
tell application "Finder"
|
|
||||||
set desktopSize to bounds of window of desktop
|
|
||||||
end tell
|
|
||||||
|
|
||||||
set position of front window of process "kitty" to {0, 0}
|
|
||||||
set size of front window of process "kitty" to {item 3 of desktopSize, item 4 of desktopSize}
|
|
||||||
end tell
|
|
||||||
end tell
|
|
||||||
EOF
|
|
||||||
}
|
|
||||||
|
|
||||||
resize_to_true_full_screen() {
|
|
||||||
osascript <<-EOF
|
|
||||||
tell application "kitty"
|
|
||||||
activate
|
|
||||||
delay 1
|
|
||||||
tell application "System Events" to tell process "kitty"
|
|
||||||
keystroke "f" using {control down, command down}
|
|
||||||
end tell
|
|
||||||
end tell
|
|
||||||
EOF
|
|
||||||
}
|
|
||||||
|
|
||||||
main() {
|
|
||||||
start_terminal_and_run_tmux
|
|
||||||
if [ "$TRUE_FULL_SCREEN" == "fullscreen" ]; then
|
|
||||||
resize_to_true_full_screen
|
|
||||||
else
|
|
||||||
resize_window_to_full_screen
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
main
|
|
||||||
@@ -1,52 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
# for "true full screen" call the script with "fullscreen" as the first argument
|
|
||||||
TRUE_FULL_SCREEN="$1"
|
|
||||||
|
|
||||||
start_terminal_and_run_tmux() {
|
|
||||||
osascript <<-EOF
|
|
||||||
tell application "Terminal"
|
|
||||||
if not (exists window 1) then reopen
|
|
||||||
activate
|
|
||||||
set winID to id of window 1
|
|
||||||
do script "tmux" in window id winID
|
|
||||||
end tell
|
|
||||||
EOF
|
|
||||||
}
|
|
||||||
|
|
||||||
resize_window_to_full_screen() {
|
|
||||||
osascript <<-EOF
|
|
||||||
tell application "Terminal"
|
|
||||||
set winID to id of window 1
|
|
||||||
tell application "Finder"
|
|
||||||
set desktopSize to bounds of window of desktop
|
|
||||||
end tell
|
|
||||||
set bounds of window id winID to desktopSize
|
|
||||||
end tell
|
|
||||||
EOF
|
|
||||||
}
|
|
||||||
|
|
||||||
resize_to_true_full_screen() {
|
|
||||||
osascript <<-EOF
|
|
||||||
tell application "Terminal"
|
|
||||||
# waiting for Terminal.app to start
|
|
||||||
delay 1
|
|
||||||
activate
|
|
||||||
# short wait for Terminal to gain focus
|
|
||||||
delay 0.1
|
|
||||||
tell application "System Events"
|
|
||||||
keystroke "f" using {control down, command down}
|
|
||||||
end tell
|
|
||||||
end tell
|
|
||||||
EOF
|
|
||||||
}
|
|
||||||
|
|
||||||
main() {
|
|
||||||
start_terminal_and_run_tmux
|
|
||||||
if [ "$TRUE_FULL_SCREEN" == "fullscreen" ]; then
|
|
||||||
resize_to_true_full_screen
|
|
||||||
else
|
|
||||||
resize_window_to_full_screen
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
main
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
# Maintainer: Sven Vowe @nuclearglow
|
|
||||||
# Contact maintainer for any change to this file.
|
|
||||||
|
|
||||||
CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
|
||||||
|
|
||||||
source "$CURRENT_DIR/../variables.sh"
|
|
||||||
|
|
||||||
main() {
|
|
||||||
systemctl --user disable ${systemd_service_name}
|
|
||||||
}
|
|
||||||
main
|
|
||||||
@@ -1,78 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
# Maintainer: Sven Vowe @nuclearglow
|
|
||||||
# Contact maintainer for any change to this file.
|
|
||||||
|
|
||||||
CURRENT_DIR="$( dirname ${BASH_SOURCE[0]} )"
|
|
||||||
|
|
||||||
source "$CURRENT_DIR/../helpers.sh"
|
|
||||||
source "$CURRENT_DIR/../variables.sh"
|
|
||||||
|
|
||||||
template() {
|
|
||||||
local tmux_start_script="$1"
|
|
||||||
shift
|
|
||||||
local options="$@"
|
|
||||||
local content=""
|
|
||||||
local resurrect_save_script_path="$(get_tmux_option "$resurrect_save_path_option" "$(realpath ${CURRENT_DIR}/../../../tmux-resurrect/scripts/save.sh)")"
|
|
||||||
local tmux_path="$(command -v tmux)"
|
|
||||||
|
|
||||||
read -r -d '' content <<-EOF
|
|
||||||
[Unit]
|
|
||||||
Description=tmux default session (detached)
|
|
||||||
Documentation=man:tmux(1)
|
|
||||||
|
|
||||||
[Service]
|
|
||||||
Type=forking
|
|
||||||
Environment=DISPLAY=:0
|
|
||||||
ExecStart=${tmux_path} ${systemd_tmux_server_start_cmd}
|
|
||||||
|
|
||||||
ExecStop=${resurrect_save_script_path}
|
|
||||||
ExecStop=${tmux_path} kill-server
|
|
||||||
KillMode=control-group
|
|
||||||
|
|
||||||
RestartSec=2
|
|
||||||
|
|
||||||
[Install]
|
|
||||||
WantedBy=default.target
|
|
||||||
EOF
|
|
||||||
|
|
||||||
echo "$content"
|
|
||||||
}
|
|
||||||
|
|
||||||
systemd_tmux_is_enabled() {
|
|
||||||
systemctl --user is-enabled $(basename "${systemd_unit_file_path}") >/dev/null 2>&1
|
|
||||||
}
|
|
||||||
|
|
||||||
enable_tmux_unit_on_boot() {
|
|
||||||
if ! systemd_tmux_is_enabled; then
|
|
||||||
systemctl --user enable ${systemd_service_name}
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
systemd_unit_file() {
|
|
||||||
local options="$(get_tmux_option "$auto_start_config_option" "${auto_start_config_default}")"
|
|
||||||
local systemd_tmux_server_start_cmd="$(get_tmux_option "${systemd_tmux_server_start_cmd_option}" "${systemd_tmux_server_start_cmd_default}" )"
|
|
||||||
local tmux_start_script_path="${CURRENT_DIR}/linux_start_tmux.sh"
|
|
||||||
local systemd_unit_file=$(template "${tmux_start_script_path}" "${options}")
|
|
||||||
echo "$systemd_unit_file"
|
|
||||||
}
|
|
||||||
|
|
||||||
write_unit_file() {
|
|
||||||
systemd_unit_file > "${systemd_unit_file_path}"
|
|
||||||
}
|
|
||||||
|
|
||||||
write_unit_file_unless_exists() {
|
|
||||||
local systemd_unit_file_dir=$(dirname ${systemd_unit_file_path})
|
|
||||||
if ! [ -d $systemd_unit_file_dir ]; then
|
|
||||||
mkdir -p $systemd_unit_file_dir
|
|
||||||
write_unit_file
|
|
||||||
elif ! [ -e "${systemd_unit_file_path}" ]; then
|
|
||||||
write_unit_file
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
main() {
|
|
||||||
write_unit_file_unless_exists
|
|
||||||
enable_tmux_unit_on_boot
|
|
||||||
}
|
|
||||||
main
|
|
||||||
@@ -1,49 +0,0 @@
|
|||||||
get_tmux_option() {
|
|
||||||
local option="$1"
|
|
||||||
local default_value="$2"
|
|
||||||
local option_value=$(tmux show-option -gqv "$option")
|
|
||||||
if [ -z "$option_value" ]; then
|
|
||||||
echo "$default_value"
|
|
||||||
else
|
|
||||||
echo "$option_value"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
set_tmux_option() {
|
|
||||||
local option="$1"
|
|
||||||
local value="$2"
|
|
||||||
tmux set-option -gq "$option" "$value"
|
|
||||||
}
|
|
||||||
|
|
||||||
# multiple tmux server detection helpers
|
|
||||||
|
|
||||||
current_tmux_server_pid() {
|
|
||||||
echo "$TMUX" |
|
|
||||||
cut -f2 -d","
|
|
||||||
}
|
|
||||||
|
|
||||||
all_tmux_processes() {
|
|
||||||
# ignores `tmux source-file .tmux.conf` command used to reload tmux.conf
|
|
||||||
local user_id=$(id -u)
|
|
||||||
ps -u $user_id -o "command pid" |
|
|
||||||
\grep "^tmux" |
|
|
||||||
\grep -v "^tmux source"
|
|
||||||
}
|
|
||||||
|
|
||||||
number_tmux_processes_except_current_server() {
|
|
||||||
all_tmux_processes |
|
|
||||||
\grep -v " $(current_tmux_server_pid)$" |
|
|
||||||
wc -l |
|
|
||||||
sed "s/ //g"
|
|
||||||
}
|
|
||||||
|
|
||||||
number_current_server_client_processes() {
|
|
||||||
tmux list-clients |
|
|
||||||
wc -l |
|
|
||||||
sed "s/ //g"
|
|
||||||
}
|
|
||||||
|
|
||||||
another_tmux_server_running_on_startup() {
|
|
||||||
# there are 2 tmux processes (current tmux server + 1) on tmux startup
|
|
||||||
[ "$(number_tmux_processes_except_current_server)" -gt 1 ]
|
|
||||||
}
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
current_timestamp() {
|
|
||||||
echo "$(date +%s)"
|
|
||||||
}
|
|
||||||
|
|
||||||
set_last_save_timestamp() {
|
|
||||||
set_tmux_option "$last_auto_save_option" "$(current_timestamp)"
|
|
||||||
}
|
|
||||||
@@ -1,43 +0,0 @@
|
|||||||
SUPPORTED_VERSION="1.9"
|
|
||||||
|
|
||||||
# these tmux options contain paths to tmux resurrect save and restore scripts
|
|
||||||
resurrect_save_path_option="@resurrect-save-script-path"
|
|
||||||
resurrect_restore_path_option="@resurrect-restore-script-path"
|
|
||||||
|
|
||||||
auto_save_interval_option="@continuum-save-interval"
|
|
||||||
auto_save_interval_default="15"
|
|
||||||
|
|
||||||
# time when the tmux environment was last saved (unix timestamp)
|
|
||||||
last_auto_save_option="@continuum-save-last-timestamp"
|
|
||||||
|
|
||||||
auto_restore_option="@continuum-restore"
|
|
||||||
auto_restore_default="off"
|
|
||||||
|
|
||||||
auto_restore_halt_file="${HOME}/tmux_no_auto_restore"
|
|
||||||
|
|
||||||
auto_restore_max_delay_option="@continuum-restore-max-delay"
|
|
||||||
auto_restore_max_delay_default="10"
|
|
||||||
|
|
||||||
# tmux auto start options
|
|
||||||
auto_start_option="@continuum-boot"
|
|
||||||
auto_start_default="off"
|
|
||||||
|
|
||||||
# comma separated list of additional options for tmux auto start
|
|
||||||
auto_start_config_option="@continuum-boot-options"
|
|
||||||
auto_start_config_default=""
|
|
||||||
|
|
||||||
osx_auto_start_file_name="Tmux.Start.plist"
|
|
||||||
osx_auto_start_file_path="${HOME}/Library/LaunchAgents/${osx_auto_start_file_name}"
|
|
||||||
|
|
||||||
status_interpolation_string="\#{continuum_status}"
|
|
||||||
status_script="#($CURRENT_DIR/scripts/continuum_status.sh)"
|
|
||||||
# below options set style/color for #{continuum_status} interpolation
|
|
||||||
status_on_style_wrap_option="@continuum-status-on-wrap-style" # example value: "#[fg=green]#{value}#[fg=white]"
|
|
||||||
status_off_style_wrap_option="@continuum-status-off-wrap-style" # example value: "#[fg=yellow,bold]#{value}#[fg=white,nobold]"
|
|
||||||
status_wrap_string="\#{value}"
|
|
||||||
|
|
||||||
systemd_service_name="tmux.service"
|
|
||||||
systemd_unit_file_path="$HOME/.config/systemd/user/${systemd_service_name}"
|
|
||||||
|
|
||||||
systemd_tmux_server_start_cmd_option="@continuum-systemd-start-cmd"
|
|
||||||
systemd_tmux_server_start_cmd_default="new-session -d"
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
MIT License
|
|
||||||
|
|
||||||
Copyright (c) 2019-2021 Seong Yong-ju
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
|
||||||
copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
SOFTWARE.
|
|
||||||
@@ -1,79 +0,0 @@
|
|||||||
# tmux-project
|
|
||||||
|
|
||||||
Search projects and open them in a new session.
|
|
||||||
|
|
||||||
## Prequisites
|
|
||||||
|
|
||||||
- find
|
|
||||||
- [fzf](https://github.com/junegunn/fzf) (needs `fzf-tmux` to be installed)
|
|
||||||
|
|
||||||
## Install
|
|
||||||
|
|
||||||
### Installation with [tpm](https://github.com/tmux-plugins/tpm) (recommended)
|
|
||||||
|
|
||||||
Add the following line to your `.tmux.conf`.
|
|
||||||
|
|
||||||
```tmux
|
|
||||||
set -g @plugin 'sei40kr/tmux-project'
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
It is also recommended to add the following line to your `.tmux.conf` to prevent
|
|
||||||
a client from being detached when the active session is destroyed.
|
|
||||||
|
|
||||||
```tmux
|
|
||||||
set detach-on-destroy no-detached
|
|
||||||
```
|
|
||||||
|
|
||||||
## Customization
|
|
||||||
|
|
||||||
| Variable | Default value | Description |
|
|
||||||
| :------------------------------ | :-------------------- | :-------------------------------------------------------------------------------- |
|
|
||||||
| `@project-key` | `"g"` | The key to invoke the project search. If you set it to `""`, the key is disabled. |
|
|
||||||
| `@project-base-dirs` | `""` | A comma-separated list of directories and their depths to search for projects. |
|
|
||||||
| `@project-rooters` | `".git"` | A comma-separated list of rooters. |
|
|
||||||
| `@project-fzf-tmux-layout-opts` | `""` | The layout options for fzf-tmux. See `fzf-tmux(1)` for details. |
|
|
||||||
| `@project-fzf-opts` | `"--preview 'ls {}'"` | The options for fzf. See `fzf(1)` for details. |
|
|
||||||
|
|
||||||
### Setting `@project-base-dirs`
|
|
||||||
|
|
||||||
`@project-base-dirs` is a comma-separated list of directories and their depths to search for projects.
|
|
||||||
|
|
||||||
Each element of the list is in the following format:
|
|
||||||
|
|
||||||
```
|
|
||||||
/path/to/dir[:<min depth>[:<max depth>]]
|
|
||||||
```
|
|
||||||
|
|
||||||
- If you omit `<min depth>` and `<max depth>`, they are set to `0` and `0` respectively.
|
|
||||||
- If you omit `<max depth>`, it is set to `<min depth>`. (means `<min depth>` is the exact depth)
|
|
||||||
|
|
||||||
If you omit the depth or explicitly set it to `0`, the directory itself will be
|
|
||||||
added as a project. In that case, you can add the directory as a project even if
|
|
||||||
it contains no rooter.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
For example, if you want to search for ghq repositories as projects:
|
|
||||||
|
|
||||||
```tmux
|
|
||||||
set -ag @project-base-dirs ,"${GHQ_ROOT}:3"
|
|
||||||
```
|
|
||||||
|
|
||||||
For example, if you want to add `~/.vim` itself as a project:
|
|
||||||
|
|
||||||
```tmux
|
|
||||||
set -ag @project-base-dirs ,"${HOME}/.vim"
|
|
||||||
```
|
|
||||||
|
|
||||||
## tmuxinator Integration
|
|
||||||
|
|
||||||
tmux-project can be integrated with [tmuxinator](https://github.com/tmuxinator/tmuxinator).
|
|
||||||
When you have tmuxinator installed and the selected project has
|
|
||||||
`.tmuxinator.yml` at the root, tmux-project will start a new session with
|
|
||||||
tmuxinator.
|
|
||||||
|
|
||||||
## License
|
|
||||||
|
|
||||||
MIT
|
|
||||||
@@ -1,61 +0,0 @@
|
|||||||
{
|
|
||||||
"nodes": {
|
|
||||||
"flake-utils": {
|
|
||||||
"inputs": {
|
|
||||||
"systems": "systems"
|
|
||||||
},
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1681202837,
|
|
||||||
"narHash": "sha256-H+Rh19JDwRtpVPAWp64F+rlEtxUWBAQW28eAi3SRSzg=",
|
|
||||||
"owner": "numtide",
|
|
||||||
"repo": "flake-utils",
|
|
||||||
"rev": "cfacdce06f30d2b68473a46042957675eebb3401",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "numtide",
|
|
||||||
"repo": "flake-utils",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"nixpkgs": {
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1683014792,
|
|
||||||
"narHash": "sha256-6Va9iVtmmsw4raBc3QKvQT2KT/NGRWlvUlJj46zN8B8=",
|
|
||||||
"owner": "NixOS",
|
|
||||||
"repo": "nixpkgs",
|
|
||||||
"rev": "1a411f23ba299db155a5b45d5e145b85a7aafc42",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "NixOS",
|
|
||||||
"ref": "nixos-unstable",
|
|
||||||
"repo": "nixpkgs",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"root": {
|
|
||||||
"inputs": {
|
|
||||||
"flake-utils": "flake-utils",
|
|
||||||
"nixpkgs": "nixpkgs"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"systems": {
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1681028828,
|
|
||||||
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
|
||||||
"owner": "nix-systems",
|
|
||||||
"repo": "default",
|
|
||||||
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "nix-systems",
|
|
||||||
"repo": "default",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"root": "root",
|
|
||||||
"version": 7
|
|
||||||
}
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
{
|
|
||||||
description = "A very basic flake";
|
|
||||||
|
|
||||||
inputs = {
|
|
||||||
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
|
|
||||||
flake-utils.url = "github:numtide/flake-utils";
|
|
||||||
};
|
|
||||||
|
|
||||||
outputs = { self, flake-utils, nixpkgs }: flake-utils.lib.eachDefaultSystem (system:
|
|
||||||
let
|
|
||||||
pkgs = import nixpkgs { inherit system; };
|
|
||||||
in
|
|
||||||
{
|
|
||||||
packages.default = pkgs.callPackage ./packages/default.nix { };
|
|
||||||
|
|
||||||
devShells.default =
|
|
||||||
let
|
|
||||||
tmux_conf = pkgs.writeText "tmux.conf" ''
|
|
||||||
run-shell ${self.packages.${system}.default.rtp}/project.tmux
|
|
||||||
'';
|
|
||||||
in
|
|
||||||
pkgs.mkShell {
|
|
||||||
buildInputs = with pkgs; [ tmux fzf ];
|
|
||||||
shellHook = ''
|
|
||||||
TMUX= TMUX_TMPDIR= exec tmux -f ${tmux_conf}
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
get_tmux_option() {
|
|
||||||
local option=$1
|
|
||||||
local default_value=$2
|
|
||||||
local option_value
|
|
||||||
|
|
||||||
option_value=$(tmux show -gqv "$option")
|
|
||||||
echo "${option_value:-$default_value}"
|
|
||||||
}
|
|
||||||
@@ -1,98 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
basedir="$(cd "$(dirname "$0")/.." && pwd)"
|
|
||||||
# shellcheck source=../lib/tmux.bash
|
|
||||||
. "$basedir/lib/tmux.bash"
|
|
||||||
|
|
||||||
find_projects() {
|
|
||||||
local -a base_dirs rooters rooter_opts
|
|
||||||
|
|
||||||
IFS=',' read -ra base_dirs < <(get_tmux_option '@project-base-dirs')
|
|
||||||
IFS=',' read -ra rooters < <(get_tmux_option '@project-rooters' '.git')
|
|
||||||
|
|
||||||
for rooter in "${rooters[@]}"; do
|
|
||||||
rooter_opts+=("-o" "-name" "$rooter")
|
|
||||||
done
|
|
||||||
rooter_opts=('(' "${rooter_opts[@]:1}" ')')
|
|
||||||
|
|
||||||
for base_dir in "${base_dirs[@]}"; do
|
|
||||||
# If the base_dir is empty, skip it
|
|
||||||
if [[ -z "$base_dir" ]]; then
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
|
|
||||||
local -a tmp
|
|
||||||
IFS=':' read -ra tmp <<<"$base_dir"
|
|
||||||
path="${tmp[0]}"
|
|
||||||
min_depth="${tmp[1]:-0}"
|
|
||||||
max_depth="${tmp[2]:-${min_depth}}"
|
|
||||||
|
|
||||||
if [[ min_depth -eq 0 && max_depth -eq 0 ]]; then
|
|
||||||
# If min_depth and max_depth are both 0, that means we
|
|
||||||
# want to add the base_dir itself as a project.
|
|
||||||
# In that case, add the base_dir as a project even if it
|
|
||||||
# contains no rooter.
|
|
||||||
if [[ -d "$path" || -L "$path" ]]; then
|
|
||||||
echo "$path"
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
find "$path" -mindepth "$((min_depth + 1))" \
|
|
||||||
-maxdepth "$((max_depth + 1))" \
|
|
||||||
"${rooter_opts[@]}" \
|
|
||||||
-printf '%h\n'
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
}
|
|
||||||
|
|
||||||
# Convert a path to a session name. The session name is the last component of
|
|
||||||
# the path. Dots are replaced with underscores. If the path starts with a dot,
|
|
||||||
# the dot is removed.
|
|
||||||
# e.g. /home/username/.emacs.d -> emacs_d
|
|
||||||
to_session_name() {
|
|
||||||
local session_name="$1"
|
|
||||||
|
|
||||||
session_name="${session_name##*/}"
|
|
||||||
|
|
||||||
# Dots are not allowed in a tmux session name
|
|
||||||
# e.g. .emacs.d -> _emacs_d
|
|
||||||
session_name="${session_name//./_}"
|
|
||||||
# If the path starts with a slash (a dot), remove it
|
|
||||||
# e.g. .emacs.d -> _emacs_d -> emacs_d
|
|
||||||
session_name="${session_name#_}"
|
|
||||||
|
|
||||||
echo "$session_name"
|
|
||||||
}
|
|
||||||
|
|
||||||
main() {
|
|
||||||
local fzf_opts fzf_tmux_layout_opts selected_path session_name
|
|
||||||
|
|
||||||
# shellcheck disable=SC2207
|
|
||||||
fzf_opts="$(get_tmux_option "@project-fzf-opts" "--preview 'ls {}'")"
|
|
||||||
# shellcheck disable=SC2207
|
|
||||||
fzf_tmux_layout_opts="$(get_tmux_option "@project-fzf-tmux-layout-opts")"
|
|
||||||
|
|
||||||
selected_path="$(find_projects | eval "fzf-tmux ${fzf_tmux_layout_opts} -- ${fzf_opts}")"
|
|
||||||
if [[ -z "$selected_path" ]]; then
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
# If the selected project has .tmuxinator.yml file, use tmuxinator to
|
|
||||||
# start the session.
|
|
||||||
if command -v tmuxinator &>/dev/null && [[ -f "${selected_path}/.tmuxinator.yml" ]]; then
|
|
||||||
tmuxinator start -p "${selected_path}/.tmuxinator.yml"
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
session_name="$(to_session_name "$selected_path")"
|
|
||||||
|
|
||||||
# If the session already exists, attach to it. Otherwise, create a new
|
|
||||||
# session and attach to it.
|
|
||||||
if ! tmux has-session -t "$session_name" 2>/dev/null; then
|
|
||||||
# Return 0 even if creating the session fails.
|
|
||||||
tmux new-session -d -s "$session_name" -c "$selected_path" \; \
|
|
||||||
set -t "$session_name" destroy-unattached off || :
|
|
||||||
fi
|
|
||||||
tmux switch-client -t "$session_name"
|
|
||||||
}
|
|
||||||
|
|
||||||
main "$@"
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
{ lib, tmuxPlugins }:
|
|
||||||
|
|
||||||
tmuxPlugins.mkTmuxPlugin {
|
|
||||||
pluginName = "project";
|
|
||||||
version = "unstable-2023-05-04";
|
|
||||||
src = ../.;
|
|
||||||
meta = with lib; {
|
|
||||||
license = licenses.mit;
|
|
||||||
platforms = platforms.unix;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
basedir="$(cd "$(dirname "$0")" && pwd)"
|
|
||||||
# shellcheck source=lib/tmux.bash
|
|
||||||
. "${basedir}/lib/tmux.bash"
|
|
||||||
|
|
||||||
key="$(get_tmux_option '@project-key' 'g')"
|
|
||||||
if [[ -n "$key" ]]; then
|
|
||||||
tmux bind-key "$key" run-shell -b "${basedir}/libexec/switch-project.bash"
|
|
||||||
fi
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
# Force text files to have unix eols, so Windows/Cygwin does not break them
|
|
||||||
*.* eol=lf
|
|
||||||
|
|
||||||
# Except for images because then on checkout the files have been altered.
|
|
||||||
*.png binary
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
run_tests
|
|
||||||
tests/run_tests_in_isolation
|
|
||||||
tests/helpers/helpers.sh
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
[submodule "lib/tmux-test"]
|
|
||||||
path = lib/tmux-test
|
|
||||||
url = https://github.com/tmux-plugins/tmux-test.git
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
# generic packages and tmux
|
|
||||||
before_install:
|
|
||||||
- sudo apt-get update
|
|
||||||
- sudo apt-get install -y git-core expect
|
|
||||||
- sudo apt-get install -y python-software-properties software-properties-common
|
|
||||||
- sudo apt-get install -y libevent-dev libncurses-dev
|
|
||||||
- git clone https://github.com/tmux/tmux.git
|
|
||||||
- cd tmux
|
|
||||||
- git checkout 2.5
|
|
||||||
- sh autogen.sh
|
|
||||||
- ./configure && make && sudo make install
|
|
||||||
|
|
||||||
install:
|
|
||||||
- git fetch --unshallow --recurse-submodules || git fetch --recurse-submodules
|
|
||||||
# manual `git clone` required for testing `tmux-test` plugin itself
|
|
||||||
- git clone https://github.com/tmux-plugins/tmux-test lib/tmux-test; true
|
|
||||||
- lib/tmux-test/setup
|
|
||||||
|
|
||||||
script: ./tests/run_tests_in_isolation
|
|
||||||
@@ -1,163 +0,0 @@
|
|||||||
# Changelog
|
|
||||||
|
|
||||||
### master
|
|
||||||
- Remove deprecated "restoring shell history" feature.
|
|
||||||
|
|
||||||
### v4.0.0, 2022-04-10
|
|
||||||
- Proper handling of `automatic-rename` window option.
|
|
||||||
- save and restore tmux pane title (breaking change: you have to re-save to be
|
|
||||||
able to properly restore!)
|
|
||||||
|
|
||||||
### v3.0.0, 2021-08-30
|
|
||||||
- save and restore tmux pane contents (@laomaiweng)
|
|
||||||
- update tmux-test to solve issue with recursing git submodules in that project
|
|
||||||
- set options quietly in `resurrect.tmux` script
|
|
||||||
- improve pane contents restoration: `cat <file>` is no longer shown in pane
|
|
||||||
content history
|
|
||||||
- refactoring: drop dependency on `paste` command
|
|
||||||
- bugfix for pane contents restoration
|
|
||||||
- expand tilde char `~` if used with `@resurrect-dir`
|
|
||||||
- do not save empty trailing lines when pane content is saved
|
|
||||||
- do not save pane contents if pane is empty (only for 'save pane contents'
|
|
||||||
feature)
|
|
||||||
- "save pane contents" feature saves files to a separate directory
|
|
||||||
- archive and compress pane contents file
|
|
||||||
- make archive & compress pane contents process more portable
|
|
||||||
- `mutt` added to the list of automatically restored programs
|
|
||||||
- added guide for migrating from tmuxinator
|
|
||||||
- fixed a bug for restoring commands on tmux 2.5 (and probably tmux 2.4)
|
|
||||||
- do not create another resurrect file if there are no changes (credit @vburdo)
|
|
||||||
- allow using '$HOSTNAME' in @resurrect-dir
|
|
||||||
- add zsh history saving and restoring
|
|
||||||
- delete resurrect files older than 30 days, but keep at least 5 files
|
|
||||||
- add save and restore hooks
|
|
||||||
- always use `-ao` flags for `ps` command to detect commands
|
|
||||||
- Deprecate restoring shell history feature.
|
|
||||||
- `view` added to the list of automatically restored programs
|
|
||||||
- Enable vim session strategy to work with custom session files,
|
|
||||||
e.g. `vim -S Session1.vim`.
|
|
||||||
- Enable restoring command arguments for inline strategies with `*` character.
|
|
||||||
- Kill session "0" if it wasn't restored.
|
|
||||||
- Add `@resurrect-delete-backup-after` option to specify how many days of
|
|
||||||
backups to keep - default is 30.
|
|
||||||
|
|
||||||
### v2.4.0, 2015-02-23
|
|
||||||
- add "tmux-test"
|
|
||||||
- add test for "resurrect save" feature
|
|
||||||
- add test for "resurrect restore" feature
|
|
||||||
- make the tests work and pass on travis
|
|
||||||
- add travis badge to the readme
|
|
||||||
|
|
||||||
### v2.3.0, 2015-02-12
|
|
||||||
- Improve fetching proper window_layout for zoomed windows. In order to fetch
|
|
||||||
proper value, window has to get unzoomed. This is now done faster so that
|
|
||||||
"unzoom,fetch value,zoom" cycle is almost unnoticable to the user.
|
|
||||||
|
|
||||||
### v2.2.0, 2015-02-12
|
|
||||||
- bugfix: zoomed windows related regression
|
|
||||||
- export save and restore script paths so that 'tmux-resurrect-save' plugin can
|
|
||||||
use them
|
|
||||||
- enable "quiet" saving (used by 'tmux-resurrect-save' plugin)
|
|
||||||
|
|
||||||
### v2.1.0, 2015-02-12
|
|
||||||
- if restore is started when there's only **1 pane in the whole tmux server**,
|
|
||||||
assume the users wants the "full restore" and overrwrite that pane.
|
|
||||||
|
|
||||||
### v2.0.0, 2015-02-10
|
|
||||||
- add link to the wiki page for "first pane/window issue" to the README as well
|
|
||||||
as other tweaks
|
|
||||||
- save and restore grouped sessions (used with multi-monitor workflow)
|
|
||||||
- save and restore active and alternate windows in grouped sessions
|
|
||||||
- if there are no grouped sessions, do not output empty line to "last" file
|
|
||||||
- restore active and alternate windows only if they are present in the "last" file
|
|
||||||
- refactoring: prefer using variable with tab character
|
|
||||||
- remove deprecated `M-s` and `M-r` key bindings (breaking change)
|
|
||||||
|
|
||||||
### v1.5.0, 2014-11-09
|
|
||||||
- add support for restoring neovim sessions
|
|
||||||
|
|
||||||
### v1.4.0, 2014-10-25
|
|
||||||
- plugin now uses strategies when fetching pane full command. Implemented
|
|
||||||
'default' strategy.
|
|
||||||
- save command strategy: 'pgrep'. It's here only if fallback is needed.
|
|
||||||
- save command strategy: 'gdb'
|
|
||||||
- rename default strategy name to 'ps'
|
|
||||||
- create `expect` script that can fully restore tmux environment
|
|
||||||
- fix default save command strategy `ps` command flags. Flags are different for
|
|
||||||
FreeBSD.
|
|
||||||
- add bash history saving and restoring (@rburny)
|
|
||||||
- preserving layout of zoomed windows across restores (@Azrael3000)
|
|
||||||
|
|
||||||
### v1.3.0, 2014-09-20
|
|
||||||
- remove dependency on `pgrep` command. Use `ps` for fetching process names.
|
|
||||||
|
|
||||||
### v1.2.1, 2014-09-02
|
|
||||||
- tweak 'new_pane' creation strategy to fix #36
|
|
||||||
- when running multiple tmux server and for a large number of panes (120 +) when
|
|
||||||
doing a restore, some panes might not be created. When that is the case also
|
|
||||||
don't restore programs for those panes.
|
|
||||||
|
|
||||||
### v1.2.0, 2014-09-01
|
|
||||||
- new feature: inline strategies when restoring a program
|
|
||||||
|
|
||||||
### v1.1.0, 2014-08-31
|
|
||||||
- bugfix: sourcing `variables.sh` file in save script
|
|
||||||
- add `Ctrl` key mappings, deprecate `Alt` keys mappings.
|
|
||||||
|
|
||||||
### v1.0.0, 2014-08-30
|
|
||||||
- show spinner during the save process
|
|
||||||
- add screencast script
|
|
||||||
- make default program running list even more conservative
|
|
||||||
|
|
||||||
### v0.4.0, 2014-08-29
|
|
||||||
- change plugin name to `tmux-resurrect`. Change all the variable names.
|
|
||||||
|
|
||||||
### v0.3.0, 2014-08-29
|
|
||||||
- bugfix: when top is running the pane `$PWD` can't be saved. This was causing
|
|
||||||
issues during the restore and is now fixed.
|
|
||||||
- restoring sessions multiple times messes up the whole environment - new panes
|
|
||||||
are all around. This is now fixed - pane restorations are now idempotent.
|
|
||||||
- if pane exists from before session restore - do not restore the process within
|
|
||||||
it. This makes the restoration process even more idempotent.
|
|
||||||
- more panes within a window can now be restored
|
|
||||||
- restore window zoom state
|
|
||||||
|
|
||||||
### v0.2.0, 2014-08-29
|
|
||||||
- bugfix: with vim 'session' strategy, if the session file does not exist - make
|
|
||||||
sure vim does not contain `-S` flag
|
|
||||||
- enable restoring programs with arguments (e.g. "rails console") and also
|
|
||||||
processes that contain program name
|
|
||||||
- improve `irb` restore strategy
|
|
||||||
|
|
||||||
### v0.1.0, 2014-08-28
|
|
||||||
- refactor checking if saved tmux session exists
|
|
||||||
- spinner while tmux sessions are restored
|
|
||||||
|
|
||||||
### v0.0.5, 2014-08-28
|
|
||||||
- restore pane processes
|
|
||||||
- user option for disabling pane process restoring
|
|
||||||
- enable whitelisting processes that will be restored
|
|
||||||
- expand readme with configuration options
|
|
||||||
- enable command strategies; enable restoring vim sessions
|
|
||||||
- update readme: explain restoring vim sessions
|
|
||||||
|
|
||||||
### v0.0.4, 2014-08-26
|
|
||||||
- restore pane layout for each window
|
|
||||||
- bugfix: correct pane ordering in a window
|
|
||||||
|
|
||||||
### v0.0.3, 2014-08-26
|
|
||||||
- save and restore current and alternate session
|
|
||||||
- fix a bug with non-existing window names
|
|
||||||
- restore active pane for each window that has multiple panes
|
|
||||||
- restore active and alternate window for each session
|
|
||||||
|
|
||||||
### v0.0.2, 2014-08-26
|
|
||||||
- saving a new session does not remove the previous one
|
|
||||||
- make the directory where sessions are stored configurable
|
|
||||||
- support only Tmux v1.9 or greater
|
|
||||||
- display a nice error message if saved session file does not exist
|
|
||||||
- added README
|
|
||||||
|
|
||||||
### v0.0.1, 2014-08-26
|
|
||||||
- started a project
|
|
||||||
- basic saving and restoring works
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
### Contributing
|
|
||||||
|
|
||||||
Code contributions are welcome!
|
|
||||||
|
|
||||||
### Reporting a bug
|
|
||||||
|
|
||||||
If you find a bug please report it in the issues. When reporting a bug please
|
|
||||||
attach:
|
|
||||||
- a file symlinked to `~/.tmux/resurrect/last`.
|
|
||||||
- your `.tmux.conf`
|
|
||||||
- if you're getting an error paste it to a [gist](https://gist.github.com/) and
|
|
||||||
link it in the issue
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
Copyright (C) 2014 Bruno Sutic
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
a copy of this software and associated documentation files (the "Software"),
|
|
||||||
to deal in the Software without restriction, including without limitation
|
|
||||||
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
Software is furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included
|
|
||||||
in all copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
||||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
|
||||||
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
||||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
|
||||||
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
|
||||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
|
|
||||||
OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
@@ -1,129 +0,0 @@
|
|||||||
# Tmux Resurrect
|
|
||||||
|
|
||||||
[](https://travis-ci.org/tmux-plugins/tmux-resurrect)
|
|
||||||
|
|
||||||
Restore `tmux` environment after system restart.
|
|
||||||
|
|
||||||
Tmux is great, except when you have to restart the computer. You lose all the
|
|
||||||
running programs, working directories, pane layouts etc.
|
|
||||||
There are helpful management tools out there, but they require initial
|
|
||||||
configuration and continuous updates as your workflow evolves or you start new
|
|
||||||
projects.
|
|
||||||
|
|
||||||
`tmux-resurrect` saves all the little details from your tmux environment so it
|
|
||||||
can be completely restored after a system restart (or when you feel like it).
|
|
||||||
No configuration is required. You should feel like you never quit tmux.
|
|
||||||
|
|
||||||
It even (optionally)
|
|
||||||
[restores vim and neovim sessions](docs/restoring_vim_and_neovim_sessions.md)!
|
|
||||||
|
|
||||||
Automatic restoring and continuous saving of tmux env is also possible with
|
|
||||||
[tmux-continuum](https://github.com/tmux-plugins/tmux-continuum) plugin.
|
|
||||||
|
|
||||||
### Screencast
|
|
||||||
|
|
||||||
[](https://vimeo.com/104763018)
|
|
||||||
|
|
||||||
### Key bindings
|
|
||||||
|
|
||||||
- `prefix + Ctrl-s` - save
|
|
||||||
- `prefix + Ctrl-r` - restore
|
|
||||||
|
|
||||||
### About
|
|
||||||
|
|
||||||
This plugin goes to great lengths to save and restore all the details from your
|
|
||||||
`tmux` environment. Here's what's been taken care of:
|
|
||||||
|
|
||||||
- all sessions, windows, panes and their order
|
|
||||||
- current working directory for each pane
|
|
||||||
- **exact pane layouts** within windows (even when zoomed)
|
|
||||||
- active and alternative session
|
|
||||||
- active and alternative window for each session
|
|
||||||
- windows with focus
|
|
||||||
- active pane for each window
|
|
||||||
- "grouped sessions" (useful feature when using tmux with multiple monitors)
|
|
||||||
- programs running within a pane! More details in the
|
|
||||||
[restoring programs doc](docs/restoring_programs.md).
|
|
||||||
|
|
||||||
Optional:
|
|
||||||
|
|
||||||
- [restoring vim and neovim sessions](docs/restoring_vim_and_neovim_sessions.md)
|
|
||||||
- [restoring pane contents](docs/restoring_pane_contents.md)
|
|
||||||
- [restoring a previously saved environment](docs/restoring_previously_saved_environment.md)
|
|
||||||
|
|
||||||
Requirements / dependencies: `tmux 1.9` or higher, `bash`.
|
|
||||||
|
|
||||||
Tested and working on Linux, OSX and Cygwin.
|
|
||||||
|
|
||||||
`tmux-resurrect` is idempotent! It will not try to restore panes or windows that
|
|
||||||
already exist.<br/>
|
|
||||||
The single exception to this is when tmux is started with only 1 pane in order
|
|
||||||
to restore previous tmux env. Only in this case will this single pane be
|
|
||||||
overwritten.
|
|
||||||
|
|
||||||
### Installation with [Tmux Plugin Manager](https://github.com/tmux-plugins/tpm) (recommended)
|
|
||||||
|
|
||||||
Add plugin to the list of TPM plugins in `.tmux.conf`:
|
|
||||||
|
|
||||||
set -g @plugin 'tmux-plugins/tmux-resurrect'
|
|
||||||
|
|
||||||
Hit `prefix + I` to fetch the plugin and source it. You should now be able to
|
|
||||||
use the plugin.
|
|
||||||
|
|
||||||
### Manual Installation
|
|
||||||
|
|
||||||
Clone the repo:
|
|
||||||
|
|
||||||
$ git clone https://github.com/tmux-plugins/tmux-resurrect ~/clone/path
|
|
||||||
|
|
||||||
Add this line to the bottom of `.tmux.conf`:
|
|
||||||
|
|
||||||
run-shell ~/clone/path/resurrect.tmux
|
|
||||||
|
|
||||||
Reload TMUX environment with: `$ tmux source-file ~/.tmux.conf`.
|
|
||||||
You should now be able to use the plugin.
|
|
||||||
|
|
||||||
### Docs
|
|
||||||
|
|
||||||
- [Guide for migrating from tmuxinator](docs/migrating_from_tmuxinator.md)
|
|
||||||
|
|
||||||
**Configuration**
|
|
||||||
|
|
||||||
- [Changing the default key bindings](docs/custom_key_bindings.md).
|
|
||||||
- [Setting up hooks on save & restore](docs/hooks.md).
|
|
||||||
- Only a conservative list of programs is restored by default:<br/>
|
|
||||||
`vi vim nvim emacs man less more tail top htop irssi weechat mutt`.<br/>
|
|
||||||
[Restoring programs doc](docs/restoring_programs.md) explains how to restore
|
|
||||||
additional programs.
|
|
||||||
- [Change a directory](docs/save_dir.md) where `tmux-resurrect` saves tmux
|
|
||||||
environment.
|
|
||||||
|
|
||||||
**Optional features**
|
|
||||||
|
|
||||||
- [Restoring vim and neovim sessions](docs/restoring_vim_and_neovim_sessions.md)
|
|
||||||
is nice if you're a vim/neovim user.
|
|
||||||
- [Restoring pane contents](docs/restoring_pane_contents.md) feature.
|
|
||||||
|
|
||||||
### Other goodies
|
|
||||||
|
|
||||||
- [tmux-copycat](https://github.com/tmux-plugins/tmux-copycat) - a plugin for
|
|
||||||
regex searches in tmux and fast match selection
|
|
||||||
- [tmux-yank](https://github.com/tmux-plugins/tmux-yank) - enables copying
|
|
||||||
highlighted text to system clipboard
|
|
||||||
- [tmux-open](https://github.com/tmux-plugins/tmux-open) - a plugin for quickly
|
|
||||||
opening highlighted file or a url
|
|
||||||
- [tmux-continuum](https://github.com/tmux-plugins/tmux-continuum) - automatic
|
|
||||||
restoring and continuous saving of tmux env
|
|
||||||
|
|
||||||
### Reporting bugs and contributing
|
|
||||||
|
|
||||||
Both contributing and bug reports are welcome. Please check out
|
|
||||||
[contributing guidelines](CONTRIBUTING.md).
|
|
||||||
|
|
||||||
### Credits
|
|
||||||
|
|
||||||
[Mislav Marohnić](https://github.com/mislav) - the idea for the plugin came from his
|
|
||||||
[tmux-session script](https://github.com/mislav/dotfiles/blob/2036b5e03fb430bbcbc340689d63328abaa28876/bin/tmux-session).
|
|
||||||
|
|
||||||
### License
|
|
||||||
[MIT](LICENSE.md)
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
# Custom key bindings
|
|
||||||
|
|
||||||
The default key bindings are:
|
|
||||||
|
|
||||||
- `prefix + Ctrl-s` - save
|
|
||||||
- `prefix + Ctrl-r` - restore
|
|
||||||
|
|
||||||
To change these, add to `.tmux.conf`:
|
|
||||||
|
|
||||||
set -g @resurrect-save 'S'
|
|
||||||
set -g @resurrect-restore 'R'
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
# Save & Restore Hooks
|
|
||||||
|
|
||||||
Hooks allow to set custom commands that will be executed during session save
|
|
||||||
and restore. Most hooks are called with zero arguments, unless explicitly
|
|
||||||
stated otherwise.
|
|
||||||
|
|
||||||
Currently the following hooks are supported:
|
|
||||||
|
|
||||||
- `@resurrect-hook-post-save-layout`
|
|
||||||
|
|
||||||
Called after all sessions, panes and windows have been saved.
|
|
||||||
|
|
||||||
Passed single argument of the state file.
|
|
||||||
|
|
||||||
- `@resurrect-hook-post-save-all`
|
|
||||||
|
|
||||||
Called at end of save process right before the spinner is turned off.
|
|
||||||
|
|
||||||
- `@resurrect-hook-pre-restore-all`
|
|
||||||
|
|
||||||
Called before any tmux state is altered.
|
|
||||||
|
|
||||||
- `@resurrect-hook-pre-restore-pane-processes`
|
|
||||||
|
|
||||||
Called before running processes are restored.
|
|
||||||
|
|
||||||
### Examples
|
|
||||||
|
|
||||||
Here is an example how to save and restore window geometry for most terminals in X11.
|
|
||||||
Add this to `.tmux.conf`:
|
|
||||||
|
|
||||||
set -g @resurrect-hook-post-save-all 'eval $(xdotool getwindowgeometry --shell $WINDOWID); echo 0,$X,$Y,$WIDTH,$HEIGHT > $HOME/.tmux/resurrect/geometry'
|
|
||||||
set -g @resurrect-hook-pre-restore-all 'wmctrl -i -r $WINDOWID -e $(cat $HOME/.tmux/resurrect/geometry)'
|
|
||||||
@@ -1,72 +0,0 @@
|
|||||||
# Migrating from `tmuxinator`
|
|
||||||
|
|
||||||
### Why migrate to `tmux-resurrect`?
|
|
||||||
|
|
||||||
Here are some reasons why you'd want to migrate from `tmuxinator` to
|
|
||||||
`tmux-resurrect`:
|
|
||||||
|
|
||||||
- **Less dependencies**<br/>
|
|
||||||
`tmuxinator` depends on `ruby` which can be a hassle to set up if you're not a
|
|
||||||
rubyist.<br/>
|
|
||||||
`tmux-resurrect` depends just on `bash` which is virtually
|
|
||||||
omnipresent.
|
|
||||||
|
|
||||||
- **Simplicity**<br/>
|
|
||||||
`tmuxinator` has an executable, CLI interface with half dozen commands and
|
|
||||||
command completion.<br/>
|
|
||||||
`tmux-resurrect` defines just 2 tmux key bindings.
|
|
||||||
|
|
||||||
- **No configuration**<br/>
|
|
||||||
`tmuxinator` is all about config files (and their constant updating).<br/>
|
|
||||||
`tmux-resurrect` requires no configuration to work.
|
|
||||||
|
|
||||||
- **Better change handling**<br/>
|
|
||||||
When you make a change to any aspect of tmux layout, you also have to
|
|
||||||
update related `tmuxinator` project file (and test to make sure change is
|
|
||||||
ok).<br/>
|
|
||||||
With `tmux-resurrect` there's nothing to do: your change will be
|
|
||||||
remembered on the next save.
|
|
||||||
|
|
||||||
### How to migrate?
|
|
||||||
|
|
||||||
1. Install `tmux-resurrect`.
|
|
||||||
2. Open \*all* existing `tmuxinator` projects.<br/>
|
|
||||||
Verify all projects are open by pressing `prefix + s` and checking they are
|
|
||||||
all on the list.
|
|
||||||
3. Perform a `tmux-resurrect` save.
|
|
||||||
|
|
||||||
That's it! You can continue using just `tmux-resurrect` should you choose so.
|
|
||||||
|
|
||||||
Note: it probably makes no sense to use both tools at the same time as they do
|
|
||||||
the same thing (creating tmux environment for you to work in).
|
|
||||||
Technically however, there should be no issues.
|
|
||||||
|
|
||||||
### Usage differences
|
|
||||||
|
|
||||||
`tmuxinator` focuses on managing individual tmux sessions (projects).
|
|
||||||
`tmux-resurrect` keeps track of the \*whole* tmux environment: all sessions are
|
|
||||||
saved and restored together.
|
|
||||||
|
|
||||||
A couple tips if you decide to switch to `tmux-resurrect`:
|
|
||||||
|
|
||||||
- Keep all tmux sessions (projects) running all the time.<br/>
|
|
||||||
If you want to work on an existing project, you should be able to just
|
|
||||||
\*switch* to an already open session using `prefix + s`.<br/>
|
|
||||||
This is different from `tmuxinator` where you'd usually run `mux new [project]`
|
|
||||||
in order to start working on something.
|
|
||||||
|
|
||||||
- No need to kill sessions with `tmux kill-session` (unless you really don't
|
|
||||||
want to work on it ever).<br/>
|
|
||||||
It's the recurring theme by now: just keep all the sessions running all the
|
|
||||||
time. This is convenient and also cheap in terms of resources.
|
|
||||||
|
|
||||||
- The only 2 situations when you need `tmux-resurrect`:<br/>
|
|
||||||
1) Save tmux environment just before restarting/shutting down your
|
|
||||||
computer.<br/>
|
|
||||||
2) Restore tmux env after you turn the computer on.
|
|
||||||
|
|
||||||
### Other questions?
|
|
||||||
|
|
||||||
Still have questions? Feel free to open an
|
|
||||||
[issue](ihttps://github.com/tmux-plugins/tmux-resurrect/issues). We'll try to
|
|
||||||
answer it and also update this doc.
|
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
tmux-ressurect no longer restores shell history for each pane, as of [this PR](https://github.com/tmux-plugins/tmux-resurrect/pull/308).
|
|
||||||
|
|
||||||
As a workaround, you can use the `HISTFILE` environment variable to preserve history for each pane separately, and modify
|
|
||||||
`PROMPT_COMMAND` to make sure history gets saved with each new command.
|
|
||||||
|
|
||||||
Unfortunately, we haven't found a perfect way of getting a unique identifier for each pane, as the `TMUX_PANE` variable
|
|
||||||
seems to occasionally change when resurrecting. As a workaround, the example below sets a unique ID in each pane's `title`.
|
|
||||||
The downside of this implementation is that pane titles must all be unique across sessions/windows, and also must use the `pane_id_prefix`.
|
|
||||||
|
|
||||||
Any improvements/suggestions for getting a unique, persistent ID for each pane are welcome!
|
|
||||||
|
|
||||||
```bash
|
|
||||||
pane_id_prefix="resurrect_"
|
|
||||||
|
|
||||||
# Create history directory if it doesn't exist
|
|
||||||
HISTS_DIR=$HOME/.bash_history.d
|
|
||||||
mkdir -p "${HISTS_DIR}"
|
|
||||||
|
|
||||||
if [ -n "${TMUX_PANE}" ]; then
|
|
||||||
|
|
||||||
# Check if we've already set this pane title
|
|
||||||
pane_id=$(tmux display -pt "${TMUX_PANE:?}" "#{pane_title}")
|
|
||||||
if [[ $pane_id != "$pane_id_prefix"* ]]; then
|
|
||||||
|
|
||||||
# if not, set it to a random ID
|
|
||||||
random_id=$(head /dev/urandom | tr -dc A-Za-z0-9 | head -c 16)
|
|
||||||
printf "\033]2;$pane_id_prefix$random_id\033\\"
|
|
||||||
pane_id=$(tmux display -pt "${TMUX_PANE:?}" "#{pane_title}")
|
|
||||||
fi
|
|
||||||
|
|
||||||
# use the pane's random ID for the HISTFILE
|
|
||||||
export HISTFILE="${HISTS_DIR}/bash_history_tmux_${pane_id}"
|
|
||||||
else
|
|
||||||
export HISTFILE="${HISTS_DIR}/bash_history_no_tmux"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Stash the new history each time a command runs.
|
|
||||||
export PROMPT_COMMAND="$PROMPT_COMMAND;history -a"
|
|
||||||
```
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
# Restoring pane contents
|
|
||||||
|
|
||||||
This plugin enables saving and restoring tmux pane contents.
|
|
||||||
|
|
||||||
This feature can be enabled by adding this line to `.tmux.conf`:
|
|
||||||
|
|
||||||
set -g @resurrect-capture-pane-contents 'on'
|
|
||||||
|
|
||||||
##### Known issue
|
|
||||||
|
|
||||||
When using this feature, please check the value of `default-command`
|
|
||||||
tmux option. That can be done with `$ tmux show -g default-command`.
|
|
||||||
|
|
||||||
The value should NOT contain `&&` or `||` operators. If it does, simplify the
|
|
||||||
option so those operators are removed.
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
- this will cause issues (notice the `&&` and `||` operators):
|
|
||||||
|
|
||||||
set -g default-command "which reattach-to-user-namespace > /dev/null && reattach-to-user-namespace -l $SHELL || $SHELL -l"
|
|
||||||
|
|
||||||
- this is ok:
|
|
||||||
|
|
||||||
set -g default-command "reattach-to-user-namespace -l $SHELL"
|
|
||||||
|
|
||||||
Related [bug](https://github.com/tmux-plugins/tmux-resurrect/issues/98).
|
|
||||||
|
|
||||||
Alternatively, you can let
|
|
||||||
[tmux-sensible](https://github.com/tmux-plugins/tmux-sensible)
|
|
||||||
handle this option in a cross-platform way and you'll have no problems.
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
# Restoring previously saved environment
|
|
||||||
|
|
||||||
None of the previous saves are deleted (unless you explicitly do that). All save
|
|
||||||
files are kept in `~/.tmux/resurrect/` directory, or `~/.local/share/tmux/resurrect`
|
|
||||||
(unless `${XDG_DATA_HOME}` says otherwise).<br/>
|
|
||||||
Here are the steps to restore to a previous point in time:
|
|
||||||
|
|
||||||
- make sure you start this with a "fresh" tmux instance
|
|
||||||
- `$ cd ~/.tmux/resurrect/`
|
|
||||||
- locate the save file you'd like to use for restore (file names have a timestamp)
|
|
||||||
- symlink the `last` file to the desired save file: `$ ln -sf <file_name> last`
|
|
||||||
- do a restore with `tmux-resurrect` key: `prefix + Ctrl-r`
|
|
||||||
|
|
||||||
You should now be restored to the time when `<file_name>` save happened.
|
|
||||||
@@ -1,205 +0,0 @@
|
|||||||
# Restoring programs
|
|
||||||
- [General instructions](#general-instructions)
|
|
||||||
- [Clarifications](#clarifications)
|
|
||||||
- [Working with NodeJS](#nodejs)
|
|
||||||
- [Restoring Mosh](#mosh)
|
|
||||||
|
|
||||||
### General instructions <a name="general-instructions"></a>
|
|
||||||
Only a conservative list of programs is restored by default:<br/>
|
|
||||||
`vi vim nvim emacs man less more tail top htop irssi weechat mutt`.
|
|
||||||
|
|
||||||
This can be configured with `@resurrect-processes` option in `.tmux.conf`. It
|
|
||||||
contains space-separated list of additional programs to restore.
|
|
||||||
|
|
||||||
- Example restoring additional programs:
|
|
||||||
|
|
||||||
set -g @resurrect-processes 'ssh psql mysql sqlite3'
|
|
||||||
|
|
||||||
- Programs with arguments should be double quoted:
|
|
||||||
|
|
||||||
set -g @resurrect-processes 'some_program "git log"'
|
|
||||||
|
|
||||||
- Start with tilde to restore a program whose process contains target name:
|
|
||||||
|
|
||||||
set -g @resurrect-processes 'irb pry "~rails server" "~rails console"'
|
|
||||||
|
|
||||||
- Use `->` to specify a command to be used when restoring a program (useful if
|
|
||||||
the default restore command fails ):
|
|
||||||
|
|
||||||
set -g @resurrect-processes 'some_program "grunt->grunt development"'
|
|
||||||
|
|
||||||
- Use `*` to expand the arguments from the saved command when restoring:
|
|
||||||
|
|
||||||
set -g @resurrect-processes 'some_program "~rails server->rails server *"'
|
|
||||||
|
|
||||||
- Don't restore any programs:
|
|
||||||
|
|
||||||
set -g @resurrect-processes 'false'
|
|
||||||
|
|
||||||
- Restore **all** programs (dangerous!):
|
|
||||||
|
|
||||||
set -g @resurrect-processes ':all:'
|
|
||||||
|
|
||||||
Be *very careful* with this: tmux-resurrect can not know which programs take
|
|
||||||
which context, and a `sudo mkfs.vfat /dev/sdb` that was just formatting an
|
|
||||||
external USB stick could wipe your backup hard disk if that's what's attached
|
|
||||||
after rebooting.
|
|
||||||
|
|
||||||
This option is primarily useful for experimentation (e.g., to find out which
|
|
||||||
program is recognized in a pane).
|
|
||||||
|
|
||||||
### Clarifications <a name="clarfications"></a>
|
|
||||||
|
|
||||||
> I don't understand tilde `~`, what is it and why is it used when restoring
|
|
||||||
programs?
|
|
||||||
|
|
||||||
Let's say you use `rails server` command often. You want `tmux-resurrect` to
|
|
||||||
save and restore it automatically. You might try adding `rails server` to the
|
|
||||||
list of programs that will be restored:
|
|
||||||
|
|
||||||
set -g @resurrect-processes '"rails server"' # will NOT work
|
|
||||||
|
|
||||||
Upon save, `rails server` command will actually be saved as this command:
|
|
||||||
`/Users/user/.rbenv/versions/2.0.0-p481/bin/ruby script/rails server`
|
|
||||||
(if you wanna see how is any command saved, check it yourself in
|
|
||||||
`~/.tmux/resurrect/last` file).
|
|
||||||
|
|
||||||
When programs are restored, the `rails server` command will NOT be restored
|
|
||||||
because it does not **strictly** match the long
|
|
||||||
`/Users/user/.rbenv/versions/2.0.0-p481/bin/ruby script/rails server` string.
|
|
||||||
|
|
||||||
The tilde `~` at the start of the string relaxes process name matching.
|
|
||||||
|
|
||||||
set -g @resurrect-processes '"~rails server"' # OK
|
|
||||||
|
|
||||||
The above option says: "restore full process if `rails server` string is found
|
|
||||||
ANYWHERE in the process name".
|
|
||||||
|
|
||||||
If you check long process string, there is in fact a `rails server` string at
|
|
||||||
the end, so now the process will be successfully restored.
|
|
||||||
|
|
||||||
> What is arrow `->` and why is is used?
|
|
||||||
|
|
||||||
(Please read the above clarification about tilde `~`).
|
|
||||||
|
|
||||||
Continuing with our `rails server` example, when the process is finally restored
|
|
||||||
correctly it might not look pretty as you'll see the whole
|
|
||||||
`/Users/user/.rbenv/versions/2.0.0-p481/bin/ruby script/rails server` string in
|
|
||||||
the command line.
|
|
||||||
|
|
||||||
Naturally, you'd rather want to see just `rails server` (what you initially
|
|
||||||
typed), but that information is now unfortunately lost.
|
|
||||||
|
|
||||||
To aid this, you can use arrow `->`: (**note**: there is no space before and after `->`)
|
|
||||||
|
|
||||||
set -g @resurrect-processes '"~rails server->rails server"' # OK
|
|
||||||
|
|
||||||
This option says: "when this process is restored use `rails server` as the
|
|
||||||
command name".
|
|
||||||
|
|
||||||
Full (long) process name is now ignored and you'll see just `rails server` in
|
|
||||||
the command line when the program is restored.
|
|
||||||
|
|
||||||
> What is asterisk `*` and why is it used?
|
|
||||||
|
|
||||||
(Please read the above clarifications about tilde `~` and arrow `->`).
|
|
||||||
|
|
||||||
Continuing with the `rails server` example, you might have added flags for e.g.
|
|
||||||
verbose logging, but with the above configuration, the flags would be lost.
|
|
||||||
|
|
||||||
To preserve the command arguments when restoring, use the asterisk `*`: (**note**: there **must** be a space before `*`)
|
|
||||||
|
|
||||||
set -g @resurrect-processes '"~rails server->rails server *"'
|
|
||||||
|
|
||||||
This option says: "when this process is restored use `rails server` as the
|
|
||||||
command name, but preserve its arguments".
|
|
||||||
|
|
||||||
> Now I understand the tilde and the arrow, but things still don't work for me
|
|
||||||
|
|
||||||
Here's the general workflow for figuring this out:
|
|
||||||
|
|
||||||
- Set up your whole tmux environment manually.<br/>
|
|
||||||
In our example case, we'd type `rails server` in a pane where we want it to
|
|
||||||
run.
|
|
||||||
- Save tmux env (it will get saved to `~/.tmux/resurrect/last`).
|
|
||||||
- Open `~/.tmux/resurrect/last` file and try to find full process string for
|
|
||||||
your program.<br/>
|
|
||||||
Unfortunately this is a little vague but it should be easy. A smart
|
|
||||||
thing to do for our example is to search for string `rails` in the `last`
|
|
||||||
file.
|
|
||||||
- Now that you know the full and the desired process string use tilde `~` and
|
|
||||||
arrow `->` in `.tmux.conf` to make things work.
|
|
||||||
|
|
||||||
### Working with NodeJS <a name="nodejs"></a>
|
|
||||||
If you are working with NodeJS, you may get some troubles with configuring restoring programs.
|
|
||||||
|
|
||||||
Particularly, some programs like `gulp`, `grunt` or `npm` are not saved with parameters so tmux-resurrect cannot restore it. This is actually **not tmux-resurrect's issue** but more likely, those programs' issues. For example if you run `gulp watch` or `npm start` and then try to look at `ps` or `pgrep`, you will only see `gulp` or `npm`.
|
|
||||||
|
|
||||||
To deal with these issues, one solution is to use [yarn](https://yarnpkg.com/en/docs/install) which a package manager for NodeJS and an alternative for `npm`. It's nearly identical to `npm` and very easy to use. Therefore you don't have to do any migration, you can simply use it immediately. For example:
|
|
||||||
- `npm test` is equivalent to `yarn test`,
|
|
||||||
- `npm run watch:dev` is equivalent to `yarn watch:dev`
|
|
||||||
- more interestingly, `gulp watch:dev` is equivalent to `yarn gulp watch:dev`
|
|
||||||
|
|
||||||
Before continuing, please ensure that you understand the [clarifications](#clarifications) section about `~` and `->`
|
|
||||||
|
|
||||||
#### yarn
|
|
||||||
It's fairly straight forward if you have been using `yarn` already.
|
|
||||||
|
|
||||||
set -g @resurrect-processes '"~yarn watch"'
|
|
||||||
set -g @resurrect-processes '"~yarn watch->yarn watch"'
|
|
||||||
|
|
||||||
|
|
||||||
#### npm
|
|
||||||
Instead of
|
|
||||||
|
|
||||||
set -g @resurrect-processes '"~npm run watch"' # will NOT work
|
|
||||||
|
|
||||||
we use
|
|
||||||
|
|
||||||
set -g @resurrect-processes '"~yarn watch"' # OK
|
|
||||||
|
|
||||||
|
|
||||||
#### gulp
|
|
||||||
Instead of
|
|
||||||
|
|
||||||
set -g @resurrect-processes '"~gulp test"' # will NOT work
|
|
||||||
|
|
||||||
we use
|
|
||||||
|
|
||||||
set -g @resurrect-processes '"~yarn gulp test"' # OK
|
|
||||||
|
|
||||||
|
|
||||||
#### nvm
|
|
||||||
If you use `nvm` in your project, here is how you could config tmux-resurrect:
|
|
||||||
|
|
||||||
set -g @resurrect-processes '"~yarn gulp test->nvm use && gulp test"'
|
|
||||||
|
|
||||||
#### Another problem
|
|
||||||
Let take a look at this example
|
|
||||||
|
|
||||||
set -g @resurrect-processes '\
|
|
||||||
"~yarn gulp test->gulp test" \
|
|
||||||
"~yarn gulp test-it->gulp test-it" \
|
|
||||||
'
|
|
||||||
**This will not work properly**, only `gulp test` is run, although you can see the command `node /path/to/yarn gulp test-it` is added correctly in `.tmux/resurrect/last` file.
|
|
||||||
|
|
||||||
The reason is when restoring program, the **command part after the dash `-` is ignored** so instead of command `gulp test-it`, the command `gulp test` which will be run.
|
|
||||||
|
|
||||||
A work around, for this problem until it's fixed, is:
|
|
||||||
- the config should be like this:
|
|
||||||
|
|
||||||
set -g @resurrect-processes '\
|
|
||||||
"~yarn gulp test->gulp test" \
|
|
||||||
"~yarn gulp \"test-it\"->gulp test-it" \
|
|
||||||
|
|
||||||
- and in `.tmux/resurrect/last`, we should add quote to `test-it` word
|
|
||||||
|
|
||||||
... node:node /path/to/yarn gulp "test-it"
|
|
||||||
|
|
||||||
|
|
||||||
### Restoring Mosh <a name="#mosh"></a>
|
|
||||||
Mosh spawns a `mosh-client` process, so we need to specify that as the process to be resurrected.
|
|
||||||
|
|
||||||
set -g @resurrect-processes 'mosh-client'
|
|
||||||
|
|
||||||
Additionally a mosh-client strategy is provided to handle extracting the original arguments and re-run Mosh.
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
# Restoring vim and neovim sessions
|
|
||||||
|
|
||||||
- save vim/neovim sessions. I recommend
|
|
||||||
[tpope/vim-obsession](https://github.com/tpope/vim-obsession) (as almost every
|
|
||||||
plugin, it works for both vim and neovim).
|
|
||||||
- in `.tmux.conf`:
|
|
||||||
|
|
||||||
# for vim
|
|
||||||
set -g @resurrect-strategy-vim 'session'
|
|
||||||
# for neovim
|
|
||||||
set -g @resurrect-strategy-nvim 'session'
|
|
||||||
|
|
||||||
`tmux-resurrect` will now restore vim and neovim sessions if `Session.vim` file
|
|
||||||
is present.
|
|
||||||
|
|
||||||
> If you're using the vim binary provided by MacVim.app then you'll need to set `@resurrect-processes`, for example:
|
|
||||||
> ```
|
|
||||||
> set -g @resurrect-processes '~Vim -> vim'
|
|
||||||
> ```
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
# Resurrect save dir
|
|
||||||
|
|
||||||
By default Tmux environment is saved to a file in `~/.tmux/resurrect` dir.
|
|
||||||
Change this with:
|
|
||||||
|
|
||||||
set -g @resurrect-dir '/some/path'
|
|
||||||
|
|
||||||
Using environment variables or shell interpolation in this option is not
|
|
||||||
allowed as the string is used literally. So the following won't do what is
|
|
||||||
expected:
|
|
||||||
|
|
||||||
set -g @resurrect-dir '/path/$MY_VAR/$(some_executable)'
|
|
||||||
|
|
||||||
Only the following variables and special chars are allowed:
|
|
||||||
`$HOME`, `$HOSTNAME`, and `~`.
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
.vagrant/
|
|
||||||
lib/
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
# generic packages and tmux
|
|
||||||
before_install:
|
|
||||||
- sudo apt-get update
|
|
||||||
- sudo apt-get install -y git-core expect
|
|
||||||
- sudo apt-get install -y python-software-properties software-properties-common
|
|
||||||
- sudo apt-get install -y libevent-dev libncurses-dev
|
|
||||||
- git clone https://github.com/tmux/tmux.git
|
|
||||||
- cd tmux
|
|
||||||
- git checkout 2.5
|
|
||||||
- sh autogen.sh
|
|
||||||
- ./configure && make && sudo make install
|
|
||||||
|
|
||||||
install:
|
|
||||||
- git fetch --unshallow --recurse-submodules || git fetch --recurse-submodules
|
|
||||||
# manual `git clone` required for testing `tmux-test` plugin itself
|
|
||||||
- git clone https://github.com/tmux-plugins/tmux-test lib/tmux-test; true
|
|
||||||
- lib/tmux-test/setup
|
|
||||||
|
|
||||||
script: ./tests/run_tests_in_isolation
|
|
||||||
@@ -1,46 +0,0 @@
|
|||||||
# Changelog
|
|
||||||
|
|
||||||
### master
|
|
||||||
- move `setup` task to `.travis.yml` for travis tests
|
|
||||||
- "merge" travis.yml and travis_for_plugins.yml files (no need to keep em
|
|
||||||
separate)
|
|
||||||
- add more useful helper functions
|
|
||||||
- remove tmux-test repo as a submodule from self, this causes issues with
|
|
||||||
`$ git submodule update --recursive --init` command that some users use for
|
|
||||||
managing other plugins
|
|
||||||
- add new helper `teardown_helper`
|
|
||||||
- add `run_tests` helper
|
|
||||||
- change CLI syntax for choosing vagrant machine to run the tests on
|
|
||||||
- enable running just a single test via `run_tests` cli interface
|
|
||||||
- add `--keep-running` cli option to continue running vagrant after the tests
|
|
||||||
are done executing
|
|
||||||
- start using tmux 2.0 for tests
|
|
||||||
- use tmux 2.5 for tests
|
|
||||||
|
|
||||||
### v0.2.0, 2015-02-22
|
|
||||||
- `setup` script gitignores `tests/helpers.sh`
|
|
||||||
- move `tests/helpers.sh` to `tests/helpers/helpers.sh`
|
|
||||||
- `setup` undo removes added lines from gitignore file
|
|
||||||
|
|
||||||
### v0.1.0, 2015-02-22
|
|
||||||
- changes so that 'tmux-test' can be included with tmux plugins
|
|
||||||
- do not gitignore submodules directory
|
|
||||||
- add installation and usage instructions
|
|
||||||
- copy `.travis.yml` to the project root when running `setup` script
|
|
||||||
- add a brief mention of travis CI to the readme
|
|
||||||
- add test helpers
|
|
||||||
- `setup` script symlinks helpers file to `tests/` directory
|
|
||||||
- `setup` script can undo most of its actions
|
|
||||||
- add a tmux scripting test
|
|
||||||
- `tmux-test` uses `tmux-test` to test itself
|
|
||||||
- update `tmux-test` submodule
|
|
||||||
- a different `travis.yml` for `tmux-test` and for plugins
|
|
||||||
|
|
||||||
### v0.0.1, 2015-02-21
|
|
||||||
- git init
|
|
||||||
- add vagrant provisioning scripts for ubuntu and debian
|
|
||||||
- add a ".travis.yml" file
|
|
||||||
- generic "run_tests" script
|
|
||||||
- "run_tests_in_isolation" script
|
|
||||||
- add "Vagrantfile"
|
|
||||||
- enable passing VM names as arguments to "run_tests" script
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
Copyright (C) Bruno Sutic
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
a copy of this software and associated documentation files (the "Software"),
|
|
||||||
to deal in the Software without restriction, including without limitation
|
|
||||||
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
||||||
and/or sell copies of the Software, and to permit persons to whom the
|
|
||||||
Software is furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included
|
|
||||||
in all copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
||||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
|
||||||
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
||||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
|
||||||
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
|
||||||
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
|
|
||||||
OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
||||||
@@ -1,134 +0,0 @@
|
|||||||
# tmux-test
|
|
||||||
|
|
||||||
[](https://travis-ci.org/tmux-plugins/tmux-test)
|
|
||||||
|
|
||||||
A small framework for isolated testing of tmux plugins. Isolation is achieved by
|
|
||||||
running the tests in `Vagrant`. Works on [travis](travis-ci.org) too.
|
|
||||||
|
|
||||||
Extracted from [tmux plugin manager](https://github.com/tmux-plugins/tpm) and
|
|
||||||
[tmux-copycat](https://github.com/tmux-plugins/tmux-copycat).
|
|
||||||
|
|
||||||
Dependencies: `Vagrant` (not required when running on travis).
|
|
||||||
|
|
||||||
### Setup
|
|
||||||
|
|
||||||
Let's say you made tmux plugin with the following file hierarchy:
|
|
||||||
|
|
||||||
```text
|
|
||||||
/tmux-plugin
|
|
||||||
|-- plugin.tmux
|
|
||||||
`-- scripts
|
|
||||||
`-- plugin_script.sh
|
|
||||||
```
|
|
||||||
|
|
||||||
From your project root directory (tmux-plugin/) execute the following shell
|
|
||||||
command to fetch `tmux-test` and add it as a submodule:
|
|
||||||
|
|
||||||
$ git submodule add https://github.com/tmux-plugins/tmux-test.git lib/tmux-test
|
|
||||||
|
|
||||||
Run the `setup` script:
|
|
||||||
|
|
||||||
$ lib/tmux-test/setup
|
|
||||||
|
|
||||||
The project directory will now look like this (additions have comments):
|
|
||||||
|
|
||||||
```text
|
|
||||||
/tmux-plugin
|
|
||||||
|-- plugin.tmux
|
|
||||||
|-- run_tests # symlink, gitignored
|
|
||||||
|-- .gitignore # 2 lines appended to gitignore
|
|
||||||
|-- .travis.yml # added
|
|
||||||
|-- lib/tmux-test/ # git submodule
|
|
||||||
|-- scripts
|
|
||||||
| `-- plugin_script.sh
|
|
||||||
`-- tests # dir to put the tests in
|
|
||||||
`-- run_tests_in_isolation.sh # symlink, gitignored
|
|
||||||
`-- helpers
|
|
||||||
`-- helpers.sh # symlinked bash helpers, gitignored
|
|
||||||
```
|
|
||||||
|
|
||||||
`tmux-test` is now set up. You are ok to commit the additions to the repo.
|
|
||||||
|
|
||||||
### Writing and running tests
|
|
||||||
|
|
||||||
A test is any executable with a name starting with `test_` in `tests/`
|
|
||||||
directory.
|
|
||||||
|
|
||||||
Now that you installed `tmux-test` let's create an example test.
|
|
||||||
|
|
||||||
- create a `tests/test_example.sh` file with the following content (it's a
|
|
||||||
`bash` script but it can be any executable):
|
|
||||||
|
|
||||||
#/usr/bin/env bash
|
|
||||||
|
|
||||||
CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
|
||||||
|
|
||||||
# bash helpers provided by 'tmux-test'
|
|
||||||
source $CURRENT_DIR/helpers/helpers.sh
|
|
||||||
|
|
||||||
# installs plugin from current repo in Vagrant (or on Travis)
|
|
||||||
install_tmux_plugin_under_test_helper
|
|
||||||
|
|
||||||
# start tmux in background (plugin under test is sourced)
|
|
||||||
tmux new -d
|
|
||||||
|
|
||||||
# get first session name
|
|
||||||
session_name="$(tmux list-sessions -F "#{session_name}")"
|
|
||||||
|
|
||||||
# fail the test if first session name is not "0"
|
|
||||||
if [ "$session_name" == "0" ]; then
|
|
||||||
# fail_helper is also provided by 'tmux-test'
|
|
||||||
fail_helper "First session name is not '0' by default"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# sets the right script exit code ('tmux-test' helper)
|
|
||||||
exit_helper
|
|
||||||
|
|
||||||
- make the test file executable with `$ chmod +x tests/test_example.sh`
|
|
||||||
- run the test by executing `./run_tests` from the project root directory
|
|
||||||
- the first invocation might take some time because Vagrant's ubuntu virtual
|
|
||||||
machine is downloading. You should see `Success, tests pass!` message when it's
|
|
||||||
done.
|
|
||||||
|
|
||||||
Check out more example test scripts in this project's [tests/ directory](tests/).
|
|
||||||
|
|
||||||
### Continuous integration
|
|
||||||
|
|
||||||
The setup script (`lib/tmux-test/setup`) added a `.travis.yml` file to the
|
|
||||||
project root. To setup continuous integration, just add/enable the project on
|
|
||||||
[travis](travis-ci.org).
|
|
||||||
|
|
||||||
### Notes
|
|
||||||
|
|
||||||
- The `tests/` directory for tests and `lib/tmux-test/` for cloning `tmux-test`
|
|
||||||
into cannot be changed currently
|
|
||||||
- Don't run `tests/run_tests_in_isolation` script on your local development
|
|
||||||
environment. That's an internal test runner meant to be executed in an
|
|
||||||
isolated environment like `vagrant` or `travis`.<br/>
|
|
||||||
Use `./run_tests` script.
|
|
||||||
- You can use `KEEP_RUNNING=true ./run_tests` for faster test running cycle.
|
|
||||||
If this case `Vagrant` will keep running even after the tests are done.
|
|
||||||
- You can use `VAGRANT_CWD=lib/tmux-test/ vagrant ssh ubuntu` for ssh login to
|
|
||||||
`Vagrant`.
|
|
||||||
|
|
||||||
### Running `tmux-test` framework tests
|
|
||||||
|
|
||||||
`tmux-test` uses itself to test itself. To run framework tests:
|
|
||||||
|
|
||||||
- clone this project `$ git clone git@github.com:tmux-plugins/tmux-test.git`
|
|
||||||
- `$ cd tmux-test`
|
|
||||||
- run `$ ./run_framework_tests`
|
|
||||||
|
|
||||||
### Other goodies
|
|
||||||
|
|
||||||
- [tmux-copycat](https://github.com/tmux-plugins/tmux-copycat) - a plugin for
|
|
||||||
regex searches in tmux and fast match selection
|
|
||||||
- [tmux-continuum](https://github.com/tmux-plugins/tmux-continuum) - automatic
|
|
||||||
restoring and continuous saving of tmux env
|
|
||||||
|
|
||||||
You might want to follow [@brunosutic](https://twitter.com/brunosutic) on
|
|
||||||
twitter if you want to hear about new tmux plugins or feature updates.
|
|
||||||
|
|
||||||
### License
|
|
||||||
|
|
||||||
[MIT](LICENSE.md)
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
VAGRANTFILE_API_VERSION = "2"
|
|
||||||
|
|
||||||
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
|
|
||||||
|
|
||||||
config.vm.synced_folder "../../", "/vagrant"
|
|
||||||
|
|
||||||
config.vm.define :ubuntu do |ubuntu|
|
|
||||||
ubuntu.vm.box = "hashicorp/precise64"
|
|
||||||
ubuntu.vm.provision "shell", path: "vagrant_ubuntu_provisioning.sh"
|
|
||||||
end
|
|
||||||
|
|
||||||
config.vm.define :centos do |centos|
|
|
||||||
centos.vm.box = "chef/centos-6.5"
|
|
||||||
centos.vm.provision "shell", path: "vagrant_centos_provisioning.sh"
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
# This file is used to run "tmux-test" framework tests.
|
|
||||||
|
|
||||||
# "setup" script is needed to run the tests, but it overrides some working dir
|
|
||||||
# files. To address that, "setup" is run before the tests and its actions are
|
|
||||||
# undone after.
|
|
||||||
|
|
||||||
main() {
|
|
||||||
git clone https://github.com/tmux-plugins/tmux-test lib/tmux-test
|
|
||||||
lib/tmux-test/setup
|
|
||||||
./run_tests
|
|
||||||
local exit_value=$?
|
|
||||||
lib/tmux-test/setup "undo"
|
|
||||||
exit "$exit_value"
|
|
||||||
}
|
|
||||||
main
|
|
||||||
@@ -1,93 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
# invoke this script from your projects root directory
|
|
||||||
|
|
||||||
CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
|
||||||
|
|
||||||
# pass "undo" as a script arg to undo most of the setup actions
|
|
||||||
UNDO_SETUP="$1"
|
|
||||||
undo() {
|
|
||||||
[ "$UNDO_SETUP" == "undo" ]
|
|
||||||
}
|
|
||||||
|
|
||||||
restore() {
|
|
||||||
local file="$1"
|
|
||||||
rm -f "$file"
|
|
||||||
git checkout -- "$file" 2>/dev/null
|
|
||||||
}
|
|
||||||
|
|
||||||
gitignore() {
|
|
||||||
local file="$1"
|
|
||||||
grep -q "^${file}$" .gitignore 2>/dev/null || echo "$file" >> .gitignore
|
|
||||||
}
|
|
||||||
|
|
||||||
remove_from_gitignore() {
|
|
||||||
local file="$1"
|
|
||||||
local escaped_filename="$(echo "$file" | sed "s,/,\\\/,g")"
|
|
||||||
sed -i"" "/^${escaped_filename}$/d" .gitignore
|
|
||||||
}
|
|
||||||
|
|
||||||
add_files_to_gitignore() {
|
|
||||||
if ! undo; then
|
|
||||||
gitignore "run_tests"
|
|
||||||
gitignore "tests/run_tests_in_isolation"
|
|
||||||
gitignore "tests/helpers/helpers.sh"
|
|
||||||
else
|
|
||||||
remove_from_gitignore "run_tests"
|
|
||||||
remove_from_gitignore "tests/run_tests_in_isolation"
|
|
||||||
remove_from_gitignore "tests/helpers/helpers.sh"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
symlink_user_test_runner() {
|
|
||||||
local file="run_tests"
|
|
||||||
if ! undo; then
|
|
||||||
ln -sf "lib/tmux-test/${file}" "$file"
|
|
||||||
else
|
|
||||||
restore "$file"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
create_directory_for_tests() {
|
|
||||||
if ! undo; then
|
|
||||||
mkdir -p tests/helpers/
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
symlink_internal_test_runner() {
|
|
||||||
local file="tests/run_tests_in_isolation"
|
|
||||||
if ! undo; then
|
|
||||||
ln -sf "../lib/tmux-test/${file}" "$file"
|
|
||||||
else
|
|
||||||
restore "$file"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
symlink_test_helpers() {
|
|
||||||
local file="tests/helpers/helpers.sh"
|
|
||||||
if ! undo; then
|
|
||||||
ln -sf "../../lib/tmux-test/${file}" "$file"
|
|
||||||
else
|
|
||||||
restore "$file"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
copy_travis_yml() {
|
|
||||||
local file=".travis.yml"
|
|
||||||
if ! undo; then
|
|
||||||
cp "lib/tmux-test/${file}" "$file"
|
|
||||||
else
|
|
||||||
restore "$file"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
main() {
|
|
||||||
add_files_to_gitignore
|
|
||||||
symlink_user_test_runner
|
|
||||||
create_directory_for_tests
|
|
||||||
symlink_internal_test_runner
|
|
||||||
symlink_test_helpers
|
|
||||||
copy_travis_yml
|
|
||||||
}
|
|
||||||
main
|
|
||||||
|
|
||||||
@@ -1,68 +0,0 @@
|
|||||||
# This file is a symlink from 'tmux-test' plugin.
|
|
||||||
# You probably don't want to edit it.
|
|
||||||
|
|
||||||
|
|
||||||
# Global variable that keeps the value of test status (success/fail).
|
|
||||||
# Suggested usage is via `fail_helper` and `exit_helper` functions.
|
|
||||||
TEST_STATUS="success"
|
|
||||||
|
|
||||||
# PRIVATE FUNCTIONS
|
|
||||||
|
|
||||||
_clone_the_plugin() {
|
|
||||||
local plugin_path="${HOME}/.tmux/plugins/tmux-plugin-under-test/"
|
|
||||||
rm -rf "$plugin_path"
|
|
||||||
git clone --recursive "${CURRENT_DIR}/../" "$plugin_path" >/dev/null 2>&1
|
|
||||||
}
|
|
||||||
|
|
||||||
_add_plugin_to_tmux_conf() {
|
|
||||||
set_tmux_conf_helper<<-HERE
|
|
||||||
run-shell '~/.tmux/plugins/tmux-plugin-under-test/*.tmux'
|
|
||||||
HERE
|
|
||||||
}
|
|
||||||
|
|
||||||
# PUBLIC HELPER FUNCTIONS
|
|
||||||
|
|
||||||
teardown_helper() {
|
|
||||||
rm -f ~/.tmux.conf
|
|
||||||
rm -rf ~/.tmux/
|
|
||||||
tmux kill-server >/dev/null 2>&1
|
|
||||||
}
|
|
||||||
|
|
||||||
set_tmux_conf_helper() {
|
|
||||||
> ~/.tmux.conf # empty tmux.conf file
|
|
||||||
while read line; do
|
|
||||||
echo "$line" >> ~/.tmux.conf
|
|
||||||
done
|
|
||||||
}
|
|
||||||
|
|
||||||
fail_helper() {
|
|
||||||
local message="$1"
|
|
||||||
echo "$message" >&2
|
|
||||||
TEST_STATUS="fail"
|
|
||||||
}
|
|
||||||
|
|
||||||
exit_helper() {
|
|
||||||
teardown_helper
|
|
||||||
if [ "$TEST_STATUS" == "fail" ]; then
|
|
||||||
echo "FAIL!"
|
|
||||||
echo
|
|
||||||
exit 1
|
|
||||||
else
|
|
||||||
echo "SUCCESS"
|
|
||||||
echo
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
install_tmux_plugin_under_test_helper() {
|
|
||||||
_clone_the_plugin
|
|
||||||
_add_plugin_to_tmux_conf
|
|
||||||
}
|
|
||||||
|
|
||||||
run_tests() {
|
|
||||||
# get all the functions starting with 'test_' and invoke them
|
|
||||||
for test in $(compgen -A function | grep "^test_"); do
|
|
||||||
"$test"
|
|
||||||
done
|
|
||||||
exit_helper
|
|
||||||
}
|
|
||||||
@@ -1,47 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
# This file is a symlink from 'tmux-test' plugin.
|
|
||||||
# You probably don't want to edit it.
|
|
||||||
|
|
||||||
# This script should be run within an isolated enviroment (Vagrant, travis).
|
|
||||||
# Depending on what the tests do, it might NOT be safe to run this script
|
|
||||||
# directly on the development machine.
|
|
||||||
|
|
||||||
CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
|
||||||
|
|
||||||
EXIT_VALUE=0 # running a test suite is successful by default
|
|
||||||
|
|
||||||
all_test_files() {
|
|
||||||
ls -1 "$CURRENT_DIR" | # test files are in the current dir
|
|
||||||
\grep -i "^test" | # test file names start with "test"
|
|
||||||
xargs # file names in a single line
|
|
||||||
}
|
|
||||||
|
|
||||||
set_exit_val_to_false() {
|
|
||||||
EXIT_VALUE=1
|
|
||||||
}
|
|
||||||
|
|
||||||
run_tests() {
|
|
||||||
local test_file tests_files
|
|
||||||
if [ "$#" -gt 0 ]; then
|
|
||||||
test_files="${@//tests\//}" # remove 'tests/' directory prefix
|
|
||||||
else
|
|
||||||
test_files="$(all_test_files)"
|
|
||||||
fi
|
|
||||||
for test_file in $test_files; do
|
|
||||||
echo "Running test: $test_file"
|
|
||||||
"${CURRENT_DIR}/${test_file}"
|
|
||||||
|
|
||||||
# handling exit value
|
|
||||||
local test_exit_value="$?"
|
|
||||||
if [ "$test_exit_value" -ne 0 ]; then
|
|
||||||
set_exit_val_to_false
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
}
|
|
||||||
|
|
||||||
main() {
|
|
||||||
run_tests "$@"
|
|
||||||
exit "$EXIT_VALUE"
|
|
||||||
}
|
|
||||||
main "$@"
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
exit 0
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
#/usr/bin/env bash
|
|
||||||
|
|
||||||
CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
|
||||||
|
|
||||||
# bash helpers provided by 'tmux-test'
|
|
||||||
source $CURRENT_DIR/helpers/helpers.sh
|
|
||||||
|
|
||||||
# installs plugin from current repo in Vagrant (or on Travis)
|
|
||||||
install_tmux_plugin_under_test_helper
|
|
||||||
|
|
||||||
# start tmux in background (plugin under test is sourced)
|
|
||||||
tmux new -d
|
|
||||||
|
|
||||||
# get first session name
|
|
||||||
session_name="$(tmux list-sessions -F "#{session_name}")"
|
|
||||||
|
|
||||||
# fail the test if first session name is not "0"
|
|
||||||
if ! [ "$session_name" == "0" ]; then
|
|
||||||
# fail_helper is also provided by 'tmux-test'
|
|
||||||
fail_helper "First session name is not '0' by default"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# sets the right script exit code ('tmux-test' helper)
|
|
||||||
exit_helper
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
|
||||||
|
|
||||||
source $CURRENT_DIR/helpers/helpers.sh
|
|
||||||
|
|
||||||
number_of_windows() {
|
|
||||||
tmux list-windows |
|
|
||||||
wc -l |
|
|
||||||
sed "s/ //g"
|
|
||||||
}
|
|
||||||
|
|
||||||
main() {
|
|
||||||
# start tmux in the background
|
|
||||||
tmux new -d
|
|
||||||
tmux new-window
|
|
||||||
|
|
||||||
local number_of_windows="$(number_of_windows)"
|
|
||||||
if ! [ "$number_of_windows" -eq 2 ]; then
|
|
||||||
fail_helper "Incorrect number of windows. Expected 2, got $number_of_windows"
|
|
||||||
fi
|
|
||||||
exit_helper
|
|
||||||
}
|
|
||||||
main
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
# libevent2 installation instructions from here
|
|
||||||
# https://gist.github.com/rschuman/6168833
|
|
||||||
|
|
||||||
sudo su -
|
|
||||||
|
|
||||||
yum -y install gcc kernel-devel make automake autoconf ncurses-devel
|
|
||||||
yum -y install git-core expect vim ruby ruby-devel ruby-irb
|
|
||||||
|
|
||||||
# install libevent2 from source
|
|
||||||
curl http://sourceforge.net/projects/levent/files/latest/download?source=files -L -o libevent2.tar.gz -w 'Last URL was: %{url_effective}'
|
|
||||||
cd ~/downloads
|
|
||||||
tar zxvf libevent2.tar.gz
|
|
||||||
cd ./libevent-*
|
|
||||||
./configure --prefix=/usr/local
|
|
||||||
make
|
|
||||||
make install
|
|
||||||
|
|
||||||
# compile tmux
|
|
||||||
git clone https://github.com/tmux/tmux.git ~/tmux_source
|
|
||||||
cd ~/tmux_source
|
|
||||||
git checkout 2.5
|
|
||||||
sh autogen.sh
|
|
||||||
LDFLAGS="-L/usr/local/lib -Wl,-rpath=/usr/local/lib" ./configure --prefix=/usr/local
|
|
||||||
make && sudo make install
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
sudo apt-get update
|
|
||||||
sudo apt-get install -y git-core expect vim
|
|
||||||
sudo apt-get install -y python-software-properties software-properties-common
|
|
||||||
sudo apt-get install -y build-essential libtool autotools-dev autoconf
|
|
||||||
sudo apt-get install -y pkg-config libevent-dev libncurses-dev
|
|
||||||
sudo apt-get install -y man-db
|
|
||||||
|
|
||||||
# install tmux 2.5
|
|
||||||
git clone https://github.com/tmux/tmux.git ~/tmux_source
|
|
||||||
cd ~/tmux_source
|
|
||||||
git checkout 2.5
|
|
||||||
sh autogen.sh
|
|
||||||
./configure && make && sudo make install
|
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
|
||||||
|
|
||||||
source "$CURRENT_DIR/scripts/variables.sh"
|
|
||||||
source "$CURRENT_DIR/scripts/helpers.sh"
|
|
||||||
|
|
||||||
set_save_bindings() {
|
|
||||||
local key_bindings=$(get_tmux_option "$save_option" "$default_save_key")
|
|
||||||
local key
|
|
||||||
for key in $key_bindings; do
|
|
||||||
tmux bind-key "$key" run-shell "$CURRENT_DIR/scripts/save.sh"
|
|
||||||
done
|
|
||||||
}
|
|
||||||
|
|
||||||
set_restore_bindings() {
|
|
||||||
local key_bindings=$(get_tmux_option "$restore_option" "$default_restore_key")
|
|
||||||
local key
|
|
||||||
for key in $key_bindings; do
|
|
||||||
tmux bind-key "$key" run-shell "$CURRENT_DIR/scripts/restore.sh"
|
|
||||||
done
|
|
||||||
}
|
|
||||||
|
|
||||||
set_default_strategies() {
|
|
||||||
tmux set-option -gq "${restore_process_strategy_option}irb" "default_strategy"
|
|
||||||
tmux set-option -gq "${restore_process_strategy_option}mosh-client" "default_strategy"
|
|
||||||
}
|
|
||||||
|
|
||||||
set_script_path_options() {
|
|
||||||
tmux set-option -gq "$save_path_option" "$CURRENT_DIR/scripts/save.sh"
|
|
||||||
tmux set-option -gq "$restore_path_option" "$CURRENT_DIR/scripts/restore.sh"
|
|
||||||
}
|
|
||||||
|
|
||||||
main() {
|
|
||||||
set_save_bindings
|
|
||||||
set_restore_bindings
|
|
||||||
set_default_strategies
|
|
||||||
set_script_path_options
|
|
||||||
}
|
|
||||||
main
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
|
||||||
|
|
||||||
PANE_PID="$1"
|
|
||||||
|
|
||||||
exit_safely_if_empty_ppid() {
|
|
||||||
if [ -z "$PANE_PID" ]; then
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
full_command() {
|
|
||||||
gdb -batch --eval "attach $PANE_PID" --eval "call write_history(\"/tmp/bash_history-${PANE_PID}.txt\")" --eval 'detach' --eval 'q' >/dev/null 2>&1
|
|
||||||
\tail -1 "/tmp/bash_history-${PANE_PID}.txt"
|
|
||||||
}
|
|
||||||
|
|
||||||
main() {
|
|
||||||
exit_safely_if_empty_ppid
|
|
||||||
full_command
|
|
||||||
}
|
|
||||||
main
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
|
||||||
|
|
||||||
PANE_PID="$1"
|
|
||||||
COMMAND_PID=$(pgrep -P $PANE_PID)
|
|
||||||
|
|
||||||
exit_safely_if_empty_ppid() {
|
|
||||||
if [ -z "$PANE_PID" ]; then
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
full_command() {
|
|
||||||
[[ -z "$COMMAND_PID" ]] && exit 0
|
|
||||||
# See: https://unix.stackexchange.com/a/567021
|
|
||||||
# Avoid complications with system printf by using bash subshell interpolation.
|
|
||||||
# This will properly escape sequences and null in cmdline.
|
|
||||||
cat /proc/${COMMAND_PID}/cmdline | xargs -0 bash -c 'printf "%q " "$0" "$@"'
|
|
||||||
}
|
|
||||||
|
|
||||||
main() {
|
|
||||||
exit_safely_if_empty_ppid
|
|
||||||
full_command
|
|
||||||
}
|
|
||||||
main
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
|
||||||
|
|
||||||
PANE_PID="$1"
|
|
||||||
|
|
||||||
exit_safely_if_empty_ppid() {
|
|
||||||
if [ -z "$PANE_PID" ]; then
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
full_command() {
|
|
||||||
\pgrep -lf -P "$PANE_PID" |
|
|
||||||
cut -d' ' -f2-
|
|
||||||
}
|
|
||||||
|
|
||||||
main() {
|
|
||||||
exit_safely_if_empty_ppid
|
|
||||||
full_command
|
|
||||||
}
|
|
||||||
main
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
|
||||||
|
|
||||||
PANE_PID="$1"
|
|
||||||
|
|
||||||
exit_safely_if_empty_ppid() {
|
|
||||||
if [ -z "$PANE_PID" ]; then
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
full_command() {
|
|
||||||
ps -ao "ppid,args" |
|
|
||||||
sed "s/^ *//" |
|
|
||||||
grep "^${PANE_PID}" |
|
|
||||||
cut -d' ' -f2-
|
|
||||||
}
|
|
||||||
|
|
||||||
main() {
|
|
||||||
exit_safely_if_empty_ppid
|
|
||||||
full_command
|
|
||||||
}
|
|
||||||
main
|
|
||||||
@@ -1,78 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
VERSION="$1"
|
|
||||||
UNSUPPORTED_MSG="$2"
|
|
||||||
|
|
||||||
get_tmux_option() {
|
|
||||||
local option=$1
|
|
||||||
local default_value=$2
|
|
||||||
local option_value=$(tmux show-option -gqv "$option")
|
|
||||||
if [ -z "$option_value" ]; then
|
|
||||||
echo "$default_value"
|
|
||||||
else
|
|
||||||
echo "$option_value"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
# Ensures a message is displayed for 5 seconds in tmux prompt.
|
|
||||||
# Does not override the 'display-time' tmux option.
|
|
||||||
display_message() {
|
|
||||||
local message="$1"
|
|
||||||
|
|
||||||
# display_duration defaults to 5 seconds, if not passed as an argument
|
|
||||||
if [ "$#" -eq 2 ]; then
|
|
||||||
local display_duration="$2"
|
|
||||||
else
|
|
||||||
local display_duration="5000"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# saves user-set 'display-time' option
|
|
||||||
local saved_display_time=$(get_tmux_option "display-time" "750")
|
|
||||||
|
|
||||||
# sets message display time to 5 seconds
|
|
||||||
tmux set-option -gq display-time "$display_duration"
|
|
||||||
|
|
||||||
# displays message
|
|
||||||
tmux display-message "$message"
|
|
||||||
|
|
||||||
# restores original 'display-time' value
|
|
||||||
tmux set-option -gq display-time "$saved_display_time"
|
|
||||||
}
|
|
||||||
|
|
||||||
# this is used to get "clean" integer version number. Examples:
|
|
||||||
# `tmux 1.9` => `19`
|
|
||||||
# `1.9a` => `19`
|
|
||||||
get_digits_from_string() {
|
|
||||||
local string="$1"
|
|
||||||
local only_digits="$(echo "$string" | tr -dC '[:digit:]')"
|
|
||||||
echo "$only_digits"
|
|
||||||
}
|
|
||||||
|
|
||||||
tmux_version_int() {
|
|
||||||
local tmux_version_string=$(tmux -V)
|
|
||||||
echo "$(get_digits_from_string "$tmux_version_string")"
|
|
||||||
}
|
|
||||||
|
|
||||||
unsupported_version_message() {
|
|
||||||
if [ -n "$UNSUPPORTED_MSG" ]; then
|
|
||||||
echo "$UNSUPPORTED_MSG"
|
|
||||||
else
|
|
||||||
echo "Error, Tmux version unsupported! Please install Tmux version $VERSION or greater!"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
exit_if_unsupported_version() {
|
|
||||||
local current_version="$1"
|
|
||||||
local supported_version="$2"
|
|
||||||
if [ "$current_version" -lt "$supported_version" ]; then
|
|
||||||
display_message "$(unsupported_version_message)"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
main() {
|
|
||||||
local supported_version_int="$(get_digits_from_string "$VERSION")"
|
|
||||||
local current_version_int="$(tmux_version_int)"
|
|
||||||
exit_if_unsupported_version "$current_version_int" "$supported_version_int"
|
|
||||||
}
|
|
||||||
main
|
|
||||||
@@ -1,159 +0,0 @@
|
|||||||
if [ -d "$HOME/.tmux/resurrect" ]; then
|
|
||||||
default_resurrect_dir="$HOME/.tmux/resurrect"
|
|
||||||
else
|
|
||||||
default_resurrect_dir="${XDG_DATA_HOME:-$HOME/.local/share}"/tmux/resurrect
|
|
||||||
fi
|
|
||||||
resurrect_dir_option="@resurrect-dir"
|
|
||||||
|
|
||||||
SUPPORTED_VERSION="1.9"
|
|
||||||
RESURRECT_FILE_PREFIX="tmux_resurrect"
|
|
||||||
RESURRECT_FILE_EXTENSION="txt"
|
|
||||||
_RESURRECT_DIR=""
|
|
||||||
_RESURRECT_FILE_PATH=""
|
|
||||||
|
|
||||||
d=$'\t'
|
|
||||||
|
|
||||||
# helper functions
|
|
||||||
get_tmux_option() {
|
|
||||||
local option="$1"
|
|
||||||
local default_value="$2"
|
|
||||||
local option_value=$(tmux show-option -gqv "$option")
|
|
||||||
if [ -z "$option_value" ]; then
|
|
||||||
echo "$default_value"
|
|
||||||
else
|
|
||||||
echo "$option_value"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
# Ensures a message is displayed for 5 seconds in tmux prompt.
|
|
||||||
# Does not override the 'display-time' tmux option.
|
|
||||||
display_message() {
|
|
||||||
local message="$1"
|
|
||||||
|
|
||||||
# display_duration defaults to 5 seconds, if not passed as an argument
|
|
||||||
if [ "$#" -eq 2 ]; then
|
|
||||||
local display_duration="$2"
|
|
||||||
else
|
|
||||||
local display_duration="5000"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# saves user-set 'display-time' option
|
|
||||||
local saved_display_time=$(get_tmux_option "display-time" "750")
|
|
||||||
|
|
||||||
# sets message display time to 5 seconds
|
|
||||||
tmux set-option -gq display-time "$display_duration"
|
|
||||||
|
|
||||||
# displays message
|
|
||||||
tmux display-message "$message"
|
|
||||||
|
|
||||||
# restores original 'display-time' value
|
|
||||||
tmux set-option -gq display-time "$saved_display_time"
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
supported_tmux_version_ok() {
|
|
||||||
$CURRENT_DIR/check_tmux_version.sh "$SUPPORTED_VERSION"
|
|
||||||
}
|
|
||||||
|
|
||||||
remove_first_char() {
|
|
||||||
echo "$1" | cut -c2-
|
|
||||||
}
|
|
||||||
|
|
||||||
capture_pane_contents_option_on() {
|
|
||||||
local option="$(get_tmux_option "$pane_contents_option" "off")"
|
|
||||||
[ "$option" == "on" ]
|
|
||||||
}
|
|
||||||
|
|
||||||
files_differ() {
|
|
||||||
! cmp -s "$1" "$2"
|
|
||||||
}
|
|
||||||
|
|
||||||
get_grouped_sessions() {
|
|
||||||
local grouped_sessions_dump="$1"
|
|
||||||
export GROUPED_SESSIONS="${d}$(echo "$grouped_sessions_dump" | cut -f2 -d"$d" | tr "\\n" "$d")"
|
|
||||||
}
|
|
||||||
|
|
||||||
is_session_grouped() {
|
|
||||||
local session_name="$1"
|
|
||||||
[[ "$GROUPED_SESSIONS" == *"${d}${session_name}${d}"* ]]
|
|
||||||
}
|
|
||||||
|
|
||||||
# pane content file helpers
|
|
||||||
|
|
||||||
pane_contents_create_archive() {
|
|
||||||
tar cf - -C "$(resurrect_dir)/save/" ./pane_contents/ |
|
|
||||||
gzip > "$(pane_contents_archive_file)"
|
|
||||||
}
|
|
||||||
|
|
||||||
pane_content_files_restore_from_archive() {
|
|
||||||
local archive_file="$(pane_contents_archive_file)"
|
|
||||||
if [ -f "$archive_file" ]; then
|
|
||||||
mkdir -p "$(pane_contents_dir "restore")"
|
|
||||||
gzip -d < "$archive_file" |
|
|
||||||
tar xf - -C "$(resurrect_dir)/restore/"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
# path helpers
|
|
||||||
|
|
||||||
resurrect_dir() {
|
|
||||||
if [ -z "$_RESURRECT_DIR" ]; then
|
|
||||||
local path="$(get_tmux_option "$resurrect_dir_option" "$default_resurrect_dir")"
|
|
||||||
# expands tilde, $HOME and $HOSTNAME if used in @resurrect-dir
|
|
||||||
echo "$path" | sed "s,\$HOME,$HOME,g; s,\$HOSTNAME,$(hostname),g; s,\~,$HOME,g"
|
|
||||||
else
|
|
||||||
echo "$_RESURRECT_DIR"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
_RESURRECT_DIR="$(resurrect_dir)"
|
|
||||||
|
|
||||||
resurrect_file_path() {
|
|
||||||
if [ -z "$_RESURRECT_FILE_PATH" ]; then
|
|
||||||
local timestamp="$(date +"%Y%m%dT%H%M%S")"
|
|
||||||
echo "$(resurrect_dir)/${RESURRECT_FILE_PREFIX}_${timestamp}.${RESURRECT_FILE_EXTENSION}"
|
|
||||||
else
|
|
||||||
echo "$_RESURRECT_FILE_PATH"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
_RESURRECT_FILE_PATH="$(resurrect_file_path)"
|
|
||||||
|
|
||||||
last_resurrect_file() {
|
|
||||||
echo "$(resurrect_dir)/last"
|
|
||||||
}
|
|
||||||
|
|
||||||
pane_contents_dir() {
|
|
||||||
echo "$(resurrect_dir)/$1/pane_contents/"
|
|
||||||
}
|
|
||||||
|
|
||||||
pane_contents_file() {
|
|
||||||
local save_or_restore="$1"
|
|
||||||
local pane_id="$2"
|
|
||||||
echo "$(pane_contents_dir "$save_or_restore")/pane-${pane_id}"
|
|
||||||
}
|
|
||||||
|
|
||||||
pane_contents_file_exists() {
|
|
||||||
local pane_id="$1"
|
|
||||||
[ -f "$(pane_contents_file "restore" "$pane_id")" ]
|
|
||||||
}
|
|
||||||
|
|
||||||
pane_contents_archive_file() {
|
|
||||||
echo "$(resurrect_dir)/pane_contents.tar.gz"
|
|
||||||
}
|
|
||||||
|
|
||||||
execute_hook() {
|
|
||||||
local kind="$1"
|
|
||||||
shift
|
|
||||||
local args="" hook=""
|
|
||||||
|
|
||||||
hook=$(get_tmux_option "$hook_prefix$kind" "")
|
|
||||||
|
|
||||||
# If there are any args, pass them to the hook (in a way that preserves/copes
|
|
||||||
# with spaces and unusual characters.
|
|
||||||
if [ "$#" -gt 0 ]; then
|
|
||||||
printf -v args "%q " "$@"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -n "$hook" ]; then
|
|
||||||
eval "$hook $args"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
@@ -1,198 +0,0 @@
|
|||||||
restore_pane_processes_enabled() {
|
|
||||||
local restore_processes="$(get_tmux_option "$restore_processes_option" "$restore_processes")"
|
|
||||||
if [ "$restore_processes" == "false" ]; then
|
|
||||||
return 1
|
|
||||||
else
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
restore_pane_process() {
|
|
||||||
local pane_full_command="$1"
|
|
||||||
local session_name="$2"
|
|
||||||
local window_number="$3"
|
|
||||||
local pane_index="$4"
|
|
||||||
local dir="$5"
|
|
||||||
local command
|
|
||||||
if _process_should_be_restored "$pane_full_command" "$session_name" "$window_number" "$pane_index"; then
|
|
||||||
tmux switch-client -t "${session_name}:${window_number}"
|
|
||||||
tmux select-pane -t "$pane_index"
|
|
||||||
|
|
||||||
local inline_strategy="$(_get_inline_strategy "$pane_full_command")" # might not be defined
|
|
||||||
if [ -n "$inline_strategy" ]; then
|
|
||||||
# inline strategy exists
|
|
||||||
# check for additional "expansion" of inline strategy, e.g. `vim` to `vim -S`
|
|
||||||
if _strategy_exists "$inline_strategy"; then
|
|
||||||
local strategy_file="$(_get_strategy_file "$inline_strategy")"
|
|
||||||
local inline_strategy="$($strategy_file "$pane_full_command" "$dir")"
|
|
||||||
fi
|
|
||||||
command="$inline_strategy"
|
|
||||||
elif _strategy_exists "$pane_full_command"; then
|
|
||||||
local strategy_file="$(_get_strategy_file "$pane_full_command")"
|
|
||||||
local strategy_command="$($strategy_file "$pane_full_command" "$dir")"
|
|
||||||
command="$strategy_command"
|
|
||||||
else
|
|
||||||
# just invoke the raw command
|
|
||||||
command="$pane_full_command"
|
|
||||||
fi
|
|
||||||
tmux send-keys -t "${session_name}:${window_number}.${pane_index}" "$command" "C-m"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
# private functions below
|
|
||||||
|
|
||||||
_process_should_be_restored() {
|
|
||||||
local pane_full_command="$1"
|
|
||||||
local session_name="$2"
|
|
||||||
local window_number="$3"
|
|
||||||
local pane_index="$4"
|
|
||||||
if is_pane_registered_as_existing "$session_name" "$window_number" "$pane_index"; then
|
|
||||||
# Scenario where pane existed before restoration, so we're not
|
|
||||||
# restoring the proces either.
|
|
||||||
return 1
|
|
||||||
elif ! pane_exists "$session_name" "$window_number" "$pane_index"; then
|
|
||||||
# pane number limit exceeded, pane does not exist
|
|
||||||
return 1
|
|
||||||
elif _restore_all_processes; then
|
|
||||||
return 0
|
|
||||||
elif _process_on_the_restore_list "$pane_full_command"; then
|
|
||||||
return 0
|
|
||||||
else
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
_restore_all_processes() {
|
|
||||||
local restore_processes="$(get_tmux_option "$restore_processes_option" "$restore_processes")"
|
|
||||||
if [ "$restore_processes" == ":all:" ]; then
|
|
||||||
return 0
|
|
||||||
else
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
_process_on_the_restore_list() {
|
|
||||||
local pane_full_command="$1"
|
|
||||||
# TODO: make this work without eval
|
|
||||||
eval set $(_restore_list)
|
|
||||||
local proc
|
|
||||||
local match
|
|
||||||
for proc in "$@"; do
|
|
||||||
match="$(_get_proc_match_element "$proc")"
|
|
||||||
if _proc_matches_full_command "$pane_full_command" "$match"; then
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
|
|
||||||
_proc_matches_full_command() {
|
|
||||||
local pane_full_command="$1"
|
|
||||||
local match="$2"
|
|
||||||
if _proc_starts_with_tildae "$match"; then
|
|
||||||
match="$(remove_first_char "$match")"
|
|
||||||
# regex matching the command makes sure `$match` string is somewhere in the command string
|
|
||||||
if [[ "$pane_full_command" =~ ($match) ]]; then
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
# regex matching the command makes sure process is a "word"
|
|
||||||
if [[ "$pane_full_command" =~ (^${match} ) ]] || [[ "$pane_full_command" =~ (^${match}$) ]]; then
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
|
|
||||||
_get_proc_match_element() {
|
|
||||||
echo "$1" | sed "s/${inline_strategy_token}.*//"
|
|
||||||
}
|
|
||||||
|
|
||||||
_get_proc_restore_element() {
|
|
||||||
echo "$1" | sed "s/.*${inline_strategy_token}//"
|
|
||||||
}
|
|
||||||
|
|
||||||
# given full command: 'ruby /Users/john/bin/my_program arg1 arg2'
|
|
||||||
# and inline strategy: '~bin/my_program->my_program *'
|
|
||||||
# returns: 'arg1 arg2'
|
|
||||||
_get_command_arguments() {
|
|
||||||
local pane_full_command="$1"
|
|
||||||
local match="$2"
|
|
||||||
if _proc_starts_with_tildae "$match"; then
|
|
||||||
match="$(remove_first_char "$match")"
|
|
||||||
fi
|
|
||||||
echo "$pane_full_command" | sed "s,^.*${match}[^ ]* *,,"
|
|
||||||
}
|
|
||||||
|
|
||||||
_get_proc_restore_command() {
|
|
||||||
local pane_full_command="$1"
|
|
||||||
local proc="$2"
|
|
||||||
local match="$3"
|
|
||||||
local restore_element="$(_get_proc_restore_element "$proc")"
|
|
||||||
if [[ "$restore_element" =~ " ${inline_strategy_arguments_token}" ]]; then
|
|
||||||
# replaces "%" with command arguments
|
|
||||||
local command_arguments="$(_get_command_arguments "$pane_full_command" "$match")"
|
|
||||||
echo "$restore_element" | sed "s,${inline_strategy_arguments_token},${command_arguments},"
|
|
||||||
else
|
|
||||||
echo "$restore_element"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
_restore_list() {
|
|
||||||
local user_processes="$(get_tmux_option "$restore_processes_option" "$restore_processes")"
|
|
||||||
local default_processes="$(get_tmux_option "$default_proc_list_option" "$default_proc_list")"
|
|
||||||
if [ -z "$user_processes" ]; then
|
|
||||||
# user didn't define any processes
|
|
||||||
echo "$default_processes"
|
|
||||||
else
|
|
||||||
echo "$default_processes $user_processes"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
_proc_starts_with_tildae() {
|
|
||||||
[[ "$1" =~ (^~) ]]
|
|
||||||
}
|
|
||||||
|
|
||||||
_get_inline_strategy() {
|
|
||||||
local pane_full_command="$1"
|
|
||||||
# TODO: make this work without eval
|
|
||||||
eval set $(_restore_list)
|
|
||||||
local proc
|
|
||||||
local match
|
|
||||||
for proc in "$@"; do
|
|
||||||
if [[ "$proc" =~ "$inline_strategy_token" ]]; then
|
|
||||||
match="$(_get_proc_match_element "$proc")"
|
|
||||||
if _proc_matches_full_command "$pane_full_command" "$match"; then
|
|
||||||
echo "$(_get_proc_restore_command "$pane_full_command" "$proc" "$match")"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
}
|
|
||||||
|
|
||||||
_strategy_exists() {
|
|
||||||
local pane_full_command="$1"
|
|
||||||
local strategy="$(_get_command_strategy "$pane_full_command")"
|
|
||||||
if [ -n "$strategy" ]; then # strategy set?
|
|
||||||
local strategy_file="$(_get_strategy_file "$pane_full_command")"
|
|
||||||
[ -e "$strategy_file" ] # strategy file exists?
|
|
||||||
else
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
_get_command_strategy() {
|
|
||||||
local pane_full_command="$1"
|
|
||||||
local command="$(_just_command "$pane_full_command")"
|
|
||||||
get_tmux_option "${restore_process_strategy_option}${command}" ""
|
|
||||||
}
|
|
||||||
|
|
||||||
_just_command() {
|
|
||||||
echo "$1" | cut -d' ' -f1
|
|
||||||
}
|
|
||||||
|
|
||||||
_get_strategy_file() {
|
|
||||||
local pane_full_command="$1"
|
|
||||||
local strategy="$(_get_command_strategy "$pane_full_command")"
|
|
||||||
local command="$(_just_command "$pane_full_command")"
|
|
||||||
echo "$CURRENT_DIR/../strategies/${command}_${strategy}.sh"
|
|
||||||
}
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
#!/usr/bin/env expect
|
|
||||||
|
|
||||||
# start tmux
|
|
||||||
spawn tmux -S/tmp/foo
|
|
||||||
|
|
||||||
# delay with sleep to compensate for tmux starting time
|
|
||||||
sleep 2
|
|
||||||
|
|
||||||
# run restore script directly
|
|
||||||
send "~/.tmux/plugins/tmux-resurrect/scripts/restore.sh\r"
|
|
||||||
|
|
||||||
# long wait until tmux restore is complete
|
|
||||||
# (things get messed up if expect client isn't attached)
|
|
||||||
sleep 100
|
|
||||||
@@ -1,387 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
|
||||||
|
|
||||||
source "$CURRENT_DIR/variables.sh"
|
|
||||||
source "$CURRENT_DIR/helpers.sh"
|
|
||||||
source "$CURRENT_DIR/process_restore_helpers.sh"
|
|
||||||
source "$CURRENT_DIR/spinner_helpers.sh"
|
|
||||||
|
|
||||||
# delimiter
|
|
||||||
d=$'\t'
|
|
||||||
|
|
||||||
# Global variable.
|
|
||||||
# Used during the restore: if a pane already exists from before, it is
|
|
||||||
# saved in the array in this variable. Later, process running in existing pane
|
|
||||||
# is also not restored. That makes the restoration process more idempotent.
|
|
||||||
EXISTING_PANES_VAR=""
|
|
||||||
|
|
||||||
RESTORING_FROM_SCRATCH="false"
|
|
||||||
|
|
||||||
RESTORE_PANE_CONTENTS="false"
|
|
||||||
|
|
||||||
is_line_type() {
|
|
||||||
local line_type="$1"
|
|
||||||
local line="$2"
|
|
||||||
echo "$line" |
|
|
||||||
\grep -q "^$line_type"
|
|
||||||
}
|
|
||||||
|
|
||||||
check_saved_session_exists() {
|
|
||||||
local resurrect_file="$(last_resurrect_file)"
|
|
||||||
if [ ! -f $resurrect_file ]; then
|
|
||||||
display_message "Tmux resurrect file not found!"
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
pane_exists() {
|
|
||||||
local session_name="$1"
|
|
||||||
local window_number="$2"
|
|
||||||
local pane_index="$3"
|
|
||||||
tmux list-panes -t "${session_name}:${window_number}" -F "#{pane_index}" 2>/dev/null |
|
|
||||||
\grep -q "^$pane_index$"
|
|
||||||
}
|
|
||||||
|
|
||||||
register_existing_pane() {
|
|
||||||
local session_name="$1"
|
|
||||||
local window_number="$2"
|
|
||||||
local pane_index="$3"
|
|
||||||
local pane_custom_id="${session_name}:${window_number}:${pane_index}"
|
|
||||||
local delimiter=$'\t'
|
|
||||||
EXISTING_PANES_VAR="${EXISTING_PANES_VAR}${delimiter}${pane_custom_id}"
|
|
||||||
}
|
|
||||||
|
|
||||||
is_pane_registered_as_existing() {
|
|
||||||
local session_name="$1"
|
|
||||||
local window_number="$2"
|
|
||||||
local pane_index="$3"
|
|
||||||
local pane_custom_id="${session_name}:${window_number}:${pane_index}"
|
|
||||||
[[ "$EXISTING_PANES_VAR" =~ "$pane_custom_id" ]]
|
|
||||||
}
|
|
||||||
|
|
||||||
restore_from_scratch_true() {
|
|
||||||
RESTORING_FROM_SCRATCH="true"
|
|
||||||
}
|
|
||||||
|
|
||||||
is_restoring_from_scratch() {
|
|
||||||
[ "$RESTORING_FROM_SCRATCH" == "true" ]
|
|
||||||
}
|
|
||||||
|
|
||||||
restore_pane_contents_true() {
|
|
||||||
RESTORE_PANE_CONTENTS="true"
|
|
||||||
}
|
|
||||||
|
|
||||||
is_restoring_pane_contents() {
|
|
||||||
[ "$RESTORE_PANE_CONTENTS" == "true" ]
|
|
||||||
}
|
|
||||||
|
|
||||||
restored_session_0_true() {
|
|
||||||
RESTORED_SESSION_0="true"
|
|
||||||
}
|
|
||||||
|
|
||||||
has_restored_session_0() {
|
|
||||||
[ "$RESTORED_SESSION_0" == "true" ]
|
|
||||||
}
|
|
||||||
|
|
||||||
window_exists() {
|
|
||||||
local session_name="$1"
|
|
||||||
local window_number="$2"
|
|
||||||
tmux list-windows -t "$session_name" -F "#{window_index}" 2>/dev/null |
|
|
||||||
\grep -q "^$window_number$"
|
|
||||||
}
|
|
||||||
|
|
||||||
session_exists() {
|
|
||||||
local session_name="$1"
|
|
||||||
tmux has-session -t "$session_name" 2>/dev/null
|
|
||||||
}
|
|
||||||
|
|
||||||
first_window_num() {
|
|
||||||
tmux show -gv base-index
|
|
||||||
}
|
|
||||||
|
|
||||||
tmux_socket() {
|
|
||||||
echo $TMUX | cut -d',' -f1
|
|
||||||
}
|
|
||||||
|
|
||||||
# Tmux option stored in a global variable so that we don't have to "ask"
|
|
||||||
# tmux server each time.
|
|
||||||
cache_tmux_default_command() {
|
|
||||||
local default_shell="$(get_tmux_option "default-shell" "")"
|
|
||||||
local opt=""
|
|
||||||
if [ "$(basename "$default_shell")" == "bash" ]; then
|
|
||||||
opt="-l "
|
|
||||||
fi
|
|
||||||
export TMUX_DEFAULT_COMMAND="$(get_tmux_option "default-command" "$opt$default_shell")"
|
|
||||||
}
|
|
||||||
|
|
||||||
tmux_default_command() {
|
|
||||||
echo "$TMUX_DEFAULT_COMMAND"
|
|
||||||
}
|
|
||||||
|
|
||||||
pane_creation_command() {
|
|
||||||
echo "cat '$(pane_contents_file "restore" "${1}:${2}.${3}")'; exec $(tmux_default_command)"
|
|
||||||
}
|
|
||||||
|
|
||||||
new_window() {
|
|
||||||
local session_name="$1"
|
|
||||||
local window_number="$2"
|
|
||||||
local dir="$3"
|
|
||||||
local pane_index="$4"
|
|
||||||
local pane_id="${session_name}:${window_number}.${pane_index}"
|
|
||||||
dir="${dir/#\~/$HOME}"
|
|
||||||
if is_restoring_pane_contents && pane_contents_file_exists "$pane_id"; then
|
|
||||||
local pane_creation_command="$(pane_creation_command "$session_name" "$window_number" "$pane_index")"
|
|
||||||
tmux new-window -d -t "${session_name}:${window_number}" -c "$dir" "$pane_creation_command"
|
|
||||||
else
|
|
||||||
tmux new-window -d -t "${session_name}:${window_number}" -c "$dir"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
new_session() {
|
|
||||||
local session_name="$1"
|
|
||||||
local window_number="$2"
|
|
||||||
local dir="$3"
|
|
||||||
local pane_index="$4"
|
|
||||||
local pane_id="${session_name}:${window_number}.${pane_index}"
|
|
||||||
if is_restoring_pane_contents && pane_contents_file_exists "$pane_id"; then
|
|
||||||
local pane_creation_command="$(pane_creation_command "$session_name" "$window_number" "$pane_index")"
|
|
||||||
TMUX="" tmux -S "$(tmux_socket)" new-session -d -s "$session_name" -c "$dir" "$pane_creation_command"
|
|
||||||
else
|
|
||||||
TMUX="" tmux -S "$(tmux_socket)" new-session -d -s "$session_name" -c "$dir"
|
|
||||||
fi
|
|
||||||
# change first window number if necessary
|
|
||||||
local created_window_num="$(first_window_num)"
|
|
||||||
if [ $created_window_num -ne $window_number ]; then
|
|
||||||
tmux move-window -s "${session_name}:${created_window_num}" -t "${session_name}:${window_number}"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
new_pane() {
|
|
||||||
local session_name="$1"
|
|
||||||
local window_number="$2"
|
|
||||||
local dir="$3"
|
|
||||||
local pane_index="$4"
|
|
||||||
local pane_id="${session_name}:${window_number}.${pane_index}"
|
|
||||||
if is_restoring_pane_contents && pane_contents_file_exists "$pane_id"; then
|
|
||||||
local pane_creation_command="$(pane_creation_command "$session_name" "$window_number" "$pane_index")"
|
|
||||||
tmux split-window -t "${session_name}:${window_number}" -c "$dir" "$pane_creation_command"
|
|
||||||
else
|
|
||||||
tmux split-window -t "${session_name}:${window_number}" -c "$dir"
|
|
||||||
fi
|
|
||||||
# minimize window so more panes can fit
|
|
||||||
tmux resize-pane -t "${session_name}:${window_number}" -U "999"
|
|
||||||
}
|
|
||||||
|
|
||||||
restore_pane() {
|
|
||||||
local pane="$1"
|
|
||||||
while IFS=$d read line_type session_name window_number window_active window_flags pane_index pane_title dir pane_active pane_command pane_full_command; do
|
|
||||||
dir="$(remove_first_char "$dir")"
|
|
||||||
pane_full_command="$(remove_first_char "$pane_full_command")"
|
|
||||||
if [ "$session_name" == "0" ]; then
|
|
||||||
restored_session_0_true
|
|
||||||
fi
|
|
||||||
if pane_exists "$session_name" "$window_number" "$pane_index"; then
|
|
||||||
if is_restoring_from_scratch; then
|
|
||||||
# overwrite the pane
|
|
||||||
# happens only for the first pane if it's the only registered pane for the whole tmux server
|
|
||||||
local pane_id="$(tmux display-message -p -F "#{pane_id}" -t "$session_name:$window_number")"
|
|
||||||
new_pane "$session_name" "$window_number" "$dir" "$pane_index"
|
|
||||||
tmux kill-pane -t "$pane_id"
|
|
||||||
else
|
|
||||||
# Pane exists, no need to create it!
|
|
||||||
# Pane existence is registered. Later, its process also won't be restored.
|
|
||||||
register_existing_pane "$session_name" "$window_number" "$pane_index"
|
|
||||||
fi
|
|
||||||
elif window_exists "$session_name" "$window_number"; then
|
|
||||||
new_pane "$session_name" "$window_number" "$dir" "$pane_index"
|
|
||||||
elif session_exists "$session_name"; then
|
|
||||||
new_window "$session_name" "$window_number" "$dir" "$pane_index"
|
|
||||||
else
|
|
||||||
new_session "$session_name" "$window_number" "$dir" "$pane_index"
|
|
||||||
fi
|
|
||||||
# set pane title
|
|
||||||
tmux select-pane -t "$session_name:$window_number.$pane_index" -T "$pane_title"
|
|
||||||
done < <(echo "$pane")
|
|
||||||
}
|
|
||||||
|
|
||||||
restore_state() {
|
|
||||||
local state="$1"
|
|
||||||
echo "$state" |
|
|
||||||
while IFS=$d read line_type client_session client_last_session; do
|
|
||||||
tmux switch-client -t "$client_last_session"
|
|
||||||
tmux switch-client -t "$client_session"
|
|
||||||
done
|
|
||||||
}
|
|
||||||
|
|
||||||
restore_grouped_session() {
|
|
||||||
local grouped_session="$1"
|
|
||||||
echo "$grouped_session" |
|
|
||||||
while IFS=$d read line_type grouped_session original_session alternate_window active_window; do
|
|
||||||
TMUX="" tmux -S "$(tmux_socket)" new-session -d -s "$grouped_session" -t "$original_session"
|
|
||||||
done
|
|
||||||
}
|
|
||||||
|
|
||||||
restore_active_and_alternate_windows_for_grouped_sessions() {
|
|
||||||
local grouped_session="$1"
|
|
||||||
echo "$grouped_session" |
|
|
||||||
while IFS=$d read line_type grouped_session original_session alternate_window_index active_window_index; do
|
|
||||||
alternate_window_index="$(remove_first_char "$alternate_window_index")"
|
|
||||||
active_window_index="$(remove_first_char "$active_window_index")"
|
|
||||||
if [ -n "$alternate_window_index" ]; then
|
|
||||||
tmux switch-client -t "${grouped_session}:${alternate_window_index}"
|
|
||||||
fi
|
|
||||||
if [ -n "$active_window_index" ]; then
|
|
||||||
tmux switch-client -t "${grouped_session}:${active_window_index}"
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
}
|
|
||||||
|
|
||||||
never_ever_overwrite() {
|
|
||||||
local overwrite_option_value="$(get_tmux_option "$overwrite_option" "")"
|
|
||||||
[ -n "$overwrite_option_value" ]
|
|
||||||
}
|
|
||||||
|
|
||||||
detect_if_restoring_from_scratch() {
|
|
||||||
if never_ever_overwrite; then
|
|
||||||
return
|
|
||||||
fi
|
|
||||||
local total_number_of_panes="$(tmux list-panes -a | wc -l | sed 's/ //g')"
|
|
||||||
if [ "$total_number_of_panes" -eq 1 ]; then
|
|
||||||
restore_from_scratch_true
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
detect_if_restoring_pane_contents() {
|
|
||||||
if capture_pane_contents_option_on; then
|
|
||||||
cache_tmux_default_command
|
|
||||||
restore_pane_contents_true
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
# functions called from main (ordered)
|
|
||||||
|
|
||||||
restore_all_panes() {
|
|
||||||
detect_if_restoring_from_scratch # sets a global variable
|
|
||||||
detect_if_restoring_pane_contents # sets a global variable
|
|
||||||
if is_restoring_pane_contents; then
|
|
||||||
pane_content_files_restore_from_archive
|
|
||||||
fi
|
|
||||||
while read line; do
|
|
||||||
if is_line_type "pane" "$line"; then
|
|
||||||
restore_pane "$line"
|
|
||||||
fi
|
|
||||||
done < $(last_resurrect_file)
|
|
||||||
}
|
|
||||||
|
|
||||||
handle_session_0() {
|
|
||||||
if is_restoring_from_scratch && ! has_restored_session_0; then
|
|
||||||
local current_session="$(tmux display -p "#{client_session}")"
|
|
||||||
if [ "$current_session" == "0" ]; then
|
|
||||||
tmux switch-client -n
|
|
||||||
fi
|
|
||||||
tmux kill-session -t "0"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
restore_window_properties() {
|
|
||||||
local window_name
|
|
||||||
\grep '^window' $(last_resurrect_file) |
|
|
||||||
while IFS=$d read line_type session_name window_number window_name window_active window_flags window_layout automatic_rename; do
|
|
||||||
tmux select-layout -t "${session_name}:${window_number}" "$window_layout"
|
|
||||||
|
|
||||||
# Below steps are properly handling window names and automatic-rename
|
|
||||||
# option. `rename-window` is an extra command in some scenarios, but we
|
|
||||||
# opted for always doing it to keep the code simple.
|
|
||||||
window_name="$(remove_first_char "$window_name")"
|
|
||||||
tmux rename-window -t "${session_name}:${window_number}" "$window_name"
|
|
||||||
if [ "${automatic_rename}" = ":" ]; then
|
|
||||||
tmux set-option -u -t "${session_name}:${window_number}" automatic-rename
|
|
||||||
else
|
|
||||||
tmux set-option -t "${session_name}:${window_number}" automatic-rename "$automatic_rename"
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
}
|
|
||||||
|
|
||||||
restore_all_pane_processes() {
|
|
||||||
if restore_pane_processes_enabled; then
|
|
||||||
local pane_full_command
|
|
||||||
awk 'BEGIN { FS="\t"; OFS="\t" } /^pane/ && $11 !~ "^:$" { print $2, $3, $6, $8, $11; }' $(last_resurrect_file) |
|
|
||||||
while IFS=$d read -r session_name window_number pane_index dir pane_full_command; do
|
|
||||||
dir="$(remove_first_char "$dir")"
|
|
||||||
pane_full_command="$(remove_first_char "$pane_full_command")"
|
|
||||||
restore_pane_process "$pane_full_command" "$session_name" "$window_number" "$pane_index" "$dir"
|
|
||||||
done
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
restore_active_pane_for_each_window() {
|
|
||||||
awk 'BEGIN { FS="\t"; OFS="\t" } /^pane/ && $9 == 1 { print $2, $3, $6; }' $(last_resurrect_file) |
|
|
||||||
while IFS=$d read session_name window_number active_pane; do
|
|
||||||
tmux switch-client -t "${session_name}:${window_number}"
|
|
||||||
tmux select-pane -t "$active_pane"
|
|
||||||
done
|
|
||||||
}
|
|
||||||
|
|
||||||
restore_zoomed_windows() {
|
|
||||||
awk 'BEGIN { FS="\t"; OFS="\t" } /^pane/ && $5 ~ /Z/ && $9 == 1 { print $2, $3; }' $(last_resurrect_file) |
|
|
||||||
while IFS=$d read session_name window_number; do
|
|
||||||
tmux resize-pane -t "${session_name}:${window_number}" -Z
|
|
||||||
done
|
|
||||||
}
|
|
||||||
|
|
||||||
restore_grouped_sessions() {
|
|
||||||
while read line; do
|
|
||||||
if is_line_type "grouped_session" "$line"; then
|
|
||||||
restore_grouped_session "$line"
|
|
||||||
restore_active_and_alternate_windows_for_grouped_sessions "$line"
|
|
||||||
fi
|
|
||||||
done < $(last_resurrect_file)
|
|
||||||
}
|
|
||||||
|
|
||||||
restore_active_and_alternate_windows() {
|
|
||||||
awk 'BEGIN { FS="\t"; OFS="\t" } /^window/ && $6 ~ /[*-]/ { print $2, $5, $3; }' $(last_resurrect_file) |
|
|
||||||
sort -u |
|
|
||||||
while IFS=$d read session_name active_window window_number; do
|
|
||||||
tmux switch-client -t "${session_name}:${window_number}"
|
|
||||||
done
|
|
||||||
}
|
|
||||||
|
|
||||||
restore_active_and_alternate_sessions() {
|
|
||||||
while read line; do
|
|
||||||
if is_line_type "state" "$line"; then
|
|
||||||
restore_state "$line"
|
|
||||||
fi
|
|
||||||
done < $(last_resurrect_file)
|
|
||||||
}
|
|
||||||
|
|
||||||
# A cleanup that happens after 'restore_all_panes' seems to fix fish shell
|
|
||||||
# users' restore problems.
|
|
||||||
cleanup_restored_pane_contents() {
|
|
||||||
if is_restoring_pane_contents; then
|
|
||||||
rm "$(pane_contents_dir "restore")"/*
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
main() {
|
|
||||||
if supported_tmux_version_ok && check_saved_session_exists; then
|
|
||||||
start_spinner "Restoring..." "Tmux restore complete!"
|
|
||||||
execute_hook "pre-restore-all"
|
|
||||||
restore_all_panes
|
|
||||||
handle_session_0
|
|
||||||
restore_window_properties >/dev/null 2>&1
|
|
||||||
execute_hook "pre-restore-pane-processes"
|
|
||||||
restore_all_pane_processes
|
|
||||||
# below functions restore exact cursor positions
|
|
||||||
restore_active_pane_for_each_window
|
|
||||||
restore_zoomed_windows
|
|
||||||
restore_grouped_sessions # also restores active and alt windows for grouped sessions
|
|
||||||
restore_active_and_alternate_windows
|
|
||||||
restore_active_and_alternate_sessions
|
|
||||||
cleanup_restored_pane_contents
|
|
||||||
execute_hook "post-restore-all"
|
|
||||||
stop_spinner
|
|
||||||
display_message "Tmux restore complete!"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
main
|
|
||||||
@@ -1,278 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
|
||||||
|
|
||||||
source "$CURRENT_DIR/variables.sh"
|
|
||||||
source "$CURRENT_DIR/helpers.sh"
|
|
||||||
source "$CURRENT_DIR/spinner_helpers.sh"
|
|
||||||
|
|
||||||
# delimiters
|
|
||||||
d=$'\t'
|
|
||||||
delimiter=$'\t'
|
|
||||||
|
|
||||||
# if "quiet" script produces no output
|
|
||||||
SCRIPT_OUTPUT="$1"
|
|
||||||
|
|
||||||
grouped_sessions_format() {
|
|
||||||
local format
|
|
||||||
format+="#{session_grouped}"
|
|
||||||
format+="${delimiter}"
|
|
||||||
format+="#{session_group}"
|
|
||||||
format+="${delimiter}"
|
|
||||||
format+="#{session_id}"
|
|
||||||
format+="${delimiter}"
|
|
||||||
format+="#{session_name}"
|
|
||||||
echo "$format"
|
|
||||||
}
|
|
||||||
|
|
||||||
pane_format() {
|
|
||||||
local format
|
|
||||||
format+="pane"
|
|
||||||
format+="${delimiter}"
|
|
||||||
format+="#{session_name}"
|
|
||||||
format+="${delimiter}"
|
|
||||||
format+="#{window_index}"
|
|
||||||
format+="${delimiter}"
|
|
||||||
format+="#{window_active}"
|
|
||||||
format+="${delimiter}"
|
|
||||||
format+=":#{window_flags}"
|
|
||||||
format+="${delimiter}"
|
|
||||||
format+="#{pane_index}"
|
|
||||||
format+="${delimiter}"
|
|
||||||
format+="#{pane_title}"
|
|
||||||
format+="${delimiter}"
|
|
||||||
format+=":#{pane_current_path}"
|
|
||||||
format+="${delimiter}"
|
|
||||||
format+="#{pane_active}"
|
|
||||||
format+="${delimiter}"
|
|
||||||
format+="#{pane_current_command}"
|
|
||||||
format+="${delimiter}"
|
|
||||||
format+="#{pane_pid}"
|
|
||||||
format+="${delimiter}"
|
|
||||||
format+="#{history_size}"
|
|
||||||
echo "$format"
|
|
||||||
}
|
|
||||||
|
|
||||||
window_format() {
|
|
||||||
local format
|
|
||||||
format+="window"
|
|
||||||
format+="${delimiter}"
|
|
||||||
format+="#{session_name}"
|
|
||||||
format+="${delimiter}"
|
|
||||||
format+="#{window_index}"
|
|
||||||
format+="${delimiter}"
|
|
||||||
format+=":#{window_name}"
|
|
||||||
format+="${delimiter}"
|
|
||||||
format+="#{window_active}"
|
|
||||||
format+="${delimiter}"
|
|
||||||
format+=":#{window_flags}"
|
|
||||||
format+="${delimiter}"
|
|
||||||
format+="#{window_layout}"
|
|
||||||
echo "$format"
|
|
||||||
}
|
|
||||||
|
|
||||||
state_format() {
|
|
||||||
local format
|
|
||||||
format+="state"
|
|
||||||
format+="${delimiter}"
|
|
||||||
format+="#{client_session}"
|
|
||||||
format+="${delimiter}"
|
|
||||||
format+="#{client_last_session}"
|
|
||||||
echo "$format"
|
|
||||||
}
|
|
||||||
|
|
||||||
dump_panes_raw() {
|
|
||||||
tmux list-panes -a -F "$(pane_format)"
|
|
||||||
}
|
|
||||||
|
|
||||||
dump_windows_raw(){
|
|
||||||
tmux list-windows -a -F "$(window_format)"
|
|
||||||
}
|
|
||||||
|
|
||||||
toggle_window_zoom() {
|
|
||||||
local target="$1"
|
|
||||||
tmux resize-pane -Z -t "$target"
|
|
||||||
}
|
|
||||||
|
|
||||||
_save_command_strategy_file() {
|
|
||||||
local save_command_strategy="$(get_tmux_option "$save_command_strategy_option" "$default_save_command_strategy")"
|
|
||||||
local strategy_file="$CURRENT_DIR/../save_command_strategies/${save_command_strategy}.sh"
|
|
||||||
local default_strategy_file="$CURRENT_DIR/../save_command_strategies/${default_save_command_strategy}.sh"
|
|
||||||
if [ -e "$strategy_file" ]; then # strategy file exists?
|
|
||||||
echo "$strategy_file"
|
|
||||||
else
|
|
||||||
echo "$default_strategy_file"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
pane_full_command() {
|
|
||||||
local pane_pid="$1"
|
|
||||||
local strategy_file="$(_save_command_strategy_file)"
|
|
||||||
# execute strategy script to get pane full command
|
|
||||||
$strategy_file "$pane_pid"
|
|
||||||
}
|
|
||||||
|
|
||||||
number_nonempty_lines_on_screen() {
|
|
||||||
local pane_id="$1"
|
|
||||||
tmux capture-pane -pJ -t "$pane_id" |
|
|
||||||
sed '/^$/d' |
|
|
||||||
wc -l |
|
|
||||||
sed 's/ //g'
|
|
||||||
}
|
|
||||||
|
|
||||||
# tests if there was any command output in the current pane
|
|
||||||
pane_has_any_content() {
|
|
||||||
local pane_id="$1"
|
|
||||||
local history_size="$(tmux display -p -t "$pane_id" -F "#{history_size}")"
|
|
||||||
local cursor_y="$(tmux display -p -t "$pane_id" -F "#{cursor_y}")"
|
|
||||||
# doing "cheap" tests first
|
|
||||||
[ "$history_size" -gt 0 ] || # history has any content?
|
|
||||||
[ "$cursor_y" -gt 0 ] || # cursor not in first line?
|
|
||||||
[ "$(number_nonempty_lines_on_screen "$pane_id")" -gt 1 ]
|
|
||||||
}
|
|
||||||
|
|
||||||
capture_pane_contents() {
|
|
||||||
local pane_id="$1"
|
|
||||||
local start_line="-$2"
|
|
||||||
local pane_contents_area="$3"
|
|
||||||
if pane_has_any_content "$pane_id"; then
|
|
||||||
if [ "$pane_contents_area" = "visible" ]; then
|
|
||||||
start_line="0"
|
|
||||||
fi
|
|
||||||
# the printf hack below removes *trailing* empty lines
|
|
||||||
printf '%s\n' "$(tmux capture-pane -epJ -S "$start_line" -t "$pane_id")" > "$(pane_contents_file "save" "$pane_id")"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
get_active_window_index() {
|
|
||||||
local session_name="$1"
|
|
||||||
tmux list-windows -t "$session_name" -F "#{window_flags} #{window_index}" |
|
|
||||||
awk '$1 ~ /\*/ { print $2; }'
|
|
||||||
}
|
|
||||||
|
|
||||||
get_alternate_window_index() {
|
|
||||||
local session_name="$1"
|
|
||||||
tmux list-windows -t "$session_name" -F "#{window_flags} #{window_index}" |
|
|
||||||
awk '$1 ~ /-/ { print $2; }'
|
|
||||||
}
|
|
||||||
|
|
||||||
dump_grouped_sessions() {
|
|
||||||
local current_session_group=""
|
|
||||||
local original_session
|
|
||||||
tmux list-sessions -F "$(grouped_sessions_format)" |
|
|
||||||
grep "^1" |
|
|
||||||
cut -c 3- |
|
|
||||||
sort |
|
|
||||||
while IFS=$d read session_group session_id session_name; do
|
|
||||||
if [ "$session_group" != "$current_session_group" ]; then
|
|
||||||
# this session is the original/first session in the group
|
|
||||||
original_session="$session_name"
|
|
||||||
current_session_group="$session_group"
|
|
||||||
else
|
|
||||||
# this session "points" to the original session
|
|
||||||
active_window_index="$(get_active_window_index "$session_name")"
|
|
||||||
alternate_window_index="$(get_alternate_window_index "$session_name")"
|
|
||||||
echo "grouped_session${d}${session_name}${d}${original_session}${d}:${alternate_window_index}${d}:${active_window_index}"
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
}
|
|
||||||
|
|
||||||
fetch_and_dump_grouped_sessions(){
|
|
||||||
local grouped_sessions_dump="$(dump_grouped_sessions)"
|
|
||||||
get_grouped_sessions "$grouped_sessions_dump"
|
|
||||||
if [ -n "$grouped_sessions_dump" ]; then
|
|
||||||
echo "$grouped_sessions_dump"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
# translates pane pid to process command running inside a pane
|
|
||||||
dump_panes() {
|
|
||||||
local full_command
|
|
||||||
dump_panes_raw |
|
|
||||||
while IFS=$d read line_type session_name window_number window_active window_flags pane_index pane_title dir pane_active pane_command pane_pid history_size; do
|
|
||||||
# not saving panes from grouped sessions
|
|
||||||
if is_session_grouped "$session_name"; then
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
full_command="$(pane_full_command $pane_pid)"
|
|
||||||
dir=$(echo $dir | sed 's/ /\\ /') # escape all spaces in directory path
|
|
||||||
echo "${line_type}${d}${session_name}${d}${window_number}${d}${window_active}${d}${window_flags}${d}${pane_index}${d}${pane_title}${d}${dir}${d}${pane_active}${d}${pane_command}${d}:${full_command}"
|
|
||||||
done
|
|
||||||
}
|
|
||||||
|
|
||||||
dump_windows() {
|
|
||||||
dump_windows_raw |
|
|
||||||
while IFS=$d read line_type session_name window_index window_name window_active window_flags window_layout; do
|
|
||||||
# not saving windows from grouped sessions
|
|
||||||
if is_session_grouped "$session_name"; then
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
automatic_rename="$(tmux show-window-options -vt "${session_name}:${window_index}" automatic-rename)"
|
|
||||||
# If the option was unset, use ":" as a placeholder.
|
|
||||||
[ -z "${automatic_rename}" ] && automatic_rename=":"
|
|
||||||
echo "${line_type}${d}${session_name}${d}${window_index}${d}${window_name}${d}${window_active}${d}${window_flags}${d}${window_layout}${d}${automatic_rename}"
|
|
||||||
done
|
|
||||||
}
|
|
||||||
|
|
||||||
dump_state() {
|
|
||||||
tmux display-message -p "$(state_format)"
|
|
||||||
}
|
|
||||||
|
|
||||||
dump_pane_contents() {
|
|
||||||
local pane_contents_area="$(get_tmux_option "$pane_contents_area_option" "$default_pane_contents_area")"
|
|
||||||
dump_panes_raw |
|
|
||||||
while IFS=$d read line_type session_name window_number window_active window_flags pane_index pane_title dir pane_active pane_command pane_pid history_size; do
|
|
||||||
capture_pane_contents "${session_name}:${window_number}.${pane_index}" "$history_size" "$pane_contents_area"
|
|
||||||
done
|
|
||||||
}
|
|
||||||
|
|
||||||
remove_old_backups() {
|
|
||||||
# remove resurrect files older than 30 days (default), but keep at least 5 copies of backup.
|
|
||||||
local delete_after="$(get_tmux_option "$delete_backup_after_option" "$default_delete_backup_after")"
|
|
||||||
local -a files
|
|
||||||
files=($(ls -t $(resurrect_dir)/${RESURRECT_FILE_PREFIX}_*.${RESURRECT_FILE_EXTENSION} | tail -n +6))
|
|
||||||
[[ ${#files[@]} -eq 0 ]] ||
|
|
||||||
find "${files[@]}" -type f -mtime "+${delete_after}" -exec rm -v "{}" \; > /dev/null
|
|
||||||
}
|
|
||||||
|
|
||||||
save_all() {
|
|
||||||
local resurrect_file_path="$(resurrect_file_path)"
|
|
||||||
local last_resurrect_file="$(last_resurrect_file)"
|
|
||||||
mkdir -p "$(resurrect_dir)"
|
|
||||||
fetch_and_dump_grouped_sessions > "$resurrect_file_path"
|
|
||||||
dump_panes >> "$resurrect_file_path"
|
|
||||||
dump_windows >> "$resurrect_file_path"
|
|
||||||
dump_state >> "$resurrect_file_path"
|
|
||||||
execute_hook "post-save-layout" "$resurrect_file_path"
|
|
||||||
if files_differ "$resurrect_file_path" "$last_resurrect_file"; then
|
|
||||||
ln -fs "$(basename "$resurrect_file_path")" "$last_resurrect_file"
|
|
||||||
else
|
|
||||||
rm "$resurrect_file_path"
|
|
||||||
fi
|
|
||||||
if capture_pane_contents_option_on; then
|
|
||||||
mkdir -p "$(pane_contents_dir "save")"
|
|
||||||
dump_pane_contents
|
|
||||||
pane_contents_create_archive
|
|
||||||
rm "$(pane_contents_dir "save")"/*
|
|
||||||
fi
|
|
||||||
remove_old_backups
|
|
||||||
execute_hook "post-save-all"
|
|
||||||
}
|
|
||||||
|
|
||||||
show_output() {
|
|
||||||
[ "$SCRIPT_OUTPUT" != "quiet" ]
|
|
||||||
}
|
|
||||||
|
|
||||||
main() {
|
|
||||||
if supported_tmux_version_ok; then
|
|
||||||
if show_output; then
|
|
||||||
start_spinner "Saving..." "Tmux environment saved!"
|
|
||||||
fi
|
|
||||||
save_all
|
|
||||||
if show_output; then
|
|
||||||
stop_spinner
|
|
||||||
display_message "Tmux environment saved!"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
main
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
start_spinner() {
|
|
||||||
$CURRENT_DIR/tmux_spinner.sh "$1" "$2" &
|
|
||||||
export SPINNER_PID=$!
|
|
||||||
}
|
|
||||||
|
|
||||||
stop_spinner() {
|
|
||||||
kill $SPINNER_PID
|
|
||||||
}
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
# This script shows tmux spinner with a message. It is intended to be running
|
|
||||||
# as a background process which should be `kill`ed at the end.
|
|
||||||
#
|
|
||||||
# Example usage:
|
|
||||||
#
|
|
||||||
# ./tmux_spinner.sh "Working..." "End message!" &
|
|
||||||
# SPINNER_PID=$!
|
|
||||||
# ..
|
|
||||||
# .. execute commands here
|
|
||||||
# ..
|
|
||||||
# kill $SPINNER_PID # Stops spinner and displays 'End message!'
|
|
||||||
|
|
||||||
MESSAGE="$1"
|
|
||||||
END_MESSAGE="$2"
|
|
||||||
SPIN='-\|/'
|
|
||||||
|
|
||||||
trap "tmux display-message '$END_MESSAGE'; exit" SIGINT SIGTERM
|
|
||||||
|
|
||||||
main() {
|
|
||||||
local i=0
|
|
||||||
while true; do
|
|
||||||
i=$(( (i+1) %4 ))
|
|
||||||
tmux display-message " ${SPIN:$i:1} $MESSAGE"
|
|
||||||
sleep 0.1
|
|
||||||
done
|
|
||||||
}
|
|
||||||
main
|
|
||||||
@@ -1,48 +0,0 @@
|
|||||||
# key bindings
|
|
||||||
default_save_key="C-s"
|
|
||||||
save_option="@resurrect-save"
|
|
||||||
save_path_option="@resurrect-save-script-path"
|
|
||||||
|
|
||||||
default_restore_key="C-r"
|
|
||||||
restore_option="@resurrect-restore"
|
|
||||||
restore_path_option="@resurrect-restore-script-path"
|
|
||||||
|
|
||||||
# default processes that are restored
|
|
||||||
default_proc_list_option="@resurrect-default-processes"
|
|
||||||
default_proc_list='vi vim view nvim emacs man less more tail top htop irssi weechat mutt'
|
|
||||||
|
|
||||||
# User defined processes that are restored
|
|
||||||
# 'false' - nothing is restored
|
|
||||||
# ':all:' - all processes are restored
|
|
||||||
#
|
|
||||||
# user defined list of programs that are restored:
|
|
||||||
# 'my_program foo another_program'
|
|
||||||
restore_processes_option="@resurrect-processes"
|
|
||||||
restore_processes=""
|
|
||||||
|
|
||||||
# Defines part of the user variable. Example usage:
|
|
||||||
# set -g @resurrect-strategy-vim "session"
|
|
||||||
restore_process_strategy_option="@resurrect-strategy-"
|
|
||||||
|
|
||||||
inline_strategy_token="->"
|
|
||||||
inline_strategy_arguments_token="*"
|
|
||||||
|
|
||||||
save_command_strategy_option="@resurrect-save-command-strategy"
|
|
||||||
default_save_command_strategy="ps"
|
|
||||||
|
|
||||||
# Pane contents capture options.
|
|
||||||
# @resurrect-pane-contents-area option can be:
|
|
||||||
# 'visible' - capture only the visible pane area
|
|
||||||
# 'full' - capture the full pane contents
|
|
||||||
pane_contents_option="@resurrect-capture-pane-contents"
|
|
||||||
pane_contents_area_option="@resurrect-pane-contents-area"
|
|
||||||
default_pane_contents_area="full"
|
|
||||||
|
|
||||||
# set to 'on' to ensure panes are never ever overwritten
|
|
||||||
overwrite_option="@resurrect-never-overwrite"
|
|
||||||
|
|
||||||
# Hooks are set via ${hook_prefix}${name}, i.e. "@resurrect-hook-post-save-all"
|
|
||||||
hook_prefix="@resurrect-hook-"
|
|
||||||
|
|
||||||
delete_backup_after_option="@resurrect-delete-backup-after"
|
|
||||||
default_delete_backup_after="30" # days
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
# "irb default strategy"
|
|
||||||
#
|
|
||||||
# Example irb process with junk variables:
|
|
||||||
# irb RBENV_VERSION=1.9.3-p429 GREP_COLOR=34;47 TERM_PROGRAM=Apple_Terminal
|
|
||||||
#
|
|
||||||
# When executed, the above will fail. This strategy handles that.
|
|
||||||
|
|
||||||
ORIGINAL_COMMAND="$1"
|
|
||||||
DIRECTORY="$2"
|
|
||||||
|
|
||||||
original_command_wo_junk_vars() {
|
|
||||||
echo "$ORIGINAL_COMMAND" |
|
|
||||||
sed 's/RBENV_VERSION[^ ]*//' |
|
|
||||||
sed 's/GREP_COLOR[^ ]*//' |
|
|
||||||
sed 's/TERM_PROGRAM[^ ]*//'
|
|
||||||
}
|
|
||||||
|
|
||||||
main() {
|
|
||||||
echo "$(original_command_wo_junk_vars)"
|
|
||||||
}
|
|
||||||
main
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
# "mosh-client default strategy"
|
|
||||||
#
|
|
||||||
# Example mosh-client process:
|
|
||||||
# mosh-client -# charm tmux at | 198.199.104.142 60001
|
|
||||||
#
|
|
||||||
# When executed, the above will fail. This strategy handles that.
|
|
||||||
|
|
||||||
ORIGINAL_COMMAND="$1"
|
|
||||||
DIRECTORY="$2"
|
|
||||||
|
|
||||||
mosh_command() {
|
|
||||||
local args="$ORIGINAL_COMMAND"
|
|
||||||
|
|
||||||
args="${args#*-#}"
|
|
||||||
args="${args%|*}"
|
|
||||||
|
|
||||||
echo "mosh $args"
|
|
||||||
}
|
|
||||||
|
|
||||||
main() {
|
|
||||||
echo "$(mosh_command)"
|
|
||||||
}
|
|
||||||
main
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
# "nvim session strategy"
|
|
||||||
#
|
|
||||||
# Same as vim strategy, see file 'vim_session.sh'
|
|
||||||
|
|
||||||
ORIGINAL_COMMAND="$1"
|
|
||||||
DIRECTORY="$2"
|
|
||||||
|
|
||||||
nvim_session_file_exists() {
|
|
||||||
[ -e "${DIRECTORY}/Session.vim" ]
|
|
||||||
}
|
|
||||||
|
|
||||||
original_command_contains_session_flag() {
|
|
||||||
[[ "$ORIGINAL_COMMAND" =~ "-S" ]]
|
|
||||||
}
|
|
||||||
|
|
||||||
main() {
|
|
||||||
if nvim_session_file_exists; then
|
|
||||||
echo "nvim -S"
|
|
||||||
elif original_command_contains_session_flag; then
|
|
||||||
# Session file does not exist, yet the original nvim command contains
|
|
||||||
# session flag `-S`. This will cause an error, so we're falling back to
|
|
||||||
# starting plain nvim.
|
|
||||||
echo "nvim"
|
|
||||||
else
|
|
||||||
echo "$ORIGINAL_COMMAND"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
main
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
# "vim session strategy"
|
|
||||||
#
|
|
||||||
# Restores a vim session from 'Session.vim' file, if it exists.
|
|
||||||
# If 'Session.vim' does not exist, it falls back to invoking the original
|
|
||||||
# command (without the `-S` flag).
|
|
||||||
|
|
||||||
ORIGINAL_COMMAND="$1"
|
|
||||||
DIRECTORY="$2"
|
|
||||||
|
|
||||||
vim_session_file_exists() {
|
|
||||||
[ -e "${DIRECTORY}/Session.vim" ]
|
|
||||||
}
|
|
||||||
|
|
||||||
main() {
|
|
||||||
if vim_session_file_exists; then
|
|
||||||
echo "vim -S"
|
|
||||||
else
|
|
||||||
echo "$ORIGINAL_COMMAND"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
main
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
pane 0 0 :bash 1 :* 0 :/tmp 1 bash :
|
|
||||||
pane blue 0 :vim 0 : 0 :/tmp 1 vim :vim foo.txt
|
|
||||||
pane blue 1 :man 0 :- 0 :/tmp 0 bash :
|
|
||||||
pane blue 1 :man 0 :- 1 :/usr/share/man 1 man :man echo
|
|
||||||
pane blue 2 :bash 1 :* 0 :/tmp 1 bash :
|
|
||||||
pane red 0 :bash 0 : 0 :/tmp 1 bash :
|
|
||||||
pane red 1 :bash 0 :-Z 0 :/tmp 0 bash :
|
|
||||||
pane red 1 :bash 0 :-Z 1 :/tmp 0 bash :
|
|
||||||
pane red 1 :bash 0 :-Z 2 :/tmp 1 bash :
|
|
||||||
pane red 2 :bash 1 :* 0 :/tmp 0 bash :
|
|
||||||
pane red 2 :bash 1 :* 1 :/tmp 1 bash :
|
|
||||||
pane yellow 0 :bash 1 :* 0 :/tmp/bar 1 bash :
|
|
||||||
window 0 0 1 :* ce9e,200x49,0,0,1
|
|
||||||
window blue 0 0 : ce9f,200x49,0,0,2
|
|
||||||
window blue 1 0 :- 178b,200x49,0,0{100x49,0,0,3,99x49,101,0,4}
|
|
||||||
window blue 2 1 :* cea2,200x49,0,0,5
|
|
||||||
window red 0 0 : cea3,200x49,0,0,6
|
|
||||||
window red 1 0 :-Z 135b,200x49,0,0[200x24,0,0,7,200x24,0,25{100x24,0,25,8,99x24,101,25,9}]
|
|
||||||
window red 2 1 :* db81,200x49,0,0[200x24,0,0,10,200x24,0,25,11]
|
|
||||||
window yellow 0 1 :* 6781,200x49,0,0,12
|
|
||||||
state yellow blue
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
pane 0 0 :bash 1 :* 0 :/tmp 1 bash :
|
|
||||||
pane blue 0 :vim 0 :! 0 :/tmp 1 vim :vim foo.txt
|
|
||||||
pane blue 1 :man 0 :!- 0 :/tmp 0 bash :
|
|
||||||
pane blue 1 :man 0 :!- 1 :/usr/share/man 1 man :man echo
|
|
||||||
pane blue 2 :bash 1 :* 0 :/tmp 1 bash :
|
|
||||||
pane red 0 :bash 0 : 0 :/tmp 1 bash :
|
|
||||||
pane red 1 :bash 0 :-Z 0 :/tmp 0 bash :
|
|
||||||
pane red 1 :bash 0 :-Z 1 :/tmp 0 bash :
|
|
||||||
pane red 1 :bash 0 :-Z 2 :/tmp 1 bash :
|
|
||||||
pane red 2 :bash 1 :* 0 :/tmp 0 bash :
|
|
||||||
pane red 2 :bash 1 :* 1 :/tmp 1 bash :
|
|
||||||
pane yellow 0 :bash 1 :* 0 :/tmp/bar 1 bash :
|
|
||||||
window 0 0 1 :* ce9d,200x49,0,0,0
|
|
||||||
window blue 0 0 :! cea4,200x49,0,0,7
|
|
||||||
window blue 1 0 :!- 9797,200x49,0,0{100x49,0,0,8,99x49,101,0,9}
|
|
||||||
window blue 2 1 :* 677f,200x49,0,0,10
|
|
||||||
window red 0 0 : ce9e,200x49,0,0,1
|
|
||||||
window red 1 0 :-Z 52b7,200x49,0,0[200x24,0,0,2,200x24,0,25{100x24,0,25,3,99x24,101,25,4}]
|
|
||||||
window red 2 1 :* bd68,200x49,0,0[200x24,0,0,5,200x24,0,25,6]
|
|
||||||
window yellow 0 1 :* 6780,200x49,0,0,11
|
|
||||||
state yellow blue
|
|
||||||
@@ -1,42 +0,0 @@
|
|||||||
#!/usr/bin/env expect
|
|
||||||
|
|
||||||
source "./tests/helpers/expect_helpers.exp"
|
|
||||||
|
|
||||||
expect_setup
|
|
||||||
|
|
||||||
spawn tmux
|
|
||||||
# delay with sleep to compensate for tmux starting time
|
|
||||||
sleep 1
|
|
||||||
|
|
||||||
run_shell_command "cd /tmp"
|
|
||||||
|
|
||||||
# session red
|
|
||||||
new_tmux_session "red"
|
|
||||||
|
|
||||||
new_tmux_window
|
|
||||||
horizontal_split
|
|
||||||
vertical_split
|
|
||||||
toggle_zoom_pane
|
|
||||||
|
|
||||||
new_tmux_window
|
|
||||||
horizontal_split
|
|
||||||
|
|
||||||
# session blue
|
|
||||||
new_tmux_session "blue"
|
|
||||||
|
|
||||||
run_shell_command "touch foo.txt"
|
|
||||||
run_shell_command "vim foo.txt"
|
|
||||||
|
|
||||||
new_tmux_window
|
|
||||||
vertical_split
|
|
||||||
run_shell_command "man echo"
|
|
||||||
|
|
||||||
new_tmux_window
|
|
||||||
|
|
||||||
# session yellow
|
|
||||||
new_tmux_session "yellow"
|
|
||||||
run_shell_command "cd /tmp/bar"
|
|
||||||
|
|
||||||
start_resurrect_save
|
|
||||||
|
|
||||||
run_shell_command "tmux kill-server"
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user