rwx/sh/tmux.sh

555 lines
14 KiB
Bash
Raw Normal View History

2025-06-28 04:36:16 +02:00
# ╭──────╮
# │ tmux │
# ╰──────╯
2025-07-25 23:02:35 +02:00
# ╭──────┬───────────┬────────╮
# │ tmux │ constants │ values │
# ╰──────┴───────────┴────────╯
2025-07-25 22:05:55 +02:00
2025-07-25 21:42:21 +02:00
RWX_TMUX_MAIN_BACKGROUND="#080808"
2025-07-25 22:05:55 +02:00
RWX_TMUX_MAIN_FOREGROUND="white"
2025-07-25 21:52:05 +02:00
RWX_TMUX_MESSAGE_BACKGROUND="red"
RWX_TMUX_MESSAGE_FOREGROUND="white"
2025-07-25 22:05:55 +02:00
2025-07-26 10:39:11 +02:00
RWX_TMUX_TITLE_PATH=" - "
RWX_TMUX_TITLE_SIZE=" × "
RWX_TMUX_TITLE_SPLIT=" | "
2025-07-25 23:02:35 +02:00
# ╭──────┬───────────┬──────────╮
# │ tmux │ constants │ commands │
# ╰──────┴───────────┴──────────╯
RWX_TMUX_BORDER_BACKGROUND="#[bg=##181818]"
RWX_TMUX_ITEM_BACKGROUND="#[bg=##282828]"
RWX_TMUX_ITEM_FOREGROUND="#[fg=yellow]"
2025-07-25 22:56:16 +02:00
RWX_TMUX_PATH_FOREGROUND="#[fg=cyan]"
2025-07-25 21:49:06 +02:00
RWX_TMUX_PREFIX_CHARACTER="p"
2025-07-25 23:02:35 +02:00
RWX_TMUX_PREFIX_FOREGROUND="#[fg=red]"
2025-07-25 21:32:51 +02:00
2025-07-26 00:02:02 +02:00
RWX_TMUX_RESET="\
#[bg=default]\
#[fg=default]\
"
2025-07-25 23:17:49 +02:00
2025-07-25 22:42:31 +02:00
RWX_TMUX_SESSION_MANY="#[fg=red]"
RWX_TMUX_SESSION_ONE="#[fg=green]"
2025-07-25 21:32:51 +02:00
# ╭──────┬───────────╮
# │ tmux │ functions │
# ╰──────┴───────────╯
2025-07-06 07:32:55 +02:00
# attach
#= tma
rwx_tmux_attach() {
local server="${1}"
2025-07-06 15:59:31 +02:00
if [ -n "${server}" ]; then
2025-07-06 07:32:55 +02:00
tmux -L "${server}" attach-session
else
rwx_tmux_list
fi
}
2025-07-06 07:32:06 +02:00
# kill
#= tmk
rwx_tmux_kill() {
local server="${1}"
2025-07-06 15:59:31 +02:00
if [ -n "${server}" ]; then
2025-07-06 07:32:06 +02:00
tmux -L "${server}" kill-server 2>"/dev/null"
else
rwx_tmux_list
fi
}
2025-07-06 07:30:42 +02:00
# list
#= tml
rwx_tmux_list() {
2025-07-06 16:09:46 +02:00
local user_id
user_id="$(id --user)"
ls "/tmp/tmux-${user_id}"
2025-07-06 07:30:42 +02:00
}
2025-07-25 22:29:57 +02:00
# ╭──────┬──────╮
# │ tmux │ help │
# ╰──────┴──────╯
# display key bindings
2025-07-25 22:33:01 +02:00
#= tmh
2025-07-25 22:29:57 +02:00
rwx_tmux_help() {
# TODO pad constants
rwx_log "\
╭─────────────────────┬─────────────╮
│ rwx │ tmux │
├───────────┬─────────┼─────┬───────┤
│ -n │ F12 │ -n │ C-b │
╭───────────────────┼───────────┼─────────┼─────┼───────┤
│ command-prompt │ │ │ │ : │
│ copy-mode │ │ │ │ PPage │
│ detach-client │ F6 │ │ │ d │
│ kill-server │ │ k │ │ │
2025-07-26 00:17:12 +02:00
│ kill-session │ S-M-Up │ │ │ │
│ kill-window │ S-M-Left │ │ │ │
2025-07-25 22:29:57 +02:00
│ new-session │ S-M-Down │ │ │ │
│ new-window │ S-M-Right │ │ │ c │
│ next-window │ M-Right │ │ │ n │
│ previous-window │ M-Left │ │ │ p │
│ rename-session │ │ C-s │ │ │
│ rename-window │ │ C-w │ │ │
│ resize-pane -Z │ │ │ │ z │
select-layout -n │ M-Home │ │ │ │
select-layout -p │ M-End │ │ │ │
select-pane -D │ C-S-Down │ │ │ │
select-pane -L │ C-S-Left │ │ │ │
select-pane -R │ C-S-Right │ │ │ │
select-pane -U │ C-S-Up │ │ │ │
set -g mouse │ │ M │ │ │
set -g status off │ C-F6 │ │ │ │
set -g status on │ C-F1 │ │ │ │
set -g status 2 │ C-F2 │ │ │ │
set -g status 3 │ C-F3 │ │ │ │
set -g status 4 │ C-F4 │ │ │ │
set -g status 5 │ C-F5 │ │ │ │
│ source-file │ │ r │ │ │
│ split-window -h │ │ h │ │ % │
│ split-window -v │ │ v │ │ \"
│ swap-window -t -1 │ │ M-Left │ │ │
│ swap-window -t +1 │ │ M-Right │ │ │
│ switch-client -n │ M-Down │ │ │ │
│ switch-client -p │ M-Up │ │ │ │
│ synchronize-panes │ │ S │ │ │
╰───────────────────┴───────────┴─────────┴─────┴───────╯
"
}
2025-07-25 23:17:49 +02:00
# ╭──────┬──────╮
# │ tmux │ item │
# ╰──────┴──────╯
2025-07-26 01:01:53 +02:00
rwx_tmux_item_date() {
printf "%s" "\
${RWX_TMUX_ITEM_FOREGROUND}\
${RWX_TMUX_BORDER_BACKGROUND} \
${RWX_TMUX_ITEM_BACKGROUND}%Y-%m-%d\
${RWX_TMUX_BORDER_BACKGROUND} \
"
}
2025-07-26 01:34:15 +02:00
rwx_tmux_item_host() {
printf "%s" "\
${RWX_TMUX_ITEM_FOREGROUND}\
${RWX_TMUX_BORDER_BACKGROUND} \
${RWX_TMUX_ITEM_BACKGROUND}#{host}\
${RWX_TMUX_BORDER_BACKGROUND} \
"
}
2025-07-26 01:56:14 +02:00
rwx_tmux_item_script() {
local script="${1}"
local name="${2}"
echo "#(sh -c \". ${script}; rwx_tmux_${name}\")"
}
2025-07-26 01:25:52 +02:00
rwx_tmux_item_session() {
printf "%s" "\
#{?session_many_attached,${RWX_TMUX_SESSION_MANY},\
#{?session_attached,${RWX_TMUX_SESSION_ONE},${RWX_TMUX_ITEM_FOREGROUND}}}\
${RWX_TMUX_BORDER_BACKGROUND} \
${RWX_TMUX_ITEM_BACKGROUND}#{session_name}\
${RWX_TMUX_BORDER_BACKGROUND} \
"
}
2025-07-26 01:05:24 +02:00
rwx_tmux_item_time() {
printf "%s" "\
${RWX_TMUX_ITEM_FOREGROUND}\
${RWX_TMUX_BORDER_BACKGROUND} \
${RWX_TMUX_ITEM_BACKGROUND}%H:%M:%S\
${RWX_TMUX_BORDER_BACKGROUND}#{?client_prefix,\
${RWX_TMUX_PREFIX_FOREGROUND}${RWX_TMUX_PREFIX_CHARACTER}, }\
"
}
2025-07-26 10:39:11 +02:00
rwx_tmux_item_title() {
printf "%s" "\
${server}\
${RWX_TMUX_TITLE_PATH}\
#{session_name}\
${RWX_TMUX_TITLE_PATH}\
#{window_name}\
${RWX_TMUX_TITLE_PATH}\
#{pane_index}: #{pane_current_command}\
${RWX_TMUX_TITLE_SPLIT}\
#{window_width}${RWX_TMUX_TITLE_SIZE}#{window_height}\
${RWX_TMUX_TITLE_PATH}\
#{pane_index}: #{pane_width}${RWX_TMUX_TITLE_SIZE}#{pane_height}\
"
}
2025-07-26 01:30:49 +02:00
rwx_tmux_item_user() {
# TODO constants
printf "%s" "\
#{?uid,#[fg=green],#[fg=red]}\
${RWX_TMUX_BORDER_BACKGROUND} \
${RWX_TMUX_ITEM_BACKGROUND}#{user}\
${RWX_TMUX_BORDER_BACKGROUND} \
"
}
2025-07-26 01:01:53 +02:00
rwx_tmux_item_window() {
printf "%s" "\
${RWX_TMUX_BORDER_BACKGROUND}#{?window_zoomed_flag,\
#{?pane_synchronized,#[fg=magenta][,#[fg=red][},\
#{?pane_synchronized,#[fg=blue][, }}\
\
#{?window_active,#[fg=green],\
#{?window_activity_flag,#[fg=red],${RWX_TMUX_ITEM_FOREGROUND}}}\
${RWX_TMUX_ITEM_BACKGROUND}#{window_name}\
\
${RWX_TMUX_BORDER_BACKGROUND}#{?window_zoomed_flag,\
#{?pane_synchronized,#[fg=magenta]],#[fg=red]]},\
#{?pane_synchronized,#[fg=blue]], }}\
"
}
2025-07-25 23:17:49 +02:00
# ╭──────┬───────╮
# │ tmux │ setup │
# ╰──────┴───────╯
2025-07-25 23:17:49 +02:00
#= tms
2025-07-25 23:18:49 +02:00
#/ tmux_setup
rwx_tmux_setup() {
2025-06-30 00:28:33 +02:00
local file script
2025-07-02 15:18:47 +02:00
if rwx_root; then
file="/etc/tmux.conf"
script="/etc/tmux.sh"
else
file="${HOME}/.tmux.conf"
script="${HOME}/.tmux.sh"
fi
2025-07-25 23:51:13 +02:00
# FIXME skip parsing these functions
2025-06-30 00:28:33 +02:00
rwx_file_write "${script}" "\
2025-07-25 23:51:13 +02:00
# ╭─────┬──────┬────────╮
# │ rwx │ tmux │ script │
# ╰─────┴──────┴────────╯
# return current server socket name
2025-06-30 00:28:33 +02:00
rwx_tmux_server() {
basename \"\${TMUX}\" |
cut \\
--delimiter \",\" \\
--fields \"1\"
}
2025-07-25 23:51:13 +02:00
# return active & current servers socket names
2025-06-30 01:08:26 +02:00
rwx_tmux_servers() {
2025-07-25 23:57:07 +02:00
local active name root sockets text
2025-07-22 20:53:49 +02:00
active=\"\$(rwx_tmux_server)\"
2025-07-25 23:57:07 +02:00
root=\"\$(dirname \"\${TMUX}\")\"
2025-07-22 20:53:49 +02:00
sockets=\"\$(find \"\${root}\" -type s -printf \"%P\\n\")\"
while IFS= read -r name; do
2025-07-25 16:08:05 +02:00
if tmux -L \"\${name}\" list-sessions >/dev/null; then
2025-07-22 20:53:49 +02:00
text=\"\${text}\\
2025-07-25 23:17:49 +02:00
${RWX_TMUX_RESET} \\
2025-06-30 03:40:04 +02:00
\"
2025-07-22 20:53:49 +02:00
if [ \"\${name}\" = \"\${active}\" ]; then
text=\"\${text}#[fg=green]\"
else
2025-07-25 22:14:22 +02:00
text=\"\${text}${RWX_TMUX_ITEM_FOREGROUND}\"
2025-07-22 20:53:49 +02:00
fi
text=\"\${text}\\
2025-07-25 21:41:13 +02:00
${RWX_TMUX_BORDER_BACKGROUND} \\
2025-07-25 21:32:51 +02:00
${RWX_TMUX_ITEM_BACKGROUND}\${name}\\
2025-07-25 21:41:13 +02:00
${RWX_TMUX_BORDER_BACKGROUND} \\
2025-06-30 03:40:04 +02:00
\"
2025-07-22 20:53:49 +02:00
fi
2025-07-04 07:50:19 +02:00
done <<EOF
2025-07-22 20:53:49 +02:00
\${sockets}
2025-07-04 07:50:19 +02:00
EOF
2025-06-30 02:10:17 +02:00
echo \"\${text}\"
2025-06-30 01:08:26 +02:00
}
2025-07-25 23:51:13 +02:00
# set status lines option
# off, on, 2, 3, 4, 5
2025-07-02 01:07:24 +02:00
rwx_tmux_status() {
local current=\"\${1}\"
local operand=\"\${2}\"
case \"\${operand}\" in
\"+\")
case \"\${current}\" in
\"off\") current=\"on\" ;;
\"on\") current=\"2\" ;;
\"2\") current=\"3\" ;;
\"3\") current=\"4\" ;;
\"4\") current=\"5\" ;;
2025-07-26 11:02:41 +02:00
\"5\") current=\"off\" ;;
2025-07-02 01:07:24 +02:00
*) ;;
esac
;;
\"-\")
case \"\${current}\" in
2025-07-26 11:02:41 +02:00
\"off\") current=\"5\" ;;
2025-07-02 01:07:24 +02:00
\"on\") current=\"off\" ;;
\"2\") current=\"on\" ;;
\"3\") current=\"2\" ;;
\"4\") current=\"3\" ;;
\"5\") current=\"4\" ;;
*) ;;
esac
;;
*) ;;
esac
2025-07-02 03:25:56 +02:00
tmux set-option -g status \"\${current}\"
2025-07-02 01:07:24 +02:00
}
2025-07-25 23:51:13 +02:00
# render uptime date & time
2025-06-30 03:52:26 +02:00
rwx_tmux_uptime() {
local since=\"\$(uptime --since)\"
local date=\"\$(echo \"\${since}\" | awk '{print \$1}')\"
local time=\"\$(echo \"\${since}\" | awk '{print \$2}')\"
echo \"\\
2025-07-25 22:14:22 +02:00
${RWX_TMUX_ITEM_FOREGROUND}\\
2025-07-25 21:41:13 +02:00
${RWX_TMUX_BORDER_BACKGROUND} \\
2025-07-25 21:32:51 +02:00
${RWX_TMUX_ITEM_BACKGROUND}\${date}\\
2025-07-25 21:41:13 +02:00
${RWX_TMUX_BORDER_BACKGROUND} \\
2025-07-25 23:17:49 +02:00
${RWX_TMUX_RESET} \\
2025-07-25 22:14:22 +02:00
${RWX_TMUX_ITEM_FOREGROUND}\\
2025-07-25 21:41:13 +02:00
${RWX_TMUX_BORDER_BACKGROUND} \\
2025-07-25 21:32:51 +02:00
${RWX_TMUX_ITEM_BACKGROUND}\${time}\\
2025-07-25 21:41:13 +02:00
${RWX_TMUX_BORDER_BACKGROUND} \\
2025-06-30 03:52:26 +02:00
\"
}
2025-06-30 00:28:33 +02:00
"
2025-07-26 10:39:11 +02:00
local date host session space time user window
local server servers title uptime
2025-07-26 01:01:53 +02:00
date="$(rwx_tmux_item_date)"
2025-07-26 01:34:15 +02:00
host="$(rwx_tmux_item_host)"
2025-07-26 01:56:14 +02:00
server="$(rwx_tmux_item_script "${script}" server)"
servers="$(rwx_tmux_item_script "${script}" servers)"
2025-07-26 01:25:52 +02:00
session="$(rwx_tmux_item_session)"
2025-07-26 01:43:50 +02:00
space="${RWX_TMUX_RESET} "
2025-07-26 01:05:24 +02:00
time="$(rwx_tmux_item_time)"
2025-07-26 10:39:11 +02:00
title="$(rwx_tmux_item_title)"
2025-07-26 01:56:14 +02:00
uptime="$(rwx_tmux_item_script "${script}" uptime)"
2025-07-26 01:30:49 +02:00
user="$(rwx_tmux_item_user)"
2025-07-26 01:01:53 +02:00
window="$(rwx_tmux_item_window)"
rwx_file_write "${file}" "\
# ╭────────╮
# │ option │
# ╰────────╯
# empty name for windows
set-option -g automatic-rename on
2025-07-20 18:25:44 +02:00
set-option -g automatic-rename-format '#{pane_current_command}'
# first index number
set-option -g base-index 1
# display duration
set-option -g display-time 1536
# extend history limit
set-option -g history-limit 1048576
# style for messages
2025-07-25 21:52:05 +02:00
set-option -g message-style '\
bg=${RWX_TMUX_MESSAGE_BACKGROUND},fg=${RWX_TMUX_MESSAGE_FOREGROUND}'
# activity monitoring
set-window-option -g monitor-activity on
# silence monitoring
set-window-option -g monitor-silence 0
# enable mouse actions
set-option -g mouse on
# prefix with ^B or F12
set-option -g prefix C-b
set-option -g prefix2 F12
# renumber windows after closing one
set-option -g renumber-windows on
# enable title
set-option -g set-titles on
# set title to working directory
2025-07-26 10:39:11 +02:00
set-option -g set-titles-string '${title}'
# ╭────────┬──────╮
# │ option │ pane │
# ╰────────┴──────╯
# first index number
set-option -g pane-base-index 1
# ╭────────┬──────┬────────╮
# │ option │ pane │ border │
# ╰────────┴──────┴────────╯
# active style
set-option -g pane-active-border-style fg=green
# regular style
set-option -g pane-border-style fg=blue
# ╭────────┬────────╮
# │ option │ status │
# ╰────────┴────────╯
# status lines
2025-06-29 10:19:01 +02:00
set-option -g status 2
# background color
2025-07-25 21:42:21 +02:00
set-option -g status-bg '${RWX_TMUX_MAIN_BACKGROUND}'
# foreground color
2025-07-25 22:05:55 +02:00
set-option -g status-fg '${RWX_TMUX_MAIN_FOREGROUND}'
# line 1
set-option -g status-format[0] '\
#{W:\
2025-07-26 01:05:24 +02:00
${window}\
2025-07-26 01:43:50 +02:00
${space}\
}\
${space}\
2025-06-30 05:27:22 +02:00
\
#[align=right]\
2025-07-26 01:43:50 +02:00
\
2025-07-26 01:05:24 +02:00
${date}\
2025-07-26 01:43:50 +02:00
${space}\
2025-07-26 01:05:24 +02:00
${time}\
'
# line 2
set-option -g status-format[1] '\
#{S:\
2025-07-26 01:25:52 +02:00
${session}\
2025-07-26 01:43:50 +02:00
${space}\
}\
${space}\
2025-06-30 05:27:22 +02:00
\
#[align=right]\
2025-07-26 01:43:50 +02:00
\
2025-07-26 01:56:14 +02:00
${servers}\
'
# line 3
set-option -g status-format[2] '\
2025-07-25 22:56:16 +02:00
${RWX_TMUX_PATH_FOREGROUND}#{pane_current_path}\
'
# line 4
set-option -g status-format[3] '\
#{P:\
2025-07-25 22:14:22 +02:00
#{?pane_active,#[fg=green],${RWX_TMUX_ITEM_FOREGROUND}}\
2025-07-25 21:41:13 +02:00
${RWX_TMUX_BORDER_BACKGROUND} \
2025-07-25 21:32:51 +02:00
${RWX_TMUX_ITEM_BACKGROUND}#{pane_current_command}\
2025-07-25 21:41:13 +02:00
${RWX_TMUX_BORDER_BACKGROUND} \
2025-07-26 01:43:50 +02:00
${space}\
}\
${space}\
2025-06-30 05:27:22 +02:00
\
2025-06-30 05:42:42 +02:00
#[align=right]\
2025-07-26 01:43:50 +02:00
\
'
# line 5
set-option -g status-format[4] '\
2025-07-26 01:30:49 +02:00
${user}\
2025-07-26 01:43:50 +02:00
${space}\
2025-07-26 01:34:15 +02:00
${host}\
2025-07-26 01:43:50 +02:00
${space}\
2025-07-02 05:17:29 +02:00
\
#[align=right]\
2025-07-26 01:43:50 +02:00
\
2025-07-26 01:56:14 +02:00
${uptime}\
'
# refresh period
set-option -g status-interval 1
# bar location
set-option -g status-position bottom
# ╭─────╮
# │ key │
# ╰─────╯
# detach client
bind-key -n F6 detach-client
2025-07-26 00:17:12 +02:00
# kill
bind-key -n S-M-Up kill-session
bind-key -n S-M-Left kill-window
2025-06-16 15:25:26 +02:00
# new
bind-key -n S-M-Down new-session
bind-key -n S-M-Right new-window
2025-07-19 18:53:25 +02:00
# like byobu
bind-key -n F2 new-window
2025-07-20 00:00:09 +02:00
# select layout
bind-key -n M-Home select-layout -n
bind-key -n M-End select-layout -p
# select pane
bind-key -n C-S-Down select-pane -D
bind-key -n C-S-Left select-pane -L
bind-key -n C-S-Right select-pane -R
bind-key -n C-S-Up select-pane -U
# status lines
2025-06-16 14:33:48 +02:00
bind-key -n C-F6 set-option -g status off
bind-key -n C-F1 set-option -g status on
bind-key -n C-F2 set-option -g status 2
bind-key -n C-F3 set-option -g status 3
bind-key -n C-F4 set-option -g status 4
bind-key -n C-F5 set-option -g status 5
2025-07-02 01:07:24 +02:00
bind-key -n M-NPage run-shell '. ${script}; rwx_tmux_status #{status} -'
bind-key -n M-PPage run-shell '. ${script}; rwx_tmux_status #{status} +'
# switch session
bind-key -n M-Down switch-client -n
bind-key -n M-Up switch-client -p
# switch window
bind-key -n M-Left previous-window
bind-key -n M-Right next-window
# ╭─────┬────────╮
# │ key │ prefix │
# ╰─────┴────────╯
# rename
bind-key C-s command-prompt { rename-session '%%' }
bind-key C-w command-prompt { rename-window '%%' }
# split window
2025-06-30 11:40:58 +02:00
bind-key h split-window -c '#{pane_current_path}' -h
bind-key v split-window -c '#{pane_current_path}' -v
2025-06-29 10:11:44 +02:00
# kill server
bind-key k kill-server
# reload configuration
2025-07-19 18:36:06 +02:00
bind-key r source-file ${file} \
\\; display-message 'source-file ${file}'
2025-06-29 10:11:44 +02:00
# toggle mouse
2025-07-19 18:36:06 +02:00
bind-key M set-option -g mouse \
\\; display-message 'mouse = #{mouse}'
2025-06-29 10:11:44 +02:00
# swap window
bind-key M-Left swap-window -t -1
bind-key M-Right swap-window -t +1
2025-07-19 18:36:06 +02:00
# synchronize panes
bind-key S set-window-option synchronize-panes \
\\; display-message 'sync = #{synchronize-panes}'
"
}