diff options
Diffstat (limited to 'linux/home/.config/tmux')
| -rwxr-xr-x | linux/home/.config/tmux/file_manager.sh | 108 | ||||
| -rwxr-xr-x | linux/home/.config/tmux/fzf-menu.sh | 60 | ||||
| -rwxr-xr-x | linux/home/.config/tmux/left-status.sh | 25 | ||||
| -rwxr-xr-x | linux/home/.config/tmux/notes.sh | 113 | ||||
| -rwxr-xr-x | linux/home/.config/tmux/right-status.sh | 27 | ||||
| -rwxr-xr-x | linux/home/.config/tmux/tmux-popup-pane-manager.sh | 152 | ||||
| -rwxr-xr-x | linux/home/.config/tmux/tmux-toggle-option.sh | 27 | ||||
| -rw-r--r-- | linux/home/.config/tmux/tmux.conf | 835 | ||||
| -rwxr-xr-x | linux/home/.config/tmux/tmux_number.sh | 11 |
9 files changed, 1358 insertions, 0 deletions
diff --git a/linux/home/.config/tmux/file_manager.sh b/linux/home/.config/tmux/file_manager.sh new file mode 100755 index 0000000..b3a70a5 --- /dev/null +++ b/linux/home/.config/tmux/file_manager.sh @@ -0,0 +1,108 @@ +#!/usr/bin/env bash +# tmux file opener with fallback file manager (no preview) + +# Mark this pane as the file manager immediately +tmux select-pane -T "FILE_MANAGER" +# Also set the option as backup +tmux set-option -pq @file_manager 1 + +orig_pane="$1" +chooser_file="$HOME/.cache/tmux-fm-selected" +rm -f "$chooser_file" + +# Function: pick available file manager +pick_fm() { + if command -v lf >/dev/null 2>&1; then + echo "lf" + elif command -v nnn >/dev/null 2>&1; then + echo "nnn" + elif command -v ranger >/dev/null 2>&1; then + echo "ranger" + else + echo "" + fi +} + +fm=$(pick_fm) +if [[ -z "$fm" ]]; then + echo "No file manager found (lf, nnn, ranger)." >&2 + cleanup + exit 1 +fi + +# Cleanup function to reset both title and option +cleanup() { + tmux select-pane -T "" + tmux set-option -puq @file_manager + rm -f "$chooser_file" +} + +# Set trap to cleanup on exit (including when user presses 'q') +trap cleanup EXIT INT TERM + +# Launch the chosen file manager with no preview where possible +case "$fm" in + nnn) + # Disable preview completely and use picker mode + # -A: disable dir auto-select, -e: open text files in editor + # -o: open files with opener, -x: show only selection + NNN_OPENER="tee \"$chooser_file\"" nnn -Axo + ;; + lf) + # Disable preview and set selection path + lf -command 'set preview false' -selection-path="$chooser_file" + ;; + ranger) + # Disable all previews + ranger --choosefile="$chooser_file" \ + --cmd='set preview_files false' \ + --cmd='set preview_directories false' \ + --cmd='set preview_images false' + ;; +esac + +# Exit if no file chosen (user pressed 'q' or cancelled) +if [[ ! -s "$chooser_file" ]]; then + exit 0 +fi + +file="$(head -n 1 "$chooser_file")" +rm -f "$chooser_file" + +# Restrict to current window panes and exclude the file manager pane +current_window=$(tmux display-message -p '#I') +mapfile -t panes < <( + tmux list-panes -t "$current_window" -F '#S:#I.#P' | + grep -v "^$(tmux display-message -p '#S:#I').$(tmux display-message -p '#P')$" +) + +# Choose target pane +if [[ ${#panes[@]} -eq 0 ]]; then + exit 1 +elif [[ ${#panes[@]} -eq 1 ]]; then + target="${panes[0]}" +else + echo "Select target pane:" + for i in "${!panes[@]}"; do + letter=$(printf "\\$(printf '%03o' $((97 + i)))") # a, b, c... + echo "$letter) ${panes[$i]}" + done + read -n 1 -p "Choice: " choice + echo + idx=$(( $(printf "%d" "'$choice") - 97 )) + if [[ $idx -ge 0 && $idx -lt ${#panes[@]} ]]; then + target="${panes[$idx]}" + else + exit 1 + fi +fi + +# Decide if file is text or binary +if file --mime-type "$file" 2>/dev/null | grep -q 'text/'; then + opener="${EDITOR:-$(command -v nvim || command -v vim || echo 'vi')}" +else + opener="$(command -v xdg-open || command -v open || echo 'cat')" +fi + +# Send open command to target pane +tmux send-keys -t "$target" "$opener \"$file\"" C-m diff --git a/linux/home/.config/tmux/fzf-menu.sh b/linux/home/.config/tmux/fzf-menu.sh new file mode 100755 index 0000000..d7863d9 --- /dev/null +++ b/linux/home/.config/tmux/fzf-menu.sh @@ -0,0 +1,60 @@ +#!/bin/sh + +# fzf session name +FZF_SESSION_NAME="fzf" + +# Print error messages +error() { + echo "Error: $1" >&2 +} + +# Check if tmux is installed +if ! command -v tmux >/dev/null 2>&1; then + error "tmux is not installed." + exit 1 +fi + +# Function to handle file or directory opening +open_selected_item() { + # Use fzf to select a file from the specified directory + SELECTED_FILE=$(find ~ -type f | fzf --preview "bat --style=numbers --color=always --line-range=:500 {}" \ + --preview-window=up:60% --height=90% --layout=reverse --border=sharp --ansi) + + if [ "$SELECTED_FILE" != "" ]; then + # Ask whether to open the file or its directory + read -p "Open file (f) or directory (d)? " choice + case "$choice" in + f | F) + # Open the selected file in nvim + nvim "$SELECTED_FILE" + ;; + d | D) + # Change to the directory containing the selected file + cd "$(dirname "$SELECTED_FILE")" + ;; + *) + echo "Invalid choice. Please enter 'f' for file or 'd' for directory." + ;; + esac + else + echo "No file selected." + fi +} + +# Check if the fzf session exists +if tmux has-session -t "$FZF_SESSION_NAME" 2>/dev/null; then + # Get the current tmux session name + CURRENT_SESSION=$(tmux display-message -p '#S') + + # If currently in the fzf session, detach; otherwise, attach to it + if [ "$CURRENT_SESSION" = "$FZF_SESSION_NAME" ]; then + tmux detach-client + else + tmux set -gF '@last_session_name' '#S' # Store the current session name + tmux display-popup -E -x200% -y0 -w50% -h99% "tmux attach-session -t $FZF_SESSION_NAME" + fi +else + # If the fzf session doesn't exist, create it and run file selection logic in a popup + tmux set -gF '@last_session_name' '#S' # Store the current session name + tmux display-popup -E -w100% -h100% -y0 -x0 "tmux new-session -A -s fzf '$0 open_selected_item'" +fi diff --git a/linux/home/.config/tmux/left-status.sh b/linux/home/.config/tmux/left-status.sh new file mode 100755 index 0000000..e4a8c49 --- /dev/null +++ b/linux/home/.config/tmux/left-status.sh @@ -0,0 +1,25 @@ +#!/bin/bash + +function ip-address() { + # Loop through the interfaces and check for the interface that is up. + for file in /sys/class/net/*; do + iface=$(basename $file); + read status < $file/operstate; + [ "$status" == "up" ] && ip addr show $iface | awk '/inet /{printf $2""}' + done +} + +function vpn-connection() { + # Check for tun0 interface. + [ -d /sys/class/net/tun0 ] && printf "%s " 'VPN*' +} + +function main() { + # Comment out any function you do not need. + ip-address + vpn-connection +} + +# Calling the main function which will call the other functions. +main + diff --git a/linux/home/.config/tmux/notes.sh b/linux/home/.config/tmux/notes.sh new file mode 100755 index 0000000..71a8dc7 --- /dev/null +++ b/linux/home/.config/tmux/notes.sh @@ -0,0 +1,113 @@ +#!/usr/bin/env bash + +# Notes/TODO management & quick search engine via tmux + +NOTES_DIR="$HOME/documents/main" +TODO_FILE="$NOTES_DIR/inbox/tasks/TODO.md" +EDITOR="nvim" +NOTE_SESSION_NAME="note" +BROWSER_PREFERENCES=("firefox" "chromium" "google-chrome" "brave-browser" "chrome") +SEARCH_URL="https://www.google.com/search?q=" + +# simple error printing +error() { + echo "Error: $1" >&2 +} + +# add a TODO entry with timestamp +add_todo() { + local todo_text="$1" + [ -z "$todo_text" ] && return 1 + + [ ! -f "$TODO_FILE" ] && echo -e "# TODO List\n" > "$TODO_FILE" + + echo "- [ ] $todo_text ($(date '+%Y-%m-%d %H:%M'))" >> "$TODO_FILE" + tmux display-message "Added TODO: $todo_text" +} + +# open a web search +search_web() { + local query="$1" + [ -z "$query" ] && return 1 + + local encoded_query=$(printf '%s' "$query" | sed 's/ /+/g' | sed 's/[^a-zA-Z0-9+._-]//g') + local search_url="${SEARCH_URL}${encoded_query}" + + if command -v xdg-open >/dev/null 2>&1; then + xdg-open "$search_url" >/dev/null 2>&1 & + else + for browser in "${BROWSER_PREFERENCES[@]}"; do + command -v "$browser" >/dev/null 2>&1 && $browser "$search_url" >/dev/null 2>&1 & break + done + fi + + tmux display-message "Opening search for: $query" +} + +# display the notes menu (in-editor or popup) +open_menu() { + tmux set -gF '@last_session_name' '#S' + + if tmux has-session -t "$NOTE_SESSION_NAME" 2>/dev/null && tmux list-panes -t "$NOTE_SESSION_NAME" -F "#{pane_current_command}" | grep -q "^nvim$"; then + # menu for active nvim session + tmux display-menu -T "#[align=center] Notes (nvim-mode)" \ + "New note" n "command-prompt -p 'Enter note title:' 'send-keys -t $NOTE_SESSION_NAME \":e $NOTES_DIR/%%.md\" Enter'" \ + "Open note" o "send-keys -t $NOTE_SESSION_NAME \":cd $NOTES_DIR | FzfLua files\" Enter" \ + "TODO List" t "send-keys -t $NOTE_SESSION_NAME \":e $TODO_FILE\" Enter" \ + "Add Quick TODO" T "command-prompt -p 'Enter TODO:' 'run-shell \"$0 --add-todo %%\"'" \ + "Grep/find patterns" g "send-keys -t $NOTE_SESSION_NAME \":cd $NOTES_DIR | FzfLua live_grep\" Enter" \ + "Web Search" s "command-prompt -p 'Search query:' 'run-shell \"$0 --search %%\"'" \ + "Quit (q)" q "" + else + # popup menu outside of nvim + tmux display-menu -T "#[align=center] Notes (popup-mode)" \ + "New note" n "command-prompt -p 'Enter note title:' \"display-popup -w 100% -h 100% -E 'tmux new-session -A -s $NOTE_SESSION_NAME \\\"$EDITOR $NOTES_DIR/%%.md\\\"'\"" \ + "Open note" o "display-popup -w 100% -h 100% -E \"tmux new-session -A -s $NOTE_SESSION_NAME 'fzf --preview \\\"bat --style=numbers --color=always --line-range=:500 {}\\\" --preview-window=up:60% --height=90% --layout=reverse --border=sharp --ansi < <(find $NOTES_DIR -type f -name \\\"*.md\\\") | xargs -r $EDITOR'\"" \ + "TODO List" t "display-popup -w 100% -h 100% -E \"tmux new-session -A -s $NOTE_SESSION_NAME \\\"$EDITOR $TODO_FILE\\\"\"" \ + "Add Quick TODO" T "command-prompt -p 'Enter TODO:' 'run-shell \"$0 --add-todo %%\"'" \ + "Grep/find patterns" g "display-popup -w 100% -h 100% -E \"tmux new-session -A -s $NOTE_SESSION_NAME 'rg --color=always --line-number --no-heading --smart-case . $NOTES_DIR | fzf --delimiter=: --preview \\\"bat --style=numbers --color=always --line-range=:500 {1}\\\" --preview-window=up:60% --height=90% --layout=reverse --border=sharp --ansi | cut -d ':' -f 1 | xargs -r $EDITOR'\"" \ + "Web Search" s "command-prompt -p 'Search query:' 'run-shell \"$0 --search %%\"'" \ + "Quit (q)" q "" + fi +} + +# make sure tmux is installed +command -v tmux >/dev/null 2>&1 || { error "tmux is not installed."; exit 1; } + +# handle CLI arguments +if [ "$1" = "--add-todo" ]; then + shift + add_todo "$*" + exit 0 +fi + +if [ "$1" = "--search" ]; then + shift + search_web "$*" + exit 0 +fi + +if [ "$1" = "--new" ]; then + if tmux has-session -t "$NOTE_SESSION_NAME" 2>/dev/null; then + # reuse existing session + tmux display-popup -w 100% -h 100% -E " + FILE=\$(find $NOTES_DIR -type f -name '*.md' \ + | fzf --preview 'bat --style=numbers --color=always --line-range=:500 {}' \ + --preview-window=up:60% --height=90% --layout=reverse --border=sharp --ansi) + [ -n \"\$FILE\" ] && tmux send-keys -t $NOTE_SESSION_NAME \":e \$FILE\" Enter + " + else + open_menu + fi + exit 0 +fi + +# default behavior: toggle or open menu +if [ -z "$1" ]; then + if tmux has-session -t "$NOTE_SESSION_NAME" 2>/dev/null; then + CURRENT_SESSION=$(tmux display-message -p '#S') + [ "$CURRENT_SESSION" = "$NOTE_SESSION_NAME" ] && tmux detach-client || tmux display-popup -E -x200% -y0 -w50% -h99% "tmux attach-session -t $NOTE_SESSION_NAME" + else + open_menu + fi +fi diff --git a/linux/home/.config/tmux/right-status.sh b/linux/home/.config/tmux/right-status.sh new file mode 100755 index 0000000..a14bbe3 --- /dev/null +++ b/linux/home/.config/tmux/right-status.sh @@ -0,0 +1,27 @@ +#!/bin/bash + +# Get CPU average +getCPU=$[100-$(vmstat 1 2|tail -1|awk '{print $15}')] + +# Grab the second line of the ouput produced by the command: free -g (displays output in Gb) +getMem=$(free -h | sed -n '2p') +getMemPct=$(free -g | sed -n '2p') + +# Split the string in secondLine into an array +read -ra ADDR <<< "$getMem" +read -ra ADDRPct <<< "$getMemPct" + +# Get the total RAM from arrays +totalRam="${ADDR[1]//[^0-9.0-9]/}" +totalRamPct="${ADDRPct[1]}" + +# Get the used RAM from arrays +usedRam="${ADDR[2]//[^0-9.0-9]/}" +usedRamPct="${ADDRPct[2]}" + +# Calculate and display the percentages +pct="$(($usedRamPct*100/$totalRamPct))" +usage="$usedRam/$totalRam" +#echo "cpu:$getCPU% | mem:$pct% ($usage""G)" +echo "Cpu:$getCPU% | Mem:$pct% |" + diff --git a/linux/home/.config/tmux/tmux-popup-pane-manager.sh b/linux/home/.config/tmux/tmux-popup-pane-manager.sh new file mode 100755 index 0000000..bb0cfef --- /dev/null +++ b/linux/home/.config/tmux/tmux-popup-pane-manager.sh @@ -0,0 +1,152 @@ +#!/usr/bin/bash +# tmux-popup-pane-manager.sh - menu driven tmux pane activities +# github repo: https://github.com/pl643/tmux-scripts +# resize, selection, syncronize, layout, splits, kill, break + +# sample tmux.conf binding: +# bind-key -n M-p tmux-popup-pane-manager.sh + +[ "$TMUX" = "" ] && echo "NOTE: needs to be run inside a tmux sessions" && exit 1 + +run_after_popup="/tmp/.run_after_popup" +realpath="$(realpath "$0")" +if [ "$1" != "--no-popup" ]; then + tmux popup -E -T "────────────── Pane Manager ─────" -w 46 -h 35 "$realpath --no-popup" + + [ -f "$run_after_popup" ] && bash "$run_after_popup" && rm "$run_after_popup" + exit 0 +fi + +pane_border_status="off" +display_menu() { + clear + tmux list-windows | grep active | awk '{print $2}' | tail -c2 | grep -q Z && zoom_status="on" || zoom_status="off" + tmux show-options -w | grep -q 'synchronize-panes.*on' && synchronize_panes="on" || synchronize_panes="off" + tmux show-options -w | grep -q 'pane-border-status.*top' && pane_border_status="top" + tmux show-options -w | grep -q 'pane-border-status.*bottom' && pane_border_status="bottom" + printf " + Resize + + hjkl x 5 HJKL x 1 + 1 - 9 | x 10%% ! - ) ─ x 10%% + = equally | + equally ─ + + Split + + s - spilt - v | spilt | + + Navigation + + n p next/prev pane + N P next/prev layout + u d swap pane up/down + + Toggles + + b border [ %s ] + S syncronize [ %s ] + z zoom [ %s ] + + Misc + + B break (make pane into window) + o join this pane to window + D send C-d + e display panes / exit + t rename pane + X kill (no confirm!) + q quit" "$pane_border_status" "$synchronize_panes" "$zoom_status" +} +display_menu + +# https://www.reddit.com/r/tmux/comments/g9nr01/how_to_show_message_or_effect_when/ +# Uncomment this setting if want status of pane sync on the status bar +tmux set -ag status-right '#{?pane_synchronized, #[fg=red]IN_SYNC#[default],}' + +# https://www.reddit.com/r/tmux/comments/dfj5ye/rename_pane_not_window_is_there_a_builtin/ +tmux set -g pane-border-format " [ ###P #T ] " + +# If C-c is press in the while [ true ] loop, a run runaway process occurs, limiting +# it to 20 will cause the loop to exit after 20 loops. Modify MAXNUMLOOP if you +# need more keys presses. +MAXNUMLOOP=100 +COUNTER=0 +while [ "$COUNTER" -lt "$MAXNUMLOOP" ]; do + + read -sn1 c || exit + + # Resize x 1 + [ "$c" = "H" ] && tmux resize-pane -L 1 + [ "$c" = "L" ] && tmux resize-pane -R 1 + [ "$c" = "J" ] && tmux resize-pane -D 1 + [ "$c" = "K" ] && tmux resize-pane -U 1 + + # Resize x 5 + [ "$c" = "h" ] && tmux resize-pane -L 5 + [ "$c" = "l" ] && tmux resize-pane -R 5 + [ "$c" = "j" ] && tmux resize-pane -D 5 + [ "$c" = "k" ] && tmux resize-pane -U 5 + + # Resize X percent + [ "$c" = "1" ] && tmux resize-pane -x $(($(tmux display-message -p "#{window_width}") * 10 / 100)) + [ "$c" = "2" ] && tmux resize-pane -x $(($(tmux display-message -p "#{window_width}") * 20 / 100)) + [ "$c" = "3" ] && tmux resize-pane -x $(($(tmux display-message -p "#{window_width}") * 30 / 100)) + [ "$c" = "4" ] && tmux resize-pane -x $(($(tmux display-message -p "#{window_width}") * 40 / 100)) + [ "$c" = "5" ] && tmux resize-pane -x $(($(tmux display-message -p "#{window_width}") * 50 / 100)) + [ "$c" = "6" ] && tmux resize-pane -x $(($(tmux display-message -p "#{window_width}") * 60 / 100)) + [ "$c" = "7" ] && tmux resize-pane -x $(($(tmux display-message -p "#{window_width}") * 70 / 100)) + [ "$c" = "8" ] && tmux resize-pane -x $(($(tmux display-message -p "#{window_width}") * 80 / 100)) + [ "$c" = "9" ] && tmux resize-pane -x $(($(tmux display-message -p "#{window_width}") * 90 / 100)) + + # Resize Y percent + [ "$c" = "!" ] && tmux resize-pane -y $(($(tmux display-message -p "#{window_height}") * 10 / 100)) + [ "$c" = "@" ] && tmux resize-pane -y $(($(tmux display-message -p "#{window_height}") * 20 / 100)) + [ "$c" = "#" ] && tmux resize-pane -y $(($(tmux display-message -p "#{window_height}") * 30 / 100)) + [ "$c" = "$" ] && tmux resize-pane -y $(($(tmux display-message -p "#{window_height}") * 40 / 100)) + [ "$c" = "%" ] && tmux resize-pane -y $(($(tmux display-message -p "#{window_height}") * 50 / 100)) + [ "$c" = "^" ] && tmux resize-pane -y $(($(tmux display-message -p "#{window_height}") * 60 / 100)) + [ "$c" = "&" ] && tmux resize-pane -y $(($(tmux display-message -p "#{window_height}") * 70 / 100)) + [ "$c" = "*" ] && tmux resize-pane -y $(($(tmux display-message -p "#{window_height}") * 80 / 100)) + [ "$c" = "(" ] && tmux resize-pane -y $(($(tmux display-message -p "#{window_height}") * 90 / 100)) + + # Pane layout cycle + [ "$c" = "N" ] || [ "$c" = " " ] && tmux next-layout + [ "$c" = "P" ] && tmux previous-layout + + # Pane selection cycle + [ "$c" = "n" ] && tmux select-pane -t :.+ + [ "$c" = "p" ] && tmux select-pane -t :.- + + # Pane layout selection even horizontal/vertical + [ "$c" = "=" ] && tmux select-layout even-horizontal + [ "$c" = "+" ] && tmux select-layout even-vertical + + # Rotate pane + [ "$c" = "u" ] && tmux swap-pane -U + [ "$c" = "d" ] && tmux swap-pane -D + + # Syncronize pane + [ "$c" = "S" ] && tmux setw synchronize-pane && display_menu + + # border status ( 3 toggle off, top, bottom ) + [ "$c" = "b" ] && [ "$pane_border_status" = "off" ] && tmux set pane-border-status && display_menu && continue + [ "$c" = "b" ] && [ "$pane_border_status" = "top" ] && tmux set pane-border-status bottom && display_menu && continue + [ "$c" = "b" ] && [ "$pane_border_status" = "bottom" ] && tmux set pane-border-status off && + pane_border_status="off" && display_menu && continue + + # Split panes + [ "$c" = "s" ] || [ "$c" = "-" ] && tmux split -v + [ "$c" = "v" ] || [ "$c" = "|" ] && tmux split -h + + # Misc + [ "$c" = "B" ] && tmux break-pane + [ "$c" = "o" ] && printf "\n\n join window: " && read window && tmux join-pane -t "$window" + [ "$c" = "X" ] && tmux kill-pane + [ "$c" = "D" ] && tmux send-key C-d + display_menu + [ "$c" = "q" ] && exit + [ "$c" = "e" ] && echo tmux display-panes >"$run_after_popup" && exit + [ "$c" = "z" ] && tmux resize-pane -Z && display_menu + [ "$c" = "t" ] && printf "\n\n pane name: " && read pane_name && tmux select-pane -T "$pane_name" && display_menu + let COUNTER=COUNTER+1 +done diff --git a/linux/home/.config/tmux/tmux-toggle-option.sh b/linux/home/.config/tmux/tmux-toggle-option.sh new file mode 100755 index 0000000..52d5fdb --- /dev/null +++ b/linux/home/.config/tmux/tmux-toggle-option.sh @@ -0,0 +1,27 @@ +#!/usr/bin/bash + +#USAGE="USAGE: $0 OPTION_NAME ON_STATE OFF_STATE" + +#OPTION_NAME=$1 +#ON_STATE=$2 +#OFF_STATE=$3 +# +#if [[ "$#" != 3 ]]; then +# echo $USAGE +# exit 1 +#fi +# +#if [[ `tmux show-option -w | grep "$OPTION_NAME $ON_STATE"` ]]; then +# OPTION_VALUE=$OFF_STATE +#else +# OPTION_VALUE=$ON_STATE +#fi +# +#tmux display-message "monitor activity: $OPTION_NAME $OPTION_VALUE" +#tmux set-option -w $OPTION_NAME $OPTION_VALUE > /dev/null + +if [ $(tmux show-option -A status-left) != 'status-left* "#[fg=#50fa7b,bg=default] #[bg=#50fa7b,fg=black]❐ #S #[fg=#50fa7b,bg=default]"' ]; then + tmux set -g status-left "#[fg=#50fa7b,bg=default] #[bg=#50fa7b,fg=black]❐ #S #[fg=#50fa7b,bg=default] "; +else + tmux set -g status-left "#[fg=#50fa7b,bg=default]#[bg=#50fa7b,fg=black] ❐ #S #( ~/.config/tmux/left-status.sh ) #[fg=#50fa7b,bg=default]" && tmux set -g status-right "#[fg=#50fa7b,bg=default] #{?client_prefix,#[reverse] Prefix #[noreverse] ,}#[bg=default,fg=#50fa7b]#[bg=#50fa7b,fg=black] #( ~/.config/tmux/right-status.sh ) %d-%b-%y | %H:%M #[bg=default,fg=#50fa7b]"; +fi diff --git a/linux/home/.config/tmux/tmux.conf b/linux/home/.config/tmux/tmux.conf new file mode 100644 index 0000000..a62e3e3 --- /dev/null +++ b/linux/home/.config/tmux/tmux.conf @@ -0,0 +1,835 @@ +# ████████╗███╗ ███╗██╗ ██╗██╗ ██╗ +# ╚══██╔══╝████╗ ████║██║ ██║╚██╗██╔╝ +# ██║ ██╔████╔██║██║ ██║ ╚███╔╝ +# ██║ ██║╚██╔╝██║██║ ██║ ██╔██╗ +# ██║ ██║ ╚═╝ ██║╚██████╔╝██╔╝ ██╗ +# ╚═╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝ +#―――――――――――――――――――――――――――――――――――――――――― + +### Options ### + +# Setting the Prefix from Ctrl+b to Ctrl+s +unbind C-b +set -g prefix C-s +#set -g prefix M-Space + +# Ensure that we can send Ctrl+s to other apps +bind C-s send-prefix + +# Check if in (n)vim +is_vim="ps -o state= -o comm= -t '#{pane_tty}' | grep -iqE '^[^TXZ ]+ +(\\S+\\/)?g?(view|n?vim?x?)(diff)?$'" + +# Send the prefix to client inside window (nested tmux) +#bind-key -n C-a send-prefix +bind -n C-a if-shell "$is_vim" "send-keys C-a" "send-prefix" + +# Disable local tmux keys (nested tmux) +bind -T root F12 \ + set prefix None \;\ + set key-table off \;\ + if -F '#{pane_in_mode}' 'send-keys -X cancel' \;\ + refresh-client -S \;\ + +bind -T off F12 \ + set -u prefix \;\ + set -u key-table \;\ + refresh-client -S + +# Toggle Sync Panes +bind C-y set-window-option synchronize-panes\; display-message "Synchronize-Panes is now #{?pane_synchronized,on,off}" + +# Setting the delay between Prefix and Command +set -sg escape-time 10 +#set-option -sg escape-time 10 + +# Reload tmux with <Prefix>r +bind r source-file ~/.config/tmux/tmux.conf \; display "Reloaded!" + +# Use <Prefix>L to clear terminal +bind -r L send-keys "clear" Enter + +# Rename current window (Ctrl + A, A) +bind R rename-window '' \; \ + command-prompt -I "#W" "rename-window -- '%%'" + +# Auto rename pane +set -wg automatic-rename on +set -g automatic-rename-format "#{pane_current_command}" + +# Renumber all windows when one is killed +set -g renumber-windows on + +# Mouse +set -g mouse on + +# Right Click Menu +bind -n MouseDown3Pane \ + if-shell -F "#{||:#{match:#{pane_current_command},nvim},#{match:#{pane_current_command},vim}}" \ + "send-keys -M" \ + "display-menu -t= -xM -yM -T '#[align=centre]#{pane_index} (#{pane_id})' \ + 'Vim' v 'send-keys \"vi\" Enter' \ + 'File-manager' f 'send-keys \"yazi\" Enter' \ + '' \ + 'Horizontal Split' '\\\\' 'split-window -h -c \"#{pane_current_path}\"' \ + 'Vertical Split' '-' 'split-window -v -c \"#{pane_current_path}\"' \ + '' \ + 'Copy Mode' 'C' 'copy-mode -e' \ + 'Paste' 'p' {send-keys C-v} \ + 'Open with xdg-open' 'o' 'send-keys \"xdg-open #{pane_current_path}\"' \ + 'Enter' 'e' 'send-keys Enter' \ + '' \ + 'Go To Top' '↑' 'copy-mode -e; send-keys gg' \ + 'Go To Bottom' '↓' 'copy-mode -e; send-keys G' \ + '' \ + 'Break Pane' 't' 'break-pane' \ + 'Join Pane' 'j' 'choose-window \"join-pane -h -s %%\"' \ + '#{?pane_marked,Unmark,Mark}' 'm' 'select-pane -m' \ + '#{?#{>:#{window_panes},1},,-}Swap Up' 'u' 'swap-pane -U' \ + '#{?#{>:#{window_panes},1},,-}Swap Down' 'd' 'swap-pane -D' \ + '' \ + 'New Window' 'n' 'new-window' \ + 'Previous Window' '🡠' 'previous-window' \ + 'Next Window' '🡢' 'next-window' \ + 'Swap Window Left' '<' 'swap-window -t -1' \ + 'Swap Window Right' '>' 'swap-window -t +1' \ + '' \ + 'Kill' 'X' 'kill-pane' \ + 'Respawn' 'R' 'respawn-pane -k' \ + 'Interrupt (Ctrl+C)' 'c' 'send-keys C-c' \ + '#{?#{>:#{window_panes},1},,-}#{?window_zoomed_flag,Unzoom,Zoom}' 'z' 'resize-pane -Z'" + + +# Disable copy on primary selection (prevents auto-copy on mouse drag release) +unbind -T root MouseDrag1Pane +unbind -T copy-mode MouseDragEnd1Pane +unbind -T copy-mode-vi MouseDragEnd1Pane + +# Left-click to select a pane (no copy mode) +bind -T root MouseDown1Pane { + select-pane -t= # Select pane under mouse + send-keys -M # Enable mouse interaction in pane +} + +# Don't go into copy-mode on first click/drag +bind -T root MouseDrag1Pane if-shell '[ "#{mouse_flags}" = "drag" ]' { + if-shell '[ "#{pane_id}" = "#{mouse_pane}" ]' { + copy-mode + send-keys -X begin-selection + } { + select-pane -t= + send-keys -M + } +} { + select-pane -t= + send-keys -M +} + +# Left-click to start selection in copy-mode +bind -T root DoubleClick1Pane { + copy-mode + send-keys -X begin-selection +} + +# Left-click to start selection in copy-mode +bind -T copy-mode-vi MouseDown1Pane { + send-keys -X cancel-selection + send-keys -X begin-selection +} + +# Left-click drag to start selection in copy-mode +bind -T copy-mode-vi MouseDown1Pane { + send-keys -X begin-selection +} + +# Right click to copy the selected text and exit copy mode +bind -T copy-mode-vi MouseDown3Pane { + send-keys -X copy-pipe-no-clear + send-keys -X end-selection + send-keys Escape +} + +# Middle click exit copy mode without copying (cancel the selection) +bind -T copy-mode-vi MouseDown2Pane { + send-keys -X end-selection + send-keys Escape +} + +# Middle click paste if not in copy-mode +# Conditional behavior for MouseDown2Pane +if-shell '[ "$CTRL_V_PASTE" = "true" ]' \ + "bind -T root MouseDown2Pane send-keys C-v" \ + "bind -T root MouseDown2Pane send-keys C-S-v" + +## Right-click drag to exit copy mode without selecting text +#bind -T copy-mode-vi MouseDragEnd3Pane { +# send-keys -X end-selection # End selection +# send-keys Escape # Exit copy mode +#} + +# Make mouse-drag work only with Ctrl +#unbind -T root MouseDrag1Pane +#unbind -T copy-mode-vi MouseDrag1Pane +#bind -n C-MouseDrag1Pane if -Ft= \ +#'#{mouse_any_flag}' 'if -Ft= \"#{pane_in_mode}\" \"copy-mode -M\" send-keys -X \"send-keys -M\"' 'copy-mode -M' +#bind -T copy-mode-vi C-MouseDrag1Pane send-keys -X begin-selection + +# Exiting copy mode without copying (Left-click to exit) +#bind -T copy-mode-vi MouseDown1Pane { +# select-pane -t= # Deselect pane +# send-keys Escape # Exit copy mode +#} + + +# Scrollback +set -g history-limit 10000 + +# Sane scrolling +set -g terminal-overrides 'xterm*:smcup@:rmcup@' + +# Sane scrolling +bind -n WheelUpPane { + if -F '#{==:#{window_name},nvim}' { + #send-keys -M + send-keys Up + } { + copy-mode -e + } +} +bind -n WheelDownPane { + if -F '#{==:#{window_name},nvim}' { + #send-keys -M + send-keys Down + } { + copy-mode -e + } +} + +# Focus events, allow supported requests from applications to passthrough/run in tmux +set-option -g focus-events on + +# Update the TERM variable of terminal emulator when creating a new session or attaching a existing session +set -g update-environment 'DISPLAY SSH_ASKPASS SSH_AGENT_PID SSH_CONNECTION WINDOWID XAUTHORITY TERM' + +# New session +#bind -n M-N new-session + + +# Lock +#set-option -g lock-command "vlock -c" +#set -g lock-after-time 910 # Seconds; 0 = never +#bind -n M-Escape lock-session + + +#―――――――――――――――――――――――――――――――――――――――――― + +### Window Movement/Control ### + +# Aggressive resizing, useful when using "grouped sessions" and multi-monitor setup +setw -g aggressive-resize on + +# Menu +bind-key -n M-m display-menu -x W -y S \ + "New Session" S "command-prompt -p \"New Session:\" \"new-session -A -s '%%'\"" \ + "Kill Session" x "kill-session" \ + "Kill Other Session(s)" X "kill-session -a" \ + "" \ + "New Window" ␍ new-window \ + "Kill Window" k "killw" \ + "Choose Window" w choose-window \ + "Previous Window" 🡠 previous-window \ + "Next Window" 🡢 next-window \ + "Swap Window Right" ↑ "swap-window -t -1" \ + "Swap Window Left" ↓ "swap-window -t +1" \ + "Horizontal Split" v "split-window -h" \ + "Vertical Split" s "split-window -v" \ + "" \ + "Layout Horizontal" h "select-layout even-horizontal" \ + "Layout Vertical" k "select-layout even-horizontal" \ + "" \ + "Swap Pane Up" < "swap-pane -U" \ + "Swap Pane Down" > "swap-pane -D" \ + "Break Pane" t break-pane \ + "Join Pane" j "choose-window 'join-pane -h -s \"%%\"'" \ + "#{?window_zoomed_flag,Unzoom,Zoom}" z "resize-pane -Z" + + +# Popup Pane Manager +bind-key -n M-/ run-shell ~/.config/tmux/tmux-popup-pane-manager.sh + +# List sessions + +#bind M-q display-popup -E -w 75% -h 75% "\ +# tmux list-sessions -F '#{?session_attached,,#{session_name}}' |\ +# sed '/^$/d' |\ +# fzf --reverse --header jump-to-session --preview 'tmux capture-pane -pt {}' |\ +# xargs tmux switch-client -t" + +# Kill sessions +bind M-q display-popup -E "\ + tmux list-sessions -F '#{?session_attached,,#{session_name}}' |\ + fzf --reverse -m --header=kill-session |\ + xargs -I {} tmux kill-session -t {}" + +# List sessions +bind -n M-Space display-popup -E "\ + tmux list-sessions -F '#{?session_attached,,#{session_name}}' |\ + sed '/^$/d' |\ + fzf --reverse --header jump-to-session --preview 'tmux capture-pane -pt {}' |\ + xargs tmux switch-client -t" + +# Session chooser +#bind -n M-q choose-tree -Zs -O time + +# Quick window select +bind -n M-? list-keys +bind -n M-0 select-window -t :=0 +bind -n M-1 select-window -t :=1 +bind -n M-2 select-window -t :=2 +bind -n M-3 select-window -t :=3 +bind -n M-4 select-window -t :=4 +bind -n M-5 select-window -t :=5 +bind -n M-6 select-window -t :=6 +bind -n M-7 select-window -t :=7 +bind -n M-8 select-window -t :=8 +bind -n M-9 select-window -t :=9 + +# move pane to existing window or create it +bind-key -n M-! run -C '#{?#{m:*|1|*,|#{W:#I|}},joinp -ht :1,breakp -t :1}' +bind-key -n M-@ run -C '#{?#{m:*|2|*,|#{W:#I|}},joinp -ht :2,breakp -t :2}' +bind-key -n M-# run -C '#{?#{m:*|3|*,|#{W:#I|}},joinp -ht :3,breakp -t :3}' +bind-key -n M-$ run -C '#{?#{m:*|4|*,|#{W:#I|}},joinp -ht :4,breakp -t :4}' +bind-key -n M-% run -C '#{?#{m:*|5|*,|#{W:#I|}},joinp -ht :5,breakp -t :5}' +bind-key -n M-^ run -C '#{?#{m:*|6|*,|#{W:#I|}},joinp -ht :6,breakp -t :6}' +bind-key -n M-& run -C '#{?#{m:*|7|*,|#{W:#I|}},joinp -ht :7,breakp -t :7}' +bind-key -n M-* run -C '#{?#{m:*|8|*,|#{W:#I|}},joinp -ht :8,breakp -t :8}' +bind-key -n M-( run -C '#{?#{m:*|9|*,|#{W:#I|}},joinp -ht :9,breakp -t :9}' +bind-key -n M-) run -C '#{?#{m:*|0|*,|#{W:#I|}},joinp -ht :0,breakp -t :0}' + +#―――――――――――――――――――――――――――――――――――――――――― + +### Pane Movement/Control ### + +# Smart pane switching with awareness of Vim splits. +# See: https://github.com/christoomey/vim-tmux-navigator +# Navigate across tmux-vim + +# {{{ keybinds: select-pane +#bind -Tnav h select-pane -L +#bind h select-pane -L +#bind -Tnav C-h select-pane -L +#bind C-h select-pane -L +#bind -Tnav j select-pane -D +#bind j select-pane -D +#bind -Tnav C-j select-pane -D +#bind C-j select-pane -D +#bind -Tnav k select-pane -U +#bind k select-pane -U +#bind -Tnav C-k select-pane -U +#bind C-k select-pane -U +#bind -Tnav l select-pane -R +#bind l select-pane -R +#bind -Tnav C-l select-pane -R +#bind C-l select-pane -R + +# {{{ keybinds: select-pane +# Smart pane switching with Vim awareness +is_vim="ps -o state= -o comm= -t '#{pane_tty}' | grep -iqE '^[^TXZ ]+ +(n?vim|vimx?)'" + +bind -n C-h if-shell "$is_vim" "send-keys C-\\ C-n C-h" "select-pane -L" +bind -n C-j if-shell "$is_vim" "send-keys C-\\ C-n C-j" "select-pane -D" +bind -n C-k if-shell "$is_vim" "send-keys C-\\ C-n C-k" "select-pane -U" +bind -n C-l if-shell "$is_vim" "send-keys C-\\ C-n C-l" "select-pane -R" +# keybinds: select-pane }}} + +# {{{ keybinds: split-window +bind -Tnav "\\" split-window -h -c "#{pane_current_path}" # vertical +bind "\\" split-window -h -c "#{pane_current_path}" # vertical +bind -Tnav "|" split-window -fh -c "#{pane_current_path}" # full vertical +bind "|" split-window -fh -c "#{pane_current_path}" # full vertical +bind -Tnav "-" split-window -v -c "#{pane_current_path}" # horizontal +bind "-" split-window -v -c "#{pane_current_path}" # horizontal +bind -Tnav "_" split-window -fv -c "#{pane_current_path}" # full horizontal +bind "_" split-window -fv -c "#{pane_current_path}" # full horizontal +# keybinds: split-window }}} + +# {{{ keybinds: resize-pane +bind -r -Tnav M-h resize-pane -L 10 +bind -r M-h resize-pane -L 10 +bind -r -Tnav M-j resize-pane -D 5 +bind -r M-j resize-pane -D 5 +bind -r -Tnav M-k resize-pane -U 5 +bind -r M-k resize-pane -U 5 +bind -r -Tnav M-l resize-pane -R 10 +bind -r M-l resize-pane -R 10 +# keybinds: resize-pane }}} + +# Hide a pane and bring it back with <Prefix>! and <Prefix>@ respectively +bind-key ! break-pane -d -n _hidden_pane +bind-key @ join-pane -s $.0 + +# Send Pane to another session/window with <Prefix>= +bind-key = command-prompt -p "send pane to:" "join-pane -t '%%'" + +#―――――――――――――――――――――――――――――――――――――――――― + +### Popup ### + +# Toggle popup "term" session +set -g @term_session_name "term" +bind -n M-t if-shell -F '#{==:#{session_name},term}' { + detach-client + } { + if-shell "tmux has-session -t term" { + set -gF '@last_session_name' '#S' # Store the current session name + display-popup -E -xC -yC -w60% -h60% "tmux attach-session -t term" + } { + set -gF '@last_session_name' '#S' # Store the current session name + display-popup -E -xC -yC -w60% -h60% "tmux new-session -d -c '#{pane_current_path}' -s term && tmux set-option -t term status off && tmux attach-session -t term" + } +} + + +## Toggle popup "note" session +bind-key -n M-n if-shell -F "#{client_in_popup}" \ + "detach-client -P" \ + "run-shell ~/.config/tmux/notes.sh" + +bind-key -n M-N run-shell "~/.config/tmux/notes.sh --new" + +# Toggle popup "pack" session +bind-key -n M-p if-shell -F '#{==:#{session_name},pack}' { + detach-client +} { + set -gF '@last_session_name' '#S' # Store the current session name + #display-popup -w 80% -h 80% -E "tmux new-session -A -s pack" + display-popup -E -x200% -y0 -w50% -h99% "tmux new-session -A -s pack" +} + +# M-T → Open TODO.md in popup +bind-key -n M-o if-shell -F '#{==:#{session_name},todo}' { + + detach-client +} { + set -gF '@last_session_name' '#S' + display-popup -E -x200% -y0 -w50% -h99% "tmux new-session -A -s todo 'nvim ~/documents/main/inbox/tasks/TODO.md'" +} + +# M-y → Toggle VM popup (starts/attaches session "virt" inside popup) +bind-key -n M-y if-shell -F '#{==:#{session_name},virt}' { + detach-client -P +} { + set -gF '@last_session_name' '#S' + display-popup -E -x200% -y0 -w40% -h60% "tmux new-session -A -s virt bash -lc 'echo \"### VM Manager ###\"; echo; echo \"Available VM scripts:\"; ls -1 ~/.scripts/env/virt/ 2>/dev/null || echo \"No scripts found in ~/.scripts/env/virt/\"; echo; echo \"Run your VM by typing its script name (e.g., ubuntu, fedora, win11).\"; exec \$SHELL'" +} + +# M-H → Open history in popup +bind-key -n M-H if-shell -F '#{==:#{session_name},hist}' { + detach-client +} { + set -gF '@last_session_name' '#S' + display-popup -E -x200% -y0 -w50% -h99% "tmux new-session -A -s hist \"bash -c \' + shell=\\\$(basename \\\$SHELL) + if [[ \\\$shell == zsh ]]; then + if [[ -f \\\$HOME/.config/zsh/.zhistory ]]; then + nvim \\\$HOME/.config/zsh/.zhistory + elif [[ -f \\\$HOME/.zhistory ]]; then + nvim \\\$HOME/.zhistory + else + echo \\\"No Zsh history found\\\"; sleep 5 + fi + elif [[ \\\$shell == bash ]]; then + if [[ -f \\\$HOME/.bash_history ]]; then + nvim \\\$HOME/.bash_history + else + echo \\\"No Bash history found\\\"; sleep 5 + fi + else + echo \\\"Unknown shell: \\\$shell\\\"; sleep 5 + fi + \'\"" +} + +# Move popup session (note, term, or pack) to scratchpad (tmux)/last session or back to respective popup +bind -n M-x run-shell ' + current_session=$(tmux display-message -p "#S"); + + # Check if the current session is one of the popups (note, term, pack) + if [ "$current_session" = "note" ] || [ "$current_session" = "term" ] || [ "$current_session" = "pack" ]; then + # Detach, break the pane out of the popup, and join it to the last session + tmux detach-client; + tmux break-pane; + last_session=$(tmux show -gvq @last_session_name || echo tmux); + tmux set -g @last_popup_session "$current_session"; # Save which popup it was + tmux join-pane -s "$current_session" -t "$last_session" -h; + else + # If not in one of the popups, move the last popup session back to its popup + last_popup=$(tmux show -gqv @last_popup_session); + + if [ "$last_popup" = "note" ]; then + if ! tmux has-session -t note; then + # Spawn note session in detached mode without blocking + tmux new-session -d -s note; + fi + tmux join-pane -s $(tmux display-message -p "#P") -t note; + tmux kill-pane -a -t note:0; + elif [ "$last_popup" = "term" ]; then + if ! tmux has-session -t term; then + tmux new-session -d -s term; + fi + tmux join-pane -s $(tmux display-message -p "#P") -t term; + tmux kill-pane -a -t term:0; + elif [ "$last_popup" = "pack" ]; then + if ! tmux has-session -t pack; then + tmux new-session -d -s pack; + fi + tmux join-pane -s $(tmux display-message -p "#P") -t pack; + tmux kill-pane -a -t pack:0; + fi + fi' +# TODO: add keybinding that will allow going across the dipslay popup and main tmux session +# TODO: add keybinding for toggling the display popup size to/from fullscreen and it's original size + +# Toggle popup "fzf" session +#bind-key -n M-o run-shell ~/.config/tmux/fzf-menu.sh + +# Toggle popup "htop" session +bind -n M-i if-shell -F '#{==:#{session_name},htop}' { + detach-client + } { + if-shell "tmux has-session -t HUD" { + display-popup -E -x200% -y0 -w40% -h40% "tmux new-session -A -s HUD" + } { + display-popup -E -x200% -y0 -w40% -h40% "tmux new-session -A -s htop 'htop'" + } +} + +# Toggle popup "lazygit" session +bind-key -n M-g if-shell -F '#{==:#{session_name},lazygit}' { + detach-client +} { + display-popup -w 90% -h 90% -E "tmux new-session -A -s lazygit 'lazygit'" +} + +## Toggle popup "yazi" session +#bind-key -n M-f if-shell -F '#{==:#{session_name},yazi}' { +# detach-client +#} { +# display-popup -w 90% -h 90% -E "tmux new-session -A -s yazi 'yazi'" +#} +#tmux split-window -h -p 30 \ +# "NNN_OPENER=~/.config/tmux/file_manager.sh nnn" + +#bind-key -n M-f run-shell 'tmux split-window -hb -p 30 "~/.config/tmux/file_manager.sh $(tmux display-message -p "#I.#P")"' + +# Robust file manager toggle - checks both title and option +bind-key -n M-f run-shell "\ +fm_pane_title=\$(tmux list-panes -F '#{pane_id} #{pane_title}' | awk '\$2==\"FILE_MANAGER\" {print \$1}'); \ +fm_pane_option=\$(tmux list-panes -F '#{pane_id} #{@file_manager}' | awk '\$2==\"1\" {print \$1}'); \ +fm_pane=\${fm_pane_title:-\$fm_pane_option}; \ +if [ -n \"\$fm_pane\" ]; then \ + tmux kill-pane -t \"\$fm_pane\"; \ +else \ + current_pane=\$(tmux display-message -p '#{session_name}:#{window_index}.#{pane_index}'); \ + tmux split-window -hb -p 30 \"~/.config/tmux/file_manager.sh \$current_pane\"; \ +fi" + +## Toggle popup "speedtest" session +#bind-key -n M-s if-shell -F '#{==:#{session_name},speedtest}' { +# detach-client +#} { +# display-popup -E "tmux new-session -A -s speedtest 'speedtest'" +#} + + +# Toggle popup "nvim" session +bind-key -n M-v if-shell -F '#{==:#{session_name},edit}' { + detach-client +} { + display-popup -w 100% -h 100% -E "tmux new-session -A -s edit 'cd && nvim'" +} + + +# Toggle popup "ssh" session +bind-key -n M-s if-shell -F '#{==:#{session_name},ssh}' { + detach-client +} { + display-popup -w 40% -h 50% -E "tmux new-session -A -s ssh" +} + +# Toggle popup session to fullscreen +bind-key -n M-F run-shell ' + popup_session=$(tmux display-message -p "#{session_name}"); + if [[ "$popup_session" == "term" || "$popup_session" == "note" || "$popup_session" == "lazygit" || "$popup_session" == "yazi" || "$popup_session" == "speedtest" || "$popup_session" == "nvim" || "$popup_session" == "ssh" || "$popup_session" == "pack" || "$popup_session" == "htop" ]]; then + tmux detach-client + sleep 0.1 + tmux display-popup -E -w 100% -h 100% "tmux new-session -A -s $popup_session" + fi +' + +bind -n M-L lock-session + +#bind-key -n M-o display-popup -E nvim -c ":ObsidianNew" +#bind-key -n M-/ display-popup -w "90%" -h "85%" -E nvim -c ":ObsidianSearch" + + +#proc +#netw +#ssh + + +#―――――――――――――――――――――――――――――――――――――――――― + +### Copy Mode (Copy/Paste) ### + +# Set Vi copy mode, use <prefix>[ to enter copy mode +setw -g mode-keys vi # `<prefix>:list-keys -T copy-mode-vi` to confirm + +# super fast way to reach copy-mode and search upwards +bind-key / copy-mode \; send-key ? + +# Alt + Space copy-mode without prefix +bind-key -n M-c copy-mode + +# Shift up/down copy-mode without prefix +bind-key -n S-Up copy-mode \; send-key Up +bind-key -n S-Down copy-mode \; send-key Down +bind-key -n Pageup copy-mode \; send-key Pageup +bind-key -n Pagedown copy-mode \; send-key Pagedown +#bind -n Pageup if-shell "$is_vim" "send-keys Pageup" "copy-mode -u" +#bind -n S-Pageup if-shell "$is_vim" "send-keys Pageup" "copy-mode -u" +bind -n Pageup if-shell "$is_vim" "send-keys Pageup" +bind -n S-Pageup if-shell "$is_vim" "send-keys Pageup" +bind -n S-Pagedown send-keys Pagedown + +# Change selection <space> and enter to vi keybinding +bind-key -T copy-mode-vi 'v' send -X begin-selection +bind-key -T copy-mode-vi 'y' send -X copy-selection-and-cancel +bind -T copy-mode-vi Escape send -X cancel +bind -T copy-mode-vi C-c send -X clear-selection +bind -T copy-mode-vi C-v send -X begin-selection \; send-keys -X rectangle-toggle + +# Unbind any previous 'y' in copy-mode-vi to prevent conflicts +unbind -T copy-mode-vi 'y' + +# Clipboard copy for X11/XWayland +if-shell -b '[ "$DISPLAY" ] && command -v xclip >/dev/null' "\ + bind-key -T copy-mode-vi 'y' send-keys -X copy-pipe-and-cancel 'xclip -in -selection clipboard > /dev/null 2>&1'" + +# Clipboard copy for Wayland +if-shell -b '[ \"$WAYLAND_DISPLAY\" ] && command -v wl-copy >/dev/null' "\ + bind-key -T copy-mode-vi 'y' send-keys -X copy-pipe-and-cancel 'wl-copy --foreground --type text/plain > /dev/null 2>&1'" + +# macOS clipboard copy +if-shell -b '[ \"$(uname -s)\" = \"Darwin\" ] && command -v pbcopy >/dev/null' "\ + bind-key -T copy-mode-vi 'y' send-keys -X copy-pipe-and-cancel 'pbcopy'" + +# Windows (WSL) clipboard copy +if-shell -b 'uname -r | grep -qi microsoft && command -v clip.exe >/dev/null' "\ + bind-key -T copy-mode-vi 'y' send-keys -X copy-pipe-and-cancel 'clip.exe > /dev/null 2>&1'" + +# For OSC-Yank in vim to work over ssh +# https://github.com/ojroques/vim-oscyank +#set -s set-clipboard on +#set -g set-clipboard on +#set -g terminal-overrides 'xterm*:paste:Ctrl+Shift+V' + +set -g allow-passthrough on +set extended-keys on + +# notify when a window has activity +set-window-option -g monitor-activity on + +# Copy mode search with a simple shortcut (@see https://superuser.com/a/1253137) +bind-key / copy-mode \; send-key ? + +#―――――――――――――――――――――――――――――――――――――――――― + +### Colors ### + +## Assume external terminal supports the 256 colors palette (when TERM=xterm-256color) +#set -sa terminal-features ",xterm-256color:256" +## Assume external terminal supports RGB colors (when TERM=xterm-256color) +#set -sa terminal-features ",xterm-256color:RGB" +# +## Set TERM for proper colors +#set -g default-terminal "tmux-256color" +#set -g default-terminal "xterm-256color" + +# Set 256 color terminal +#set-option -sa terminal-overrides ",tmux-256color:Tc" +#set-option -sa terminal-overrides ",xterm*:Tc,alacritty*:Tc" + +# Colors for pane borders(default) +setw -g pane-border-style fg=white +setw -g pane-active-border-style fg=green + +# Active pane normal, other shaded out +setw -g window-style fg=colour240 +setw -g window-active-style fg=white + +# Popup border +set -g popup-border-lines rounded + +# + +#―――――――――――――――――――――――――――――――――――――――――― + +### Status ### + +set -g status-position bottom # [top, bottom] +set -g status on +#set -g status-interval 1 +set -g status-interval 500 +#set -g status-style fg=#50fa7b,bg=default + +# Toggle status +bind T set status + +# Inactive windows +set -g status-style bg=default +set -g window-status-activity-style noreverse +set -g window-status-format "#[fg=#ffffff,bg=default]#I: #W" + +## Left +set -g status-left "" +set -g status-left-length 60 + +## Center +set -g status-justify absolute-centre + +## Right +set -g status-right-length 60 +set-option -g status-right "" + + +### Status Style +set -g status-style "bg=default,fg=#CDD6F4" +#set -g status-left-length 100 +#set -g status-right-length 150 + +### Left +set -g status-left '#( \ + if fc-list | grep -qi nerd; then \ + cat ~/.vi-mode | awk '\''/-- NORMAL --/ {print "#[fg=#39BAE6]#[bg=default]#[bg=#39BAE6,fg=#000000] ❐ #S #[fg=#39BAE6,bg=default]"} \ + /-- INSERT --/ {print "#[fg=#50fa7b]#[bg=default]#[bg=#50fa7b,fg=#000000] ❐ #S #[fg=#50fa7b,bg=default]"}'\''; \ + else \ + cat ~/.vi-mode | awk '\''/-- NORMAL --/ {print "#[bg=default,fg=#39BAE6] #S "} \ + /-- INSERT --/ {print "#[bg=default,fg=#50fa7b] #S "}'\''; \ + fi \ +)' + +### Center +set -g window-status-current-format '#( \ + if fc-list | grep -qi nerd; then \ + cat ~/.vi-mode | awk '\''/-- NORMAL --/ {print "#[fg=#39BAE6]#[bg=default]#[fg=#000000,bg=#39BAE6] #I:#W #[bg=default,fg=#39BAE6]"} \ + /-- INSERT --/ {print "#[fg=#50fa7b]#[bg=default]#[fg=#000000,bg=#50fa7b] #I:#W #[bg=default,fg=#50fa7b]"}'\''; \ + else \ + cat ~/.vi-mode | awk '\''/-- NORMAL --/ {print "#[fg=#39BAE6,bg=default] #I:#W "} \ + /-- INSERT --/ {print "#[fg=#50fa7b,bg=default] #I:#W "}'\''; \ + fi \ +)' + +### Right +set -g status-right '#( \ + key_off="#[fg=#50fa7b,bg=default]#([ $(tmux show-option -qv key-table) = off ] && echo KEYS\ OFF)#[default]"; \ + vi_segment=$(cat ~/.vi-mode | awk '\''/-- NORMAL --/ {print "#[fg=#50fa7b,bg=default] #[fg=#39BAE6]#[bg=#39BAE6,fg=#000000] %H:%M #[bg=default,fg=#39BAE6]"} \ + /-- INSERT --/ {print "#[fg=#39BAE6,bg=default] #[fg=#50fa7b]#[bg=#50fa7b,fg=#000000] %H:%M #[bg=default,fg=#50fa7b]"}'\'') + + if fc-list | grep -qi nerd; then \ + echo "$key_off $vi_segment"; \ + else \ + cat ~/.vi-mode | awk '\''/-- NORMAL --/ {print "#[fg=#50fa7b,bg=default] #[fg=#39BAE6] %H:%M "} \ + /-- INSERT --/ {print "#[fg=#39BAE6,bg=default] #[fg=#50fa7b] %H:%M "}'\''; \ + fi \ +)' + +# Force refresh after session creation +#set-hook -g after-new-session 'source-file ~/.tmux.conf' +#set-hook -g client-attached 'source-file ~/.tmux.conf' + + +# Set environment variable from script output +#run-shell 'tmux set-environment -g NERD_FONT_DETECTED "$(~/.config/tmux/detect_nerd_font)"' + +## Reload Status with IP addr, Cpu, Mem and Date +bind a run-shell ~/.config/tmux/tmux-toggle-option.sh + +## Numbers +bind < command-prompt -p index "run-shell '~/.config/tmux/tmux_number.sh %%'" + +## Reload Config/Status silently +bind b source-file ~/.config/tmux/tmux.conf + +set-option -g default-shell "/usr/bin/zsh" + + +#―――――――――――――――――――――――――――――――――――――――――― + +### Plugin Install ### + +set -g @plugin "tmux-plugins/tpm" +set -g @plugin "tmux-plugins/tmux-sensible" +set -g @plugin "tmux-plugins/tmux-resurrect" +set -g @plugin "tmux-plugins/tmux-continuum" +#set -g @plugin "loichyan/tmux-toggle-popup" +set -g @plugin "christoomey/vim-tmux-navigator" +#set -g @plugin "tmux-plugins/tmux-yank" +#set -g @plugin 'srdusr/tmux-vi-mode' +#set -g @plugin 'vi-mode ~/.config/tmux/plugins/vi-mode.sh' + + +set -g @plugin 'catppuccin/tmux' +set -g @plugin 'tmux-plugins/tmux-online-status' +set -g @plugin 'tmux-plugins/tmux-battery' + +#―――――――――――――――――――――――――――――――――――――――――― + +### Plugins Settings ### + +# Plugin to save and restore tmux sessions after restart +# * Save with: <Prefix> + Ctrl-s +# * Restore with: <Prefix> + Ctlr-r +# Change default save and restore keybindings + set -g @resurrect-save "W" # <Prefix> + W + set -g @resurrect-restore "E" # <Prefix> + E + +# Restore vim and nvim sessions as well +# For vim: + set -g @resurrect-strategy-vim "session" +# For neovim: + set -g @resurrect-strategy-nvim "session" + +# Automatic restore + #set -g @continuum-restore "on" + #set -g @continuum-boot "on" + +# Restore Panes +# set -g @resurrect-capture-pane-contents "on" + +# This is a hook for tmux-resurrect which tells it to kill session 0 before restoring the panels + set -g @resurrect-hook-pre-restore-pane-processes "tmux switch-client -n && tmux kill-session -t=0" + +# Tmux navigation + #set -g @plugin 'christoomey/vim-tmux-navigator' +# Plugin uninstall + # Delete or comment out the plugin in .tmux.conf. + # Press <prefix> + alt + u to remove the plugin. + +# >>>>> CATPPUCCIN CONFIGS <<<<< + +# Configure Catppuccin +set -g @catppuccin_flavor "mocha" +set -g @catppuccin_status_background "none" +set -g @catppuccin_window_status_style "none" +set -g @catppuccin_pane_status_enabled "off" +set -g @catppuccin_pane_border_status "off" + +# Configure Online status +set -g @online_icon "ok" +set -g @offline_icon "nok" + +# TMUX plugin manager (keep at the bottom of tmux.conf) + #run "~/.config/tmux/plugins/tpm/tpm" + if "test ! -d ~/.config/tmux/plugins/tpm" \ + "run 'git clone https://github.com/tmux-plugins/tpm ~/.config/tmux/plugins/tpm && ~/.config/tmux/plugins/tpm/bin/install_plugins'" +run -b "~/.config/tmux/plugins/tpm/tpm" diff --git a/linux/home/.config/tmux/tmux_number.sh b/linux/home/.config/tmux/tmux_number.sh new file mode 100755 index 0000000..5d239d0 --- /dev/null +++ b/linux/home/.config/tmux/tmux_number.sh @@ -0,0 +1,11 @@ +#!/bin/sh +set -x +dest="$1" +[ "x""$dest" != "x" ] +tmux list-windows -F "#{window_index}" | grep "^${dest}$" 2>&1 >/dev/null +ret="$?" +if [ "x""$ret" = "x0" ]; then + tmux swap-window -t ":${dest}" +else + tmux move-window -t ":${dest}" +fi |
