Добавлены конфиги tmux и zsh
This commit is contained in:
commit
7d0a7691c6
1
install.sh
Executable file
1
install.sh
Executable file
@ -0,0 +1 @@
|
|||||||
|
#!/bin/bash
|
401
tmux/local.conf
Normal file
401
tmux/local.conf
Normal file
@ -0,0 +1,401 @@
|
|||||||
|
# ==========================
|
||||||
|
# === General settings ===
|
||||||
|
# ==========================
|
||||||
|
|
||||||
|
set -g default-terminal "screen-256color"
|
||||||
|
set -g history-limit 20000
|
||||||
|
set -g buffer-limit 20
|
||||||
|
set -sg escape-time 0
|
||||||
|
set -g display-time 1500
|
||||||
|
set -g remain-on-exit off
|
||||||
|
set -g repeat-time 300
|
||||||
|
setw -g allow-rename off
|
||||||
|
setw -g automatic-rename off
|
||||||
|
setw -g aggressive-resize on
|
||||||
|
|
||||||
|
# Change prefix key to C-a, easier to type, same to "screen"
|
||||||
|
unbind C-b
|
||||||
|
set -g prefix C-a
|
||||||
|
|
||||||
|
# Set parent terminal title to reflect current window in tmux session
|
||||||
|
set -g set-titles on
|
||||||
|
set -g set-titles-string "#I:#W"
|
||||||
|
|
||||||
|
# Start index of window/pane with 1, because we're humans, not computers
|
||||||
|
set -g base-index 1
|
||||||
|
setw -g pane-base-index 1
|
||||||
|
|
||||||
|
# Enable mouse support
|
||||||
|
set -g mouse on
|
||||||
|
|
||||||
|
|
||||||
|
# ==========================
|
||||||
|
# === Key bindings ===
|
||||||
|
# ==========================
|
||||||
|
|
||||||
|
# Unbind default key bindings, we're going to override
|
||||||
|
unbind "\$" # rename-session
|
||||||
|
unbind , # rename-window
|
||||||
|
unbind % # split-window -h
|
||||||
|
unbind '"' # split-window
|
||||||
|
unbind } # swap-pane -D
|
||||||
|
unbind { # swap-pane -U
|
||||||
|
unbind [ # paste-buffer
|
||||||
|
unbind ]
|
||||||
|
unbind "'" # select-window
|
||||||
|
unbind n # next-window
|
||||||
|
unbind p # previous-window
|
||||||
|
unbind l # last-window
|
||||||
|
unbind M-n # next window with alert
|
||||||
|
unbind M-p # next window with alert
|
||||||
|
unbind o # focus thru panes
|
||||||
|
unbind & # kill-window
|
||||||
|
unbind "#" # list-buffer
|
||||||
|
unbind = # choose-buffer
|
||||||
|
unbind z # zoom-pane
|
||||||
|
unbind M-Up # resize 5 rows up
|
||||||
|
unbind M-Down # resize 5 rows down
|
||||||
|
unbind M-Right # resize 5 rows right
|
||||||
|
unbind M-Left # resize 5 rows left
|
||||||
|
|
||||||
|
|
||||||
|
# Edit configuration and reload
|
||||||
|
bind C-e new-window -n 'tmux.conf' "sh -c '\${EDITOR:-vim} ~/.tmux.conf && tmux source ~/.tmux.conf && tmux display \"Config reloaded\"'"
|
||||||
|
|
||||||
|
# Reload tmux configuration
|
||||||
|
bind C-r source-file ~/.tmux.conf \; display "Config reloaded"
|
||||||
|
|
||||||
|
# new window and retain cwd
|
||||||
|
bind c new-window -c "#{pane_current_path}"
|
||||||
|
|
||||||
|
# Prompt to rename window right after it's created
|
||||||
|
#set-hook -g after-new-window 'command-prompt -I "#{window_name}" "rename-window '%%'"'
|
||||||
|
|
||||||
|
# Rename session and window
|
||||||
|
bind r command-prompt -I "#{window_name}" "rename-window '%%'"
|
||||||
|
bind R command-prompt -I "#{session_name}" "rename-session '%%'"
|
||||||
|
|
||||||
|
# Split panes
|
||||||
|
bind | split-window -h -c "#{pane_current_path}"
|
||||||
|
bind _ split-window -v -c "#{pane_current_path}"
|
||||||
|
|
||||||
|
# Select pane and windows
|
||||||
|
bind -r C-[ previous-window
|
||||||
|
bind -r C-] next-window
|
||||||
|
bind -r [ select-pane -t :.-
|
||||||
|
bind -r ] select-pane -t :.+
|
||||||
|
bind -r Tab last-window # cycle thru MRU tabs
|
||||||
|
bind -r C-o swap-pane -D
|
||||||
|
|
||||||
|
# Zoom pane
|
||||||
|
bind + resize-pane -Z
|
||||||
|
|
||||||
|
# Link window
|
||||||
|
bind L command-prompt -p "Link window from (session:window): " "link-window -s %% -a"
|
||||||
|
|
||||||
|
# Swap panes back and forth with 1st pane
|
||||||
|
# When in main-(horizontal|vertical) layouts, the biggest/widest panel is always @1
|
||||||
|
bind \ if '[ #{pane_index} -eq 1 ]' \
|
||||||
|
'swap-pane -s "!"' \
|
||||||
|
'select-pane -t:.1 ; swap-pane -d -t 1 -s "!"'
|
||||||
|
|
||||||
|
# Kill pane/window/session shortcuts
|
||||||
|
bind x kill-pane
|
||||||
|
bind X kill-window
|
||||||
|
bind C-x confirm-before -p "kill other windows? (y/n)" "kill-window -a"
|
||||||
|
bind Q confirm-before -p "kill-session #S? (y/n)" kill-session
|
||||||
|
|
||||||
|
# Merge session with another one (e.g. move all windows)
|
||||||
|
# If you use adhoc 1-window sessions, and you want to preserve session upon exit
|
||||||
|
# but don't want to create a lot of small unnamed 1-window sessions around
|
||||||
|
# move all windows from current session to main named one (dev, work, etc)
|
||||||
|
bind C-u command-prompt -p "Session to merge with: " \
|
||||||
|
"run-shell 'yes | head -n #{session_windows} | xargs -I {} -n 1 tmux movew -t %%'"
|
||||||
|
|
||||||
|
# Detach from session
|
||||||
|
bind d detach
|
||||||
|
bind D if -F '#{session_many_attached}' \
|
||||||
|
'confirm-before -p "Detach other clients? (y/n)" "detach -a"' \
|
||||||
|
'display "Session has only 1 client attached"'
|
||||||
|
|
||||||
|
# Hide status bar on demand
|
||||||
|
bind C-s if -F '#{s/off//:status}' 'set status off' 'set status on'
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# ==================================================
|
||||||
|
# === Window monitoring for activity and silence ===
|
||||||
|
# ==================================================
|
||||||
|
bind m setw monitor-activity \; display-message 'Monitor window activity [#{?monitor-activity,ON,OFF}]'
|
||||||
|
bind M if -F '#{monitor-silence}' \
|
||||||
|
'setw monitor-silence 0 ; display-message "Monitor window silence [OFF]"' \
|
||||||
|
'command-prompt -p "Monitor silence: interval (s)" "setw monitor-silence %%"'
|
||||||
|
|
||||||
|
# Activity bell and whistles
|
||||||
|
set -g visual-activity on
|
||||||
|
|
||||||
|
# TODO: Does not work as well, check on newer versions
|
||||||
|
# set -g visual-silence on
|
||||||
|
|
||||||
|
# BUG: bell-action other ignored · Issue #1027 · tmux/tmux · GitHub - https://github.com/tmux/tmux/issues/1027
|
||||||
|
# set -g visual-bell on
|
||||||
|
# setw -g bell-action other
|
||||||
|
|
||||||
|
# ================================================
|
||||||
|
# === Copy mode, scroll and clipboard ===
|
||||||
|
# ================================================
|
||||||
|
set -g @copy_use_osc52_fallback on
|
||||||
|
|
||||||
|
# Prefer vi style key table
|
||||||
|
setw -g mode-keys vi
|
||||||
|
|
||||||
|
bind p paste-buffer
|
||||||
|
bind C-p choose-buffer
|
||||||
|
|
||||||
|
# trigger copy mode by
|
||||||
|
bind -n M-Up copy-mode
|
||||||
|
|
||||||
|
# Scroll up/down by 1 line, half screen, whole screen
|
||||||
|
bind -T copy-mode-vi M-Up send-keys -X scroll-up
|
||||||
|
bind -T copy-mode-vi M-Down send-keys -X scroll-down
|
||||||
|
bind -T copy-mode-vi M-PageUp send-keys -X halfpage-up
|
||||||
|
bind -T copy-mode-vi M-PageDown send-keys -X halfpage-down
|
||||||
|
bind -T copy-mode-vi PageDown send-keys -X page-down
|
||||||
|
bind -T copy-mode-vi PageUp send-keys -X page-up
|
||||||
|
|
||||||
|
# When scrolling with mouse wheel, reduce number of scrolled rows per tick to "2" (default is 5)
|
||||||
|
bind -T copy-mode-vi WheelUpPane select-pane \; send-keys -X -N 2 scroll-up
|
||||||
|
bind -T copy-mode-vi WheelDownPane select-pane \; send-keys -X -N 2 scroll-down
|
||||||
|
|
||||||
|
# wrap default shell in reattach-to-user-namespace if available
|
||||||
|
# there is some hack with `exec & reattach`, credits to "https://github.com/gpakosz/.tmux"
|
||||||
|
# don't really understand how it works, but at least window are not renamed to "reattach-to-user-namespace"
|
||||||
|
if -b "command -v reattach-to-user-namespace > /dev/null 2>&1" \
|
||||||
|
"run 'tmux set -g default-command \"exec $(tmux show -gv default-shell) 2>/dev/null & reattach-to-user-namespace -l $(tmux show -gv default-shell)\"'"
|
||||||
|
|
||||||
|
yank="~/.dots/tmux/utils/yank.sh"
|
||||||
|
|
||||||
|
# Copy selected text
|
||||||
|
bind -T copy-mode-vi Enter send-keys -X copy-pipe-and-cancel "$yank"
|
||||||
|
bind -T copy-mode-vi y send-keys -X copy-pipe-and-cancel "$yank"
|
||||||
|
bind -T copy-mode-vi Y send-keys -X copy-line \;\
|
||||||
|
run "tmux save-buffer - | $yank"
|
||||||
|
bind-key -T copy-mode-vi D send-keys -X copy-end-of-line \;\
|
||||||
|
run "tmux save-buffer - | $yank"
|
||||||
|
bind -T copy-mode-vi C-j send-keys -X copy-pipe-and-cancel "$yank"
|
||||||
|
bind-key -T copy-mode-vi A send-keys -X append-selection-and-cancel \;\
|
||||||
|
run "tmux save-buffer - | $yank"
|
||||||
|
|
||||||
|
# Copy selection on drag end event, but do not cancel copy mode and do not clear selection
|
||||||
|
# clear select on subsequence mouse click
|
||||||
|
bind -T copy-mode-vi MouseDragEnd1Pane \
|
||||||
|
send-keys -X copy-pipe "$yank"
|
||||||
|
bind -T copy-mode-vi MouseDown1Pane select-pane \;\
|
||||||
|
send-keys -X clear-selection
|
||||||
|
|
||||||
|
# iTerm2 works with clipboard out of the box, set-clipboard already set to "external"
|
||||||
|
# tmux show-options -g -s set-clipboard
|
||||||
|
# set-clipboard on|external
|
||||||
|
|
||||||
|
# =====================================
|
||||||
|
# === Theme ===
|
||||||
|
# =====================================
|
||||||
|
|
||||||
|
# Feel free to NOT use this variables at all (remove, rename)
|
||||||
|
# this are named colors, just for convenience
|
||||||
|
color_orange="colour166" # 208, 166
|
||||||
|
color_purple="colour134" # 135, 134
|
||||||
|
color_green="colour076" # 070
|
||||||
|
color_blue="colour39"
|
||||||
|
color_yellow="colour220"
|
||||||
|
color_red="colour160"
|
||||||
|
color_black="colour232"
|
||||||
|
color_white="white" # 015
|
||||||
|
|
||||||
|
# This is a theme CONTRACT, you are required to define variables below
|
||||||
|
# Change values, but not remove/rename variables itself
|
||||||
|
color_dark="$color_black"
|
||||||
|
color_light="$color_white"
|
||||||
|
color_session_text="$color_blue"
|
||||||
|
color_status_text="colour245"
|
||||||
|
color_main="$color_orange"
|
||||||
|
color_secondary="$color_purple"
|
||||||
|
color_level_ok="$color_green"
|
||||||
|
color_level_warn="$color_yellow"
|
||||||
|
color_level_stress="$color_red"
|
||||||
|
color_window_off_indicator="colour088"
|
||||||
|
color_window_off_status_bg="colour238"
|
||||||
|
color_window_off_status_current_bg="colour254"
|
||||||
|
|
||||||
|
# =====================================
|
||||||
|
# === Appearence and status bar ===
|
||||||
|
# ======================================
|
||||||
|
|
||||||
|
set -g mode-style "fg=default,bg=$color_main"
|
||||||
|
|
||||||
|
# command line style
|
||||||
|
set -g message-style "fg=$color_main,bg=$color_dark"
|
||||||
|
|
||||||
|
# status line style
|
||||||
|
set -g status-style "fg=$color_status_text,bg=$color_dark"
|
||||||
|
|
||||||
|
# window segments in status line
|
||||||
|
set -g window-status-separator ""
|
||||||
|
separator_powerline_left=""
|
||||||
|
separator_powerline_right=""
|
||||||
|
|
||||||
|
# setw -g window-status-style "fg=$color_status_text,bg=$color_dark"
|
||||||
|
setw -g window-status-format " #I:#W "
|
||||||
|
setw -g window-status-current-style "fg=$color_light,bold,bg=$color_main"
|
||||||
|
setw -g window-status-current-format "#[fg=$color_dark,bg=$color_main]$separator_powerline_right#[default] #I:#W# #[fg=$color_main,bg=$color_dark]$separator_powerline_right#[default]"
|
||||||
|
|
||||||
|
# when window has monitoring notification
|
||||||
|
setw -g window-status-activity-style "fg=$color_main"
|
||||||
|
|
||||||
|
# outline for active pane
|
||||||
|
setw -g pane-active-border-style "fg=$color_main"
|
||||||
|
|
||||||
|
# general status bar settings
|
||||||
|
set -g status on
|
||||||
|
set -g status-interval 5
|
||||||
|
set -g status-position top
|
||||||
|
set -g status-justify left
|
||||||
|
set -g status-right-length 100
|
||||||
|
|
||||||
|
# define widgets we're going to use in status bar
|
||||||
|
# note, that this is not the complete list, some of them are loaded from plugins
|
||||||
|
wg_session="#[fg=$color_session_text] #S #[default]"
|
||||||
|
wg_battery="#{battery_status_fg} #{battery_icon} #{battery_percentage}"
|
||||||
|
wg_date="#[fg=$color_secondary]%h %d %H:%M#[default]"
|
||||||
|
wg_user_host="#[fg=$color_secondary]#(whoami)#[default]@#H"
|
||||||
|
wg_is_zoomed="#[fg=$color_dark,bg=$color_secondary]#{?window_zoomed_flag,[Z],}#[default]"
|
||||||
|
# TODO: highlighted for nested local session as well
|
||||||
|
wg_is_keys_off="#[fg=$color_light,bg=$color_window_off_indicator]#([ $(tmux show-option -qv key-table) = 'off' ] && echo 'OFF')#[default]"
|
||||||
|
|
||||||
|
set -g status-left "$wg_session"
|
||||||
|
set -g status-right "#{prefix_highlight} $wg_is_keys_off $wg_is_zoomed #{sysstat_cpu} | #{sysstat_mem} | #{sysstat_loadavg} | $wg_user_host | $wg_date $wg_battery #{online_status}"
|
||||||
|
|
||||||
|
# online and offline icon for tmux-online-status
|
||||||
|
set -g @online_icon "#[fg=$color_level_ok]●#[default]"
|
||||||
|
set -g @offline_icon "#[fg=$color_level_stress]●#[default]"
|
||||||
|
|
||||||
|
# Configure view templates for tmux-plugin-sysstat "MEM" and "CPU" widget
|
||||||
|
set -g @sysstat_mem_view_tmpl 'MEM:#[fg=#{mem.color}]#{mem.pused}#[default] #{mem.used}'
|
||||||
|
|
||||||
|
# Configure colors for tmux-plugin-sysstat "MEM" and "CPU" widget
|
||||||
|
set -g @sysstat_cpu_color_low "$color_level_ok"
|
||||||
|
set -g @sysstat_cpu_color_medium "$color_level_warn"
|
||||||
|
set -g @sysstat_cpu_color_stress "$color_level_stress"
|
||||||
|
|
||||||
|
set -g @sysstat_mem_color_low "$color_level_ok"
|
||||||
|
set -g @sysstat_mem_color_medium "$color_level_warn"
|
||||||
|
set -g @sysstat_mem_color_stress "$color_level_stress"
|
||||||
|
|
||||||
|
set -g @sysstat_swap_color_low "$color_level_ok"
|
||||||
|
set -g @sysstat_swap_color_medium "$color_level_warn"
|
||||||
|
set -g @sysstat_swap_color_stress "$color_level_stress"
|
||||||
|
|
||||||
|
|
||||||
|
# Configure tmux-battery widget colors
|
||||||
|
set -g @batt_color_full_charge "#[fg=$color_level_ok]"
|
||||||
|
set -g @batt_color_high_charge "#[fg=$color_level_ok]"
|
||||||
|
set -g @batt_color_medium_charge "#[fg=$color_level_warn]"
|
||||||
|
set -g @batt_color_low_charge "#[fg=$color_level_stress]"
|
||||||
|
|
||||||
|
# Configure tmux-prefix-highlight colors
|
||||||
|
set -g @prefix_highlight_output_prefix '['
|
||||||
|
set -g @prefix_highlight_output_suffix ']'
|
||||||
|
set -g @prefix_highlight_fg "$color_dark"
|
||||||
|
set -g @prefix_highlight_bg "$color_secondary"
|
||||||
|
set -g @prefix_highlight_show_copy_mode 'on'
|
||||||
|
set -g @prefix_highlight_copy_mode_attr "fg=$color_dark,bg=$color_secondary"
|
||||||
|
|
||||||
|
|
||||||
|
# =====================================
|
||||||
|
# === Renew environment ===
|
||||||
|
# =====================================
|
||||||
|
set -g update-environment \
|
||||||
|
"DISPLAY\
|
||||||
|
SSH_ASKPASS\
|
||||||
|
SSH_AUTH_SOCK\
|
||||||
|
SSH_AGENT_PID\
|
||||||
|
SSH_CONNECTION\
|
||||||
|
SSH_TTY\
|
||||||
|
WINDOWID\
|
||||||
|
XAUTHORITY"
|
||||||
|
|
||||||
|
bind '$' run "~/.dots/tmux/utils/renew_env.sh"
|
||||||
|
|
||||||
|
|
||||||
|
# ============================
|
||||||
|
# === Plugins ===
|
||||||
|
# ============================
|
||||||
|
#set -g @plugin 'tmux-plugins/tpm'
|
||||||
|
|
||||||
|
#set -g @plugin 'tmux-plugins/tmux-battery'
|
||||||
|
#set -g @plugin 'tmux-plugins/tmux-prefix-highlight'
|
||||||
|
#set -g @plugin 'tmux-plugins/tmux-online-status'
|
||||||
|
#set -g @plugin 'tmux-plugins/tmux-sidebar'
|
||||||
|
#set -g @plugin 'tmux-plugins/tmux-copycat'
|
||||||
|
#set -g @plugin 'tmux-plugins/tmux-open'
|
||||||
|
#set -g @plugin 'samoshkin/tmux-plugin-sysstat'
|
||||||
|
|
||||||
|
#set -g @plugin 'tmux-plugins/tmux-resurrect'
|
||||||
|
#set -g @plugin 'tmux-plugins/tmux-continuum'
|
||||||
|
|
||||||
|
# Plugin properties
|
||||||
|
set -g @sidebar-tree 't'
|
||||||
|
set -g @sidebar-tree-focus 'T'
|
||||||
|
set -g @sidebar-tree-command 'tree -C'
|
||||||
|
|
||||||
|
set -g @continuum-restore 'on'
|
||||||
|
|
||||||
|
set -g @open-S 'https://www.google.com/search?q='
|
||||||
|
|
||||||
|
|
||||||
|
# ==============================================
|
||||||
|
# === Nesting local and remote sessions ===
|
||||||
|
# ==============================================
|
||||||
|
|
||||||
|
# Session is considered to be remote when we ssh into host
|
||||||
|
if-shell 'test -n "$SSH_CLIENT"' \
|
||||||
|
'source-file ~/.dots/tmux/remote.conf'
|
||||||
|
|
||||||
|
# We want to have single prefix key "C-a", usable both for local and remote session
|
||||||
|
# we don't want to "C-a" + "a" approach either
|
||||||
|
# Idea is to turn off all key bindings and prefix handling on local session,
|
||||||
|
# so that all keystrokes are passed to inner/remote session
|
||||||
|
|
||||||
|
# see: toggle on/off all keybindings · Issue #237 · tmux/tmux - https://github.com/tmux/tmux/issues/237
|
||||||
|
|
||||||
|
# Also, change some visual styles when window keys are off
|
||||||
|
bind -T root F12 \
|
||||||
|
set prefix None \;\
|
||||||
|
set key-table off \;\
|
||||||
|
set status-style "fg=$color_status_text,bg=$color_window_off_status_bg" \;\
|
||||||
|
set window-status-current-format "#[fg=$color_window_off_status_bg,bg=$color_window_off_status_current_bg]$separator_powerline_right#[default] #I:#W# #[fg=$color_window_off_status_current_bg,bg=$color_window_off_status_bg]$separator_powerline_right#[default]" \;\
|
||||||
|
set window-status-current-style "fg=$color_dark,bold,bg=$color_window_off_status_current_bg" \;\
|
||||||
|
if -F '#{pane_in_mode}' 'send-keys -X cancel' \;\
|
||||||
|
refresh-client -S \;\
|
||||||
|
|
||||||
|
bind -T off F12 \
|
||||||
|
set -u prefix \;\
|
||||||
|
set -u key-table \;\
|
||||||
|
set -u status-style \;\
|
||||||
|
set -u window-status-current-style \;\
|
||||||
|
set -u window-status-current-format \;\
|
||||||
|
refresh-client -S
|
||||||
|
|
||||||
|
# Run all plugins' scripts
|
||||||
|
#run '~/.tmux/plugins/tpm/tpm'
|
||||||
|
run '~/.dots/tmux/plugins/tmux-battery/battery.tmux'
|
||||||
|
run '~/.dots/tmux/plugins/tmux-online-status/online_status.tmux'
|
||||||
|
run '~/.dots/tmux/plugins/tmux-plugin-sysstat/sysstat.tmux'
|
||||||
|
run '~/.dots/tmux/plugins/tmux-prefix-highlight/prefix_highlight.tmux'
|
||||||
|
run '~/.dots/tmux/plugins/tmux-copycat/copycat.tmux'
|
||||||
|
run '~/.dots/tmux/plugins/tmux-open/open.tmux'
|
||||||
|
run '~/.dots/tmux/plugins/tmux-sidebar/sidebar.tmux'
|
||||||
|
#run '~/.dots/tmux/plugins/tmux-yank/yank.tmux'
|
||||||
|
|
||||||
|
run '~/.dots/tmux/plugins/tmux-ressurect/resurrect.tmux'
|
||||||
|
run '~/.dots/tmux/plugins/tmux-continuum/continuum.tmux'
|
19
tmux/plugins/tmux-battery/LICENSE.md
Normal file
19
tmux/plugins/tmux-battery/LICENSE.md
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
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.
|
262
tmux/plugins/tmux-battery/README.md
Normal file
262
tmux/plugins/tmux-battery/README.md
Normal file
@ -0,0 +1,262 @@
|
|||||||
|
# Tmux battery status
|
||||||
|
|
||||||
|
Enables displaying battery percentage and status icon in tmux status-right.
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
In order to read the battery status, this plugin depends on having one of the following applications installed:
|
||||||
|
- pmset (MacOS only)
|
||||||
|
- acpi
|
||||||
|
- upower
|
||||||
|
- termux-battery-status
|
||||||
|
- apm
|
||||||
|
|
||||||
|
In a normal situation, one of the above should be installed on your system by default and thus it should not be necessary to specifically install one of them. That being said, the `acpi` utility is currently recommended for use over `upower` where possible due to ongoing CPU usage issues.
|
||||||
|
|
||||||
|
### Installation with [Tmux Plugin Manager](https://github.com/tmux-plugins/tpm) (recommended)
|
||||||
|
|
||||||
|
Add plugin to the list of TPM plugins in `.tmux.conf`:
|
||||||
|
|
||||||
|
```tmux
|
||||||
|
set -g @plugin 'tmux-plugins/tmux-battery'
|
||||||
|
```
|
||||||
|
|
||||||
|
Hit `<prefix> + I` to fetch the plugin and source it.
|
||||||
|
|
||||||
|
If format strings are added to `status-right`, they should now be visible.
|
||||||
|
|
||||||
|
### Manual Installation
|
||||||
|
|
||||||
|
Clone the repo:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
git clone https://github.com/tmux-plugins/tmux-battery ~/clone/path
|
||||||
|
```
|
||||||
|
|
||||||
|
Add this line to the bottom of `.tmux.conf`:
|
||||||
|
|
||||||
|
```tmux
|
||||||
|
run-shell ~/clone/path/battery.tmux
|
||||||
|
```
|
||||||
|
|
||||||
|
From the terminal, reload TMUX environment:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
tmux source-file ~/.tmux.conf
|
||||||
|
```
|
||||||
|
|
||||||
|
If format strings are added to `status-right`, they should now be visible.
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
Add any of the supported format strings (see below) to the `status-right` tmux option in `.tmux.conf`. Example:
|
||||||
|
|
||||||
|
```tmux
|
||||||
|
set -g status-right '#{battery_status_bg} Batt: #{battery_icon} #{battery_percentage} #{battery_remain} | %a %h-%d %H:%M '
|
||||||
|
```
|
||||||
|
|
||||||
|
### Supported Format Strings
|
||||||
|
|
||||||
|
- `#{battery_color_bg}` - will set the background color of the status bar based on the battery charge level if discharging and status otherwise
|
||||||
|
- `#{battery_color_fg}` - will set the foreground color of the status bar based on the battery charge level if discharging and status otherwise
|
||||||
|
- `#{battery_color_charge_bg}` - will set the background color of the status bar based solely on the battery charge level
|
||||||
|
- `#{battery_color_charge_fg}` - will set the foreground color of the status bar based solely on the battery charge level
|
||||||
|
- `#{battery_color_status_bg}` - will set the background color of the status bar based solely on the battery status
|
||||||
|
- `#{battery_color_status_fg}` - will set the foreground color of the status bar based solely on the battery status
|
||||||
|
- `#{battery_graph}` - will show battery percentage as a bar graph: ▁▂▄▆█
|
||||||
|
- `#{battery_icon}` - will display a battery status/charge icon
|
||||||
|
- `#{battery_icon_charge}` - will display a battery charge icon
|
||||||
|
- `#{battery_icon_status}` - will display a battery status icon
|
||||||
|
- `#{battery_percentage}` - will show battery percentage
|
||||||
|
- `#{battery_remain}` - will show remaining time of battery charge\*
|
||||||
|
|
||||||
|
\* These format strings can be further customized via options as described below.
|
||||||
|
|
||||||
|
#### Options
|
||||||
|
|
||||||
|
`#{battery_remain}`
|
||||||
|
|
||||||
|
- `@batt_remain_short`: 'true' / 'false' - This will shorten the time remaining (when charging or discharging) to `~H:MM`.
|
||||||
|
|
||||||
|
### Defaults
|
||||||
|
|
||||||
|
#### Options
|
||||||
|
|
||||||
|
- `@batt_remain_short`: 'false'
|
||||||
|
|
||||||
|
#### Icons/Colors
|
||||||
|
|
||||||
|
By default, the following colors and icons are used. (The exact colors displayed depends on your terminal / X11 config.)
|
||||||
|
|
||||||
|
Please be aware that the 'level of charge' as noted below (e.g. `[80%-95%)`) uses interval notation. If you are unfamiliar with it, <a href="https://en.wikipedia.org/wiki/Bracket_(mathematics)#Intervals">check it out here</a>.
|
||||||
|
|
||||||
|
Also, a note about the `@batt_color_...` options: `@batt_color_..._primary_...` options are what will be displayed in the main `bg` or `fg` format strings you choose - e.g. if you use `#{battery_color_bg}`, the `@batt_color_..._primary_...` colors you choose will be the background. Likewise, the corresponding `@batt_color_..._secondary_...` color will be the foreground.
|
||||||
|
|
||||||
|
Level of Charge Colors:
|
||||||
|
|
||||||
|
- primary tier 8 \[95%-100%] (`@batt_color_charge_primary_tier8`): '#00ff00'
|
||||||
|
- primary tier 7 \[80%-95%) (`@batt_color_charge_primary_tier7`): '#55ff00'
|
||||||
|
- primary tier 6 \[65%-80%) (`@batt_color_charge_primary_tier6`): '#aaff00'
|
||||||
|
- primary tier 5 \[50%-65%) (`@batt_color_charge_primary_tier5`): '#ffff00'
|
||||||
|
- primary tier 4 \[35%-50%) (`@batt_color_charge_primary_tier4`): '#ffc000'
|
||||||
|
- primary tier 3 \[20%-35%) (`@batt_color_charge_primary_tier3`): '#ff8000'
|
||||||
|
- primary tier 2 (5%-20%) (`@batt_color_charge_primary_tier2`): '#ff4000'
|
||||||
|
- primary tier 1 \[0%-5%] (`@batt_color_charge_primary_tier1`): '#ff0000'
|
||||||
|
- secondary tier 8 \[95%-100%] (`@batt_color_charge_secondary_tier8`): 'colour0'
|
||||||
|
- secondary tier 7 \[80%-95%) (`@batt_color_charge_secondary_tier7`): 'colour0'
|
||||||
|
- secondary tier 6 \[65%-80%) (`@batt_color_charge_secondary_tier6`): 'colour0'
|
||||||
|
- secondary tier 5 \[50%-65%) (`@batt_color_charge_secondary_tier5`): 'colour0'
|
||||||
|
- secondary tier 4 \[35%-50%) (`@batt_color_charge_secondary_tier4`): 'colour0'
|
||||||
|
- secondary tier 3 \[20%-35%) (`@batt_color_charge_secondary_tier3`): 'colour0'
|
||||||
|
- secondary tier 2 (5%-20%) (`@batt_color_charge_secondary_tier2`): 'colour0'
|
||||||
|
- secondary tier 1 \[0%-5%] (`@batt_color_charge_secondary_tier1`): 'colour0'
|
||||||
|
|
||||||
|
Status Colors:
|
||||||
|
|
||||||
|
- primary charged (`@batt_color_status_primary_charged`): 'colour33'
|
||||||
|
- primary charging (`@batt_color_status_primary_charging`): 'colour33'
|
||||||
|
- primary discharging (`@batt_color_status_primary_discharging`): 'colour14'
|
||||||
|
- primary attached (`@batt_color_status_primary_attached`): 'colour201'
|
||||||
|
- primary unknown (`@batt_color_status_primary_unknown`): 'colour7'
|
||||||
|
- secondary charged (`@batt_color_status_secondary_charged`): 'colour0'
|
||||||
|
- secondary charging (`@batt_color_status_secondary_charging`): 'colour0'
|
||||||
|
- secondary discharging (`@batt_color_status_secondary_discharging`): 'colour0'
|
||||||
|
- secondary attached (`@batt_color_status_secondary_attached`): 'colour0'
|
||||||
|
- secondary unknown (`@batt_color_status_secondary_unknown`): 'colour0'
|
||||||
|
|
||||||
|
Level of Charge Icons:
|
||||||
|
|
||||||
|
- tier 8 \[95%-100%] (`@batt_icon_charge_tier8`): '█'
|
||||||
|
- tier 7 \[80%-95%) (`@batt_icon_charge_tier7`): '▇'
|
||||||
|
- tier 6 \[65%-80%) (`@batt_icon_charge_tier6`): '▆'
|
||||||
|
- tier 5 \[50%-65%) (`@batt_icon_charge_tier5`): '▅'
|
||||||
|
- tier 4 \[35%-50%) (`@batt_icon_charge_tier4`): '▄'
|
||||||
|
- tier 3 \[20%-35%) (`@batt_icon_charge_tier3`): '▃'
|
||||||
|
- tier 2 (5%-20%) (`@batt_icon_charge_tier2`): '▂'
|
||||||
|
- tier 1 \[0%-5%] (`@batt_icon_charge_tier1`): '▁'
|
||||||
|
|
||||||
|
Status Icons:
|
||||||
|
|
||||||
|
- charged (`@batt_icon_status_charged`): '🔌'
|
||||||
|
- charged - OS X (`@batt_icon_status_charged`): '🔌'
|
||||||
|
- charging (`@batt_icon_status_charging`): '🔌'
|
||||||
|
- discharging (`@batt_icon_status_discharging`): '🔋'
|
||||||
|
- attached (`@batt_icon_status_attached`): '⚠️'
|
||||||
|
- unknown (`@batt_icon_status_unknown`): '?'
|
||||||
|
|
||||||
|
#### Changing the Defaults
|
||||||
|
|
||||||
|
All efforts have been made to make sane defaults, but if you wish to change any of them, add the option to `.tmux.conf`. For example:
|
||||||
|
|
||||||
|
```tmux
|
||||||
|
set -g @batt_icon_charge_tier8 '🌕'
|
||||||
|
set -g @batt_icon_charge_tier7 '🌖'
|
||||||
|
set -g @batt_icon_charge_tier6 '🌖'
|
||||||
|
set -g @batt_icon_charge_tier5 '🌗'
|
||||||
|
set -g @batt_icon_charge_tier4 '🌗'
|
||||||
|
set -g @batt_icon_charge_tier3 '🌘'
|
||||||
|
set -g @batt_icon_charge_tier2 '🌘'
|
||||||
|
set -g @batt_icon_charge_tier1 '🌑'
|
||||||
|
set -g @batt_icon_status_charged '🔋'
|
||||||
|
set -g @batt_icon_status_charging '⚡'
|
||||||
|
set -g @batt_icon_status_discharging '👎'
|
||||||
|
set -g @batt_color_status_primary_charged '#3daee9'
|
||||||
|
set -g @batt_color_status_primary_charging '#3daee9'
|
||||||
|
```
|
||||||
|
|
||||||
|
Don't forget to reload the tmux environment after you do this by either hitting `<prefix> + I` if tmux battery is installed via the tmux plugin manager, or by typing `tmux source-file ~/.tmux.conf` in the terminal if tmux battery is manually installed.
|
||||||
|
|
||||||
|
*Warning*: The battery icon change most likely will not be instant. When you un-plug the power cord, it will take some time (15 - 60 seconds) for the icon to change. This depends on the `status-interval` tmux option. Setting it to 15 seconds should be good enough.
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
These are all examples of the default plugin color and icon schemes paired with the default tmux color scheme using the following `status-right` and `status-right-length` settings in `.tmux.conf`
|
||||||
|
|
||||||
|
```tmux
|
||||||
|
set -g status-right 'Colors: #{battery_color_bg}bg#[default] #{battery_color_fg}fg#[default] #{battery_color_charge_bg}charge_bg#[default] #{battery_color_charge_fg}charge_fg#[default] #{battery_color_status_bg}status_bg#[default] #{battery_color_status_fg}status_fg#[default] | Graph: #{battery_graph} | Icon: #{battery_icon} | Charge Icon: #{battery_icon_charge} | Status Icon: #{battery_icon_status} | Percent: #{battery_percentage} | Remain: #{battery_remain}'
|
||||||
|
set -g status-right-length '150'
|
||||||
|
```
|
||||||
|
|
||||||
|
Battery charging at tier 8 \[95%-100%]:<br>
|
||||||
|

|
||||||
|
|
||||||
|
Battery charging at tier 7 \[80%-95%):<br>
|
||||||
|

|
||||||
|
|
||||||
|
Battery charging at tier 6 \[65%-80%):<br>
|
||||||
|

|
||||||
|
|
||||||
|
Battery charging at tier 5 \[50%-65%):<br>
|
||||||
|

|
||||||
|
|
||||||
|
Battery charging at tier 4 \[35%-50%):<br>
|
||||||
|

|
||||||
|
|
||||||
|
Battery charging at tier 3 \[20%-35%):<br>
|
||||||
|

|
||||||
|
|
||||||
|
Battery charging at tier 2 (5%-20%):<br>
|
||||||
|

|
||||||
|
|
||||||
|
Battery charging at tier 1 \[0%-5%]:<br>
|
||||||
|

|
||||||
|
|
||||||
|
Battery discharging at tier 8 \[95%-100%]:<br>
|
||||||
|

|
||||||
|
|
||||||
|
Battery discharging at tier 7 \[80%-95%):<br>
|
||||||
|

|
||||||
|
|
||||||
|
Battery discharging at tier 6 \[65%-80%):<br>
|
||||||
|

|
||||||
|
|
||||||
|
Battery discharging at tier 5 \[50%-65%):<br>
|
||||||
|

|
||||||
|
|
||||||
|
Battery discharging at tier 4 \[35%-50%):<br>
|
||||||
|

|
||||||
|
|
||||||
|
Battery discharging at tier 3 \[20%-35%):<br>
|
||||||
|

|
||||||
|
|
||||||
|
Battery discharging at tier 2 (5%-20%):<br>
|
||||||
|

|
||||||
|
|
||||||
|
Battery discharging at tier 1 \[0%-5%]:<br>
|
||||||
|

|
||||||
|
|
||||||
|
Battery in 'attached' status:<br>
|
||||||
|

|
||||||
|
|
||||||
|
Battery in an unknown status:<br>
|
||||||
|

|
||||||
|
|
||||||
|
### Tmux Plugins
|
||||||
|
|
||||||
|
This plugin is part of the [tmux-plugins](https://github.com/tmux-plugins) organisation. Checkout plugins as [resurrect](https://github.com/tmux-plugins/tmux-resurrect), [logging](https://github.com/tmux-plugins/tmux-logging), [online status](https://github.com/tmux-plugins/tmux-online-status), and many more over at the [tmux-plugins](https://github.com/tmux-plugins) organisation page.
|
||||||
|
|
||||||
|
### Maintainer
|
||||||
|
|
||||||
|
- [Martin Beentjes](https://github.com/martinbeentjes)
|
||||||
|
|
||||||
|
### Contributors
|
||||||
|
|
||||||
|
- Adam Biggs
|
||||||
|
- Aleksandar Djurdjic
|
||||||
|
- Bruno Sutic
|
||||||
|
- Caleb
|
||||||
|
- Dan Cassidy
|
||||||
|
- Diego Ximenes
|
||||||
|
- Evan N-D
|
||||||
|
- Jan Ahrens
|
||||||
|
- Joey Geralnik
|
||||||
|
- HyunJong (Joseph) Lee
|
||||||
|
- Martin Beentjes
|
||||||
|
- Mike Foley
|
||||||
|
- Ryan Frantz
|
||||||
|
- Seth Wright
|
||||||
|
- Tom Levens
|
||||||
|
|
||||||
|
### License
|
||||||
|
|
||||||
|
[MIT](LICENSE.md)
|
62
tmux/plugins/tmux-battery/battery.tmux
Executable file
62
tmux/plugins/tmux-battery/battery.tmux
Executable file
@ -0,0 +1,62 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||||
|
|
||||||
|
source "$CURRENT_DIR/scripts/helpers.sh"
|
||||||
|
|
||||||
|
battery_interpolation=(
|
||||||
|
"\#{battery_color_bg}"
|
||||||
|
"\#{battery_color_fg}"
|
||||||
|
"\#{battery_color_charge_bg}"
|
||||||
|
"\#{battery_color_charge_fg}"
|
||||||
|
"\#{battery_color_status_bg}"
|
||||||
|
"\#{battery_color_status_fg}"
|
||||||
|
"\#{battery_graph}"
|
||||||
|
"\#{battery_icon}"
|
||||||
|
"\#{battery_icon_charge}"
|
||||||
|
"\#{battery_icon_status}"
|
||||||
|
"\#{battery_percentage}"
|
||||||
|
"\#{battery_remain}"
|
||||||
|
)
|
||||||
|
|
||||||
|
battery_commands=(
|
||||||
|
"#($CURRENT_DIR/scripts/battery_color.sh bg)"
|
||||||
|
"#($CURRENT_DIR/scripts/battery_color.sh fg)"
|
||||||
|
"#($CURRENT_DIR/scripts/battery_color_charge.sh bg)"
|
||||||
|
"#($CURRENT_DIR/scripts/battery_color_charge.sh fg)"
|
||||||
|
"#($CURRENT_DIR/scripts/battery_color_status.sh bg)"
|
||||||
|
"#($CURRENT_DIR/scripts/battery_color_status.sh fg)"
|
||||||
|
"#($CURRENT_DIR/scripts/battery_graph.sh)"
|
||||||
|
"#($CURRENT_DIR/scripts/battery_icon.sh)"
|
||||||
|
"#($CURRENT_DIR/scripts/battery_icon_charge.sh)"
|
||||||
|
"#($CURRENT_DIR/scripts/battery_icon_status.sh)"
|
||||||
|
"#($CURRENT_DIR/scripts/battery_percentage.sh)"
|
||||||
|
"#($CURRENT_DIR/scripts/battery_remain.sh)"
|
||||||
|
)
|
||||||
|
|
||||||
|
set_tmux_option() {
|
||||||
|
local option="$1"
|
||||||
|
local value="$2"
|
||||||
|
tmux set-option -gq "$option" "$value"
|
||||||
|
}
|
||||||
|
|
||||||
|
do_interpolation() {
|
||||||
|
local all_interpolated="$1"
|
||||||
|
for ((i=0; i<${#battery_commands[@]}; i++)); do
|
||||||
|
all_interpolated=${all_interpolated//${battery_interpolation[$i]}/${battery_commands[$i]}}
|
||||||
|
done
|
||||||
|
echo "$all_interpolated"
|
||||||
|
}
|
||||||
|
|
||||||
|
update_tmux_option() {
|
||||||
|
local option="$1"
|
||||||
|
local option_value="$(get_tmux_option "$option")"
|
||||||
|
local new_option_value="$(do_interpolation "$option_value")"
|
||||||
|
set_tmux_option "$option" "$new_option_value"
|
||||||
|
}
|
||||||
|
|
||||||
|
main() {
|
||||||
|
update_tmux_option "status-right"
|
||||||
|
update_tmux_option "status-left"
|
||||||
|
}
|
||||||
|
main
|
23
tmux/plugins/tmux-battery/scripts/battery_color.sh
Executable file
23
tmux/plugins/tmux-battery/scripts/battery_color.sh
Executable file
@ -0,0 +1,23 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||||
|
|
||||||
|
source "$CURRENT_DIR/helpers.sh"
|
||||||
|
|
||||||
|
print_color() {
|
||||||
|
local plane="$1"
|
||||||
|
local status="$2"
|
||||||
|
if [ "$status" == "discharging" ]; then
|
||||||
|
$CURRENT_DIR/battery_color_charge.sh "$plane"
|
||||||
|
else
|
||||||
|
$CURRENT_DIR/battery_color_status.sh "$plane" "$status"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
main() {
|
||||||
|
local status="$(battery_status)"
|
||||||
|
local plane="$1"
|
||||||
|
print_color "$plane" "$status"
|
||||||
|
}
|
||||||
|
|
||||||
|
main $@
|
98
tmux/plugins/tmux-battery/scripts/battery_color_charge.sh
Executable file
98
tmux/plugins/tmux-battery/scripts/battery_color_charge.sh
Executable file
@ -0,0 +1,98 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||||
|
|
||||||
|
source "$CURRENT_DIR/helpers.sh"
|
||||||
|
|
||||||
|
# script global variables
|
||||||
|
color_charge_primary_tier8=''
|
||||||
|
color_charge_primary_tier7=''
|
||||||
|
color_charge_primary_tier6=''
|
||||||
|
color_charge_primary_tier5=''
|
||||||
|
color_charge_primary_tier4=''
|
||||||
|
color_charge_primary_tier3=''
|
||||||
|
color_charge_primary_tier2=''
|
||||||
|
color_charge_primary_tier1=''
|
||||||
|
color_charge_secondary_tier8=''
|
||||||
|
color_charge_secondary_tier7=''
|
||||||
|
color_charge_secondary_tier6=''
|
||||||
|
color_charge_secondary_tier5=''
|
||||||
|
color_charge_secondary_tier4=''
|
||||||
|
color_charge_secondary_tier3=''
|
||||||
|
color_charge_secondary_tier2=''
|
||||||
|
color_charge_secondary_tier1=''
|
||||||
|
|
||||||
|
# script default variables
|
||||||
|
color_charge_primary_tier8_default='#00ff00'
|
||||||
|
color_charge_primary_tier7_default='#55ff00'
|
||||||
|
color_charge_primary_tier6_default='#aaff00'
|
||||||
|
color_charge_primary_tier5_default='#ffff00'
|
||||||
|
color_charge_primary_tier4_default='#ffc000'
|
||||||
|
color_charge_primary_tier3_default='#ff8000'
|
||||||
|
color_charge_primary_tier2_default='#ff4000'
|
||||||
|
color_charge_primary_tier1_default='#ff0000'
|
||||||
|
color_charge_secondary_tier8_default='colour0'
|
||||||
|
color_charge_secondary_tier7_default='colour0'
|
||||||
|
color_charge_secondary_tier6_default='colour0'
|
||||||
|
color_charge_secondary_tier5_default='colour0'
|
||||||
|
color_charge_secondary_tier4_default='colour0'
|
||||||
|
color_charge_secondary_tier3_default='colour0'
|
||||||
|
color_charge_secondary_tier2_default='colour0'
|
||||||
|
color_charge_secondary_tier1_default='colour0'
|
||||||
|
|
||||||
|
# colors are set as script global variables
|
||||||
|
get_color_charge_settings() {
|
||||||
|
color_charge_primary_tier8=$(get_tmux_option "@batt_color_charge_primary_tier8" "$color_charge_primary_tier8_default")
|
||||||
|
color_charge_primary_tier7=$(get_tmux_option "@batt_color_charge_primary_tier7" "$color_charge_primary_tier7_default")
|
||||||
|
color_charge_primary_tier6=$(get_tmux_option "@batt_color_charge_primary_tier6" "$color_charge_primary_tier6_default")
|
||||||
|
color_charge_primary_tier5=$(get_tmux_option "@batt_color_charge_primary_tier5" "$color_charge_primary_tier5_default")
|
||||||
|
color_charge_primary_tier4=$(get_tmux_option "@batt_color_charge_primary_tier4" "$color_charge_primary_tier4_default")
|
||||||
|
color_charge_primary_tier3=$(get_tmux_option "@batt_color_charge_primary_tier3" "$color_charge_primary_tier3_default")
|
||||||
|
color_charge_primary_tier2=$(get_tmux_option "@batt_color_charge_primary_tier2" "$color_charge_primary_tier2_default")
|
||||||
|
color_charge_primary_tier1=$(get_tmux_option "@batt_color_charge_primary_tier1" "$color_charge_primary_tier1_default")
|
||||||
|
color_charge_secondary_tier8=$(get_tmux_option "@batt_color_charge_secondary_tier8" "$color_charge_secondary_tier8_default")
|
||||||
|
color_charge_secondary_tier7=$(get_tmux_option "@batt_color_charge_secondary_tier7" "$color_charge_secondary_tier7_default")
|
||||||
|
color_charge_secondary_tier6=$(get_tmux_option "@batt_color_charge_secondary_tier6" "$color_charge_secondary_tier6_default")
|
||||||
|
color_charge_secondary_tier5=$(get_tmux_option "@batt_color_charge_secondary_tier5" "$color_charge_secondary_tier5_default")
|
||||||
|
color_charge_secondary_tier4=$(get_tmux_option "@batt_color_charge_secondary_tier4" "$color_charge_secondary_tier4_default")
|
||||||
|
color_charge_secondary_tier3=$(get_tmux_option "@batt_color_charge_secondary_tier3" "$color_charge_secondary_tier3_default")
|
||||||
|
color_charge_secondary_tier2=$(get_tmux_option "@batt_color_charge_secondary_tier2" "$color_charge_secondary_tier2_default")
|
||||||
|
color_charge_secondary_tier1=$(get_tmux_option "@batt_color_charge_secondary_tier1" "$color_charge_secondary_tier1_default")
|
||||||
|
}
|
||||||
|
|
||||||
|
print_color_charge() {
|
||||||
|
local primary_plane="$1"
|
||||||
|
local secondary_plane=""
|
||||||
|
if [ "$primary_plane" == "bg" ]; then
|
||||||
|
secondary_plane="fg"
|
||||||
|
else
|
||||||
|
secondary_plane="bg"
|
||||||
|
fi
|
||||||
|
percentage=$($CURRENT_DIR/battery_percentage.sh | sed -e 's/%//')
|
||||||
|
if [ $percentage -ge 95 -o "$percentage" == "" ]; then
|
||||||
|
# if percentage is empty, assume it's a desktop
|
||||||
|
printf "#[$primary_plane=$color_charge_primary_tier8${color_charge_secondary_tier8:+",$secondary_plane=$color_charge_secondary_tier8"}]"
|
||||||
|
elif [ $percentage -ge 80 ]; then
|
||||||
|
printf "#[$primary_plane=$color_charge_primary_tier7${color_charge_secondary_tier7:+",$secondary_plane=$color_charge_secondary_tier7"}]"
|
||||||
|
elif [ $percentage -ge 65 ]; then
|
||||||
|
printf "#[$primary_plane=$color_charge_primary_tier6${color_charge_secondary_tier6:+",$secondary_plane=$color_charge_secondary_tier6"}]"
|
||||||
|
elif [ $percentage -ge 50 ]; then
|
||||||
|
printf "#[$primary_plane=$color_charge_primary_tier5${color_charge_secondary_tier5:+",$secondary_plane=$color_charge_secondary_tier5"}]"
|
||||||
|
elif [ $percentage -ge 35 ]; then
|
||||||
|
printf "#[$primary_plane=$color_charge_primary_tier4${color_charge_secondary_tier4:+",$secondary_plane=$color_charge_secondary_tier4"}]"
|
||||||
|
elif [ $percentage -ge 20 ]; then
|
||||||
|
printf "#[$primary_plane=$color_charge_primary_tier3${color_charge_secondary_tier3:+",$secondary_plane=$color_charge_secondary_tier3"}]"
|
||||||
|
elif [ $percentage -gt 5 ]; then
|
||||||
|
printf "#[$primary_plane=$color_charge_primary_tier2${color_charge_secondary_tier2:+",$secondary_plane=$color_charge_secondary_tier2"}]"
|
||||||
|
else
|
||||||
|
printf "#[$primary_plane=$color_charge_primary_tier1${color_charge_secondary_tier1:+",$secondary_plane=$color_charge_secondary_tier1"}]"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
main() {
|
||||||
|
local plane="$1"
|
||||||
|
get_color_charge_settings
|
||||||
|
print_color_charge "$plane"
|
||||||
|
}
|
||||||
|
|
||||||
|
main $@
|
74
tmux/plugins/tmux-battery/scripts/battery_color_status.sh
Executable file
74
tmux/plugins/tmux-battery/scripts/battery_color_status.sh
Executable file
@ -0,0 +1,74 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||||
|
|
||||||
|
source "$CURRENT_DIR/helpers.sh"
|
||||||
|
|
||||||
|
# script global variables
|
||||||
|
color_status_primary_charged=''
|
||||||
|
color_status_primary_charging=''
|
||||||
|
color_status_primary_discharging=''
|
||||||
|
color_status_primary_attached=''
|
||||||
|
color_status_primary_unknown=''
|
||||||
|
color_status_secondary_charged=''
|
||||||
|
color_status_secondary_charging=''
|
||||||
|
color_status_secondary_discharging=''
|
||||||
|
color_status_secondary_attached=''
|
||||||
|
color_status_secondary_unknown=''
|
||||||
|
|
||||||
|
# script default variables
|
||||||
|
color_status_primary_charged_default='colour33'
|
||||||
|
color_status_primary_charging_default='colour33'
|
||||||
|
color_status_primary_discharging_default='colour14'
|
||||||
|
color_status_primary_attached_default='colour201'
|
||||||
|
color_status_primary_unknown_default='colour7'
|
||||||
|
color_status_secondary_charged_default='colour0'
|
||||||
|
color_status_secondary_charging_default='colour0'
|
||||||
|
color_status_secondary_discharging_default='colour0'
|
||||||
|
color_status_secondary_attached_default='colour0'
|
||||||
|
color_status_secondary_unknown_default='colour0'
|
||||||
|
|
||||||
|
# colors are set as script global variables
|
||||||
|
get_color_status_settings() {
|
||||||
|
color_status_primary_charged=$(get_tmux_option "@batt_color_status_primary_charged" "$color_status_primary_charged_default")
|
||||||
|
color_status_primary_charging=$(get_tmux_option "@batt_color_status_primary_charging" "$color_status_primary_charging_default")
|
||||||
|
color_status_primary_discharging=$(get_tmux_option "@batt_color_status_primary_discharging" "$color_status_primary_discharging_default")
|
||||||
|
color_status_primary_attached=$(get_tmux_option "@batt_color_status_primary_attached" "$color_status_primary_attached_default")
|
||||||
|
color_status_primary_unknown=$(get_tmux_option "@batt_color_status_primary_unknown" "$color_status_primary_unknown_default")
|
||||||
|
color_status_secondary_charged=$(get_tmux_option "@batt_color_status_secondary_charged" "$color_status_secondary_charged_default")
|
||||||
|
color_status_secondary_charging=$(get_tmux_option "@batt_color_status_secondary_charging" "$color_status_secondary_charging_default")
|
||||||
|
color_status_secondary_discharging=$(get_tmux_option "@batt_color_status_secondary_discharging" "$color_status_secondary_discharging_default")
|
||||||
|
color_status_secondary_attached=$(get_tmux_option "@batt_color_status_secondary_attached" "$color_status_secondary_attached_default")
|
||||||
|
color_status_secondary_unknown=$(get_tmux_option "@batt_color_status_secondary_unknown" "$color_status_secondary_unknown_default")
|
||||||
|
}
|
||||||
|
|
||||||
|
print_color_status() {
|
||||||
|
local plane_primary="$1"
|
||||||
|
local plane_secondary=""
|
||||||
|
if [ "$plane_primary" == "bg" ]; then
|
||||||
|
plane_secondary="fg"
|
||||||
|
else
|
||||||
|
plane_secondary="bg"
|
||||||
|
fi
|
||||||
|
local status="$2"
|
||||||
|
if [[ $status =~ (charged) || $status =~ (full) ]]; then
|
||||||
|
printf "#[$plane_primary=$color_status_primary_charged${color_status_secondary_charged:+",$plane_secondary=$color_status_secondary_charged"}]"
|
||||||
|
elif [[ $status =~ (^charging) ]]; then
|
||||||
|
printf "#[$plane_primary=$color_status_primary_charging${color_status_secondary_charging:+",$plane_secondary=$color_status_secondary_charging"}]"
|
||||||
|
elif [[ $status =~ (^discharging) ]]; then
|
||||||
|
printf "#[$plane_primary=$color_status_primary_discharging${color_status_secondary_discharging:+",$plane_secondary=$color_status_secondary_discharging"}]"
|
||||||
|
elif [[ $status =~ (attached) ]]; then
|
||||||
|
printf "#[$plane_primary=$color_status_primary_attached${color_status_secondary_attached:+",$plane_secondary=$color_status_secondary_attached"}]"
|
||||||
|
else
|
||||||
|
printf "#[$plane_primary=$color_status_primary_unknown${color_status_secondary_unknown:+",$plane_secondary=$color_status_secondary_unknown"}]"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
main() {
|
||||||
|
local plane="$1"
|
||||||
|
local status=${2:-$(battery_status)}
|
||||||
|
get_color_status_settings
|
||||||
|
print_color_status "$plane" "$status"
|
||||||
|
}
|
||||||
|
|
||||||
|
main $@
|
45
tmux/plugins/tmux-battery/scripts/battery_graph.sh
Executable file
45
tmux/plugins/tmux-battery/scripts/battery_graph.sh
Executable file
@ -0,0 +1,45 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||||
|
|
||||||
|
source "$CURRENT_DIR/helpers.sh"
|
||||||
|
|
||||||
|
print_graph() {
|
||||||
|
local percentage=$1
|
||||||
|
if [ $percentage -gt 5 ]; then
|
||||||
|
printf "▁"
|
||||||
|
else
|
||||||
|
printf " "
|
||||||
|
fi
|
||||||
|
if [ $percentage -ge 25 ]; then
|
||||||
|
printf "▂"
|
||||||
|
else
|
||||||
|
printf " "
|
||||||
|
fi
|
||||||
|
if [ $percentage -ge 50 ]; then
|
||||||
|
printf "▄"
|
||||||
|
else
|
||||||
|
printf " "
|
||||||
|
fi
|
||||||
|
if [ $percentage -ge 75 ]; then
|
||||||
|
printf "▆"
|
||||||
|
else
|
||||||
|
printf " "
|
||||||
|
fi
|
||||||
|
if [ $percentage -ge 95 ]; then
|
||||||
|
printf "█"
|
||||||
|
else
|
||||||
|
printf " "
|
||||||
|
echo "▇"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
main() {
|
||||||
|
local percentage=$($CURRENT_DIR/battery_percentage.sh)
|
||||||
|
if [ "$(uname)" == "OpenBSD" ]; then
|
||||||
|
print_graph ${percentage}
|
||||||
|
else
|
||||||
|
print_graph ${percentage%?}
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
main
|
21
tmux/plugins/tmux-battery/scripts/battery_icon.sh
Executable file
21
tmux/plugins/tmux-battery/scripts/battery_icon.sh
Executable file
@ -0,0 +1,21 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||||
|
|
||||||
|
source "$CURRENT_DIR/helpers.sh"
|
||||||
|
|
||||||
|
print_icon() {
|
||||||
|
local status=$1
|
||||||
|
if [ "$status" == "discharging" ]; then
|
||||||
|
$CURRENT_DIR/battery_icon_charge.sh
|
||||||
|
else
|
||||||
|
$CURRENT_DIR/battery_icon_status.sh "$status"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
main() {
|
||||||
|
local status=$(battery_status)
|
||||||
|
print_icon "$status"
|
||||||
|
}
|
||||||
|
|
||||||
|
main
|
66
tmux/plugins/tmux-battery/scripts/battery_icon_charge.sh
Executable file
66
tmux/plugins/tmux-battery/scripts/battery_icon_charge.sh
Executable file
@ -0,0 +1,66 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||||
|
|
||||||
|
source "$CURRENT_DIR/helpers.sh"
|
||||||
|
|
||||||
|
# script global variables
|
||||||
|
icon_charge_tier8=''
|
||||||
|
icon_charge_tier7=''
|
||||||
|
icon_charge_tier6=''
|
||||||
|
icon_charge_tier5=''
|
||||||
|
icon_charge_tier4=''
|
||||||
|
icon_charge_tier3=''
|
||||||
|
icon_charge_tier2=''
|
||||||
|
icon_charge_tier1=''
|
||||||
|
|
||||||
|
# script default variables
|
||||||
|
icon_charge_tier8_default='█'
|
||||||
|
icon_charge_tier7_default='▇'
|
||||||
|
icon_charge_tier6_default='▆'
|
||||||
|
icon_charge_tier5_default='▅'
|
||||||
|
icon_charge_tier4_default='▄'
|
||||||
|
icon_charge_tier3_default='▃'
|
||||||
|
icon_charge_tier2_default='▂'
|
||||||
|
icon_charge_tier1_default='▁'
|
||||||
|
|
||||||
|
# icons are set as script global variables
|
||||||
|
get_icon_charge_settings() {
|
||||||
|
icon_charge_tier8=$(get_tmux_option "@batt_icon_charge_tier8" "$icon_charge_tier8_default")
|
||||||
|
icon_charge_tier7=$(get_tmux_option "@batt_icon_charge_tier7" "$icon_charge_tier7_default")
|
||||||
|
icon_charge_tier6=$(get_tmux_option "@batt_icon_charge_tier6" "$icon_charge_tier6_default")
|
||||||
|
icon_charge_tier5=$(get_tmux_option "@batt_icon_charge_tier5" "$icon_charge_tier5_default")
|
||||||
|
icon_charge_tier4=$(get_tmux_option "@batt_icon_charge_tier4" "$icon_charge_tier4_default")
|
||||||
|
icon_charge_tier3=$(get_tmux_option "@batt_icon_charge_tier3" "$icon_charge_tier3_default")
|
||||||
|
icon_charge_tier2=$(get_tmux_option "@batt_icon_charge_tier2" "$icon_charge_tier2_default")
|
||||||
|
icon_charge_tier1=$(get_tmux_option "@batt_icon_charge_tier1" "$icon_charge_tier1_default")
|
||||||
|
}
|
||||||
|
|
||||||
|
print_icon_charge() {
|
||||||
|
percentage=$($CURRENT_DIR/battery_percentage.sh | sed -e 's/%//')
|
||||||
|
if [ $percentage -ge 95 -o "$percentage" == "" ]; then
|
||||||
|
# if percentage is empty, assume it's a desktop
|
||||||
|
printf "$icon_charge_tier8"
|
||||||
|
elif [ $percentage -ge 80 ]; then
|
||||||
|
printf "$icon_charge_tier7"
|
||||||
|
elif [ $percentage -ge 65 ]; then
|
||||||
|
printf "$icon_charge_tier6"
|
||||||
|
elif [ $percentage -ge 50 ]; then
|
||||||
|
printf "$icon_charge_tier5"
|
||||||
|
elif [ $percentage -ge 35 ]; then
|
||||||
|
printf "$icon_charge_tier4"
|
||||||
|
elif [ $percentage -ge 20 ]; then
|
||||||
|
printf "$icon_charge_tier3"
|
||||||
|
elif [ $percentage -gt 5 ]; then
|
||||||
|
printf "$icon_charge_tier2"
|
||||||
|
else
|
||||||
|
printf "$icon_charge_tier1"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
main() {
|
||||||
|
get_icon_charge_settings
|
||||||
|
print_icon_charge
|
||||||
|
}
|
||||||
|
|
||||||
|
main
|
61
tmux/plugins/tmux-battery/scripts/battery_icon_status.sh
Executable file
61
tmux/plugins/tmux-battery/scripts/battery_icon_status.sh
Executable file
@ -0,0 +1,61 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||||
|
|
||||||
|
source "$CURRENT_DIR/helpers.sh"
|
||||||
|
|
||||||
|
# script global variables
|
||||||
|
icon_status_charged=''
|
||||||
|
icon_status_charging=''
|
||||||
|
icon_status_discharging=''
|
||||||
|
icon_status_attached=''
|
||||||
|
icon_status_unknown=''
|
||||||
|
|
||||||
|
# script default variables
|
||||||
|
icon_status_charged_default='🔌'
|
||||||
|
icon_status_charged_default_osx='🔌'
|
||||||
|
icon_status_charging_default='🔌'
|
||||||
|
icon_status_discharging_default='🔋'
|
||||||
|
icon_status_attached_default='⚠️'
|
||||||
|
icon_status_unknown_default='?'
|
||||||
|
|
||||||
|
# determine which charged_default variable to use
|
||||||
|
get_icon_status_charged_default() {
|
||||||
|
if is_osx; then
|
||||||
|
printf "$icon_status_charged_default_osx"
|
||||||
|
else
|
||||||
|
printf "$icon_status_charged_default"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# icons are set as script global variables
|
||||||
|
get_icon_status_settings() {
|
||||||
|
icon_status_charged=$(get_tmux_option "@batt_icon_status_charged" "$(get_icon_status_charged_default)")
|
||||||
|
icon_status_charging=$(get_tmux_option "@batt_icon_status_charging" "$icon_status_charging_default")
|
||||||
|
icon_status_discharging=$(get_tmux_option "@batt_icon_status_discharging" "$icon_status_discharging_default")
|
||||||
|
icon_status_attached=$(get_tmux_option "@batt_icon_status_attached" "$icon_status_attached_default")
|
||||||
|
icon_status_unknown=$(get_tmux_option "@batt_icon_status_unknown" "$icon_status_unknown_default")
|
||||||
|
}
|
||||||
|
|
||||||
|
print_icon_status() {
|
||||||
|
local status=$1
|
||||||
|
if [[ $status =~ (charged) || $status =~ (full) ]]; then
|
||||||
|
printf "$icon_status_charged"
|
||||||
|
elif [[ $status =~ (^charging) ]]; then
|
||||||
|
printf "$icon_status_charging"
|
||||||
|
elif [[ $status =~ (^discharging) ]]; then
|
||||||
|
printf "$icon_status_discharging"
|
||||||
|
elif [[ $status =~ (attached) ]]; then
|
||||||
|
printf "$icon_status_attached"
|
||||||
|
else
|
||||||
|
printf "$icon_status_unknown"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
main() {
|
||||||
|
get_icon_status_settings
|
||||||
|
local status=${1:-$(battery_status)}
|
||||||
|
print_icon_status "$status"
|
||||||
|
}
|
||||||
|
|
||||||
|
main
|
41
tmux/plugins/tmux-battery/scripts/battery_percentage.sh
Executable file
41
tmux/plugins/tmux-battery/scripts/battery_percentage.sh
Executable file
@ -0,0 +1,41 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||||
|
|
||||||
|
source "$CURRENT_DIR/helpers.sh"
|
||||||
|
|
||||||
|
print_battery_percentage() {
|
||||||
|
# percentage displayed in the 2nd field of the 2nd row
|
||||||
|
if command_exists "pmset"; then
|
||||||
|
pmset -g batt | grep -o "[0-9]\{1,3\}%"
|
||||||
|
elif command_exists "acpi"; then
|
||||||
|
acpi -b | grep -m 1 -Eo "[0-9]+%"
|
||||||
|
elif command_exists "upower"; then
|
||||||
|
# use DisplayDevice if available otherwise battery
|
||||||
|
local battery=$(upower -e | grep -E 'battery|DisplayDevice'| tail -n1)
|
||||||
|
if [ -z "$battery" ]; then
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
local percentage=$(upower -i $battery | awk '/percentage:/ {print $2}')
|
||||||
|
if [ "$percentage" ]; then
|
||||||
|
echo ${percentage%.*%}
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
local energy
|
||||||
|
local energy_full
|
||||||
|
energy=$(upower -i $battery | awk -v nrg="$energy" '/energy:/ {print nrg+$2}')
|
||||||
|
energy_full=$(upower -i $battery | awk -v nrgfull="$energy_full" '/energy-full:/ {print nrgfull+$2}')
|
||||||
|
if [ -n "$energy" ] && [ -n "$energy_full" ]; then
|
||||||
|
echo $energy $energy_full | awk '{printf("%d%%", ($1/$2)*100)}'
|
||||||
|
fi
|
||||||
|
elif command_exists "termux-battery-status"; then
|
||||||
|
termux-battery-status | jq -r '.percentage' | awk '{printf("%d%%", $1)}'
|
||||||
|
elif command_exists "apm"; then
|
||||||
|
apm -l
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
main() {
|
||||||
|
print_battery_percentage
|
||||||
|
}
|
||||||
|
main
|
128
tmux/plugins/tmux-battery/scripts/battery_remain.sh
Executable file
128
tmux/plugins/tmux-battery/scripts/battery_remain.sh
Executable file
@ -0,0 +1,128 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||||
|
|
||||||
|
source "$CURRENT_DIR/helpers.sh"
|
||||||
|
|
||||||
|
short=false
|
||||||
|
|
||||||
|
get_remain_settings() {
|
||||||
|
short=$(get_tmux_option "@batt_remain_short" false)
|
||||||
|
}
|
||||||
|
|
||||||
|
battery_discharging() {
|
||||||
|
local status="$(battery_status)"
|
||||||
|
[[ $status =~ (discharging) ]]
|
||||||
|
}
|
||||||
|
|
||||||
|
battery_charged() {
|
||||||
|
local status="$(battery_status)"
|
||||||
|
[[ $status =~ (charged) ]]
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
convertmins() {
|
||||||
|
((h=${1}/60))
|
||||||
|
((m=${1}%60))
|
||||||
|
printf "%02d:%02d\n" $h $m $s
|
||||||
|
}
|
||||||
|
|
||||||
|
apm_battery_remaining_time() {
|
||||||
|
local remaining_time="$(convertmins $(apm -m))"
|
||||||
|
if battery_discharging; then
|
||||||
|
if $short; then
|
||||||
|
echo $remaining_time | awk '{printf "~%s", $1}'
|
||||||
|
else
|
||||||
|
echo $remaining_time | awk '{printf "- %s left", $1}'
|
||||||
|
fi
|
||||||
|
elif battery_charged; then
|
||||||
|
if $short; then
|
||||||
|
echo $remaining_time | awk '{printf "charged", $1}'
|
||||||
|
else
|
||||||
|
echo $remaining_time | awk '{printf "fully charged", $1}'
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
echo "charging"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
pmset_battery_remaining_time() {
|
||||||
|
local status="$(pmset -g batt)"
|
||||||
|
if echo $status | grep 'no estimate' >/dev/null 2>&1; then
|
||||||
|
if $short; then
|
||||||
|
echo '~?:??'
|
||||||
|
else
|
||||||
|
echo '- Calculating estimate...'
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
local remaining_time="$(echo $status | grep -o '[0-9]\{1,2\}:[0-9]\{1,2\}')"
|
||||||
|
if battery_discharging; then
|
||||||
|
if $short; then
|
||||||
|
echo $remaining_time | awk '{printf "~%s", $1}'
|
||||||
|
else
|
||||||
|
echo $remaining_time | awk '{printf "- %s left", $1}'
|
||||||
|
fi
|
||||||
|
elif battery_charged; then
|
||||||
|
if $short; then
|
||||||
|
echo $remaining_time | awk '{printf "charged", $1}'
|
||||||
|
else
|
||||||
|
echo $remaining_time | awk '{printf "fully charged", $1}'
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
if $short; then
|
||||||
|
echo $remaining_time | awk '{printf "~%s", $1}'
|
||||||
|
else
|
||||||
|
echo $remaining_time | awk '{printf "- %s till full", $1}'
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
upower_battery_remaining_time() {
|
||||||
|
battery=$(upower -e | grep -E 'battery|DisplayDevice'| tail -n1)
|
||||||
|
if battery_discharging; then
|
||||||
|
local remaining_time
|
||||||
|
remaining_time=$(upower -i "$battery" | grep -E '(remain|time to empty)')
|
||||||
|
if $short; then
|
||||||
|
echo "$remaining_time" | awk '{printf "%s %s", $(NF-1), $(NF)}'
|
||||||
|
else
|
||||||
|
echo "$remaining_time" | awk '{printf "%s %s left", $(NF-1), $(NF)}'
|
||||||
|
fi
|
||||||
|
elif battery_charged; then
|
||||||
|
if $short; then
|
||||||
|
echo ""
|
||||||
|
else
|
||||||
|
echo "charged"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
local remaining_time
|
||||||
|
remaining_time=$(upower -i "$battery" | grep -E 'time to full')
|
||||||
|
if $short; then
|
||||||
|
echo "$remaining_time" | awk '{printf "%s %s", $(NF-1), $(NF)}'
|
||||||
|
else
|
||||||
|
echo "$remaining_time" | awk '{printf "%s %s to full", $(NF-1), $(NF)}'
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
acpi_battery_remaining_time() {
|
||||||
|
acpi -b | grep -m 1 -Eo "[0-9]+:[0-9]+:[0-9]+"
|
||||||
|
}
|
||||||
|
|
||||||
|
print_battery_remain() {
|
||||||
|
if command_exists "pmset"; then
|
||||||
|
pmset_battery_remaining_time
|
||||||
|
elif command_exists "acpi"; then
|
||||||
|
acpi_battery_remaining_time
|
||||||
|
elif command_exists "upower"; then
|
||||||
|
upower_battery_remaining_time
|
||||||
|
elif command_exists "apm"; then
|
||||||
|
apm_battery_remaining_time
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
main() {
|
||||||
|
get_remain_settings
|
||||||
|
print_battery_remain
|
||||||
|
}
|
||||||
|
main
|
50
tmux/plugins/tmux-battery/scripts/battery_status_bg.sh
Executable file
50
tmux/plugins/tmux-battery/scripts/battery_status_bg.sh
Executable file
@ -0,0 +1,50 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||||
|
|
||||||
|
source "$CURRENT_DIR/helpers.sh"
|
||||||
|
|
||||||
|
color_full_charge_default="#[bg=green]"
|
||||||
|
color_high_charge_default="#[bg=yellow]"
|
||||||
|
color_medium_charge_default="#[bg=colour208]" # orange
|
||||||
|
color_low_charge_default="#[bg=red]"
|
||||||
|
color_charging_default="#[bg=green]"
|
||||||
|
|
||||||
|
color_full_charge=""
|
||||||
|
color_high_charge=""
|
||||||
|
color_medium_charge=""
|
||||||
|
color_low_charge=""
|
||||||
|
color_charging=""
|
||||||
|
|
||||||
|
get_charge_color_settings() {
|
||||||
|
color_full_charge=$(get_tmux_option "@batt_color_full_charge" "$color_full_charge_default")
|
||||||
|
color_high_charge=$(get_tmux_option "@batt_color_high_charge" "$color_high_charge_default")
|
||||||
|
color_medium_charge=$(get_tmux_option "@batt_color_medium_charge" "$color_medium_charge_default")
|
||||||
|
color_low_charge=$(get_tmux_option "@batt_color_low_charge" "$color_low_charge_default")
|
||||||
|
color_charging=$(get_tmux_option "@batt_color_charging" "$color_charging_default")
|
||||||
|
}
|
||||||
|
|
||||||
|
print_battery_status_bg() {
|
||||||
|
# Call `battery_percentage.sh`.
|
||||||
|
percentage=$($CURRENT_DIR/battery_percentage.sh | sed -e 's/%//')
|
||||||
|
status=$(battery_status | awk '{print $1;}')
|
||||||
|
if [ $status == 'charging' ]; then
|
||||||
|
printf $color_charging
|
||||||
|
elif [ $percentage -eq 100 ]; then
|
||||||
|
printf $color_full_charge
|
||||||
|
elif [ $percentage -le 99 -a $percentage -ge 51 ];then
|
||||||
|
printf $color_high_charge
|
||||||
|
elif [ $percentage -le 50 -a $percentage -ge 16 ];then
|
||||||
|
printf $color_medium_charge
|
||||||
|
elif [ "$percentage" == "" ];then
|
||||||
|
printf $color_full_charge_default # assume it's a desktop
|
||||||
|
else
|
||||||
|
printf $color_low_charge
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
main() {
|
||||||
|
get_charge_color_settings
|
||||||
|
print_battery_status_bg
|
||||||
|
}
|
||||||
|
main
|
50
tmux/plugins/tmux-battery/scripts/battery_status_fg.sh
Executable file
50
tmux/plugins/tmux-battery/scripts/battery_status_fg.sh
Executable file
@ -0,0 +1,50 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||||
|
|
||||||
|
source "$CURRENT_DIR/helpers.sh"
|
||||||
|
|
||||||
|
color_full_charge_default="#[fg=green]"
|
||||||
|
color_high_charge_default="#[fg=yellow]"
|
||||||
|
color_medium_charge_default="#[fg=colour208]" # orange
|
||||||
|
color_low_charge_default="#[fg=red]"
|
||||||
|
color_charging_default="#[fg=green]"
|
||||||
|
|
||||||
|
color_full_charge=""
|
||||||
|
color_high_charge=""
|
||||||
|
color_medium_charge=""
|
||||||
|
color_low_charge=""
|
||||||
|
color_charging=""
|
||||||
|
|
||||||
|
get_charge_color_settings() {
|
||||||
|
color_full_charge=$(get_tmux_option "@batt_color_full_charge" "$color_full_charge_default")
|
||||||
|
color_high_charge=$(get_tmux_option "@batt_color_high_charge" "$color_high_charge_default")
|
||||||
|
color_medium_charge=$(get_tmux_option "@batt_color_medium_charge" "$color_medium_charge_default")
|
||||||
|
color_low_charge=$(get_tmux_option "@batt_color_low_charge" "$color_low_charge_default")
|
||||||
|
color_charging=$(get_tmux_option "@batt_color_charging" "$color_charging_default")
|
||||||
|
}
|
||||||
|
|
||||||
|
print_battery_status_fg() {
|
||||||
|
# Call `battery_percentage.sh`.
|
||||||
|
percentage=$($CURRENT_DIR/battery_percentage.sh | sed -e 's/%//')
|
||||||
|
status=$(battery_status | awk '{print $1;}')
|
||||||
|
if [ $status == 'charging' ]; then
|
||||||
|
printf $color_charging
|
||||||
|
elif [ $percentage -eq 100 ]; then
|
||||||
|
printf $color_full_charge
|
||||||
|
elif [ $percentage -le 99 -a $percentage -ge 51 ];then
|
||||||
|
printf $color_high_charge
|
||||||
|
elif [ $percentage -le 50 -a $percentage -ge 16 ];then
|
||||||
|
printf $color_medium_charge
|
||||||
|
elif [ "$percentage" == "" ];then
|
||||||
|
printf $color_full_charge_default # assume it's a desktop
|
||||||
|
else
|
||||||
|
printf $color_low_charge
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
main() {
|
||||||
|
get_charge_color_settings
|
||||||
|
print_battery_status_fg
|
||||||
|
}
|
||||||
|
main
|
50
tmux/plugins/tmux-battery/scripts/helpers.sh
Normal file
50
tmux/plugins/tmux-battery/scripts/helpers.sh
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
is_osx() {
|
||||||
|
[ $(uname) == "Darwin" ]
|
||||||
|
}
|
||||||
|
|
||||||
|
is_chrome() {
|
||||||
|
chrome="/sys/class/chromeos/cros_ec"
|
||||||
|
if [ -d "$chrome" ]; then
|
||||||
|
return 0
|
||||||
|
else
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
command_exists() {
|
||||||
|
local command="$1"
|
||||||
|
type "$command" >/dev/null 2>&1
|
||||||
|
}
|
||||||
|
|
||||||
|
battery_status() {
|
||||||
|
if command_exists "pmset"; then
|
||||||
|
pmset -g batt | awk -F '; *' 'NR==2 { print $2 }'
|
||||||
|
elif command_exists "acpi"; then
|
||||||
|
acpi -b | awk '{gsub(/,/, ""); print tolower($3); exit}'
|
||||||
|
elif command_exists "upower"; then
|
||||||
|
local battery
|
||||||
|
battery=$(upower -e | grep -E 'battery|DisplayDevice'| tail -n1)
|
||||||
|
upower -i $battery | awk '/state/ {print $2}'
|
||||||
|
elif command_exists "termux-battery-status"; then
|
||||||
|
termux-battery-status | jq -r '.status' | awk '{printf("%s%", tolower($1))}'
|
||||||
|
elif command_exists "apm"; then
|
||||||
|
local battery
|
||||||
|
battery=$(apm -a)
|
||||||
|
if [ $battery -eq 0 ]; then
|
||||||
|
echo "discharging"
|
||||||
|
elif [ $battery -eq 1 ]; then
|
||||||
|
echo "charging"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
}
|
19
tmux/plugins/tmux-continuum/LICENSE.md
Normal file
19
tmux/plugins/tmux-continuum/LICENSE.md
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
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.
|
98
tmux/plugins/tmux-continuum/README.md
Normal file
98
tmux/plugins/tmux-continuum/README.md
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
# 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 the interval of 15 minutes. All the saving
|
||||||
|
happens in the background without the impact to your workflow.
|
||||||
|
|
||||||
|
This action starts automatically when the plugin is installed.
|
||||||
|
|
||||||
|
#### Automatic tmux start
|
||||||
|
|
||||||
|
Tmux is automatically started after the computer/server is turned on.
|
||||||
|
|
||||||
|
See the [instructions](docs/automatic_start.md) 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
|
||||||
|
|
||||||
|
### Reporting bugs and contributing
|
||||||
|
|
||||||
|
Both contributing and bug reports are welcome. Please check out
|
||||||
|
[contributing guidelines](CONTRIBUTING.md).
|
||||||
|
|
||||||
|
### License
|
||||||
|
[MIT](LICENSE.md)
|
87
tmux/plugins/tmux-continuum/continuum.tmux
Executable file
87
tmux/plugins/tmux-continuum/continuum.tmux
Executable file
@ -0,0 +1,87 @@
|
|||||||
|
#!/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}')"
|
||||||
|
[ "$tmux_start_time" == "" ] || [ "$tmux_start_time" -gt "$(($(date +%s)-10))" ]
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
33
tmux/plugins/tmux-continuum/scripts/check_tmux_version.sh
Executable file
33
tmux/plugins/tmux-continuum/scripts/check_tmux_version.sh
Executable file
@ -0,0 +1,33 @@
|
|||||||
|
#!/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
|
29
tmux/plugins/tmux-continuum/scripts/continuum_restore.sh
Executable file
29
tmux/plugins/tmux-continuum/scripts/continuum_restore.sh
Executable file
@ -0,0 +1,29 @@
|
|||||||
|
#!/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
|
60
tmux/plugins/tmux-continuum/scripts/continuum_save.sh
Executable file
60
tmux/plugins/tmux-continuum/scripts/continuum_save.sh
Executable file
@ -0,0 +1,60 @@
|
|||||||
|
#!/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
|
25
tmux/plugins/tmux-continuum/scripts/continuum_status.sh
Executable file
25
tmux/plugins/tmux-continuum/scripts/continuum_status.sh
Executable file
@ -0,0 +1,25 @@
|
|||||||
|
#!/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
|
36
tmux/plugins/tmux-continuum/scripts/handle_tmux_automatic_start.sh
Executable file
36
tmux/plugins/tmux-continuum/scripts/handle_tmux_automatic_start.sh
Executable file
@ -0,0 +1,36 @@
|
|||||||
|
#!/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
|
@ -0,0 +1 @@
|
|||||||
|
docs/automatic_start.md
|
@ -0,0 +1,10 @@
|
|||||||
|
#!/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
|
@ -0,0 +1,66 @@
|
|||||||
|
#!/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_iterm_or_teminal_option_value() {
|
||||||
|
local options="$1"
|
||||||
|
if [[ "$options" =~ "iterm" ]]; then
|
||||||
|
echo "iterm"
|
||||||
|
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 iterm_or_terminal_value="$(get_iterm_or_teminal_option_value "$options")"
|
||||||
|
local fullscreen_option_value="$(get_fullscreen_option_value "$options")"
|
||||||
|
local tmux_start_script_path="${CURRENT_DIR}/osx_${iterm_or_terminal_value}_start_tmux.sh"
|
||||||
|
|
||||||
|
local launchd_plist_file_content="$(template "$tmux_start_script_path" "$fullscreen_option_value")"
|
||||||
|
echo "$launchd_plist_file_content" > "$osx_auto_start_file_path"
|
||||||
|
}
|
||||||
|
main
|
@ -0,0 +1,66 @@
|
|||||||
|
#!/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 terminal
|
||||||
|
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 i term 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 i term 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
|
@ -0,0 +1,52 @@
|
|||||||
|
#!/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
|
@ -0,0 +1,10 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||||
|
|
||||||
|
source "$CURRENT_DIR/../variables.sh"
|
||||||
|
|
||||||
|
main() {
|
||||||
|
systemctl --user disable ${systemd_service_name}
|
||||||
|
}
|
||||||
|
main
|
@ -0,0 +1,56 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
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=""
|
||||||
|
|
||||||
|
read -r -d '' content <<-EOF
|
||||||
|
[Unit]
|
||||||
|
Description=tmux default session (detached)
|
||||||
|
Documentation=man:tmux(1)
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=forking
|
||||||
|
Environment=DISPLAY=:0
|
||||||
|
ExecStart=/usr/bin/tmux ${systemd_tmux_server_start_cmd}
|
||||||
|
|
||||||
|
ExecStop=${HOME}/.tmux/plugins/tmux-resurrect/scripts/save.sh
|
||||||
|
ExecStop=/usr/bin/tmux kill-server
|
||||||
|
KillMode=none
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
main() {
|
||||||
|
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}")
|
||||||
|
mkdir -p "$(dirname ${systemd_unit_file_path})"
|
||||||
|
echo "$systemd_unit_file" > "${systemd_unit_file_path}"
|
||||||
|
enable_tmux_unit_on_boot
|
||||||
|
}
|
||||||
|
main
|
48
tmux/plugins/tmux-continuum/scripts/helpers.sh
Normal file
48
tmux/plugins/tmux-continuum/scripts/helpers.sh
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
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
|
||||||
|
ps -Ao "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 ]
|
||||||
|
}
|
7
tmux/plugins/tmux-continuum/scripts/shared.sh
Normal file
7
tmux/plugins/tmux-continuum/scripts/shared.sh
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
current_timestamp() {
|
||||||
|
echo "$(date +%s)"
|
||||||
|
}
|
||||||
|
|
||||||
|
set_last_save_timestamp() {
|
||||||
|
set_tmux_option "$last_auto_save_option" "$(current_timestamp)"
|
||||||
|
}
|
40
tmux/plugins/tmux-continuum/scripts/variables.sh
Normal file
40
tmux/plugins/tmux-continuum/scripts/variables.sh
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
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"
|
||||||
|
|
||||||
|
# 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"
|
19
tmux/plugins/tmux-copycat/LICENSE.md
Normal file
19
tmux/plugins/tmux-copycat/LICENSE.md
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
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.
|
142
tmux/plugins/tmux-copycat/README.md
Normal file
142
tmux/plugins/tmux-copycat/README.md
Normal file
@ -0,0 +1,142 @@
|
|||||||
|
# Tmux copycat
|
||||||
|
|
||||||
|
[](https://travis-ci.org/tmux-plugins/tmux-copycat)
|
||||||
|
|
||||||
|
This plugin enables:
|
||||||
|
|
||||||
|
- regex searches
|
||||||
|
- search result highlighting
|
||||||
|
- predefined searches
|
||||||
|
|
||||||
|
Predefined searches are plugin killer feature. It speeds the workflow and
|
||||||
|
reduces mouse usage with Tmux.
|
||||||
|
|
||||||
|
It works even better when paired with
|
||||||
|
[tmux yank](https://github.com/tmux-plugins/tmux-yank). Tested and working on
|
||||||
|
Linux, OSX and Cygwin.
|
||||||
|
|
||||||
|
### Screencast
|
||||||
|
|
||||||
|
[](https://vimeo.com/101867689)
|
||||||
|
|
||||||
|
#### Search
|
||||||
|
|
||||||
|
- `prefix + /` - regex search (strings work too)
|
||||||
|
|
||||||
|
Example search entries:
|
||||||
|
|
||||||
|
- `foo` - searches for string `foo`
|
||||||
|
- `[0-9]+` - regex search for numbers
|
||||||
|
|
||||||
|
Grep is used for searching.<br/>
|
||||||
|
Searches are case insensitive.<br/>
|
||||||
|
|
||||||
|
#### Predefined searches
|
||||||
|
|
||||||
|
- `prefix + ctrl-f` - simple *f*ile search
|
||||||
|
- `prefix + ctrl-g` - jumping over *g*it status files (best used after `git status` command)
|
||||||
|
- `prefix + alt-h` - jumping over SHA-1/SHA-256 hashes (best used after `git log` command)
|
||||||
|
- `prefix + ctrl-u` - *u*rl search (http, ftp and git urls)
|
||||||
|
- `prefix + ctrl-d` - number search (mnemonic d, as digit)
|
||||||
|
- `prefix + alt-i` - *i*p address search
|
||||||
|
|
||||||
|
These start "copycat mode" and jump to first match.
|
||||||
|
|
||||||
|
#### "Copycat mode" bindings
|
||||||
|
|
||||||
|
These are enabled when you search with copycat:
|
||||||
|
|
||||||
|
- `n` - jumps to the next match
|
||||||
|
- `N` - jumps to the previous match
|
||||||
|
|
||||||
|
To copy a highlighted match:
|
||||||
|
|
||||||
|
- `Enter` - if you're using Tmux `vi` mode
|
||||||
|
- `ctrl-w` or `alt-w` - if you're using Tmux `emacs` mode
|
||||||
|
|
||||||
|
Copying a highlighted match will take you "out" of copycat mode. Paste with
|
||||||
|
`prefix + ]` (this is Tmux default paste).
|
||||||
|
|
||||||
|
Copying highlighted matches can be enhanced with
|
||||||
|
[tmux yank](https://github.com/tmux-plugins/tmux-yank).
|
||||||
|
|
||||||
|
### 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-copycat'
|
||||||
|
|
||||||
|
Hit `prefix + I` to fetch the plugin and source it. You should now be able to
|
||||||
|
use the plugin.
|
||||||
|
|
||||||
|
Optional (but recommended) install `gawk` via your package manager of choice
|
||||||
|
for better UTF-8 character support.
|
||||||
|
|
||||||
|
### Manual Installation
|
||||||
|
|
||||||
|
Clone the repo:
|
||||||
|
|
||||||
|
$ git clone https://github.com/tmux-plugins/tmux-copycat ~/clone/path
|
||||||
|
|
||||||
|
Add this line to the bottom of `.tmux.conf`:
|
||||||
|
|
||||||
|
run-shell ~/clone/path/copycat.tmux
|
||||||
|
|
||||||
|
Reload TMUX environment with: `$ tmux source-file ~/.tmux.conf`. You should now
|
||||||
|
be able to use the plugin.
|
||||||
|
|
||||||
|
Optional (but recommended) install `gawk` via your package manager of choice
|
||||||
|
for better UTF-8 character support.
|
||||||
|
|
||||||
|
### Installation for Tmux 2.3 and earlier
|
||||||
|
|
||||||
|
Due to the changes in tmux, the latest version of this plugin doesn't support
|
||||||
|
tmux 2.3 and earlier. It is recommended you upgrade to tmux version 2.4 or
|
||||||
|
later. If you must continue using older version, please follow
|
||||||
|
[these steps for installation](docs/installation_for_tmux_2.3.md).
|
||||||
|
|
||||||
|
### Limitations
|
||||||
|
|
||||||
|
This plugin has some known limitations. Please read about it
|
||||||
|
[here](docs/limitations.md).
|
||||||
|
|
||||||
|
### Docs
|
||||||
|
|
||||||
|
- Most of the behavior of tmux-copycat can be customized via tmux options.
|
||||||
|
[Check out the full options list](docs/customizations.md).
|
||||||
|
- To speed up the workflow you can define new bindings in `.tmux.conf` for
|
||||||
|
searches you use often, more info [here](docs/defining_new_stored_searches.md)
|
||||||
|
|
||||||
|
### Other goodies
|
||||||
|
|
||||||
|
`tmux-copycat` works great with:
|
||||||
|
|
||||||
|
- [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 a highlighted file or a url
|
||||||
|
- [tmux-continuum](https://github.com/tmux-plugins/tmux-continuum) - automatic
|
||||||
|
restoring and continuous saving of tmux env
|
||||||
|
|
||||||
|
### Test suite
|
||||||
|
|
||||||
|
This plugin has a pretty extensive integration test suite that runs on
|
||||||
|
[travis](https://travis-ci.org/tmux-plugins/tmux-copycat).
|
||||||
|
|
||||||
|
When run locally, it depends on `vagrant`. Run it with:
|
||||||
|
|
||||||
|
# within project top directory
|
||||||
|
$ ./run-tests
|
||||||
|
|
||||||
|
### Contributions and new features
|
||||||
|
|
||||||
|
Bug fixes and contributions are welcome.
|
||||||
|
|
||||||
|
Feel free to suggest new features, via github issues.
|
||||||
|
|
||||||
|
If you have a bigger idea you'd like to work on, please get in touch, also via
|
||||||
|
github issues.
|
||||||
|
|
||||||
|
### License
|
||||||
|
|
||||||
|
[MIT](LICENSE.md)
|
70
tmux/plugins/tmux-copycat/copycat.tmux
Executable file
70
tmux/plugins/tmux-copycat/copycat.tmux
Executable file
@ -0,0 +1,70 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||||
|
|
||||||
|
source "$CURRENT_DIR/scripts/variables.sh"
|
||||||
|
source "$CURRENT_DIR/scripts/helpers.sh"
|
||||||
|
source "$CURRENT_DIR/scripts/stored_search_helpers.sh"
|
||||||
|
|
||||||
|
# this function defines default stored searches
|
||||||
|
set_default_stored_searches() {
|
||||||
|
local file_search="$(get_tmux_option "$copycat_file_search_option" "$default_file_search_key")"
|
||||||
|
local url_search="$(get_tmux_option "$copycat_url_search_option" "$default_url_search_key")"
|
||||||
|
local digit_search="$(get_tmux_option "$copycat_digit_search_option" "$default_digit_search_key")"
|
||||||
|
local hash_search="$(get_tmux_option "$copycat_hash_search_option" "$default_hash_search_key")"
|
||||||
|
local ip_search="$(get_tmux_option "$copycat_ip_search_option" "$default_ip_search_key")"
|
||||||
|
|
||||||
|
if stored_search_not_defined "$url_search"; then
|
||||||
|
tmux set-option -g "${COPYCAT_VAR_PREFIX}_${url_search}" "(https?://|git@|git://|ssh://|ftp://|file:///)[[:alnum:]?=%/_.:,;~@!#$&()*+-]*"
|
||||||
|
fi
|
||||||
|
if stored_search_not_defined "$file_search"; then
|
||||||
|
tmux set-option -g "${COPYCAT_VAR_PREFIX}_${file_search}" "(^|^\.|[[:space:]]|[[:space:]]\.|[[:space:]]\.\.|^\.\.)[[:alnum:]~_-]*/[][[:alnum:]_.#$%&+=/@-]*"
|
||||||
|
fi
|
||||||
|
if stored_search_not_defined "$digit_search"; then
|
||||||
|
tmux set-option -g "${COPYCAT_VAR_PREFIX}_${digit_search}" "[[:digit:]]+"
|
||||||
|
fi
|
||||||
|
if stored_search_not_defined "$hash_search"; then
|
||||||
|
tmux set-option -g "${COPYCAT_VAR_PREFIX}_${hash_search}" "\b([0-9a-f]{7,40}|[[:alnum:]]{52}|[0-9a-f]{62})\b"
|
||||||
|
fi
|
||||||
|
if stored_search_not_defined "$ip_search"; then
|
||||||
|
tmux set-option -g "${COPYCAT_VAR_PREFIX}_${ip_search}" "[[:digit:]]{1,3}\.[[:digit:]]{1,3}\.[[:digit:]]{1,3}\.[[:digit:]]{1,3}"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
set_start_bindings() {
|
||||||
|
set_default_stored_searches
|
||||||
|
local stored_search_vars="$(stored_search_vars)"
|
||||||
|
local search_var
|
||||||
|
local key
|
||||||
|
local pattern
|
||||||
|
for search_var in $stored_search_vars; do
|
||||||
|
key="$(get_stored_search_key "$search_var")"
|
||||||
|
pattern="$(get_stored_search_pattern "$search_var")"
|
||||||
|
tmux bind-key "$key" run-shell "$CURRENT_DIR/scripts/copycat_mode_start.sh '$pattern'"
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
set_copycat_search_binding() {
|
||||||
|
local key_bindings
|
||||||
|
read -r -d '' -a key_bindings <<<"$(get_tmux_option "$copycat_search_option" "$default_copycat_search_key")"
|
||||||
|
local key
|
||||||
|
for key in "${key_bindings[@]}"; do
|
||||||
|
tmux bind-key "$key" run-shell "$CURRENT_DIR/scripts/copycat_search.sh"
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
set_copycat_git_special_binding() {
|
||||||
|
local key_bindings
|
||||||
|
read -r -d '' -a key_bindings <<<"$(get_tmux_option "$copycat_git_search_option" "$default_git_search_key")"
|
||||||
|
local key
|
||||||
|
for key in "${key_bindings[@]}"; do
|
||||||
|
tmux bind-key "$key" run-shell "$CURRENT_DIR/scripts/copycat_git_special.sh #{pane_current_path}"
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
main() {
|
||||||
|
set_start_bindings
|
||||||
|
set_copycat_search_binding
|
||||||
|
set_copycat_git_special_binding
|
||||||
|
}
|
||||||
|
main
|
78
tmux/plugins/tmux-copycat/scripts/check_tmux_version.sh
Executable file
78
tmux/plugins/tmux-copycat/scripts/check_tmux_version.sh
Executable file
@ -0,0 +1,78 @@
|
|||||||
|
#!/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
|
58
tmux/plugins/tmux-copycat/scripts/copycat_generate_results.sh
Executable file
58
tmux/plugins/tmux-copycat/scripts/copycat_generate_results.sh
Executable file
@ -0,0 +1,58 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||||
|
|
||||||
|
source "$CURRENT_DIR/helpers.sh"
|
||||||
|
|
||||||
|
search_pattern="$1"
|
||||||
|
|
||||||
|
capture_pane() {
|
||||||
|
local file=$1
|
||||||
|
# copying 9M lines back will hopefully fetch the whole scrollback
|
||||||
|
tmux capture-pane -S -9000000 -p > "$file"
|
||||||
|
}
|
||||||
|
|
||||||
|
# doing 2 things in 1 step so that we don't write to disk too much
|
||||||
|
reverse_and_create_copycat_file() {
|
||||||
|
local file=$1
|
||||||
|
local copycat_file=$2
|
||||||
|
local grep_pattern=$3
|
||||||
|
(tac 2>/dev/null || tail -r) < "$file" | grep -oniE "$grep_pattern" > "$copycat_file"
|
||||||
|
}
|
||||||
|
|
||||||
|
delete_old_files() {
|
||||||
|
local scrollback_filename="$(get_scrollback_filename)"
|
||||||
|
local copycat_filename="$(get_copycat_filename)"
|
||||||
|
rm -f "$scrollback_filename" "$copycat_filename"
|
||||||
|
}
|
||||||
|
|
||||||
|
generate_copycat_file() {
|
||||||
|
local grep_pattern="$1"
|
||||||
|
local scrollback_filename="$(get_scrollback_filename)"
|
||||||
|
local copycat_filename="$(get_copycat_filename)"
|
||||||
|
mkdir -p "$(_get_tmp_dir)"
|
||||||
|
chmod 0700 "$(_get_tmp_dir)"
|
||||||
|
capture_pane "$scrollback_filename"
|
||||||
|
reverse_and_create_copycat_file "$scrollback_filename" "$copycat_filename" "$grep_pattern"
|
||||||
|
}
|
||||||
|
|
||||||
|
if_no_results_exit_with_message() {
|
||||||
|
local copycat_filename="$(get_copycat_filename)"
|
||||||
|
# check for empty filename
|
||||||
|
if ! [ -s "$copycat_filename" ]; then
|
||||||
|
display_message "No results!"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
main() {
|
||||||
|
local grep_pattern="$1"
|
||||||
|
if not_in_copycat_mode; then
|
||||||
|
delete_old_files
|
||||||
|
generate_copycat_file "$grep_pattern"
|
||||||
|
if_no_results_exit_with_message
|
||||||
|
set_copycat_mode
|
||||||
|
copycat_increase_counter
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
main "$search_pattern"
|
58
tmux/plugins/tmux-copycat/scripts/copycat_git_special.sh
Executable file
58
tmux/plugins/tmux-copycat/scripts/copycat_git_special.sh
Executable file
@ -0,0 +1,58 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||||
|
|
||||||
|
PANE_CURRENT_PATH="$1"
|
||||||
|
|
||||||
|
source "$CURRENT_DIR/helpers.sh"
|
||||||
|
|
||||||
|
git_status_files() {
|
||||||
|
local git_working_dir="$PANE_CURRENT_PATH"
|
||||||
|
local git_dir="$PANE_CURRENT_PATH/.git"
|
||||||
|
echo "$(git --git-dir="$git_dir" --work-tree="$git_working_dir" status --porcelain)"
|
||||||
|
}
|
||||||
|
|
||||||
|
formatted_git_status() {
|
||||||
|
local raw_gist_status="$(git_status_files)"
|
||||||
|
echo "$(echo "$raw_gist_status" | cut -c 4-)"
|
||||||
|
}
|
||||||
|
|
||||||
|
exit_if_no_results() {
|
||||||
|
local results="$1"
|
||||||
|
if [ -z "$results" ]; then
|
||||||
|
display_message "No results!"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
concatenate_files() {
|
||||||
|
local git_status_files="$(formatted_git_status)"
|
||||||
|
exit_if_no_results "$git_status_files"
|
||||||
|
|
||||||
|
local result=""
|
||||||
|
# Undefined until later within a while loop.
|
||||||
|
local file_separator
|
||||||
|
while read -r line; do
|
||||||
|
result="${result}${file_separator}${line}"
|
||||||
|
file_separator="|"
|
||||||
|
done <<< "$git_status_files"
|
||||||
|
echo "$result"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Creates one, big regex out of git status files.
|
||||||
|
# Example:
|
||||||
|
# `git status` shows files `foo.txt` and `bar.txt`
|
||||||
|
# output regex will be:
|
||||||
|
# `(foo.txt|bar.txt)
|
||||||
|
git_status_files_regex() {
|
||||||
|
local concatenated_files="$(concatenate_files)"
|
||||||
|
local regex_result="(${concatenated_files})"
|
||||||
|
echo "$regex_result"
|
||||||
|
}
|
||||||
|
|
||||||
|
main() {
|
||||||
|
local search_regex="$(git_status_files_regex)"
|
||||||
|
# starts copycat mode
|
||||||
|
$CURRENT_DIR/copycat_mode_start.sh "$search_regex"
|
||||||
|
}
|
||||||
|
main
|
289
tmux/plugins/tmux-copycat/scripts/copycat_jump.sh
Executable file
289
tmux/plugins/tmux-copycat/scripts/copycat_jump.sh
Executable file
@ -0,0 +1,289 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||||
|
|
||||||
|
source "$CURRENT_DIR/helpers.sh"
|
||||||
|
|
||||||
|
MAXIMUM_PADDING="25" # maximum padding below the result when it can't be centered
|
||||||
|
|
||||||
|
# jump to 'next' or 'prev' match
|
||||||
|
# global var for this file
|
||||||
|
NEXT_PREV="$1"
|
||||||
|
|
||||||
|
# 'vi' or 'emacs', this variable used as a global file constant
|
||||||
|
TMUX_COPY_MODE="$(tmux_copy_mode)"
|
||||||
|
|
||||||
|
_file_number_of_lines() {
|
||||||
|
local file="$1"
|
||||||
|
echo "$(wc -l $file | $AWK_CMD '{print $1}')"
|
||||||
|
}
|
||||||
|
|
||||||
|
_get_result_line() {
|
||||||
|
local file="$1"
|
||||||
|
local number="$2"
|
||||||
|
echo "$(head -"$number" "$file" | tail -1)"
|
||||||
|
}
|
||||||
|
|
||||||
|
_string_starts_with_digit() {
|
||||||
|
local string="$1"
|
||||||
|
echo "$string" |
|
||||||
|
\grep -q '^[[:digit:]]\+:'
|
||||||
|
}
|
||||||
|
|
||||||
|
_get_line_number() {
|
||||||
|
local string="$1"
|
||||||
|
local copycat_file="$2" # args 2 & 3 used to handle bug in OSX grep
|
||||||
|
local position_number="$3"
|
||||||
|
if _string_starts_with_digit "$string"; then
|
||||||
|
# we have a number!
|
||||||
|
local grep_line_number="$(echo "$string" | cut -f1 -d:)"
|
||||||
|
# grep line number index starts from 1, tmux line number index starts from 0
|
||||||
|
local tmux_line_number="$((grep_line_number - 1))"
|
||||||
|
else
|
||||||
|
# no number in the results line This is a bug in OSX grep.
|
||||||
|
# Fetching a number from a previous line.
|
||||||
|
local previous_line_num="$((position_number - 1))"
|
||||||
|
local result_line="$(_get_result_line "$copycat_file" "$previous_line_num")"
|
||||||
|
# recursively invoke this same function
|
||||||
|
tmux_line_number="$(_get_line_number "$result_line" "$copycat_file" "$previous_line_num")"
|
||||||
|
fi
|
||||||
|
echo "$tmux_line_number"
|
||||||
|
}
|
||||||
|
|
||||||
|
_get_match() {
|
||||||
|
local string="$1"
|
||||||
|
local full_match
|
||||||
|
if _string_starts_with_digit "$string"; then
|
||||||
|
full_match="$(echo "$string" | cut -f2- -d:)"
|
||||||
|
else
|
||||||
|
# This scenario handles OS X grep bug "no number in the results line".
|
||||||
|
# When there's no number at the beginning of the line, we're taking the
|
||||||
|
# whole line as a match. This handles the result line like this:
|
||||||
|
# `http://www.example.com` (the `http` would otherwise get cut off)
|
||||||
|
full_match="$string"
|
||||||
|
fi
|
||||||
|
echo -n "$full_match"
|
||||||
|
}
|
||||||
|
|
||||||
|
_escape_backslash() {
|
||||||
|
local string="$1"
|
||||||
|
echo "$(echo "$string" | sed 's/\\/\\\\/g')"
|
||||||
|
}
|
||||||
|
|
||||||
|
_get_match_line_position() {
|
||||||
|
local file="$1"
|
||||||
|
local line_number="$2"
|
||||||
|
local match="$3"
|
||||||
|
local adjusted_line_num=$((line_number + 1))
|
||||||
|
local result_line=$(tail -"$adjusted_line_num" "$file" | head -1)
|
||||||
|
|
||||||
|
# OS X awk cannot have `=` as the first char in the variable (bug in awk).
|
||||||
|
# If exists, changing the `=` character with `.` to avoid error.
|
||||||
|
local platform="$(uname)"
|
||||||
|
if [ "$platform" == "Darwin" ]; then
|
||||||
|
result_line="$(echo "$result_line" | sed 's/^=/./')"
|
||||||
|
match="$(echo "$match" | sed 's/^=/./')"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# awk treats \r, \n, \t etc as single characters and that messes up match
|
||||||
|
# highlighting. For that reason, we're escaping backslashes so above chars
|
||||||
|
# are treated literally.
|
||||||
|
result_line="$(_escape_backslash "$result_line")"
|
||||||
|
match="$(_escape_backslash "$match")"
|
||||||
|
|
||||||
|
local index=$($AWK_CMD -v a="$result_line" -v b="$match" 'BEGIN{print index(a,b)}')
|
||||||
|
local zero_index=$((index - 1))
|
||||||
|
echo "$zero_index"
|
||||||
|
}
|
||||||
|
|
||||||
|
_copycat_jump() {
|
||||||
|
local line_number="$1"
|
||||||
|
local match_line_position="$2"
|
||||||
|
local match="$3"
|
||||||
|
local scrollback_line_number="$4"
|
||||||
|
_copycat_enter_mode
|
||||||
|
_copycat_exit_select_mode
|
||||||
|
_copycat_jump_to_line "$line_number" "$scrollback_line_number"
|
||||||
|
_copycat_position_to_match_start "$match_line_position"
|
||||||
|
_copycat_select "$match"
|
||||||
|
}
|
||||||
|
|
||||||
|
_copycat_enter_mode() {
|
||||||
|
tmux copy-mode
|
||||||
|
}
|
||||||
|
|
||||||
|
# clears selection from a previous match
|
||||||
|
_copycat_exit_select_mode() {
|
||||||
|
tmux send-keys -X clear-selection
|
||||||
|
}
|
||||||
|
|
||||||
|
# "manually" go up in the scrollback for a number of lines
|
||||||
|
_copycat_manually_go_up() {
|
||||||
|
local line_number="$1"
|
||||||
|
tmux send-keys -X -N "$line_number" cursor-up
|
||||||
|
tmux send-keys -X start-of-line
|
||||||
|
}
|
||||||
|
|
||||||
|
_copycat_create_padding_below_result() {
|
||||||
|
local number_of_lines="$1"
|
||||||
|
local maximum_padding="$2"
|
||||||
|
local padding
|
||||||
|
|
||||||
|
# Padding should not be greater than half pane height
|
||||||
|
# (it wouldn't be centered then).
|
||||||
|
if [ "$number_of_lines" -gt "$maximum_padding" ]; then
|
||||||
|
padding="$maximum_padding"
|
||||||
|
else
|
||||||
|
padding="$number_of_lines"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# cannot create padding, exit function
|
||||||
|
if [ "$padding" -eq "0" ]; then
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
tmux send-keys -X -N "$padding" cursor-down
|
||||||
|
tmux send-keys -X -N "$padding" cursor-up
|
||||||
|
}
|
||||||
|
|
||||||
|
# performs a jump to go to line
|
||||||
|
_copycat_go_to_line_with_jump() {
|
||||||
|
local line_number="$1"
|
||||||
|
# first jumps to the "bottom" in copy mode so that jumps are consistent
|
||||||
|
tmux send-keys -X history-bottom
|
||||||
|
tmux send-keys -X start-of-line
|
||||||
|
tmux send-keys -X goto-line $line_number
|
||||||
|
}
|
||||||
|
|
||||||
|
# maximum line number that can be reached via tmux 'jump'
|
||||||
|
_get_max_jump() {
|
||||||
|
local scrollback_line_number="$1"
|
||||||
|
local window_height="$2"
|
||||||
|
local max_jump=$((scrollback_line_number - $window_height))
|
||||||
|
# max jump can't be lower than zero
|
||||||
|
if [ "$max_jump" -lt "0" ]; then
|
||||||
|
max_jump="0"
|
||||||
|
fi
|
||||||
|
echo "$max_jump"
|
||||||
|
}
|
||||||
|
|
||||||
|
_copycat_jump_to_line() {
|
||||||
|
local line_number="$1"
|
||||||
|
local scrollback_line_number="$2"
|
||||||
|
local window_height="$(tmux display-message -p '#{pane_height}')"
|
||||||
|
local correct_line_number
|
||||||
|
|
||||||
|
local max_jump=$(_get_max_jump "$scrollback_line_number" "$window_height")
|
||||||
|
local correction="0"
|
||||||
|
|
||||||
|
if [ "$line_number" -gt "$max_jump" ]; then
|
||||||
|
# We need to 'reach' a line number that is not accessible via 'jump'.
|
||||||
|
# Introducing 'correction'
|
||||||
|
correct_line_number="$max_jump"
|
||||||
|
correction=$((line_number - $correct_line_number))
|
||||||
|
else
|
||||||
|
# we can reach the desired line number via 'jump'. Correction not needed.
|
||||||
|
correct_line_number="$line_number"
|
||||||
|
fi
|
||||||
|
|
||||||
|
_copycat_go_to_line_with_jump "$correct_line_number"
|
||||||
|
|
||||||
|
if [ "$correction" -gt "0" ]; then
|
||||||
|
_copycat_manually_go_up "$correction"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# If no corrections (meaning result is not at the top of scrollback)
|
||||||
|
# we can then 'center' the result within a pane.
|
||||||
|
if [ "$correction" -eq "0" ]; then
|
||||||
|
local half_window_height="$((window_height / 2))"
|
||||||
|
# creating as much padding as possible, up to half pane height
|
||||||
|
_copycat_create_padding_below_result "$line_number" "$half_window_height"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
_copycat_position_to_match_start() {
|
||||||
|
local match_line_position="$1"
|
||||||
|
[ "$match_line_position" -eq "0" ] && return 0
|
||||||
|
|
||||||
|
tmux send-keys -X -N "$match_line_position" cursor-right
|
||||||
|
}
|
||||||
|
|
||||||
|
_copycat_select() {
|
||||||
|
local match="$1"
|
||||||
|
local length="${#match}"
|
||||||
|
tmux send-keys -X begin-selection
|
||||||
|
tmux send-keys -X -N "$length" cursor-right
|
||||||
|
if [ "$TMUX_COPY_MODE" == "vi" ]; then
|
||||||
|
tmux send-keys -X cursor-left # selection correction for 1 char
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# all functions above are "private", called from `do_next_jump` function
|
||||||
|
|
||||||
|
get_new_position_number() {
|
||||||
|
local copycat_file="$1"
|
||||||
|
local current_position="$2"
|
||||||
|
local new_position
|
||||||
|
|
||||||
|
# doing a forward/up jump
|
||||||
|
if [ "$NEXT_PREV" == "next" ]; then
|
||||||
|
local number_of_results=$(wc -l "$copycat_file" | $AWK_CMD '{ print $1 }')
|
||||||
|
if [ "$current_position" -eq "$number_of_results" ]; then
|
||||||
|
# position can't go beyond the last result
|
||||||
|
new_position="$current_position"
|
||||||
|
else
|
||||||
|
new_position="$((current_position + 1))"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# doing a backward/down jump
|
||||||
|
elif [ "$NEXT_PREV" == "prev" ]; then
|
||||||
|
if [ "$current_position" -eq "1" ]; then
|
||||||
|
# position can't go below 1
|
||||||
|
new_position="1"
|
||||||
|
else
|
||||||
|
new_position="$((current_position - 1))"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
echo "$new_position"
|
||||||
|
}
|
||||||
|
|
||||||
|
do_next_jump() {
|
||||||
|
local position_number="$1"
|
||||||
|
local copycat_file="$2"
|
||||||
|
local scrollback_file="$3"
|
||||||
|
|
||||||
|
local scrollback_line_number=$(_file_number_of_lines "$scrollback_file")
|
||||||
|
local result_line="$(_get_result_line "$copycat_file" "$position_number")"
|
||||||
|
local line_number=$(_get_line_number "$result_line" "$copycat_file" "$position_number")
|
||||||
|
local match=$(_get_match "$result_line")
|
||||||
|
local match_line_position=$(_get_match_line_position "$scrollback_file" "$line_number" "$match")
|
||||||
|
_copycat_jump "$line_number" "$match_line_position" "$match" "$scrollback_line_number"
|
||||||
|
}
|
||||||
|
|
||||||
|
notify_about_first_last_match() {
|
||||||
|
local current_position="$1"
|
||||||
|
local next_position="$2"
|
||||||
|
local message_duration="1500"
|
||||||
|
|
||||||
|
# if position didn't change, we are either on a 'first' or 'last' match
|
||||||
|
if [ "$current_position" -eq "$next_position" ]; then
|
||||||
|
if [ "$NEXT_PREV" == "next" ]; then
|
||||||
|
display_message "Last match!" "$message_duration"
|
||||||
|
elif [ "$NEXT_PREV" == "prev" ]; then
|
||||||
|
display_message "First match!" "$message_duration"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
main() {
|
||||||
|
if in_copycat_mode; then
|
||||||
|
local copycat_file="$(get_copycat_filename)"
|
||||||
|
local scrollback_file="$(get_scrollback_filename)"
|
||||||
|
local current_position="$(get_copycat_position)"
|
||||||
|
local next_position="$(get_new_position_number "$copycat_file" "$current_position")"
|
||||||
|
do_next_jump "$next_position" "$copycat_file" "$scrollback_file"
|
||||||
|
notify_about_first_last_match "$current_position" "$next_position"
|
||||||
|
set_copycat_position "$next_position"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
main
|
55
tmux/plugins/tmux-copycat/scripts/copycat_mode_bindings.sh
Executable file
55
tmux/plugins/tmux-copycat/scripts/copycat_mode_bindings.sh
Executable file
@ -0,0 +1,55 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||||
|
|
||||||
|
source "$CURRENT_DIR/helpers.sh"
|
||||||
|
AWK_CMD='awk'
|
||||||
|
if command_exists gawk; then
|
||||||
|
AWK_CMD='gawk'
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Extends a keyboard key.
|
||||||
|
# Benefits: tmux won't report errors and everything will work fine even if the
|
||||||
|
# script is deleted.
|
||||||
|
extend_key() {
|
||||||
|
local key="$1"
|
||||||
|
local script="$2"
|
||||||
|
local cmd
|
||||||
|
|
||||||
|
# 1. 'cmd' or 'key' is sent to tmux. This ensures the default key action is done.
|
||||||
|
# 2. Script is executed.
|
||||||
|
# 3. `true` command ensures an exit status 0 is returned. This ensures a
|
||||||
|
# user never gets an error msg - even if the script file from step 2 is
|
||||||
|
# deleted.
|
||||||
|
# We fetch the current behavior of the 'key' mapping in
|
||||||
|
# variable 'cmd'
|
||||||
|
cmd=$(tmux list-keys -T $(tmux_copy_mode_string) | $AWK_CMD '$4 == "'$key'"' | $AWK_CMD '{ $1=""; $2=""; $3=""; $4=""; sub(" ", " "); print }')
|
||||||
|
# If 'cmd' is already a copycat command, we do nothing
|
||||||
|
if echo "$cmd" | grep -q copycat; then
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
# We save the previous mapping to a file in order to be able to recover
|
||||||
|
# the previous mapping when we unbind
|
||||||
|
tmux list-keys -T $(tmux_copy_mode_string) | $AWK_CMD '$4 == "'$key'"' >> "${TMPDIR:-/tmp}/copycat_$(whoami)_recover_keys"
|
||||||
|
tmux bind-key -T $(tmux_copy_mode_string) "$key" run-shell "tmux $cmd; $script; true"
|
||||||
|
}
|
||||||
|
|
||||||
|
copycat_cancel_bindings() {
|
||||||
|
# keys that quit copy mode are enhanced to quit copycat mode as well.
|
||||||
|
local cancel_mode_bindings=$(copycat_quit_copy_mode_keys)
|
||||||
|
local key
|
||||||
|
for key in $cancel_mode_bindings; do
|
||||||
|
extend_key "$key" "$CURRENT_DIR/copycat_mode_quit.sh"
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
copycat_mode_bindings() {
|
||||||
|
extend_key "$(copycat_next_key)" "$CURRENT_DIR/copycat_jump.sh 'next'"
|
||||||
|
extend_key "$(copycat_prev_key)" "$CURRENT_DIR/copycat_jump.sh 'prev'"
|
||||||
|
}
|
||||||
|
|
||||||
|
main() {
|
||||||
|
copycat_mode_bindings
|
||||||
|
copycat_cancel_bindings
|
||||||
|
}
|
||||||
|
main
|
38
tmux/plugins/tmux-copycat/scripts/copycat_mode_quit.sh
Executable file
38
tmux/plugins/tmux-copycat/scripts/copycat_mode_quit.sh
Executable file
@ -0,0 +1,38 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||||
|
|
||||||
|
source "$CURRENT_DIR/helpers.sh"
|
||||||
|
|
||||||
|
unbind_cancel_bindings() {
|
||||||
|
local cancel_mode_bindings=$(copycat_quit_copy_mode_keys)
|
||||||
|
local key
|
||||||
|
for key in $cancel_mode_bindings; do
|
||||||
|
tmux unbind-key -n "$key"
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
unbind_prev_next_bindings() {
|
||||||
|
tmux unbind-key -n "$(copycat_next_key)"
|
||||||
|
tmux unbind-key -n "$(copycat_prev_key)"
|
||||||
|
}
|
||||||
|
|
||||||
|
unbind_all_bindings() {
|
||||||
|
grep -v copycat <"${TMPDIR:-/tmp}/copycat_$(whoami)_recover_keys" | while read -r key_cmd; do
|
||||||
|
sh -c "tmux $key_cmd"
|
||||||
|
done < /dev/stdin
|
||||||
|
rm "${TMPDIR:-/tmp}/copycat_$(whoami)_recover_keys"
|
||||||
|
}
|
||||||
|
|
||||||
|
main() {
|
||||||
|
if in_copycat_mode; then
|
||||||
|
reset_copycat_position
|
||||||
|
unset_copycat_mode
|
||||||
|
copycat_decrease_counter
|
||||||
|
# removing all bindings only if no panes are in copycat mode
|
||||||
|
if copycat_counter_zero; then
|
||||||
|
unbind_all_bindings
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
main
|
21
tmux/plugins/tmux-copycat/scripts/copycat_mode_start.sh
Executable file
21
tmux/plugins/tmux-copycat/scripts/copycat_mode_start.sh
Executable file
@ -0,0 +1,21 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||||
|
|
||||||
|
SUPPORTED_VERSION="1.9"
|
||||||
|
|
||||||
|
PATTERN="$1"
|
||||||
|
|
||||||
|
supported_tmux_version_ok() {
|
||||||
|
$CURRENT_DIR/check_tmux_version.sh "$SUPPORTED_VERSION"
|
||||||
|
}
|
||||||
|
|
||||||
|
main() {
|
||||||
|
local pattern="$1"
|
||||||
|
if supported_tmux_version_ok; then
|
||||||
|
$CURRENT_DIR/copycat_generate_results.sh "$pattern" # will `exit 0` if no results
|
||||||
|
$CURRENT_DIR/copycat_mode_bindings.sh
|
||||||
|
$CURRENT_DIR/copycat_jump.sh 'next'
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
main "$PATTERN"
|
8
tmux/plugins/tmux-copycat/scripts/copycat_search.sh
Executable file
8
tmux/plugins/tmux-copycat/scripts/copycat_search.sh
Executable file
@ -0,0 +1,8 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||||
|
|
||||||
|
main() {
|
||||||
|
tmux command-prompt -p "copycat search:" "run-shell \"$CURRENT_DIR/copycat_mode_start.sh '%1'\""
|
||||||
|
}
|
||||||
|
main
|
192
tmux/plugins/tmux-copycat/scripts/helpers.sh
Normal file
192
tmux/plugins/tmux-copycat/scripts/helpers.sh
Normal file
@ -0,0 +1,192 @@
|
|||||||
|
# config options
|
||||||
|
|
||||||
|
default_next_key="n"
|
||||||
|
tmux_option_next="@copycat_next"
|
||||||
|
|
||||||
|
default_prev_key="N"
|
||||||
|
tmux_option_prev="@copycat_prev"
|
||||||
|
|
||||||
|
# keeps track of number of panes in copycat mode
|
||||||
|
tmux_option_counter="@copycat_counter"
|
||||||
|
|
||||||
|
# === awk vs gawk ===
|
||||||
|
command_exists() {
|
||||||
|
command -v "$@" > /dev/null 2>&1
|
||||||
|
}
|
||||||
|
AWK_CMD='awk'
|
||||||
|
if command_exists gawk; then
|
||||||
|
AWK_CMD='gawk'
|
||||||
|
fi
|
||||||
|
|
||||||
|
# === general helpers ===
|
||||||
|
|
||||||
|
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"
|
||||||
|
}
|
||||||
|
|
||||||
|
tmux_copy_mode() {
|
||||||
|
tmux show-option -gwv mode-keys
|
||||||
|
}
|
||||||
|
|
||||||
|
tmux_copy_mode_string() {
|
||||||
|
if [ $(tmux_copy_mode) == 'vi' ]; then
|
||||||
|
echo copy-mode-vi
|
||||||
|
else
|
||||||
|
echo copy-mode
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# === copycat mode specific helpers ===
|
||||||
|
|
||||||
|
set_copycat_mode() {
|
||||||
|
set_tmux_option "$(_copycat_mode_var)" "true"
|
||||||
|
}
|
||||||
|
|
||||||
|
unset_copycat_mode() {
|
||||||
|
set_tmux_option "$(_copycat_mode_var)" "false"
|
||||||
|
}
|
||||||
|
|
||||||
|
in_copycat_mode() {
|
||||||
|
local copycat_mode=$(get_tmux_option "$(_copycat_mode_var)" "false")
|
||||||
|
[ "$copycat_mode" == "true" ]
|
||||||
|
}
|
||||||
|
|
||||||
|
not_in_copycat_mode() {
|
||||||
|
if in_copycat_mode; then
|
||||||
|
return 1
|
||||||
|
else
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# === copycat mode position ===
|
||||||
|
|
||||||
|
get_copycat_position() {
|
||||||
|
local copycat_position_variable=$(_copycat_position_var)
|
||||||
|
echo $(get_tmux_option "$copycat_position_variable" "0")
|
||||||
|
}
|
||||||
|
|
||||||
|
set_copycat_position() {
|
||||||
|
local position="$1"
|
||||||
|
local copycat_position_variable=$(_copycat_position_var)
|
||||||
|
set_tmux_option "$copycat_position_variable" "$position"
|
||||||
|
}
|
||||||
|
|
||||||
|
reset_copycat_position() {
|
||||||
|
set_copycat_position "0"
|
||||||
|
}
|
||||||
|
|
||||||
|
# === scrollback and results position ===
|
||||||
|
|
||||||
|
get_scrollback_filename() {
|
||||||
|
echo "$(_get_tmp_dir)/scrollback-$(_pane_unique_id)"
|
||||||
|
}
|
||||||
|
|
||||||
|
get_copycat_filename() {
|
||||||
|
echo "$(_get_tmp_dir)/results-$(_pane_unique_id)"
|
||||||
|
}
|
||||||
|
|
||||||
|
# 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"
|
||||||
|
}
|
||||||
|
|
||||||
|
# === counter functions ===
|
||||||
|
|
||||||
|
copycat_increase_counter() {
|
||||||
|
local count=$(get_tmux_option "$tmux_option_counter" "0")
|
||||||
|
local new_count="$((count + 1))"
|
||||||
|
set_tmux_option "$tmux_option_counter" "$new_count"
|
||||||
|
}
|
||||||
|
|
||||||
|
copycat_decrease_counter() {
|
||||||
|
local count="$(get_tmux_option "$tmux_option_counter" "0")"
|
||||||
|
if [ "$count" -gt "0" ]; then
|
||||||
|
# decreasing the counter only if it won't go below 0
|
||||||
|
local new_count="$((count - 1))"
|
||||||
|
set_tmux_option "$tmux_option_counter" "$new_count"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
copycat_counter_zero() {
|
||||||
|
local count="$(get_tmux_option "$tmux_option_counter" "0")"
|
||||||
|
[ "$count" -eq "0" ]
|
||||||
|
}
|
||||||
|
|
||||||
|
# === key binding functions ===
|
||||||
|
|
||||||
|
copycat_next_key() {
|
||||||
|
echo "$(get_tmux_option "$tmux_option_next" "$default_next_key")"
|
||||||
|
}
|
||||||
|
|
||||||
|
copycat_prev_key() {
|
||||||
|
echo "$(get_tmux_option "$tmux_option_prev" "$default_prev_key")"
|
||||||
|
}
|
||||||
|
|
||||||
|
# function expected output: 'C-c Enter q'
|
||||||
|
copycat_quit_copy_mode_keys() {
|
||||||
|
local commands_that_quit_copy_mode="cancel"
|
||||||
|
local copy_mode="$(tmux_copy_mode_string)"
|
||||||
|
tmux list-keys -T "$copy_mode" |
|
||||||
|
\grep "$commands_that_quit_copy_mode" |
|
||||||
|
$AWK_CMD '{ print $4 }' |
|
||||||
|
sort -u |
|
||||||
|
sed 's/C-j//g' |
|
||||||
|
xargs echo
|
||||||
|
}
|
||||||
|
|
||||||
|
# === 'private' functions ===
|
||||||
|
|
||||||
|
_copycat_mode_var() {
|
||||||
|
local pane_id="$(_pane_unique_id)"
|
||||||
|
echo "@copycat_mode_$pane_id"
|
||||||
|
}
|
||||||
|
|
||||||
|
_copycat_position_var() {
|
||||||
|
local pane_id="$(_pane_unique_id)"
|
||||||
|
echo "@copycat_position_$pane_id"
|
||||||
|
}
|
||||||
|
|
||||||
|
_get_tmp_dir() {
|
||||||
|
echo "${TMPDIR:-/tmp}/tmux-$EUID-copycat"
|
||||||
|
}
|
||||||
|
|
||||||
|
# returns a string unique to current pane
|
||||||
|
# sed removes `$` sign because `session_id` contains is
|
||||||
|
_pane_unique_id() {
|
||||||
|
tmux display-message -p "#{session_id}-#{window_index}-#{pane_index}" |
|
||||||
|
sed 's/\$//'
|
||||||
|
}
|
23
tmux/plugins/tmux-copycat/scripts/stored_search_helpers.sh
Normal file
23
tmux/plugins/tmux-copycat/scripts/stored_search_helpers.sh
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
stored_search_not_defined() {
|
||||||
|
local key="$1"
|
||||||
|
local search_value="$(tmux show-option -gqv "${COPYCAT_VAR_PREFIX}_${key}")"
|
||||||
|
[ -z $search_value ]
|
||||||
|
}
|
||||||
|
|
||||||
|
stored_search_vars() {
|
||||||
|
tmux show-options -g |
|
||||||
|
\grep -i "^${COPYCAT_VAR_PREFIX}_" |
|
||||||
|
cut -d ' ' -f1 | # cut just variable names
|
||||||
|
xargs # splat var names in one line
|
||||||
|
}
|
||||||
|
|
||||||
|
# get the search key from the variable name
|
||||||
|
get_stored_search_key() {
|
||||||
|
local search_var="$1"
|
||||||
|
echo "$(echo "$search_var" | sed "s/^${COPYCAT_VAR_PREFIX}_//")"
|
||||||
|
}
|
||||||
|
|
||||||
|
get_stored_search_pattern() {
|
||||||
|
local search_var="$1"
|
||||||
|
echo "$(get_tmux_option "$search_var" "")"
|
||||||
|
}
|
26
tmux/plugins/tmux-copycat/scripts/variables.sh
Normal file
26
tmux/plugins/tmux-copycat/scripts/variables.sh
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
# stored search variable prefix
|
||||||
|
COPYCAT_VAR_PREFIX="@copycat_search"
|
||||||
|
|
||||||
|
# basic search
|
||||||
|
default_copycat_search_key="/"
|
||||||
|
copycat_search_option="@copycat_search"
|
||||||
|
|
||||||
|
# git special search
|
||||||
|
default_git_search_key="C-g"
|
||||||
|
copycat_git_search_option="@copycat_git_special"
|
||||||
|
|
||||||
|
# regular searches
|
||||||
|
default_file_search_key="C-f"
|
||||||
|
copycat_file_search_option="@copycat_file_search"
|
||||||
|
|
||||||
|
default_url_search_key="C-u"
|
||||||
|
copycat_url_search_option="@copycat_url_search"
|
||||||
|
|
||||||
|
default_digit_search_key="C-d"
|
||||||
|
copycat_digit_search_option="@copycat_digit_search"
|
||||||
|
|
||||||
|
default_hash_search_key="M-h"
|
||||||
|
copycat_hash_search_option="@copycat_hash_search"
|
||||||
|
|
||||||
|
default_ip_search_key="M-i"
|
||||||
|
copycat_ip_search_option="@copycat_ip_search"
|
19
tmux/plugins/tmux-online-status/LICENSE.md
Normal file
19
tmux/plugins/tmux-online-status/LICENSE.md
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
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.
|
92
tmux/plugins/tmux-online-status/README.md
Normal file
92
tmux/plugins/tmux-online-status/README.md
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
# Tmux online status
|
||||||
|
|
||||||
|
Tmux plugin that enables displaying online status for your workstation.
|
||||||
|
|
||||||
|
Introduces a new `#{online_status}` format.
|
||||||
|
|
||||||
|
This plugin is useful if:
|
||||||
|
- you spend most of your time in Tmux and don't want to "switch" away from
|
||||||
|
the terminal to check whether you're connected.
|
||||||
|
- you have a flaky internet connection and you don't want to be surprised
|
||||||
|
when a simple `curl` or `wget` fails because the connection just broke.
|
||||||
|
|
||||||
|
Tested and working on Linux, OSX, FreeBSD, and Cygwin.
|
||||||
|
|
||||||
|
### Usage
|
||||||
|
|
||||||
|
Add `#{online_status}` format string to your existing `status-right` tmux
|
||||||
|
option.
|
||||||
|
|
||||||
|
Here's the example in `.tmux.conf`:
|
||||||
|
|
||||||
|
set -g status-right "Online: #{online_status} | %a %h-%d %H:%M "
|
||||||
|
|
||||||
|
**OS X**<br/>
|
||||||
|
On OS X the above will look like this when online<br/>
|
||||||
|
<br/>
|
||||||
|
or this when offline<br/>
|
||||||
|
<br/>
|
||||||
|
|
||||||
|
**Linux**<br/>
|
||||||
|
Online status on Linux<br/>
|
||||||
|
<br/>
|
||||||
|
offline status<br/>
|
||||||
|
<br/>
|
||||||
|
|
||||||
|
#### Configure icons
|
||||||
|
If the icons don't display well on your machine you can change them in
|
||||||
|
`.tmux.conf`:
|
||||||
|
|
||||||
|
set -g @online_icon "ok"
|
||||||
|
set -g @offline_icon "offline!"
|
||||||
|
|
||||||
|
### 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-online-status'
|
||||||
|
|
||||||
|
Hit `prefix + I` to fetch the plugin and source it.
|
||||||
|
|
||||||
|
`#{online_status}` interpolation should now work.
|
||||||
|
|
||||||
|
### Manual Installation
|
||||||
|
|
||||||
|
Clone the repo:
|
||||||
|
|
||||||
|
$ git clone https://github.com/tmux-plugins/tmux-online-status ~/clone/path
|
||||||
|
|
||||||
|
Add this line to the bottom of `.tmux.conf`:
|
||||||
|
|
||||||
|
run-shell ~/clone/path/online_status.tmux
|
||||||
|
|
||||||
|
Reload TMUX environment:
|
||||||
|
|
||||||
|
# type this in terminal
|
||||||
|
$ tmux source-file ~/.tmux.conf
|
||||||
|
|
||||||
|
`#{online_status}` interpolation should now work.
|
||||||
|
|
||||||
|
### Limitations
|
||||||
|
|
||||||
|
Online status icon most likely won't be instant. The duration depends on the
|
||||||
|
`status-interval` Tmux option. So, it might take anywhere between 5 and 60
|
||||||
|
seconds for online status icon to change.
|
||||||
|
|
||||||
|
Set `status-interval` to a low number to make this faster, example:
|
||||||
|
|
||||||
|
# in .tmux.conf
|
||||||
|
set -g status-interval 5
|
||||||
|
|
||||||
|
### Other plugins
|
||||||
|
|
||||||
|
You might also find these useful:
|
||||||
|
|
||||||
|
- [battery](https://github.com/tmux-plugins/tmux-battery) - battery status in
|
||||||
|
Tmux `status-right`
|
||||||
|
- [logging](https://github.com/tmux-plugins/tmux-logging) - easy logging and
|
||||||
|
screen capturing
|
||||||
|
|
||||||
|
### License
|
||||||
|
|
||||||
|
[MIT](LICENSE.md)
|
27
tmux/plugins/tmux-online-status/online_status.tmux
Executable file
27
tmux/plugins/tmux-online-status/online_status.tmux
Executable file
@ -0,0 +1,27 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||||
|
|
||||||
|
online_status_icon="#($CURRENT_DIR/scripts/online_status_icon.sh)"
|
||||||
|
online_status_interpolation_string="\#{online_status}"
|
||||||
|
|
||||||
|
source $CURRENT_DIR/scripts/shared.sh
|
||||||
|
|
||||||
|
do_interpolation() {
|
||||||
|
local string="$1"
|
||||||
|
local interpolated="${string/$online_status_interpolation_string/$online_status_icon}"
|
||||||
|
echo "$interpolated"
|
||||||
|
}
|
||||||
|
|
||||||
|
update_tmux_option() {
|
||||||
|
local option="$1"
|
||||||
|
local option_value="$(get_tmux_option "$option")"
|
||||||
|
local new_option_value="$(do_interpolation "$option_value")"
|
||||||
|
set_tmux_option "$option" "$new_option_value"
|
||||||
|
}
|
||||||
|
|
||||||
|
main() {
|
||||||
|
update_tmux_option "status-right"
|
||||||
|
update_tmux_option "status-left"
|
||||||
|
}
|
||||||
|
main
|
77
tmux/plugins/tmux-online-status/scripts/online_status_icon.sh
Executable file
77
tmux/plugins/tmux-online-status/scripts/online_status_icon.sh
Executable file
@ -0,0 +1,77 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||||
|
|
||||||
|
online_option_string="@online_icon"
|
||||||
|
offline_option_string="@offline_icon"
|
||||||
|
ping_timeout_string="@ping_timeout"
|
||||||
|
route_to_ping_string="@route_to_ping"
|
||||||
|
|
||||||
|
online_icon_osx="✅ "
|
||||||
|
online_icon="✔"
|
||||||
|
offline_icon_osx="⛔️ "
|
||||||
|
offline_icon_cygwin="X"
|
||||||
|
offline_icon="❌ "
|
||||||
|
ping_timeout_default="3"
|
||||||
|
route_to_ping_default="www.google.com"
|
||||||
|
|
||||||
|
source $CURRENT_DIR/shared.sh
|
||||||
|
|
||||||
|
is_osx() {
|
||||||
|
[ $(uname) == "Darwin" ]
|
||||||
|
}
|
||||||
|
|
||||||
|
is_cygwin() {
|
||||||
|
[[ $(uname) =~ CYGWIN ]]
|
||||||
|
}
|
||||||
|
|
||||||
|
is_freebsd() {
|
||||||
|
[ $(uname) == FreeBSD ]
|
||||||
|
}
|
||||||
|
|
||||||
|
online_icon_default() {
|
||||||
|
if is_osx; then
|
||||||
|
echo "$online_icon_osx"
|
||||||
|
else
|
||||||
|
echo "$online_icon"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
offline_icon_default() {
|
||||||
|
if is_osx; then
|
||||||
|
echo "$offline_icon_osx"
|
||||||
|
elif is_cygwin; then
|
||||||
|
echo "$offline_icon_cygwin"
|
||||||
|
else
|
||||||
|
echo "$offline_icon"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
online_status() {
|
||||||
|
if is_osx || is_freebsd; then
|
||||||
|
local timeout_flag="-t"
|
||||||
|
else
|
||||||
|
local timeout_flag="-w"
|
||||||
|
fi
|
||||||
|
if is_cygwin; then
|
||||||
|
local number_pings_flag="-n"
|
||||||
|
else
|
||||||
|
local number_pings_flag="-c"
|
||||||
|
fi
|
||||||
|
local ping_timeout="$(get_tmux_option "$ping_timeout_string" "$ping_timeout_default")"
|
||||||
|
local ping_route="$(get_tmux_option "$route_to_ping_string" "$route_to_ping_default")"
|
||||||
|
ping "$number_pings_flag" 1 "$timeout_flag" "$ping_timeout" "$ping_route" >/dev/null 2>&1
|
||||||
|
}
|
||||||
|
|
||||||
|
print_icon() {
|
||||||
|
if $(online_status); then
|
||||||
|
printf "$(get_tmux_option "$online_option_string" "$(online_icon_default)")"
|
||||||
|
else
|
||||||
|
printf "$(get_tmux_option "$offline_option_string" "$(offline_icon_default)")"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
main() {
|
||||||
|
print_icon
|
||||||
|
}
|
||||||
|
main
|
16
tmux/plugins/tmux-online-status/scripts/shared.sh
Normal file
16
tmux/plugins/tmux-online-status/scripts/shared.sh
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
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"
|
||||||
|
}
|
19
tmux/plugins/tmux-open/LICENSE.md
Normal file
19
tmux/plugins/tmux-open/LICENSE.md
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
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.
|
95
tmux/plugins/tmux-open/README.md
Normal file
95
tmux/plugins/tmux-open/README.md
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
# Tmux open
|
||||||
|
|
||||||
|
Plugin for opening highlighted selection directly from Tmux copy mode.
|
||||||
|
|
||||||
|
Tested and working on Linux, OSX and Cygwin.
|
||||||
|
|
||||||
|
### Key bindings
|
||||||
|
|
||||||
|
In tmux copy mode:
|
||||||
|
|
||||||
|
- `o` - "open" a highlighted selection with the system default program. `open`
|
||||||
|
for OS X or `xdg-open` for Linux.
|
||||||
|
- `Ctrl-o` - open a highlighted selection with the `$EDITOR`
|
||||||
|
- `Shift-s` - search the highlighted selection directly inside a search engine (defaults to google).
|
||||||
|
|
||||||
|
### Examples
|
||||||
|
|
||||||
|
In copy mode:
|
||||||
|
|
||||||
|
- highlight `file.pdf` and press `o` - file will open in the default PDF viewer.
|
||||||
|
- highlight `file.doc` and press `o` - file will open in system default `.doc`
|
||||||
|
file viewer.
|
||||||
|
- highlight `http://example.com` and press `o` - link will be opened in the
|
||||||
|
default browser.
|
||||||
|
- highlight `file.txt` and press `Ctrl-o` - file will open in `$EDITOR`.
|
||||||
|
- highlight `TypeError: 'undefined' is not a function` and press `Shift-s` - the text snipped will be searched directly inside google by default
|
||||||
|
|
||||||
|
### Screencast
|
||||||
|
|
||||||
|
[](http://vimeo.com/102455265)
|
||||||
|
|
||||||
|
### 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-open'
|
||||||
|
|
||||||
|
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-open ~/clone/path
|
||||||
|
|
||||||
|
Add this line to the bottom of `.tmux.conf`:
|
||||||
|
|
||||||
|
run-shell ~/clone/path/open.tmux
|
||||||
|
|
||||||
|
Reload TMUX environment:
|
||||||
|
|
||||||
|
# type this in terminal
|
||||||
|
$ tmux source-file ~/.tmux.conf
|
||||||
|
|
||||||
|
You should now be able to use the plugin.
|
||||||
|
|
||||||
|
### Configuration
|
||||||
|
|
||||||
|
> How can I change the default "o" key binding to something else? For example,
|
||||||
|
> key "x"?
|
||||||
|
|
||||||
|
Put `set -g @open 'x'` in `tmux.conf`.
|
||||||
|
|
||||||
|
> How can I change the default "Ctrl-o" key binding to "Ctrl-x"?
|
||||||
|
|
||||||
|
Put `set -g @open-editor 'C-x'` in `tmux.conf`.
|
||||||
|
|
||||||
|
> How can I change the default search engine to "duckduckgo" or any other one?
|
||||||
|
|
||||||
|
Put `set -g @open-S 'https://www.duckduckgo.com/'` in `tmux.conf`
|
||||||
|
|
||||||
|
> How can I use multiple search engines?
|
||||||
|
|
||||||
|
Put:
|
||||||
|
|
||||||
|
```
|
||||||
|
set -g @open-B 'https://www.bing.com/search?q='
|
||||||
|
set -g @open-S 'https://www.google.com/search?q='
|
||||||
|
```
|
||||||
|
|
||||||
|
in `tmux.conf`
|
||||||
|
|
||||||
|
### Other goodies
|
||||||
|
|
||||||
|
`tmux-open` works great with:
|
||||||
|
|
||||||
|
- [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
|
||||||
|
|
||||||
|
### License
|
||||||
|
|
||||||
|
[MIT](LICENSE.md)
|
142
tmux/plugins/tmux-open/open.tmux
Executable file
142
tmux/plugins/tmux-open/open.tmux
Executable file
@ -0,0 +1,142 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||||
|
|
||||||
|
source "$CURRENT_DIR/scripts/helpers.sh"
|
||||||
|
|
||||||
|
default_open_key="o"
|
||||||
|
open_option="@open"
|
||||||
|
|
||||||
|
default_open_editor_key="C-o"
|
||||||
|
open_editor_option="@open-editor"
|
||||||
|
open_editor_override="@open-editor-command"
|
||||||
|
|
||||||
|
command_exists() {
|
||||||
|
local command="$1"
|
||||||
|
type "$command" >/dev/null 2>&1
|
||||||
|
}
|
||||||
|
|
||||||
|
is_osx() {
|
||||||
|
local platform=$(uname)
|
||||||
|
[ "$platform" == "Darwin" ]
|
||||||
|
}
|
||||||
|
|
||||||
|
is_cygwin() {
|
||||||
|
[[ "$(uname)" =~ CYGWIN ]]
|
||||||
|
}
|
||||||
|
|
||||||
|
get_editor_from_the_env_var() {
|
||||||
|
if [ -z $EDITOR ]; then
|
||||||
|
# $EDITOR not set, fallback
|
||||||
|
echo "vi"
|
||||||
|
else
|
||||||
|
echo "$EDITOR"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
command_generator() {
|
||||||
|
local command_string="$1"
|
||||||
|
echo "xargs -I {} tmux run-shell -b 'cd #{pane_current_path}; $command_string \"{}\" > /dev/null'"
|
||||||
|
}
|
||||||
|
|
||||||
|
search_command_generator() {
|
||||||
|
local command_string="$1"
|
||||||
|
local engine="$2"
|
||||||
|
|
||||||
|
echo "xargs -I {} tmux run-shell -b 'cd #{pane_current_path}; $command_string $engine\"{}\" > /dev/null'"
|
||||||
|
}
|
||||||
|
|
||||||
|
generate_open_command() {
|
||||||
|
if is_osx; then
|
||||||
|
echo "$(command_generator "open")"
|
||||||
|
elif is_cygwin; then
|
||||||
|
echo "$(command_generator "cygstart")"
|
||||||
|
elif command_exists "xdg-open"; then
|
||||||
|
echo "$(command_generator "xdg-open")"
|
||||||
|
else
|
||||||
|
# error command for Linux machines when 'xdg-open' not installed
|
||||||
|
"$CURRENT_DIR/scripts/tmux_open_error_message.sh" "xdg-open"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
generate_open_search_command() {
|
||||||
|
local engine="$1"
|
||||||
|
if is_osx; then
|
||||||
|
echo "$(search_command_generator "open" "$engine")"
|
||||||
|
elif is_cygwin; then
|
||||||
|
echo "$(command_generator "cygstart")"
|
||||||
|
elif command_exists "xdg-open"; then
|
||||||
|
echo "$(search_command_generator "xdg-open" "$engine")"
|
||||||
|
else
|
||||||
|
# error command for Linux machines when 'xdg-open' not installed
|
||||||
|
"$CURRENT_DIR/scripts/tmux_open_error_message.sh" "xdg-open"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# 1. write a command to the terminal, example: 'vim -- some_file.txt'
|
||||||
|
# 2. invoke the command by pressing enter/C-m
|
||||||
|
generate_editor_command() {
|
||||||
|
local environment_editor=$(get_editor_from_the_env_var)
|
||||||
|
local editor=$(get_tmux_option "$open_editor_override" "$environment_editor")
|
||||||
|
# vim freezes terminal unless there's the '--' argument. Other editors seem
|
||||||
|
# to be fine with it (textmate [mate], light table [table]).
|
||||||
|
echo "xargs -I {} tmux send-keys '$editor -- \"{}\"'; tmux send-keys 'C-m'"
|
||||||
|
}
|
||||||
|
|
||||||
|
set_copy_mode_open_bindings() {
|
||||||
|
local open_command="$(generate_open_command)"
|
||||||
|
local key_bindings=$(get_tmux_option "$open_option" "$default_open_key")
|
||||||
|
local key
|
||||||
|
for key in $key_bindings; do
|
||||||
|
if tmux-is-at-least 2.4; then
|
||||||
|
tmux bind-key -T copy-mode-vi "$key" send-keys -X copy-pipe-and-cancel "$open_command"
|
||||||
|
tmux bind-key -T copy-mode "$key" send-keys -X copy-pipe-and-cancel "$open_command"
|
||||||
|
else
|
||||||
|
tmux bind-key -t vi-copy "$key" copy-pipe "$open_command"
|
||||||
|
tmux bind-key -t emacs-copy "$key" copy-pipe "$open_command"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
set_copy_mode_open_editor_bindings() {
|
||||||
|
local editor_command="$(generate_editor_command)"
|
||||||
|
local key_bindings=$(get_tmux_option "$open_editor_option" "$default_open_editor_key")
|
||||||
|
local key
|
||||||
|
for key in $key_bindings; do
|
||||||
|
if tmux-is-at-least 2.4; then
|
||||||
|
tmux bind-key -T copy-mode-vi "$key" send-keys -X copy-pipe-and-cancel "$editor_command"
|
||||||
|
tmux bind-key -T copy-mode "$key" send-keys -X copy-pipe-and-cancel "$editor_command"
|
||||||
|
else
|
||||||
|
tmux bind-key -t vi-copy "$key" copy-pipe "$editor_command"
|
||||||
|
tmux bind-key -t emacs-copy "$key" copy-pipe "$editor_command"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
set_copy_mode_open_search_bindings() {
|
||||||
|
local stored_engine_vars="$(stored_engine_vars)"
|
||||||
|
local engine_var
|
||||||
|
local engine
|
||||||
|
local key
|
||||||
|
|
||||||
|
for engine_var in $stored_engine_vars; do
|
||||||
|
engine="$(get_engine "$engine_var")"
|
||||||
|
|
||||||
|
if tmux-is-at-least 2.4; then
|
||||||
|
tmux bind-key -T copy-mode-vi "$engine_var" send-keys -X copy-pipe-and-cancel "$(generate_open_search_command "$engine")"
|
||||||
|
tmux bind-key -T copy-mode "$engine_var" send-keys -X copy-pipe-and-cancel "$(generate_open_search_command "$engine")"
|
||||||
|
else
|
||||||
|
tmux bind-key -t vi-copy "$engine_var" copy-pipe "$(generate_open_search_command "$engine")"
|
||||||
|
tmux bind-key -t emacs-copy "$engine_var" copy-pipe "$(generate_open_search_command "$engine")"
|
||||||
|
fi
|
||||||
|
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
main() {
|
||||||
|
set_copy_mode_open_bindings
|
||||||
|
set_copy_mode_open_editor_bindings
|
||||||
|
set_copy_mode_open_search_bindings
|
||||||
|
}
|
||||||
|
|
||||||
|
main
|
21
tmux/plugins/tmux-plugin-sysstat/LICENSE
Normal file
21
tmux/plugins/tmux-plugin-sysstat/LICENSE
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
The MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2017 Alexey Samoshkin
|
||||||
|
|
||||||
|
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.
|
372
tmux/plugins/tmux-plugin-sysstat/readme.md
Normal file
372
tmux/plugins/tmux-plugin-sysstat/readme.md
Normal file
@ -0,0 +1,372 @@
|
|||||||
|
|
||||||
|
Tmux sysstat plugin
|
||||||
|
===================
|
||||||
|
Allow to print CPU usage, memory & swap, load average, net I/O metrics in Tmux status bar
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
You might checkout [tmux-config](https://github.com/samoshkin/tmux-config) repo to see this plugin in action.
|
||||||
|
|
||||||
|
Features
|
||||||
|
--------
|
||||||
|
- CPU usage
|
||||||
|
- Memory available/free, used, total (KiB,MiB,GiB), free/used %
|
||||||
|
- Swap used, free, total, free/used %
|
||||||
|
- load average for last 1,5,15 minutes
|
||||||
|
- configurable thresholds (low, medium, stress) with custom colors
|
||||||
|
- tweak each metric output using templates (e.g, 'used 10% out of 16G')
|
||||||
|
- configurable size scale (K,M,G)
|
||||||
|
- OSX, Linux support
|
||||||
|
- [ ] **TODO:** network I/O metric support
|
||||||
|
|
||||||
|
Tested on: OS X El Capitan 10.11.5, Ubuntu 14 LTS, CentOS 7, FreeBSD 11.1.
|
||||||
|
|
||||||
|
|
||||||
|
Installation
|
||||||
|
------------
|
||||||
|
Best installed through [Tmux Plugin Manager](https://github.com/tmux-plugins/tpm) (TMP). Add following line to your `.tmux.conf` file:
|
||||||
|
|
||||||
|
```
|
||||||
|
set -g @plugin 'samoshkin/tmux-plugin-sysstat'
|
||||||
|
```
|
||||||
|
|
||||||
|
Use `prefix + I` from inside tmux to install all plugins and source them. If you prefer, same effect can be achieved from [command line](https://github.com/tmux-plugins/tpm/blob/master/docs/managing_plugins_via_cmd_line.md):
|
||||||
|
|
||||||
|
```
|
||||||
|
$ ~.tmux/plugins/tpm/bin/install_plugins
|
||||||
|
```
|
||||||
|
|
||||||
|
Basic usage
|
||||||
|
-----------
|
||||||
|
|
||||||
|
Once plugged in, tmux `status-left` or `status-right` options can be configured with following placeholders. Each placeholder will be expanded to metric's default output.
|
||||||
|
|
||||||
|
- `#{sysstat_cpu}`, CPU usage - `CPU:40.2%`
|
||||||
|
- `#{sysstat_mem}`, memory usage - `MEM:73%`
|
||||||
|
- `#{sysstat_swap}`, swap usage - `SW:66%`
|
||||||
|
- `#{sysstat_loadavg}`, system load average - `0.25 0.04 0.34`
|
||||||
|
|
||||||
|
For example:
|
||||||
|
```
|
||||||
|
set -g status-right "#{sysstat_cpu} | #{sysstat_mem} | #{sysstat_swap} | #{sysstat_loadavg} | #[fg=cyan]#(echo $USER)#[default]@#H"
|
||||||
|
```
|
||||||
|
|
||||||
|
Changing default output
|
||||||
|
------------------------
|
||||||
|
|
||||||
|
You can change default output for CPU and memory metrics, if you need more fields to show, or you want to provide custom template. In your `.tmux.conf`:
|
||||||
|
|
||||||
|
For example, to get `Used 4.5G out of 16G` output for memory metric:
|
||||||
|
|
||||||
|
```
|
||||||
|
set -g @sysstat_mem_view_tmpl '#Used [fg=#{mem.color}]#{mem.used}#[default] out of #{mem.total}'
|
||||||
|
```
|
||||||
|
|
||||||
|
If you don't want `CPU:` prefix and don't like colored output for CPU metric:
|
||||||
|
|
||||||
|
```
|
||||||
|
set -g @sysstat_cpu_view_tmpl '#{cpu.pused}'
|
||||||
|
```
|
||||||
|
|
||||||
|
### Supported fields
|
||||||
|
|
||||||
|
As you can see, each metric can be configured with template, containing fixed text (`CPU:`), color placeholder (`#[fg=#{mem.color}]`) and field placeholder (`#{mem.used}`). This approach gives you the ultimate control over the output for each metric. Following field placeholders are supported:
|
||||||
|
|
||||||
|
<table>
|
||||||
|
<th>CPU</th>
|
||||||
|
<tr>
|
||||||
|
<td><code>#{cpu.color}</code></td>
|
||||||
|
<td>main metric color</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><code>#{cpu.pused}</code></td>
|
||||||
|
<td>CPU usage percentage</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<table>
|
||||||
|
<th>Memory</th>
|
||||||
|
<tr>
|
||||||
|
<td><code>#{mem.color}</code></td>
|
||||||
|
<td>main metric color</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><code>#{mem.free}</code></td>
|
||||||
|
<td>free/available memory</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><code>#{mem.pfree}</code></td>
|
||||||
|
<td>free memory percentage against total</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><code>#{mem.used}</code></td>
|
||||||
|
<td>used memory</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><code>#{mem.pused}</code></td>
|
||||||
|
<td>used memory percentage against total</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><code>#{mem.total}</code></td>
|
||||||
|
<td>total installed memory</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<table>
|
||||||
|
<th>Swap</th>
|
||||||
|
<tr>
|
||||||
|
<td><code>#{swap.color}</code></td>
|
||||||
|
<td>main swap metric color</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><code>#{swap.free}</code></td>
|
||||||
|
<td>free swap memory</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><code>#{swap.pfree}</code></td>
|
||||||
|
<td>free swap memory percentage against total swap space</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><code>#{swap.used}</code></td>
|
||||||
|
<td>used swap memory</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><code>#{swap.pused}</code></td>
|
||||||
|
<td>used swap memory percentage against total swap space</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><code>#{swap.total}</code></td>
|
||||||
|
<td>total swap space</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
### Change size scale
|
||||||
|
|
||||||
|
free/used/total memory can be shown both in absolute and relative units. When it comes to absolute units, you can choose *size scale factor* to choose between GiB, MiB, KiB. Default is GiB. If you have less than 3-4G memory installed, it makes sense to use MiB. KiB option is less practical, because it yields pretty lengthy output, which does not fit status bar limited estate.
|
||||||
|
|
||||||
|
```
|
||||||
|
set -g @sysstat_mem_size_unit "G"
|
||||||
|
```
|
||||||
|
|
||||||
|
If you choose `G` for size scale, output will have `%.1f` (1 digit after floating point), otherwise size is integer (4.5G, 1024M, 1232345K).
|
||||||
|
|
||||||
|
Thresholds and colored output
|
||||||
|
---------------
|
||||||
|
Each metric output is colored by default. Colors vary depending on metric value.
|
||||||
|
|
||||||
|
<table>
|
||||||
|
<tr>
|
||||||
|
<td><b>Threshold</b></td>
|
||||||
|
<td><b>CPU</b></td>
|
||||||
|
<td><b>Memory</b></td>
|
||||||
|
<td><b>Swap</b></td>
|
||||||
|
<td><b>Default color</b></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>low</td>
|
||||||
|
<td>x < 30%</td>
|
||||||
|
<td>x < 75%</td>
|
||||||
|
<td>x < 25%</td>
|
||||||
|
<td>green</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>medium</td>
|
||||||
|
<td>30% < x < 80%</td>
|
||||||
|
<td>75% < x < 90%</td>
|
||||||
|
<td>25% < x < 75%</td>
|
||||||
|
<td>yellow</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>high</td>
|
||||||
|
<td>x > 80%</td>
|
||||||
|
<td>x > 90%</td>
|
||||||
|
<td>x > 75%</td>
|
||||||
|
<td>red</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
You can change thresholds in your `.tmux.conf`:
|
||||||
|
|
||||||
|
```
|
||||||
|
set -g @sysstat_cpu_medium_threshold "75"
|
||||||
|
set -g @sysstat_cpu_stress_threshold "95"
|
||||||
|
|
||||||
|
set -g @sysstat_mem_medium_threshold "85"
|
||||||
|
set -g @sysstat_mem_stress_threshold "95"
|
||||||
|
|
||||||
|
set -g @sysstat_swap_medium_threshold "80"
|
||||||
|
set -g @sysstat_swap_stress_threshold "90"
|
||||||
|
```
|
||||||
|
|
||||||
|
You can change colors for each threshold individually. You can use ANSI basic colors (red, cyan, green) or if your terminal supports 256 colors (and most do nowadays), use `colourXXX` format.
|
||||||
|
|
||||||
|
```
|
||||||
|
set -g @sysstat_cpu_color_low "colour076"
|
||||||
|
set -g @sysstat_cpu_color_medium "colour220"
|
||||||
|
set -g @sysstat_cpu_color_stress "colour160"
|
||||||
|
set -g @sysstat_mem_color_low "green"
|
||||||
|
set -g @sysstat_mem_color_medium "blue"
|
||||||
|
set -g @sysstat_mem_color_stress "cyan"
|
||||||
|
```
|
||||||
|
|
||||||
|
`#{(mem|cpu|swap).color}` placeholder in your `@sysstat_(mem|cpu|swap)_view_tmpl` would be replaced by corresponding color, depending on whether metric value falls in particular threshold.
|
||||||
|
|
||||||
|
### 256 color palette support
|
||||||
|
|
||||||
|
For 256 color palette support, make sure that `tmux` and parent terminal are configured with correct terminal type. See [here](https://unix.stackexchange.com/questions/1045/getting-256-colors-to-work-in-tmux) and [there](https://github.com/tmux/tmux/wiki/FAQ)
|
||||||
|
|
||||||
|
```
|
||||||
|
# ~/.tmux.conf
|
||||||
|
set -g default-terminal "screen-256color"
|
||||||
|
```
|
||||||
|
|
||||||
|
```
|
||||||
|
# parent terminal
|
||||||
|
$ echo $TERM
|
||||||
|
xterm-256color
|
||||||
|
|
||||||
|
# jump into a tmux session
|
||||||
|
$ tmux new
|
||||||
|
$ echo $TERM
|
||||||
|
screen-256color
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### Multiple colors for each threshold
|
||||||
|
|
||||||
|
You can have up to *3* colors configured for each threshold. To understand why you might need this, let tackle this task. Note, this is rather advanced use case.
|
||||||
|
|
||||||
|
> I want `CPU: #{cpu.pused}` metric output, have green and yellow text colors at "low" and "medium" threshold, and finally, for "high" threshold, I want to use red color, but reverse foreground and background, that is use red for background, and white for text. More over I want "CPU:" text colored apart in red
|
||||||
|
|
||||||
|
Like this:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
You can achieve the result using following configuration:
|
||||||
|
|
||||||
|
```
|
||||||
|
set -g @sysstat_cpu_view_tmpl '#[fg=#{cpu.color3}]CPU:#[default] #[fg=#{cpu.color},bg=#{cpu.color2}]#{cpu.pused}#[default]'
|
||||||
|
|
||||||
|
set -g @sysstat_cpu_color_low "$color_level_ok default default"
|
||||||
|
set -g @sysstat_cpu_color_medium "$color_level_warn default default"
|
||||||
|
set -g @sysstat_cpu_color_stress "white,bold $color_level_stress $color_level_stress"
|
||||||
|
```
|
||||||
|
|
||||||
|
Tmux status-interval setting
|
||||||
|
-----------------------------
|
||||||
|
You can configure status refresh interval, increasing or reducing frequency of `tmux-plugin-sysstat` command invocations.
|
||||||
|
|
||||||
|
```
|
||||||
|
set -g status-interval 5
|
||||||
|
```
|
||||||
|
|
||||||
|
It's adviced to set `status-interval` to some reasonable value, like 5-10 seconds. More frequent updates (1 second) are useless, because they distract, and results in extra resource stress spent on metrics calculation itself.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Internals: CPU calculation
|
||||||
|
--------------------------------------------------
|
||||||
|
<span style="color: blue">**NOTE:** Stop here if you want to just use this plugin without making your feet wet. If you're hardcore tmux user and are curious about internals, keep reading</span>
|
||||||
|
|
||||||
|
Internally, we use `iostat` and `top` on OSX, and `vmstat` and `top` on Linux to collect metric value. Neither requires you to install extra packages. These commands are run in sampling mode to report stats every N seconds M times. First sample include average values since the system start. Second one is the average CPU per second for last N seconds (exactly what we need)
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ iostat -c 2 -w 5
|
||||||
|
disk0 cpu load average
|
||||||
|
KB/t tps MB/s us sy id 1m 5m 15m
|
||||||
|
44.22 6 0.26 3 2 95 1.74 1.90 2.15
|
||||||
|
5.47 8 0.04 4 5 91 1.84 1.92 2.16 << use this row, 2nd sample
|
||||||
|
```
|
||||||
|
|
||||||
|
We align CPU calculation intervals (`-w`) with tmux status bar refresh interval (`status-interval` setting).
|
||||||
|
|
||||||
|
Internals: memory calculation
|
||||||
|
----------------------------
|
||||||
|
You might ask what we treat as `free` memory and how it's calculated.
|
||||||
|
|
||||||
|
### OSX
|
||||||
|
Let's start with OSX. We use `vm_stat` command (not same as `vmstat` on Linux), which reports following data (number of memory pages, not KB):
|
||||||
|
|
||||||
|
```
|
||||||
|
$ vm_stat
|
||||||
|
Pages free: 37279
|
||||||
|
Pages active: 1514200
|
||||||
|
Pages inactive: 1152997
|
||||||
|
Pages speculative: 6214
|
||||||
|
Pages throttled: 0
|
||||||
|
Pages wired down: 1174408
|
||||||
|
Pages purgeable: 15405
|
||||||
|
Pages stored in compressor: 1615663
|
||||||
|
Pages occupied by compressor: 306717
|
||||||
|
```
|
||||||
|
|
||||||
|
Total installed memory formula is:
|
||||||
|
```
|
||||||
|
Total = free + active + inactive + speculative + occupied by compressor + wired
|
||||||
|
```
|
||||||
|
|
||||||
|
where
|
||||||
|
- `free`, completely unused memory by the system
|
||||||
|
- `wired`, critical information stored in RAM by system, kernel and key applications. Never swapped to the hard drive, never replaced with user-level data.
|
||||||
|
- `active`, information currently in use or very recently used by applications. When this kind of memory is not used for long (or application is closed), it's move to inactive memory.
|
||||||
|
- `inactive`, like buffers/cached memory in Linux. Memory for applications, which recently exited, retained for faster start-up of same application in future.
|
||||||
|
|
||||||
|
So the question what constitutes `free` and `used` memory. It turns out, that various monitoring and system statistics tools on OSX each calculate it differently.
|
||||||
|
|
||||||
|
- htop: `used = active + wired`, `free` = `total - used`
|
||||||
|
- top. Used = `used = active + inactive + occupied by compressor + wired`; Free = `free + speculative` Resident set size (RSS) = `active`
|
||||||
|
- OSX activity Monitor. Used = `app memory + wired + compressor`. Note, it's not clear what is app memory.
|
||||||
|
|
||||||
|
In general, they either treat currently used memory, which can be reclaimed in case of need (cached, inactive, occupied by compressor), as `used` or `free`.
|
||||||
|
|
||||||
|
It makes sense to talk about `available` memory rather than `free` one. Available memory is unused memory + any used memory which can be reclaimed for application needs.
|
||||||
|
|
||||||
|
So, `tmux-plugin-sysstat`, uses following formula:
|
||||||
|
|
||||||
|
```
|
||||||
|
used = active + wired
|
||||||
|
available/free = free/unused + inactive + speculative + occupied by compressor
|
||||||
|
```
|
||||||
|
|
||||||
|
### Linux
|
||||||
|
|
||||||
|
Same thinking can be applied to Linux systems.
|
||||||
|
|
||||||
|
Usually commands like `free` report free/unused, used, buffers, cache memory kinds.
|
||||||
|
|
||||||
|
```
|
||||||
|
$ free
|
||||||
|
total used free shared buffers cached
|
||||||
|
Mem: 1016464 900236 116228 21048 93448 241544
|
||||||
|
-/+ buffers/cache: 565244 451220
|
||||||
|
Swap: 1046524 141712 904812
|
||||||
|
```
|
||||||
|
|
||||||
|
Second line indicates available memory (free + buffers + cache), with an assumption that buffers and cache can be 100% reclaimed in case of need.
|
||||||
|
|
||||||
|
However, we're not using free, because its output varies per system. For example on RHEL7, there is no `-/+ buffers/cache`, and `available` memory is reported in different way. We read directly from `/proc/meminfo`
|
||||||
|
|
||||||
|
```
|
||||||
|
$ cat /proc/meminfo
|
||||||
|
|
||||||
|
MemTotal: 1016232 kB
|
||||||
|
MemFree: 152672 kB
|
||||||
|
MemAvailable: 637832 kB
|
||||||
|
Buffers: 0 kB
|
||||||
|
Cached: 529040 kB
|
||||||
|
```
|
||||||
|
|
||||||
|
`tmux-plugin-sysstat` uses following formula:
|
||||||
|
|
||||||
|
```
|
||||||
|
free/available = MemAvailable; // if MemAvailable present
|
||||||
|
free/available = MemFree + Buffers + Cached;
|
||||||
|
used = MemTotal - free/avaialble
|
||||||
|
```
|
||||||
|
|
||||||
|
Using `MemAvailable` is more accurate way of getting available memory, rather than manual calculation `free + buffers + cache`, because the assumption that `buffers + cache` can be 100% reclaimed for new application needs might be wrong. When using `MemAvailable`, OS calculates available memory for you, which is apparently better and accurate approach.
|
||||||
|
|
||||||
|
See [this topic](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=34e431b0ae398fc54ea69ff85ec700722c9da773) on more reasoning about `MemAvailable` field.
|
78
tmux/plugins/tmux-plugin-sysstat/scripts/cpu.sh
Executable file
78
tmux/plugins/tmux-plugin-sysstat/scripts/cpu.sh
Executable file
@ -0,0 +1,78 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -u
|
||||||
|
set -e
|
||||||
|
|
||||||
|
LC_NUMERIC=C
|
||||||
|
|
||||||
|
CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||||
|
source "$CURRENT_DIR/helpers.sh"
|
||||||
|
|
||||||
|
cpu_tmp_dir=$(tmux show-option -gqv "@sysstat_cpu_tmp_dir")
|
||||||
|
|
||||||
|
cpu_view_tmpl=$(get_tmux_option "@sysstat_cpu_view_tmpl" 'CPU:#[fg=#{cpu.color}]#{cpu.pused}#[default]')
|
||||||
|
|
||||||
|
cpu_medium_threshold=$(get_tmux_option "@sysstat_cpu_medium_threshold" "30")
|
||||||
|
cpu_stress_threshold=$(get_tmux_option "@sysstat_cpu_stress_threshold" "80")
|
||||||
|
|
||||||
|
cpu_color_low=$(get_tmux_option "@sysstat_cpu_color_low" "green")
|
||||||
|
cpu_color_medium=$(get_tmux_option "@sysstat_cpu_color_medium" "yellow")
|
||||||
|
cpu_color_stress=$(get_tmux_option "@sysstat_cpu_color_stress" "red")
|
||||||
|
|
||||||
|
get_cpu_color(){
|
||||||
|
local cpu_used=$1
|
||||||
|
|
||||||
|
if fcomp "$cpu_stress_threshold" "$cpu_used"; then
|
||||||
|
echo "$cpu_color_stress";
|
||||||
|
elif fcomp "$cpu_medium_threshold" "$cpu_used"; then
|
||||||
|
echo "$cpu_color_medium";
|
||||||
|
else
|
||||||
|
echo "$cpu_color_low";
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
print_cpu_usage() {
|
||||||
|
local cpu_pused=$(get_cpu_usage_or_collect)
|
||||||
|
local cpu_color=$(get_cpu_color "$cpu_pused")
|
||||||
|
|
||||||
|
local cpu_view="$cpu_view_tmpl"
|
||||||
|
cpu_view="${cpu_view//'#{cpu.pused}'/$(printf "%.1f%%" "$cpu_pused")}"
|
||||||
|
cpu_view="${cpu_view//'#{cpu.color}'/$(echo "$cpu_color" | awk '{ print $1 }')}"
|
||||||
|
cpu_view="${cpu_view//'#{cpu.color2}'/$(echo "$cpu_color" | awk '{ print $2 }')}"
|
||||||
|
cpu_view="${cpu_view//'#{cpu.color3}'/$(echo "$cpu_color" | awk '{ print $3 }')}"
|
||||||
|
|
||||||
|
echo "$cpu_view"
|
||||||
|
}
|
||||||
|
|
||||||
|
get_cpu_usage_or_collect() {
|
||||||
|
local collect_cpu_metric="$cpu_tmp_dir/cpu_collect.metric"
|
||||||
|
|
||||||
|
# read cpu metric from file, otherwise 0 as a temporary null value, until first cpu metric is collected
|
||||||
|
[ -f "$collect_cpu_metric" ] && cat "$collect_cpu_metric" || echo "0.0"
|
||||||
|
|
||||||
|
start_cpu_collect_if_required >/dev/null 2>&1
|
||||||
|
}
|
||||||
|
|
||||||
|
start_cpu_collect_if_required() {
|
||||||
|
local collect_cpu_pidfile="$cpu_tmp_dir/cpu_collect.pid"
|
||||||
|
|
||||||
|
# check if cpu collect process is running, otherwise start it in background
|
||||||
|
if [ -f "$collect_cpu_pidfile" ] && ps -p "$(cat "$collect_cpu_pidfile")" > /dev/null 2>&1; then
|
||||||
|
return;
|
||||||
|
fi
|
||||||
|
|
||||||
|
jobs >/dev/null 2>&1
|
||||||
|
"$CURRENT_DIR/cpu_collect.sh" &>/dev/null &
|
||||||
|
if [ -n "$(jobs -n)" ]; then
|
||||||
|
echo "$!" > "${collect_cpu_pidfile}"
|
||||||
|
else
|
||||||
|
echo "Failed to start CPU collect job" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
main(){
|
||||||
|
print_cpu_usage
|
||||||
|
}
|
||||||
|
|
||||||
|
main
|
53
tmux/plugins/tmux-plugin-sysstat/scripts/cpu_collect.sh
Executable file
53
tmux/plugins/tmux-plugin-sysstat/scripts/cpu_collect.sh
Executable file
@ -0,0 +1,53 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
LC_NUMERIC=C
|
||||||
|
|
||||||
|
set -u
|
||||||
|
set -e
|
||||||
|
|
||||||
|
CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||||
|
source "$CURRENT_DIR/helpers.sh"
|
||||||
|
|
||||||
|
refresh_interval=$(get_tmux_option "status-interval" "5")
|
||||||
|
samples_count="60"
|
||||||
|
cpu_metric_file="$(get_tmux_option "@sysstat_cpu_tmp_dir" "/dev/null")/cpu_collect.metric"
|
||||||
|
|
||||||
|
get_cpu_usage() {
|
||||||
|
if is_osx; then
|
||||||
|
if command_exists "iostat"; then
|
||||||
|
iostat -w "$refresh_interval" -c "$samples_count" \
|
||||||
|
| stdbuf -o0 awk 'NR > 2 { print 100-$(NF-3); }'
|
||||||
|
else
|
||||||
|
top -l "$samples_count" -s "$refresh_interval" -n 0 \
|
||||||
|
| sed -u -nr '/CPU usage/s/.*,[[:space:]]*([0-9]+[.,][0-9]*)%[[:space:]]*idle.*/\1/p' \
|
||||||
|
| stdbuf -o0 awk '{ print 100-$0 }'
|
||||||
|
fi
|
||||||
|
elif ! command_exists "vmstat"; then
|
||||||
|
if is_freebsd; then
|
||||||
|
vmstat -n "$refresh_interval" -c "$samples_count" \
|
||||||
|
| stdbuf -o0 awk 'NR>2 {print 100-$(NF-0)}'
|
||||||
|
else
|
||||||
|
vmstat -n "$refresh_interval" "$samples_count" \
|
||||||
|
| stdbuf -o0 awk 'NR>2 {print 100-$(NF-2)}'
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
if is_freebsd; then
|
||||||
|
top -d"$samples_count" \
|
||||||
|
| sed -u -nr '/CPU:/s/.*,[[:space:]]*([0-9]+[.,][0-9]*)%[[:space:]]*id.*/\1/p' \
|
||||||
|
| stdbuf -o0 awk '{ print 100-$0 }'
|
||||||
|
else
|
||||||
|
top -b -n "$samples_count" -d "$refresh_interval" \
|
||||||
|
| sed -u -nr '/%Cpu/s/.*,[[:space:]]*([0-9]+[.,][0-9]*)[[:space:]]*id.*/\1/p' \
|
||||||
|
| stdbuf -o0 awk '{ print 100-$0 }'
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
main() {
|
||||||
|
get_cpu_usage | while read -r value; do
|
||||||
|
echo "$value" | tee "$cpu_metric_file"
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
main
|
||||||
|
|
76
tmux/plugins/tmux-plugin-sysstat/scripts/helpers.sh
Executable file
76
tmux/plugins/tmux-plugin-sysstat/scripts/helpers.sh
Executable file
@ -0,0 +1,76 @@
|
|||||||
|
|
||||||
|
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"
|
||||||
|
}
|
||||||
|
|
||||||
|
is_osx() {
|
||||||
|
[ $(uname) == "Darwin" ]
|
||||||
|
}
|
||||||
|
|
||||||
|
is_linux(){
|
||||||
|
[ $(uname -s) == "Linux" ]
|
||||||
|
}
|
||||||
|
|
||||||
|
is_freebsd() {
|
||||||
|
[ $(uname) == FreeBSD ]
|
||||||
|
}
|
||||||
|
|
||||||
|
command_exists() {
|
||||||
|
local command="$1"
|
||||||
|
type "$command" >/dev/null 2>&1
|
||||||
|
}
|
||||||
|
|
||||||
|
# because bash does not support floating-point math
|
||||||
|
# but awk does
|
||||||
|
calc() {
|
||||||
|
local stdin;
|
||||||
|
read -d '' -u 0 stdin;
|
||||||
|
awk "BEGIN { print $stdin }";
|
||||||
|
}
|
||||||
|
|
||||||
|
# "<" math operator which works with floats, once again based on awk
|
||||||
|
fcomp() {
|
||||||
|
awk -v n1="$1" -v n2="$2" 'BEGIN {if (n1<n2) exit 0; exit 1}'
|
||||||
|
}
|
||||||
|
|
||||||
|
# get_mem_usage* function returns values in KiB
|
||||||
|
# 1 - scale to KiB
|
||||||
|
# 1024 - scale to MiB
|
||||||
|
# 1048576 - scale to GiB
|
||||||
|
function get_size_scale_factor(){
|
||||||
|
local size_unit="$1"
|
||||||
|
case "$size_unit" in
|
||||||
|
G) echo 1048576;;
|
||||||
|
M) echo 1024;;
|
||||||
|
K) echo 1;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
# Depending on scale factor, change precision
|
||||||
|
# 12612325K - no digits after floating point
|
||||||
|
# 1261M - no digits after floating point
|
||||||
|
# 1.1G - 1 digit after floating point
|
||||||
|
function get_size_format(){
|
||||||
|
local size_unit="$1"
|
||||||
|
case "$size_unit" in
|
||||||
|
G) echo '%.1f%s';;
|
||||||
|
M) echo '%.0f%s';;
|
||||||
|
K) echo '%.0f%s';;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
28
tmux/plugins/tmux-plugin-sysstat/scripts/loadavg.sh
Executable file
28
tmux/plugins/tmux-plugin-sysstat/scripts/loadavg.sh
Executable file
@ -0,0 +1,28 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -u
|
||||||
|
set -e
|
||||||
|
|
||||||
|
LC_NUMERIC=C
|
||||||
|
|
||||||
|
CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||||
|
source "$CURRENT_DIR/helpers.sh"
|
||||||
|
|
||||||
|
loadavg_per_cpu_core=$(get_tmux_option "@sysstat_loadavg_per_cpu_core" "true")
|
||||||
|
|
||||||
|
get_num_of_cores(){
|
||||||
|
is_osx && sysctl -n hw.ncpu || nproc
|
||||||
|
}
|
||||||
|
|
||||||
|
main(){
|
||||||
|
local num_cores=$([ "$loadavg_per_cpu_core" == "true" ] && get_num_of_cores || echo 1)
|
||||||
|
|
||||||
|
uptime | awk -v num_cores="$num_cores" '{
|
||||||
|
sub(/,$/, "", $(NF-2));
|
||||||
|
sub(/,$/, "", $(NF-1));
|
||||||
|
sub(/,$/, "", $NF);
|
||||||
|
printf "%.2f %.2f %.2f", $(NF-2)/num_cores, $(NF-1)/num_cores, $NF/num_cores
|
||||||
|
}'
|
||||||
|
}
|
||||||
|
|
||||||
|
main
|
130
tmux/plugins/tmux-plugin-sysstat/scripts/mem.sh
Executable file
130
tmux/plugins/tmux-plugin-sysstat/scripts/mem.sh
Executable file
@ -0,0 +1,130 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -u
|
||||||
|
set -e
|
||||||
|
|
||||||
|
LC_NUMERIC=C
|
||||||
|
|
||||||
|
CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||||
|
source "$CURRENT_DIR/helpers.sh"
|
||||||
|
|
||||||
|
mem_view_tmpl=$(get_tmux_option "@sysstat_mem_view_tmpl" 'MEM:#[fg=#{mem.color}]#{mem.pused}#[default]')
|
||||||
|
|
||||||
|
mem_medium_threshold=$(get_tmux_option "@sysstat_mem_medium_threshold" "75")
|
||||||
|
mem_stress_threshold=$(get_tmux_option "@sysstat_mem_stress_threshold" "90")
|
||||||
|
|
||||||
|
mem_color_low=$(get_tmux_option "@sysstat_mem_color_low" "green")
|
||||||
|
mem_color_medium=$(get_tmux_option "@sysstat_mem_color_medium" "yellow")
|
||||||
|
mem_color_stress=$(get_tmux_option "@sysstat_mem_color_stress" "red")
|
||||||
|
|
||||||
|
size_unit=$(get_tmux_option "@sysstat_mem_size_unit" "G")
|
||||||
|
|
||||||
|
get_mem_color() {
|
||||||
|
local mem_pused=$1
|
||||||
|
|
||||||
|
if fcomp "$mem_stress_threshold" "$mem_pused"; then
|
||||||
|
echo "$mem_color_stress";
|
||||||
|
elif fcomp "$mem_medium_threshold" "$mem_pused"; then
|
||||||
|
echo "$mem_color_medium";
|
||||||
|
else
|
||||||
|
echo "$mem_color_low";
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
print_mem() {
|
||||||
|
local mem_usage
|
||||||
|
local scale
|
||||||
|
local size_format
|
||||||
|
|
||||||
|
if is_osx; then
|
||||||
|
mem_usage=$(get_mem_usage_osx)
|
||||||
|
elif is_linux; then
|
||||||
|
mem_usage=$(get_mem_usage_linux)
|
||||||
|
elif is_freebsd; then
|
||||||
|
mem_usage=$(get_mem_usage_freebsd)
|
||||||
|
fi
|
||||||
|
|
||||||
|
local size_scale="$(get_size_scale_factor "$size_unit")"
|
||||||
|
local size_format="$(get_size_format "$size_unit")"
|
||||||
|
|
||||||
|
# Extract free and used memory in MiB, calculate total and percentage
|
||||||
|
local mem_free=$(echo $mem_usage | awk -v scale="$size_scale" '{ print $1/scale }')
|
||||||
|
local mem_used=$(echo $mem_usage | awk -v scale="$size_scale" '{ print $2/scale }')
|
||||||
|
local mem_total=$(echo "$mem_free + $mem_used" | calc)
|
||||||
|
local mem_pused=$(echo "($mem_used / $mem_total) * 100" | calc)
|
||||||
|
local mem_pfree=$(echo "($mem_free / $mem_total) * 100" | calc)
|
||||||
|
|
||||||
|
# Calculate colors for mem and swap
|
||||||
|
local mem_color=$(get_mem_color "$mem_pused")
|
||||||
|
|
||||||
|
local mem_view="$mem_view_tmpl"
|
||||||
|
mem_view="${mem_view//'#{mem.used}'/$(printf "$size_format" "$mem_used" "$size_unit")}"
|
||||||
|
mem_view="${mem_view//'#{mem.pused}'/$(printf "%.0f%%" "$mem_pused")}"
|
||||||
|
mem_view="${mem_view//'#{mem.free}'/$(printf "$size_format" "$mem_free" "$size_unit")}"
|
||||||
|
mem_view="${mem_view//'#{mem.pfree}'/$(printf "%.0f%%" "$mem_pfree")}"
|
||||||
|
mem_view="${mem_view//'#{mem.total}'/$(printf "$size_format" "$mem_total" "$size_unit")}"
|
||||||
|
mem_view="${mem_view//'#{mem.color}'/$(echo "$mem_color" | awk '{ print $1 }')}"
|
||||||
|
mem_view="${mem_view//'#{mem.color2}'/$(echo "$mem_color" | awk '{ print $2 }')}"
|
||||||
|
mem_view="${mem_view//'#{mem.color3}'/$(echo "$mem_color" | awk '{ print $3 }')}"
|
||||||
|
|
||||||
|
echo "$mem_view"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# Report like it does htop on OSX:
|
||||||
|
# used = active + wired
|
||||||
|
# free = free + inactive + speculative + occupied by compressor
|
||||||
|
# see `vm_stat` command
|
||||||
|
get_mem_usage_osx(){
|
||||||
|
|
||||||
|
local page_size=$(sysctl -nq "vm.pagesize")
|
||||||
|
vm_stat | awk -v page_size=$page_size -F ':' '
|
||||||
|
BEGIN { free=0; used=0 }
|
||||||
|
|
||||||
|
/Pages active/ ||
|
||||||
|
/Pages wired/ {
|
||||||
|
gsub(/^[ \t]+|[ \t]+$/, "", $2); used+=$2;
|
||||||
|
}
|
||||||
|
/Pages free/ ||
|
||||||
|
/Pages inactive/ ||
|
||||||
|
/Pages speculative/ ||
|
||||||
|
/Pages occupied by compressor/ {
|
||||||
|
gsub(/^[ \t]+|[ \t]+$/, "", $2); free+=$2;
|
||||||
|
}
|
||||||
|
|
||||||
|
END { print (free * page_size)/1024, (used * page_size)/1024 }
|
||||||
|
'
|
||||||
|
}
|
||||||
|
|
||||||
|
# Relies on vmstat, but could also be done with top on FreeBSD
|
||||||
|
get_mem_usage_freebsd(){
|
||||||
|
vmstat -H | tail -n 1 | awk '{ print $5, $4 }'
|
||||||
|
}
|
||||||
|
|
||||||
|
# Method #1. Sum up free+buffers+cached, treat it as "available" memory, assuming buff+cache can be reclaimed. Note, that this assumption is not 100% correct, buff+cache most likely cannot be 100% reclaimed, but this is how memory calculation is used to be done on Linux
|
||||||
|
|
||||||
|
# Method #2. If "MemAvailable" is provided by system, use it. This is more correct method, because we're not relying on fragile "free+buffer+cache" equation.
|
||||||
|
|
||||||
|
# See: Interpreting /proc/meminfo and free output for Red Hat Enterprise Linux 5, 6 and 7 - Red Hat Customer Portal - https://access.redhat.com/solutions/406773
|
||||||
|
|
||||||
|
# See: kernel/git/torvalds/linux.git - /proc/meminfo: provide estimated available memory - https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=34e431b0ae398fc54ea69ff85ec700722c9da773
|
||||||
|
get_mem_usage_linux(){
|
||||||
|
</proc/meminfo awk '
|
||||||
|
BEGIN { total=0; free=0; }
|
||||||
|
/MemTotal:/ { total=$2; }
|
||||||
|
|
||||||
|
/MemFree:/ { free+=$2; }
|
||||||
|
/Buffers:/ { free+=$2; }
|
||||||
|
/Cached:/ { free+=$2; }
|
||||||
|
|
||||||
|
/MemAvailable:/ { free=$2; exit;}
|
||||||
|
END { print free, total-free }
|
||||||
|
'
|
||||||
|
}
|
||||||
|
|
||||||
|
main() {
|
||||||
|
print_mem
|
||||||
|
}
|
||||||
|
|
||||||
|
main
|
||||||
|
|
95
tmux/plugins/tmux-plugin-sysstat/scripts/swap.sh
Executable file
95
tmux/plugins/tmux-plugin-sysstat/scripts/swap.sh
Executable file
@ -0,0 +1,95 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -u
|
||||||
|
set -e
|
||||||
|
|
||||||
|
LC_NUMERIC=C
|
||||||
|
|
||||||
|
CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||||
|
source "$CURRENT_DIR/helpers.sh"
|
||||||
|
|
||||||
|
swap_view_tmpl=$(get_tmux_option "@sysstat_swap_view_tmpl" 'SW:#[fg=#{swap.color}]#{swap.pused}#[default]')
|
||||||
|
|
||||||
|
swap_medium_threshold=$(get_tmux_option "@sysstat_swap_medium_threshold" "25")
|
||||||
|
swap_stress_threshold=$(get_tmux_option "@sysstat_swap_stress_threshold" "75")
|
||||||
|
|
||||||
|
swap_color_low=$(get_tmux_option "@sysstat_swap_color_low" "green")
|
||||||
|
swap_color_medium=$(get_tmux_option "@sysstat_swap_color_medium" "yellow")
|
||||||
|
swap_color_stress=$(get_tmux_option "@sysstat_swap_color_stress" "red")
|
||||||
|
|
||||||
|
size_unit=$(get_tmux_option "@sysstat_swap_size_unit" "G")
|
||||||
|
|
||||||
|
get_swap_color() {
|
||||||
|
local swap_pused=$1
|
||||||
|
|
||||||
|
if fcomp "$swap_stress_threshold" "$swap_pused"; then
|
||||||
|
echo "$swap_color_stress";
|
||||||
|
elif fcomp "$swap_medium_threshold" "$swap_pused"; then
|
||||||
|
echo "$swap_color_medium";
|
||||||
|
else
|
||||||
|
echo "$swap_color_low";
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
print_swap() {
|
||||||
|
local swap_usage
|
||||||
|
|
||||||
|
|
||||||
|
if is_osx; then
|
||||||
|
swap_usage=$(get_swap_usage_osx)
|
||||||
|
elif is_linux; then
|
||||||
|
swap_usage=$(get_swap_usage_linux)
|
||||||
|
fi
|
||||||
|
|
||||||
|
local size_scale="$(get_size_scale_factor "$size_unit")"
|
||||||
|
local size_format="$(get_size_format "$size_unit")"
|
||||||
|
|
||||||
|
# Extract swap free and used in MiB, calculate total and percentage
|
||||||
|
local swap_free=$(echo $swap_usage | awk -v scale="$size_scale" '{ print $1/scale }')
|
||||||
|
local swap_used=$(echo $swap_usage | awk -v scale="$size_scale" '{ print $2/scale }')
|
||||||
|
local swap_total=$(echo "$swap_free + $swap_used" | calc)
|
||||||
|
local swap_pused=$(echo "($swap_used / $swap_total) * 100" | calc)
|
||||||
|
local swap_pfree=$(echo "($swap_free / $swap_total) * 100" | calc)
|
||||||
|
|
||||||
|
# Calculate colors for mem and swap
|
||||||
|
local swap_color=$(get_swap_color "$swap_pused")
|
||||||
|
|
||||||
|
local swap_view="$swap_view_tmpl"
|
||||||
|
swap_view="${swap_view//'#{swap.used}'/$(printf "$size_format" "$swap_used" "$size_unit")}"
|
||||||
|
swap_view="${swap_view//'#{swap.pused}'/$(printf "%.0f%%" "$swap_pused")}"
|
||||||
|
swap_view="${swap_view//'#{swap.free}'/$(printf "$size_format" "$swap_free" "$size_unit")}"
|
||||||
|
swap_view="${swap_view//'#{swap.pfree}'/$(printf "%.0f%%" "$swap_pfree")}"
|
||||||
|
swap_view="${swap_view//'#{swap.total}'/$(printf "$size_format" "$swap_total" "$size_unit")}"
|
||||||
|
swap_view="${swap_view//'#{swap.color}'/$(echo "$swap_color" | awk '{ print $1 }')}"
|
||||||
|
swap_view="${swap_view//'#{swap.color2}'/$(echo "$swap_color" | awk '{ print $2 }')}"
|
||||||
|
swap_view="${swap_view//'#{swap.color3}'/$(echo "$swap_color" | awk '{ print $3 }')}"
|
||||||
|
|
||||||
|
echo "$swap_view"
|
||||||
|
}
|
||||||
|
|
||||||
|
get_swap_usage_osx(){
|
||||||
|
|
||||||
|
# assume swap size in MB
|
||||||
|
local swap_used=$(sysctl -nq vm.swapusage | awk -F ' ' '{ print $2 }' | awk -F '=' '{gsub(/^[ ]|[M]$/, "", $2); printf "%d", $2 * 1024 }')
|
||||||
|
local swap_free=$(sysctl -nq vm.swapusage | awk -F ' ' '{ print $3 }' | awk -F '=' '{gsub(/^[ ]|[M]$/, "", $2); printf "%d", $2 * 1024 }')
|
||||||
|
|
||||||
|
printf "%s %s" "$swap_free" "$swap_used"
|
||||||
|
}
|
||||||
|
|
||||||
|
get_swap_usage_linux(){
|
||||||
|
</proc/meminfo awk '
|
||||||
|
BEGIN { total=0; free=0; }
|
||||||
|
/SwapTotal:/ { total=$2; }
|
||||||
|
/SwapFree:/ { free=$2; }
|
||||||
|
END { print free, total-free }
|
||||||
|
'
|
||||||
|
}
|
||||||
|
|
||||||
|
main() {
|
||||||
|
print_swap
|
||||||
|
}
|
||||||
|
|
||||||
|
main
|
||||||
|
|
||||||
|
|
||||||
|
|
43
tmux/plugins/tmux-plugin-sysstat/sysstat.tmux
Executable file
43
tmux/plugins/tmux-plugin-sysstat/sysstat.tmux
Executable file
@ -0,0 +1,43 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
CURRENT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||||
|
source "$CURRENT_DIR/scripts/helpers.sh"
|
||||||
|
|
||||||
|
placeholders=(
|
||||||
|
"\#{sysstat_cpu}"
|
||||||
|
"\#{sysstat_mem}"
|
||||||
|
"\#{sysstat_swap}"
|
||||||
|
"\#{sysstat_loadavg}"
|
||||||
|
)
|
||||||
|
|
||||||
|
commands=(
|
||||||
|
"#($CURRENT_DIR/scripts/cpu.sh)"
|
||||||
|
"#($CURRENT_DIR/scripts/mem.sh)"
|
||||||
|
"#($CURRENT_DIR/scripts/swap.sh)"
|
||||||
|
"#($CURRENT_DIR/scripts/loadavg.sh)"
|
||||||
|
)
|
||||||
|
|
||||||
|
do_interpolation() {
|
||||||
|
local all_interpolated="$1"
|
||||||
|
for ((i=0; i<${#commands[@]}; i++)); do
|
||||||
|
all_interpolated=${all_interpolated//${placeholders[$i]}/${commands[$i]}}
|
||||||
|
done
|
||||||
|
echo "$all_interpolated"
|
||||||
|
}
|
||||||
|
|
||||||
|
update_tmux_option() {
|
||||||
|
local option="$1"
|
||||||
|
local option_value="$(get_tmux_option "$option")"
|
||||||
|
local new_option_value="$(do_interpolation "$option_value")"
|
||||||
|
set_tmux_option "$option" "$new_option_value"
|
||||||
|
}
|
||||||
|
|
||||||
|
main() {
|
||||||
|
cpu_tmp_dir=$(mktemp -d)
|
||||||
|
tmux set-option -gq "@sysstat_cpu_tmp_dir" "$cpu_tmp_dir"
|
||||||
|
|
||||||
|
update_tmux_option "status-right"
|
||||||
|
update_tmux_option "status-left"
|
||||||
|
}
|
||||||
|
|
||||||
|
main
|
22
tmux/plugins/tmux-prefix-highlight/LICENSE
Normal file
22
tmux/plugins/tmux-prefix-highlight/LICENSE
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright (c) 2015 Erick Pintor
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
111
tmux/plugins/tmux-prefix-highlight/README.md
Normal file
111
tmux/plugins/tmux-prefix-highlight/README.md
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
# Tmux prefix highlight
|
||||||
|
|
||||||
|
Plugin that highlights when you press tmux prefix key. Inspired by
|
||||||
|
[this](http://stackoverflow.com/questions/12003726/give-a-hint-when-press-prefix-key-in-tmux)
|
||||||
|
thread on stackoverflow.
|
||||||
|
|
||||||
|
Many thanks to [@obxhdx](https://github.com/obxhdx) for showing me this trick.
|
||||||
|
|
||||||
|
Prefix off:
|
||||||
|

|
||||||
|
|
||||||
|
Prefix on:
|
||||||
|

|
||||||
|
|
||||||
|
### Usage
|
||||||
|
|
||||||
|
Just add `#{prefix_highlight}` to your left/right status bar.
|
||||||
|
|
||||||
|
```tmux.conf
|
||||||
|
set -g status-right '#{prefix_highlight} | %a %Y-%m-%d %H:%M'
|
||||||
|
```
|
||||||
|
|
||||||
|
The plugin can also be configured to show when copy mode is active; see the
|
||||||
|
**Configurations** section for details.
|
||||||
|
|
||||||
|
### Installation with Tmux Plugin Manager (recommended)
|
||||||
|
|
||||||
|
Add plugin to the list of TPM plugins:
|
||||||
|
|
||||||
|
```tmux.conf
|
||||||
|
set -g @plugin 'tmux-plugins/tmux-prefix-highlight'
|
||||||
|
```
|
||||||
|
|
||||||
|
Press prefix + I to install it.
|
||||||
|
|
||||||
|
### Manual Installation
|
||||||
|
|
||||||
|
Clone the repo:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ git clone https://github.com/tmux-plugins/tmux-prefix-highlight.git ~/clone/path
|
||||||
|
```
|
||||||
|
|
||||||
|
Add this line to your .tmux.conf:
|
||||||
|
|
||||||
|
```tmux.conf
|
||||||
|
run-shell ~/clone/path/prefix_highlight.tmux
|
||||||
|
```
|
||||||
|
|
||||||
|
Reload TMUX environment with:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ tmux source-file ~/.tmux.conf
|
||||||
|
```
|
||||||
|
|
||||||
|
### Configurations
|
||||||
|
|
||||||
|
The colors used for the prefix highlight can be configured:
|
||||||
|
|
||||||
|
```tmux.conf
|
||||||
|
set -g @prefix_highlight_fg 'white' # default is 'colour231'
|
||||||
|
set -g @prefix_highlight_bg 'blue' # default is 'colour04'
|
||||||
|
```
|
||||||
|
|
||||||
|
The plugin can also be configured to show when copy mode is active. If enabled,
|
||||||
|
the `#{prefix_highlight}` token will be replaced with the string `Copy` when
|
||||||
|
copy mode is enabled. The style for copy mode can be configured as a
|
||||||
|
comma-separated list of colors and attributes:
|
||||||
|
|
||||||
|
```tmux.conf
|
||||||
|
set -g @prefix_highlight_show_copy_mode 'on'
|
||||||
|
set -g @prefix_highlight_copy_mode_attr 'fg=black,bg=yellow,bold' # default is 'fg=default,bg=yellow'
|
||||||
|
```
|
||||||
|
|
||||||
|
The `prefix` prompt and `copy` prompt can also be configured:
|
||||||
|
|
||||||
|
```tmux.conf
|
||||||
|
set -g @prefix_highlight_prefix_prompt 'Wait'
|
||||||
|
set -g @prefix_highlight_copy_prompt 'Copy'
|
||||||
|
```
|
||||||
|
|
||||||
|
Additionally, the plugin can be configured to attach optional affixes to the
|
||||||
|
value contained in `#{prefix_highlight}`.
|
||||||
|
(e.g. `< ^B >`)
|
||||||
|
|
||||||
|
```tmux.conf
|
||||||
|
set -g @prefix_highlight_output_prefix '< '
|
||||||
|
set -g @prefix_highlight_output_suffix ' >'
|
||||||
|
```
|
||||||
|
|
||||||
|
The empty (shown when prefix is off) prompt and attribute can be configured,
|
||||||
|
It is useful for aligning segments.
|
||||||
|
|
||||||
|
```tmux.conf
|
||||||
|
set -g @prefix_highlight_empty_prompt ' ' # default is '' (empty char)
|
||||||
|
set -g @prefix_highlight_empty_attr 'fg=default,bg=green' # default is 'fg=default,bg=default'
|
||||||
|
```
|
||||||
|
|
||||||
|
Defaultly, empty prompt can't be attached optional affixes.
|
||||||
|
If you want attach affixes on empty prompt, config `@prefix_highlight_empty_has_affixes` to `on`.
|
||||||
|
|
||||||
|
```tmux.conf
|
||||||
|
set -g @prefix_highlight_empty_has_affixes 'on' # default is 'off'
|
||||||
|
set -g @prefix_highlight_empty_prompt 'Tmux'
|
||||||
|
set -g @prefix_highlight_output_prefix '< '
|
||||||
|
set -g @prefix_highlight_output_suffix ' >'
|
||||||
|
```
|
||||||
|
|
||||||
|
### License
|
||||||
|
|
||||||
|
[MIT](LICENSE)
|
117
tmux/plugins/tmux-prefix-highlight/prefix_highlight.tmux
Executable file
117
tmux/plugins/tmux-prefix-highlight/prefix_highlight.tmux
Executable file
@ -0,0 +1,117 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# Place holder for status left/right
|
||||||
|
place_holder="\#{prefix_highlight}"
|
||||||
|
|
||||||
|
# Possible configurations
|
||||||
|
fg_color_config='@prefix_highlight_fg'
|
||||||
|
bg_color_config='@prefix_highlight_bg'
|
||||||
|
output_prefix='@prefix_highlight_output_prefix'
|
||||||
|
output_suffix='@prefix_highlight_output_suffix'
|
||||||
|
show_copy_config='@prefix_highlight_show_copy_mode'
|
||||||
|
copy_attr_config='@prefix_highlight_copy_mode_attr'
|
||||||
|
prefix_prompt='@prefix_highlight_prefix_prompt'
|
||||||
|
copy_prompt='@prefix_highlight_copy_prompt'
|
||||||
|
empty_prompt='@prefix_highlight_empty_prompt'
|
||||||
|
empty_attr_config='@prefix_highlight_empty_attr'
|
||||||
|
empty_has_affixes='@prefix_highlight_empty_has_affixes'
|
||||||
|
|
||||||
|
tmux_option() {
|
||||||
|
local -r value=$(tmux show-option -gqv "$1")
|
||||||
|
local -r default="$2"
|
||||||
|
|
||||||
|
if [ ! -z "$value" ]; then
|
||||||
|
echo "$value"
|
||||||
|
else
|
||||||
|
echo "$default"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Defaults
|
||||||
|
default_fg='colour231'
|
||||||
|
default_bg='colour04'
|
||||||
|
default_copy_attr='fg=default,bg=yellow'
|
||||||
|
default_empty_attr='fg=default,bg=default'
|
||||||
|
default_prefix_prompt=$(tmux_option prefix | tr "[:lower:]" "[:upper:]" | sed 's/C-/\^/')
|
||||||
|
default_copy_prompt='Copy'
|
||||||
|
default_empty_prompt=''
|
||||||
|
|
||||||
|
highlight() {
|
||||||
|
local -r \
|
||||||
|
status="$1" \
|
||||||
|
prefix="$2" \
|
||||||
|
prefix_highlight="$3" \
|
||||||
|
show_copy_mode="$4" \
|
||||||
|
copy_highlight="$5" \
|
||||||
|
output_prefix="$6" \
|
||||||
|
output_suffix="$7" \
|
||||||
|
copy="$8" \
|
||||||
|
empty="$9"
|
||||||
|
|
||||||
|
local -r status_value="$(tmux_option "$status")"
|
||||||
|
local -r prefix_with_optional_affixes="$output_prefix$prefix$output_suffix"
|
||||||
|
local -r copy_with_optional_affixes="$output_prefix$copy$output_suffix"
|
||||||
|
|
||||||
|
if [[ "on" = "$empty_has_affixes" ]]; then
|
||||||
|
local -r empty_with_optional_affixes="$output_prefix$empty$output_suffix"
|
||||||
|
else
|
||||||
|
local -r empty_with_optional_affixes="$empty"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "on" = "$show_copy_mode" ]]; then
|
||||||
|
local -r fallback="${copy_highlight}#{?pane_in_mode,$copy_with_optional_affixes,${empty_highlight}$empty_with_optional_affixes}"
|
||||||
|
else
|
||||||
|
local -r fallback="${empty_highlight}$empty_with_optional_affixes"
|
||||||
|
fi
|
||||||
|
|
||||||
|
local -r highlight_on_prefix="${prefix_highlight}#{?client_prefix,$prefix_with_optional_affixes,$fallback}#[default]"
|
||||||
|
tmux set-option -gq "$status" "${status_value/$place_holder/$highlight_on_prefix}"
|
||||||
|
}
|
||||||
|
|
||||||
|
main() {
|
||||||
|
local -r \
|
||||||
|
fg_color=$(tmux_option "$fg_color_config" "$default_fg") \
|
||||||
|
bg_color=$(tmux_option "$bg_color_config" "$default_bg") \
|
||||||
|
show_copy_mode=$(tmux_option "$show_copy_config" "off") \
|
||||||
|
output_prefix=$(tmux_option "$output_prefix" " ") \
|
||||||
|
output_suffix=$(tmux_option "$output_suffix" " ") \
|
||||||
|
copy_attr=$(tmux_option "$copy_attr_config" "$default_copy_attr") \
|
||||||
|
prefix_prompt=$(tmux_option "$prefix_prompt" "$default_prefix_prompt") \
|
||||||
|
copy_prompt=$(tmux_option "$copy_prompt" "$default_copy_prompt") \
|
||||||
|
empty_prompt=$(tmux_option "$empty_prompt" "$default_empty_prompt") \
|
||||||
|
empty_attr=$(tmux_option "$empty_attr_config" "$default_empty_attr") \
|
||||||
|
empty_has_affixes=$(tmux_option "$empty_has_affixes" "off")
|
||||||
|
|
||||||
|
local -r \
|
||||||
|
prefix_highlight="#[fg=$fg_color,bg=$bg_color]" \
|
||||||
|
copy_highlight="${copy_attr:+#[default,$copy_attr]}" \
|
||||||
|
empty_highlight="${empty_attr:+#[default,$empty_attr]}"
|
||||||
|
|
||||||
|
highlight "status-right" \
|
||||||
|
"$prefix_prompt" \
|
||||||
|
"$prefix_highlight" \
|
||||||
|
"$show_copy_mode" \
|
||||||
|
"$copy_highlight" \
|
||||||
|
"$output_prefix" \
|
||||||
|
"$output_suffix" \
|
||||||
|
"$copy_prompt" \
|
||||||
|
"$empty_prompt" \
|
||||||
|
"$empty_highlight" \
|
||||||
|
"$empty_has_affixes"
|
||||||
|
|
||||||
|
highlight "status-left" \
|
||||||
|
"$prefix_prompt" \
|
||||||
|
"$prefix_highlight" \
|
||||||
|
"$show_copy_mode" \
|
||||||
|
"$copy_highlight" \
|
||||||
|
"$output_prefix" \
|
||||||
|
"$output_suffix" \
|
||||||
|
"$copy_prompt" \
|
||||||
|
"$empty_prompt" \
|
||||||
|
"$empty_highlight" \
|
||||||
|
"$empty_has_affixes"
|
||||||
|
}
|
||||||
|
|
||||||
|
main
|
19
tmux/plugins/tmux-ressurect/LICENSE.md
Normal file
19
tmux/plugins/tmux-ressurect/LICENSE.md
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
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.
|
133
tmux/plugins/tmux-ressurect/README.md
Normal file
133
tmux/plugins/tmux-ressurect/README.md
Normal file
@ -0,0 +1,133 @@
|
|||||||
|
# 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 shell history](docs/restoring_shell_history.md) (experimental)
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
**Experimental features (also optional)**
|
||||||
|
|
||||||
|
- [restoring shell history](docs/restoring_shell_history.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
|
||||||
|
- [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)
|
11
tmux/plugins/tmux-ressurect/docs/custom_key_bindings.md
Normal file
11
tmux/plugins/tmux-ressurect/docs/custom_key_bindings.md
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
# 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'
|
39
tmux/plugins/tmux-ressurect/docs/hooks.md
Normal file
39
tmux/plugins/tmux-ressurect/docs/hooks.md
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
# 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-history`
|
||||||
|
|
||||||
|
Called after panes and layout have been restores, but before bash history is
|
||||||
|
restored (if it is enabled) -- the hook is always called even if history
|
||||||
|
saving is disabled.
|
||||||
|
|
||||||
|
- `@resurrect-hook-pre-restore-pane-processes`
|
||||||
|
|
||||||
|
Called after history is restored, but 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)'
|
@ -0,0 +1,72 @@
|
|||||||
|
# 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.
|
31
tmux/plugins/tmux-ressurect/docs/restoring_pane_contents.md
Normal file
31
tmux/plugins/tmux-ressurect/docs/restoring_pane_contents.md
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
# 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.
|
179
tmux/plugins/tmux-ressurect/docs/restoring_programs.md
Normal file
179
tmux/plugins/tmux-ressurect/docs/restoring_programs.md
Normal file
@ -0,0 +1,179 @@
|
|||||||
|
# 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"'
|
||||||
|
|
||||||
|
- Don't restore any programs:
|
||||||
|
|
||||||
|
set -g @resurrect-processes 'false'
|
||||||
|
|
||||||
|
- Restore **all** programs (be careful with this!):
|
||||||
|
|
||||||
|
set -g @resurrect-processes ':all:'
|
||||||
|
|
||||||
|
### 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.
|
||||||
|
|
||||||
|
> 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.
|
19
tmux/plugins/tmux-ressurect/docs/restoring_shell_history.md
Normal file
19
tmux/plugins/tmux-ressurect/docs/restoring_shell_history.md
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
# Restoring shell history (experimental)
|
||||||
|
|
||||||
|
**Supported shells**: `bash` and `zsh`.
|
||||||
|
|
||||||
|
Enable feature with this option in `.tmux.conf`:
|
||||||
|
|
||||||
|
set -g @resurrect-save-shell-history 'on'
|
||||||
|
|
||||||
|
**Note**: the older `@resurrect-save-bash-history` is now an alias to
|
||||||
|
`@resurrect-save-shell-history`.
|
||||||
|
|
||||||
|
Shell `history` for individual panes will now be saved and restored. Due to
|
||||||
|
technical limitations, this only works for panes which have no program running
|
||||||
|
in foreground when saving. `tmux-resurrect` will send history write command to
|
||||||
|
each such pane.
|
||||||
|
|
||||||
|
To prevent these commands from being added to `bash` history
|
||||||
|
themselves, add `HISTCONTROL=ignoreboth` to your `.bashrc`
|
||||||
|
(this is set by default in Ubuntu).
|
@ -0,0 +1,15 @@
|
|||||||
|
# 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.
|
||||||
|
|
15
tmux/plugins/tmux-ressurect/docs/save_dir.md
Normal file
15
tmux/plugins/tmux-ressurect/docs/save_dir.md
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
# 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 `~`.
|
40
tmux/plugins/tmux-ressurect/resurrect.tmux
Executable file
40
tmux/plugins/tmux-ressurect/resurrect.tmux
Executable file
@ -0,0 +1,40 @@
|
|||||||
|
#!/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
|
22
tmux/plugins/tmux-ressurect/save_command_strategies/gdb.sh
Executable file
22
tmux/plugins/tmux-ressurect/save_command_strategies/gdb.sh
Executable file
@ -0,0 +1,22 @@
|
|||||||
|
#!/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
|
22
tmux/plugins/tmux-ressurect/save_command_strategies/pgrep.sh
Executable file
22
tmux/plugins/tmux-ressurect/save_command_strategies/pgrep.sh
Executable file
@ -0,0 +1,22 @@
|
|||||||
|
#!/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
|
24
tmux/plugins/tmux-ressurect/save_command_strategies/ps.sh
Executable file
24
tmux/plugins/tmux-ressurect/save_command_strategies/ps.sh
Executable file
@ -0,0 +1,24 @@
|
|||||||
|
#!/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 command" |
|
||||||
|
sed "s/^ *//" |
|
||||||
|
grep "^${PANE_PID}" |
|
||||||
|
cut -d' ' -f2-
|
||||||
|
}
|
||||||
|
|
||||||
|
main() {
|
||||||
|
exit_safely_if_empty_ppid
|
||||||
|
full_command
|
||||||
|
}
|
||||||
|
main
|
78
tmux/plugins/tmux-ressurect/scripts/check_tmux_version.sh
Executable file
78
tmux/plugins/tmux-ressurect/scripts/check_tmux_version.sh
Executable file
@ -0,0 +1,78 @@
|
|||||||
|
#!/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
|
168
tmux/plugins/tmux-ressurect/scripts/helpers.sh
Normal file
168
tmux/plugins/tmux-ressurect/scripts/helpers.sh
Normal file
@ -0,0 +1,168 @@
|
|||||||
|
default_resurrect_dir="$HOME/.tmux/resurrect"
|
||||||
|
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"
|
||||||
|
}
|
||||||
|
|
||||||
|
save_shell_history_option_on() {
|
||||||
|
local option_shell="$(get_tmux_option "$shell_history_option" "off")"
|
||||||
|
local option_bash="$(get_tmux_option "$bash_history_option" "off")"
|
||||||
|
|
||||||
|
[ "$option_shell" == "on" ] || [ "$option_bash" == "on" ]
|
||||||
|
}
|
||||||
|
|
||||||
|
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"
|
||||||
|
}
|
||||||
|
|
||||||
|
resurrect_history_file() {
|
||||||
|
local pane_id="$1"
|
||||||
|
local shell_name="$2"
|
||||||
|
echo "$(resurrect_dir)/${shell_name}_history-${pane_id}"
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
172
tmux/plugins/tmux-ressurect/scripts/process_restore_helpers.sh
Normal file
172
tmux/plugins/tmux-ressurect/scripts/process_restore_helpers.sh
Normal file
@ -0,0 +1,172 @@
|
|||||||
|
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}//"
|
||||||
|
}
|
||||||
|
|
||||||
|
_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_element "$proc")"
|
||||||
|
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"
|
||||||
|
}
|
14
tmux/plugins/tmux-ressurect/scripts/restore.exp
Executable file
14
tmux/plugins/tmux-ressurect/scripts/restore.exp
Executable file
@ -0,0 +1,14 @@
|
|||||||
|
#!/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
|
369
tmux/plugins/tmux-ressurect/scripts/restore.sh
Executable file
369
tmux/plugins/tmux-ressurect/scripts/restore.sh
Executable file
@ -0,0 +1,369 @@
|
|||||||
|
#!/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" ]
|
||||||
|
}
|
||||||
|
|
||||||
|
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" "")"
|
||||||
|
export TMUX_DEFAULT_COMMAND="$(get_tmux_option "default-command" "$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 window_name="$3"
|
||||||
|
local dir="$4"
|
||||||
|
local pane_index="$5"
|
||||||
|
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 new-window -d -t "${session_name}:${window_number}" -n "$window_name" -c "$dir" "$pane_creation_command"
|
||||||
|
else
|
||||||
|
tmux new-window -d -t "${session_name}:${window_number}" -n "$window_name" -c "$dir"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
new_session() {
|
||||||
|
local session_name="$1"
|
||||||
|
local window_number="$2"
|
||||||
|
local window_name="$3"
|
||||||
|
local dir="$4"
|
||||||
|
local pane_index="$5"
|
||||||
|
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" -n "$window_name" -c "$dir" "$pane_creation_command"
|
||||||
|
else
|
||||||
|
TMUX="" tmux -S "$(tmux_socket)" new-session -d -s "$session_name" -n "$window_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 window_name="$3"
|
||||||
|
local dir="$4"
|
||||||
|
local pane_index="$5"
|
||||||
|
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_name window_active window_flags pane_index dir pane_active pane_command pane_full_command; do
|
||||||
|
dir="$(remove_first_char "$dir")"
|
||||||
|
window_name="$(remove_first_char "$window_name")"
|
||||||
|
pane_full_command="$(remove_first_char "$pane_full_command")"
|
||||||
|
if pane_exists "$session_name" "$window_number" "$pane_index"; then
|
||||||
|
tmux rename-window -t "$window_number" "$window_name"
|
||||||
|
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" "$window_name" "$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
|
||||||
|
tmux rename-window -t "$window_number" "$window_name"
|
||||||
|
new_pane "$session_name" "$window_number" "$window_name" "$dir" "$pane_index"
|
||||||
|
elif session_exists "$session_name"; then
|
||||||
|
new_window "$session_name" "$window_number" "$window_name" "$dir" "$pane_index"
|
||||||
|
else
|
||||||
|
new_session "$session_name" "$window_number" "$window_name" "$dir" "$pane_index"
|
||||||
|
fi
|
||||||
|
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)
|
||||||
|
if is_restoring_pane_contents; then
|
||||||
|
rm "$(pane_contents_dir "restore")"/*
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
restore_pane_layout_for_each_window() {
|
||||||
|
\grep '^window' $(last_resurrect_file) |
|
||||||
|
while IFS=$d read line_type session_name window_number window_active window_flags window_layout; do
|
||||||
|
tmux select-layout -t "${session_name}:${window_number}" "$window_layout"
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
restore_shell_history() {
|
||||||
|
awk 'BEGIN { FS="\t"; OFS="\t" } /^pane/ { print $2, $3, $7, $10; }' $(last_resurrect_file) |
|
||||||
|
while IFS=$d read session_name window_number pane_index pane_command; do
|
||||||
|
if ! is_pane_registered_as_existing "$session_name" "$window_number" "$pane_index"; then
|
||||||
|
local pane_id="$session_name:$window_number.$pane_index"
|
||||||
|
local history_file="$(resurrect_history_file "$pane_id" "$pane_command")"
|
||||||
|
|
||||||
|
if [ "$pane_command" = "bash" ]; then
|
||||||
|
local read_command="history -r '$history_file'"
|
||||||
|
tmux send-keys -t "$pane_id" "$read_command" C-m
|
||||||
|
elif [ "$pane_command" = "zsh" ]; then
|
||||||
|
local accept_line="$(expr "$(zsh -i -c bindkey | grep -m1 '\saccept-line$')" : '^"\(.*\)".*')"
|
||||||
|
local read_command="fc -R '$history_file'; clear"
|
||||||
|
tmux send-keys -t "$pane_id" "$read_command" "$accept_line"
|
||||||
|
fi
|
||||||
|
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, $7, $8, $11; }' $(last_resurrect_file) |
|
||||||
|
while IFS=$d read 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, $7; }' $(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/ && $6 ~ /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/ && $5 ~ /[*-]/ { print $2, $4, $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)
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
restore_pane_layout_for_each_window >/dev/null 2>&1
|
||||||
|
execute_hook "pre-restore-history"
|
||||||
|
if save_shell_history_option_on; then
|
||||||
|
restore_shell_history
|
||||||
|
fi
|
||||||
|
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
|
||||||
|
execute_hook "post-restore-all"
|
||||||
|
stop_spinner
|
||||||
|
display_message "Tmux restore complete!"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
main
|
322
tmux/plugins/tmux-ressurect/scripts/save.sh
Executable file
322
tmux/plugins/tmux-ressurect/scripts/save.sh
Executable file
@ -0,0 +1,322 @@
|
|||||||
|
#!/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_name}"
|
||||||
|
format+="${delimiter}"
|
||||||
|
format+="#{window_active}"
|
||||||
|
format+="${delimiter}"
|
||||||
|
format+=":#{window_flags}"
|
||||||
|
format+="${delimiter}"
|
||||||
|
format+="#{pane_index}"
|
||||||
|
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_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
|
||||||
|
}
|
||||||
|
|
||||||
|
save_shell_history() {
|
||||||
|
if [ "$pane_command" = "bash" ]; then
|
||||||
|
local history_w='history -w'
|
||||||
|
local history_r='history -r'
|
||||||
|
local accept_line='C-m'
|
||||||
|
local end_of_line='C-e'
|
||||||
|
local backward_kill_line='C-u'
|
||||||
|
elif [ "$pane_command" = "zsh" ]; then
|
||||||
|
# fc -W does not work with -L
|
||||||
|
# fc -l format is different from what's written by fc -W
|
||||||
|
# fc -R either reads the format produced by fc -W or considers
|
||||||
|
# the entire line to be a command. That's why we need -n.
|
||||||
|
# fc -l only list the last 16 items by default, I think 64 is more reasonable.
|
||||||
|
local history_w='fc -lLn -64 >'
|
||||||
|
local history_r='fc -R'
|
||||||
|
|
||||||
|
local zsh_bindkey="$(zsh -i -c bindkey)"
|
||||||
|
local accept_line="$(expr "$(echo "$zsh_bindkey" | grep -m1 '\saccept-line$')" : '^"\(.*\)".*')"
|
||||||
|
local end_of_line="$(expr "$(echo "$zsh_bindkey" | grep -m1 '\send-of-line$')" : '^"\(.*\)".*')"
|
||||||
|
local backward_kill_line="$(expr "$(echo "$zsh_bindkey" | grep -m1 '\sbackward-kill-line$')" : '^"\(.*\)".*')"
|
||||||
|
else
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
local pane_id="$1"
|
||||||
|
local pane_command="$2"
|
||||||
|
local full_command="$3"
|
||||||
|
if [ "$full_command" = ":" ]; then
|
||||||
|
# leading space prevents the command from being saved to history
|
||||||
|
# (assuming default HISTCONTROL settings)
|
||||||
|
local write_command=" $history_w '$(resurrect_history_file "$pane_id" "$pane_command")'"
|
||||||
|
local read_command=" $history_r '$(resurrect_history_file "$pane_id" "$pane_command")'"
|
||||||
|
# C-e C-u is a Bash shortcut sequence to clear whole line. It is necessary to
|
||||||
|
# delete any pending input so it does not interfere with our history command.
|
||||||
|
tmux send-keys -t "$pane_id" "$end_of_line" "$backward_kill_line" "$write_command" "$accept_line"
|
||||||
|
# Immediately restore after saving
|
||||||
|
tmux send-keys -t "$pane_id" "$end_of_line" "$backward_kill_line" "$read_command" "$accept_line"
|
||||||
|
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_name window_active window_flags pane_index 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_name}${d}${window_active}${d}${window_flags}${d}${pane_index}${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_active window_flags window_layout; do
|
||||||
|
# not saving windows from grouped sessions
|
||||||
|
if is_session_grouped "$session_name"; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
echo "${line_type}${d}${session_name}${d}${window_index}${d}${window_active}${d}${window_flags}${d}${window_layout}"
|
||||||
|
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_name window_active window_flags pane_index 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
|
||||||
|
}
|
||||||
|
|
||||||
|
dump_shell_history() {
|
||||||
|
dump_panes |
|
||||||
|
while IFS=$d read line_type session_name window_number window_name window_active window_flags pane_index dir pane_active pane_command full_command; do
|
||||||
|
save_shell_history "$session_name:$window_number.$pane_index" "$pane_command" "$full_command"
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
remove_old_backups() {
|
||||||
|
# remove resurrect files older than 30 days, but keep at least 5 copies of backup.
|
||||||
|
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 +30 -exec rm -v "{}" \;
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
if save_shell_history_option_on; then
|
||||||
|
dump_shell_history
|
||||||
|
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
|
8
tmux/plugins/tmux-ressurect/scripts/spinner_helpers.sh
Normal file
8
tmux/plugins/tmux-ressurect/scripts/spinner_helpers.sh
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
start_spinner() {
|
||||||
|
$CURRENT_DIR/tmux_spinner.sh "$1" "$2" &
|
||||||
|
export SPINNER_PID=$!
|
||||||
|
}
|
||||||
|
|
||||||
|
stop_spinner() {
|
||||||
|
kill $SPINNER_PID
|
||||||
|
}
|
29
tmux/plugins/tmux-ressurect/scripts/tmux_spinner.sh
Executable file
29
tmux/plugins/tmux-ressurect/scripts/tmux_spinner.sh
Executable file
@ -0,0 +1,29 @@
|
|||||||
|
#!/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
|
47
tmux/plugins/tmux-ressurect/scripts/variables.sh
Normal file
47
tmux/plugins/tmux-ressurect/scripts/variables.sh
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
# 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 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="->"
|
||||||
|
|
||||||
|
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"
|
||||||
|
|
||||||
|
bash_history_option="@resurrect-save-bash-history" # deprecated
|
||||||
|
shell_history_option="@resurrect-save-shell-history"
|
||||||
|
|
||||||
|
# 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-"
|
23
tmux/plugins/tmux-ressurect/strategies/irb_default_strategy.sh
Executable file
23
tmux/plugins/tmux-ressurect/strategies/irb_default_strategy.sh
Executable file
@ -0,0 +1,23 @@
|
|||||||
|
#!/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
|
25
tmux/plugins/tmux-ressurect/strategies/mosh-client_default_strategy.sh
Executable file
25
tmux/plugins/tmux-ressurect/strategies/mosh-client_default_strategy.sh
Executable file
@ -0,0 +1,25 @@
|
|||||||
|
#!/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
|
30
tmux/plugins/tmux-ressurect/strategies/nvim_session.sh
Executable file
30
tmux/plugins/tmux-ressurect/strategies/nvim_session.sh
Executable file
@ -0,0 +1,30 @@
|
|||||||
|
#!/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
|
32
tmux/plugins/tmux-ressurect/strategies/vim_session.sh
Executable file
32
tmux/plugins/tmux-ressurect/strategies/vim_session.sh
Executable file
@ -0,0 +1,32 @@
|
|||||||
|
#!/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" ]
|
||||||
|
}
|
||||||
|
|
||||||
|
original_command_contains_session_flag() {
|
||||||
|
[[ "$ORIGINAL_COMMAND" =~ "-S" ]]
|
||||||
|
}
|
||||||
|
|
||||||
|
main() {
|
||||||
|
if vim_session_file_exists; then
|
||||||
|
echo "vim -S"
|
||||||
|
elif original_command_contains_session_flag; then
|
||||||
|
# Session file does not exist, yet the original vim command contains
|
||||||
|
# session flag `-S`. This will cause an error, so we're falling back to
|
||||||
|
# starting plain vim.
|
||||||
|
echo "vim"
|
||||||
|
else
|
||||||
|
echo "$ORIGINAL_COMMAND"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
main
|
19
tmux/plugins/tmux-sidebar/LICENSE.md
Normal file
19
tmux/plugins/tmux-sidebar/LICENSE.md
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
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.
|
74
tmux/plugins/tmux-sidebar/README.md
Normal file
74
tmux/plugins/tmux-sidebar/README.md
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
# Tmux Sidebar
|
||||||
|
|
||||||
|
`tmux-sidebar` does one thing: it opens a tree directory listing for the current
|
||||||
|
path. It's fast, convenient and works great with vim.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
Some of the features that make the plugin more appealing than doing the same
|
||||||
|
thing manually each time:
|
||||||
|
|
||||||
|
- **fast**<br/>
|
||||||
|
Much faster than doing each step manually.
|
||||||
|
- **smart sizing**<br/>
|
||||||
|
Sidebar remembers its size, so the next time you open it, it will have the
|
||||||
|
**exact same** width. This is a per-directory property, so you can have just
|
||||||
|
the right size for multiple dirs.
|
||||||
|
- **toggling**<br/>
|
||||||
|
The same key binding opens and closes the sidebar.
|
||||||
|
- **uninterrupted workflow**<br/>
|
||||||
|
The main `prefix + Tab` key binding opens a sidebar but **does not** move
|
||||||
|
cursor to it.
|
||||||
|
- **pane layout stays the same**<br/>
|
||||||
|
No matter which pane layout you prefer, sidebar tries hard not to mess your
|
||||||
|
pane splits. Open, then close the sidebar and everything should look the same.
|
||||||
|
|
||||||
|
Requirements: `tmux 1.9` or higher, `tree` recommended but not required
|
||||||
|
|
||||||
|
Tested and working on Linux, OSX and Cygwin.
|
||||||
|
|
||||||
|
### Key bindings
|
||||||
|
|
||||||
|
- `prefix + Tab` - toggle sidebar with a directory tree
|
||||||
|
- `prefix + Backspace` - toggle sidebar and move cursor to it (focus it)
|
||||||
|
|
||||||
|
### 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-sidebar'
|
||||||
|
|
||||||
|
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-sidebar ~/clone/path
|
||||||
|
|
||||||
|
Add this line to the bottom of `.tmux.conf`:
|
||||||
|
|
||||||
|
run-shell ~/clone/path/sidebar.tmux
|
||||||
|
|
||||||
|
Reload TMUX environment:
|
||||||
|
|
||||||
|
# type this in terminal
|
||||||
|
$ tmux source-file ~/.tmux.conf
|
||||||
|
|
||||||
|
You should now be able to use the plugin.
|
||||||
|
|
||||||
|
### Docs
|
||||||
|
|
||||||
|
- [customization options](docs/options.md)
|
||||||
|
|
||||||
|
### Other goodies
|
||||||
|
|
||||||
|
- [tmux-copycat](https://github.com/tmux-plugins/tmux-copycat) - a plugin for
|
||||||
|
regex searches in tmux and fast match selection
|
||||||
|
- [tmux-resurrect](https://github.com/tmux-plugins/tmux-resurrect) - restore
|
||||||
|
tmux environment after a system restart
|
||||||
|
|
||||||
|
### License
|
||||||
|
|
||||||
|
[MIT](LICENSE.md)
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user