Add session manager for tmux.

This will open a tmux session for each monitor.
Add helper script for tmux actions.
This commit is contained in:
2025-09-22 15:26:42 +02:00
parent c4df56cb47
commit 8e563fec51
8 changed files with 622 additions and 11 deletions

View File

@@ -8,7 +8,7 @@ dimensions = { columns = 140, lines = 45 }
option_as_alt = "Both" option_as_alt = "Both"
[font] [font]
size = 16.0 size = 12.0
[font.normal] [font.normal]
family = "0xProto Nerd Font" family = "0xProto Nerd Font"
@@ -115,9 +115,11 @@ bindings = [
[terminal] [terminal]
osc52 = "CopyPaste" # Enable OSC 52 for clipboard support osc52 = "CopyPaste" # Enable OSC 52 for clipboard support
# Shell configuration - tmux sessions are now handled by smart-terminal.sh
# which creates monitor/workspace-specific sessions automatically
[terminal.shell] [terminal.shell]
program = "/usr/bin/tmux" program = "/bin/bash"
args = ["new-session", "-A", "-s", "main"] args = ["-l"]
[scrolling] [scrolling]
history = 10000 history = 10000

View File

@@ -34,10 +34,6 @@ exec --no-startup-id xss-lock --transfer-sleep-lock -- i3lock -f --nofork
# and nm-applet is a desktop environment-independent system tray GUI for it. # and nm-applet is a desktop environment-independent system tray GUI for it.
exec --no-startup-id nm-applet exec --no-startup-id nm-applet
# Wallpaper rotation script
exec --no-startup-id ~/.config/i3/wallpaper-rotate.sh --once
exec --no-startup-id ~/.config/i3/wallpaper-rotate.sh --daemon 1800
# Use pactl to adjust volume in PulseAudio. # Use pactl to adjust volume in PulseAudio.
set $refresh_i3status killall -SIGUSR1 i3status set $refresh_i3status killall -SIGUSR1 i3status
bindsym XF86AudioRaiseVolume exec --no-startup-id pactl set-sink-volume @DEFAULT_SINK@ +10% && $refresh_i3status bindsym XF86AudioRaiseVolume exec --no-startup-id pactl set-sink-volume @DEFAULT_SINK@ +10% && $refresh_i3status
@@ -48,8 +44,15 @@ bindsym XF86AudioMicMute exec --no-startup-id pactl set-source-mute @DEFAULT_SOU
# Use Mouse+$mod to drag floating windows to their wanted position # Use Mouse+$mod to drag floating windows to their wanted position
floating_modifier $mod floating_modifier $mod
# start a terminal # start a terminal with smart monitor/workspace-aware tmux sessions
bindsym $mod+Return exec alacritty bindsym $mod+Return exec --no-startup-id /home/jens/.config/i3/smart-terminal.sh
# fallback simple terminal (without smart sessions)
bindsym $mod+Shift+Return exec --no-startup-id /home/jens/.config/i3/simple-terminal.sh
# tmux session management keybindings
bindsym $mod+Shift+t exec --no-startup-id /home/jens/.cargo/bin/alacritty -e /home/jens/.config/i3/tmux-session-manager.sh
bindsym $mod+Control+t exec --no-startup-id /home/jens/.config/i3/tmux-session-manager.sh list | rofi -dmenu -p "Tmux Sessions" -width 60
# kill focused window # kill focused window
bindsym $mod+Shift+q kill bindsym $mod+Shift+q kill
@@ -63,6 +66,23 @@ bindsym $mod+Shift+q kill
# bindcode $mod+40 exec --no-startup-id i3-dmenu-desktop # bindcode $mod+40 exec --no-startup-id i3-dmenu-desktop
bindsym $mod+d exec rofi -show run bindsym $mod+d exec rofi -show run
# Screenshot bindings
bindsym Print exec --no-startup-id ~/.local/bin/screenshot.sh full
bindsym Shift+Print exec --no-startup-id ~/.local/bin/screenshot.sh selection
bindsym $mod+Print exec --no-startup-id ~/.local/bin/screenshot.sh window
bindsym Control+Print exec --no-startup-id ~/.local/bin/screenshot.sh clipboard
bindsym Control+Shift+Print exec --no-startup-id ~/.local/bin/screenshot.sh clipboard-selection
# Alternative screenshot bindings for keyboards that send different codes
bindsym XF86ScreenSaver exec --no-startup-id ~/.local/bin/screenshot.sh full
bindsym Shift+XF86ScreenSaver exec --no-startup-id ~/.local/bin/screenshot.sh selection
bindsym $mod+XF86ScreenSaver exec --no-startup-id ~/.local/bin/screenshot.sh window
# Additional screenshot bindings with mod+s combinations
bindsym $mod+Shift+s exec --no-startup-id ~/.local/bin/screenshot.sh selection
bindsym $mod+Control+s exec --no-startup-id ~/.local/bin/screenshot.sh window
bindsym $mod+Control+Shift+s exec --no-startup-id ~/.local/bin/screenshot.sh full
# change focus # change focus
bindsym $mod+j focus left bindsym $mod+j focus left
bindsym $mod+k focus down bindsym $mod+k focus down
@@ -116,7 +136,7 @@ bindsym $mod+a focus parent
# Wallpaper controls # Wallpaper controls
bindsym $mod+Shift+w exec --no-startup-id ~/.config/i3/wallpaper-rotate.sh --once bindsym $mod+Shift+w exec --no-startup-id ~/.config/i3/wallpaper-rotate.sh --once
bindsym $mod+Shift+n exec --no-startup-id ~/.config/i3/wallpaper-rotate.sh --category nature bindsym $mod+Shift+n exec --no-startup-id ~/.config/i3/wallpaper-rotate.sh --category nature
bindsym $mod+Control+s exec --no-startup-id ~/.config/i3/wallpaper-rotate.sh --category space # bindsym $mod+Control+s exec --no-startup-id ~/.config/i3/wallpaper-rotate.sh --category space # Disabled - conflicts with screenshot binding
bindsym $mod+Control+c exec --no-startup-id ~/.config/i3/wallpaper-rotate.sh --category cityscape bindsym $mod+Control+c exec --no-startup-id ~/.config/i3/wallpaper-rotate.sh --category cityscape
# Define names for default workspaces for which we configure key bindings later on. # Define names for default workspaces for which we configure key bindings later on.

13
i3/simple-terminal.sh Executable file
View File

@@ -0,0 +1,13 @@
#!/bin/bash
# Simple fallback terminal launcher
# Uses alacritty directly without complex session detection
ALACRITTY="/home/jens/.cargo/bin/alacritty"
if [ -x "$ALACRITTY" ]; then
exec "$ALACRITTY"
else
# Fallback to xterm
exec xterm
fi

97
i3/smart-terminal.sh Executable file
View File

@@ -0,0 +1,97 @@
#!/bin/bash
# Smart terminal launcher with monitor-aware tmux sessions
# This script detects the current monitor and workspace to create/attach to appropriate tmux sessions
# Get the focused monitor using i3-msg
get_current_monitor() {
if command -v i3-msg &> /dev/null && i3-msg -t get_workspaces &>/dev/null; then
i3-msg -t get_workspaces 2>/dev/null | jq -r '.[] | select(.focused==true) | .output' 2>/dev/null
else
echo "default"
fi
}
# Get the current workspace number
get_current_workspace() {
if command -v i3-msg &> /dev/null && i3-msg -t get_workspaces &>/dev/null; then
i3-msg -t get_workspaces 2>/dev/null | jq -r '.[] | select(.focused==true) | .num' 2>/dev/null
else
echo "1"
fi
}
# Determine session name based on monitor and workspace
get_session_name() {
local monitor=$(get_current_monitor)
local workspace=$(get_current_workspace)
# Fallback if we can't get monitor/workspace info
if [ -z "$monitor" ] || [ "$monitor" = "null" ]; then
monitor="default"
fi
if [ -z "$workspace" ] || [ "$workspace" = "null" ]; then
workspace="1"
fi
# Clean monitor name (remove special characters)
monitor_clean=$(echo "$monitor" | sed 's/[^a-zA-Z0-9-]/_/g')
# Map monitors to logical screen names
case "$monitor_clean" in
"eDP_1"|"eDP1")
screen="laptop"
;;
"DVI_I_2_2"|"HDMI_1"|"HDMI1"|"DP_1"|"DP1")
screen="external1"
;;
"DVI_I_1_1"|"HDMI_2"|"HDMI2"|"DP_2"|"DP2")
screen="external2"
;;
"default")
screen="main"
;;
*)
screen="${monitor_clean}"
;;
esac
# Create session name: screen-workspace (e.g., laptop-1, external1-5)
if [ "$screen" = "main" ]; then
echo "main"
else
echo "${screen}-ws${workspace}"
fi
}
# Launch alacritty with tmux
launch_terminal() {
local session_name=$(get_session_name)
# Debug logging (remove after testing)
echo "Launching terminal with session: $session_name" >> /tmp/smart-terminal.log
# Check if alacritty exists
ALACRITTY_PATH="/home/jens/.cargo/bin/alacritty"
if [ ! -x "$ALACRITTY_PATH" ]; then
ALACRITTY_PATH=$(which alacritty 2>/dev/null)
if [ -z "$ALACRITTY_PATH" ]; then
# Fallback to xterm or another terminal
echo "Alacritty not found, falling back to xterm" >> /tmp/smart-terminal.log
xterm -e tmux new-session -A -s "$session_name" &
exit 0
fi
fi
# Check if tmux session exists
if tmux has-session -t "$session_name" 2>/dev/null; then
# Session exists, attach to it
"$ALACRITTY_PATH" --title "Terminal [$session_name]" -e tmux attach-session -t "$session_name" &
else
# Create new session with meaningful name
"$ALACRITTY_PATH" --title "Terminal [$session_name]" -e tmux new-session -s "$session_name" &
fi
}
# Main execution
launch_terminal

229
i3/tmux-session-manager.sh Executable file
View File

@@ -0,0 +1,229 @@
#!/bin/bash
# Advanced tmux session management for multi-monitor setup
# Provides utilities for managing monitor-specific tmux sessions
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# List all tmux sessions with their status
list_sessions() {
echo -e "${BLUE}=== Tmux Sessions by Screen ===${NC}"
# Group sessions by screen
for screen in laptop external1 external2; do
sessions=$(tmux list-sessions 2>/dev/null | grep "^${screen}-" | cut -d: -f1)
if [ ! -z "$sessions" ]; then
echo -e "\n${GREEN}${screen}:${NC}"
while IFS= read -r session; do
workspace=$(echo "$session" | cut -d- -f2)
attached=""
if tmux list-sessions 2>/dev/null | grep "^${session}:" | grep -q "(attached)"; then
attached=" ${YELLOW}[attached]${NC}"
fi
echo -e "${session}${attached}"
done <<< "$sessions"
fi
done
# Show other sessions
other_sessions=$(tmux list-sessions 2>/dev/null | grep -v -E "^(laptop|external1|external2)-" | cut -d: -f1)
if [ ! -z "$other_sessions" ]; then
echo -e "\n${BLUE}Other sessions:${NC}"
while IFS= read -r session; do
attached=""
if tmux list-sessions 2>/dev/null | grep "^${session}:" | grep -q "(attached)"; then
attached=" ${YELLOW}[attached]${NC}"
fi
echo -e "${session}${attached}"
done <<< "$other_sessions"
fi
}
# Kill all sessions for a specific screen
kill_screen_sessions() {
local screen=$1
if [ -z "$screen" ]; then
echo -e "${RED}Error: Please specify a screen (laptop, external1, external2)${NC}"
return 1
fi
sessions=$(tmux list-sessions 2>/dev/null | grep "^${screen}-" | cut -d: -f1)
if [ -z "$sessions" ]; then
echo -e "${YELLOW}No sessions found for screen: ${screen}${NC}"
return 0
fi
echo -e "${YELLOW}Killing all sessions for ${screen}...${NC}"
while IFS= read -r session; do
tmux kill-session -t "$session" 2>/dev/null
echo -e " ${RED}${NC} Killed: $session"
done <<< "$sessions"
}
# Rename a session
rename_session() {
local old_name=$1
local new_name=$2
if [ -z "$old_name" ] || [ -z "$new_name" ]; then
echo -e "${RED}Error: Usage: rename_session <old_name> <new_name>${NC}"
return 1
fi
if tmux has-session -t "$old_name" 2>/dev/null; then
tmux rename-session -t "$old_name" "$new_name"
echo -e "${GREEN}${NC} Renamed: $old_name$new_name"
else
echo -e "${RED}Error: Session '$old_name' not found${NC}"
return 1
fi
}
# Switch to a different session
switch_session() {
local session_name=$1
if [ -z "$session_name" ]; then
# Interactive session picker using fzf if available
if command -v fzf &> /dev/null; then
session_name=$(tmux list-sessions -F "#{session_name}" 2>/dev/null | fzf --prompt="Select session: ")
else
echo -e "${RED}Error: Please specify a session name${NC}"
list_sessions
return 1
fi
fi
if [ ! -z "$session_name" ] && tmux has-session -t "$session_name" 2>/dev/null; then
if [ -n "$TMUX" ]; then
tmux switch-client -t "$session_name"
else
tmux attach-session -t "$session_name"
fi
else
echo -e "${RED}Error: Session '$session_name' not found${NC}"
return 1
fi
}
# Create a new session for current monitor/workspace
new_session_here() {
# Source the functions from smart-terminal.sh
source /home/jens/.config/i3/smart-terminal.sh
local session_name=$(get_session_name)
if tmux has-session -t "$session_name" 2>/dev/null; then
echo -e "${YELLOW}Session '$session_name' already exists${NC}"
return 1
fi
tmux new-session -d -s "$session_name"
echo -e "${GREEN}${NC} Created new session: $session_name"
}
# Clean up detached sessions
cleanup_detached() {
local detached=$(tmux list-sessions 2>/dev/null | grep -v "(attached)" | cut -d: -f1)
if [ -z "$detached" ]; then
echo -e "${GREEN}No detached sessions to clean up${NC}"
return 0
fi
echo -e "${YELLOW}Found detached sessions:${NC}"
echo "$detached"
echo -e "\n${YELLOW}Kill all detached sessions? (y/N)${NC}"
read -r response
if [[ "$response" =~ ^[Yy]$ ]]; then
while IFS= read -r session; do
tmux kill-session -t "$session" 2>/dev/null
echo -e " ${RED}${NC} Killed: $session"
done <<< "$detached"
fi
}
# Main menu
show_menu() {
echo -e "${BLUE}=== Tmux Session Manager ===${NC}"
echo "1. List all sessions"
echo "2. Switch to session"
echo "3. Kill screen sessions"
echo "4. Rename session"
echo "5. Create session for current workspace"
echo "6. Cleanup detached sessions"
echo "7. Exit"
echo -n "Select option: "
}
# Main execution
case "$1" in
list)
list_sessions
;;
kill-screen)
kill_screen_sessions "$2"
;;
rename)
rename_session "$2" "$3"
;;
switch)
switch_session "$2"
;;
new)
new_session_here
;;
cleanup)
cleanup_detached
;;
*)
if [ -z "$1" ]; then
# Interactive mode
while true; do
show_menu
read -r option
case $option in
1) list_sessions ;;
2)
echo -n "Session name: "
read -r session
switch_session "$session"
;;
3)
echo -n "Screen (laptop/external1/external2): "
read -r screen
kill_screen_sessions "$screen"
;;
4)
echo -n "Old name: "
read -r old
echo -n "New name: "
read -r new
rename_session "$old" "$new"
;;
5) new_session_here ;;
6) cleanup_detached ;;
7) exit 0 ;;
*) echo -e "${RED}Invalid option${NC}" ;;
esac
echo
done
else
echo "Usage: $0 [command] [args]"
echo "Commands:"
echo " list - List all sessions"
echo " kill-screen <screen> - Kill all sessions for a screen"
echo " rename <old> <new> - Rename a session"
echo " switch <session> - Switch to a session"
echo " new - Create session for current workspace"
echo " cleanup - Cleanup detached sessions"
echo ""
echo "Run without arguments for interactive mode"
fi
;;
esac

42
tmux/move-window.sh Executable file
View File

@@ -0,0 +1,42 @@
#!/bin/bash
# Tmux window mover with fzf
# Allows moving current window to another session
# Get current session and window
current_session=$(tmux display-message -p '#S')
current_window=$(tmux display-message -p '#I')
current_window_name=$(tmux display-message -p '#W')
# Get list of all sessions with window count
sessions=$(tmux list-sessions -F '#{session_name}: #{session_windows} windows' | grep -v "^${current_session}:")
# If no other sessions, offer to create one
if [ -z "$sessions" ]; then
echo "No other sessions available. Create a new session? (y/n)"
read -r response
if [[ "$response" =~ ^[Yy]$ ]]; then
echo "Enter new session name:"
read -r new_session
if [ ! -z "$new_session" ]; then
tmux new-session -d -s "$new_session"
tmux move-window -t "${new_session}:"
tmux switch-client -t "$new_session"
fi
fi
exit 0
fi
# Select target session with fzf
target_session=$(echo "$sessions" | fzf --header="Move window '${current_window_name}' to session:" --preview='tmux list-windows -t {1} -F "#{window_index}: #{window_name} [#{window_panes} panes]"' | cut -d: -f1)
# If a session was selected, move the window
if [ ! -z "$target_session" ]; then
# Move window to target session
tmux move-window -t "${target_session}:"
# Switch to the target session
tmux switch-client -t "$target_session"
echo "Moved window '${current_window_name}' to session '${target_session}'"
fi

193
tmux/tmux-fzf-menu.sh Executable file
View File

@@ -0,0 +1,193 @@
#!/bin/bash
# Advanced tmux operations menu using fzf
# Provides a unified interface for various tmux operations
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# Main menu options
show_menu() {
echo "Session: Switch to session"
echo "Window: Switch to window"
echo "Move Window: Move current window to another session"
echo "Move Pane: Move current pane to another window"
echo "Swap Window: Swap current window with another"
echo "Rename Window: Rename current window"
echo "Rename Session: Rename current session"
echo "Kill Window: Kill a window"
echo "Kill Session: Kill a session"
echo "New Session: Create new session"
echo "Link Window: Link window from another session"
echo "Unlink Window: Unlink current window"
}
# Function to switch session
switch_session() {
tmux list-sessions -F '#{session_name}: #{session_windows} windows#{?session_attached, (attached),}' | \
fzf --header='Switch to session:' \
--preview='tmux list-windows -t {1} -F "#{window_index}: #{window_name} [#{window_panes} panes]"' | \
cut -d: -f1 | \
xargs -I {} tmux switch-client -t {}
}
# Function to switch window
switch_window() {
tmux list-windows -a -F '#{session_name}:#{window_index}: #{window_name}' | \
fzf --header='Switch to window:' \
--preview='tmux list-panes -t {1} -F "Pane #{pane_index}: #{pane_current_command}"' | \
cut -d: -f1,2 | \
xargs -I {} tmux switch-client -t {}
}
# Function to move current window
move_window() {
current_window=$(tmux display-message -p '#W')
target=$(tmux list-sessions -F '#{session_name}' | \
fzf --header="Move window '${current_window}' to session:" \
--preview='tmux list-windows -t {} -F "#{window_index}: #{window_name}"')
if [ ! -z "$target" ]; then
tmux move-window -t "${target}:"
tmux switch-client -t "$target"
fi
}
# Function to move current pane
move_pane() {
target=$(tmux list-windows -a -F '#{session_name}:#{window_index}: #{window_name}' | \
fzf --header='Move pane to window:' \
--preview='tmux list-panes -t {1} -F "Pane #{pane_index}: #{pane_current_command}"')
if [ ! -z "$target" ]; then
window_target=$(echo "$target" | cut -d: -f1,2)
tmux join-pane -t "$window_target"
fi
}
# Function to swap windows
swap_window() {
target=$(tmux list-windows -F '#{window_index}: #{window_name}' | \
fzf --header='Swap current window with:')
if [ ! -z "$target" ]; then
window_idx=$(echo "$target" | cut -d: -f1)
tmux swap-window -t "$window_idx"
fi
}
# Function to rename window
rename_window() {
echo -n "New window name: "
read -r new_name
if [ ! -z "$new_name" ]; then
tmux rename-window "$new_name"
fi
}
# Function to rename session
rename_session() {
echo -n "New session name: "
read -r new_name
if [ ! -z "$new_name" ]; then
tmux rename-session "$new_name"
fi
}
# Function to kill window
kill_window() {
target=$(tmux list-windows -a -F '#{session_name}:#{window_index}: #{window_name}' | \
fzf --header='Kill window:' --multi \
--preview='tmux list-panes -t {1} -F "Pane #{pane_index}: #{pane_current_command}"')
if [ ! -z "$target" ]; then
echo "$target" | while IFS= read -r window; do
window_target=$(echo "$window" | cut -d: -f1,2)
tmux kill-window -t "$window_target"
done
fi
}
# Function to kill session
kill_session() {
target=$(tmux list-sessions -F '#{session_name}: #{session_windows} windows#{?session_attached, (attached),}' | \
fzf --header='Kill session:' --multi \
--preview='tmux list-windows -t {1} -F "#{window_index}: #{window_name}"')
if [ ! -z "$target" ]; then
echo "$target" | while IFS= read -r session; do
session_name=$(echo "$session" | cut -d: -f1)
tmux kill-session -t "$session_name"
done
fi
}
# Function to create new session
new_session() {
echo -n "New session name: "
read -r session_name
if [ ! -z "$session_name" ]; then
tmux new-session -d -s "$session_name"
tmux switch-client -t "$session_name"
fi
}
# Function to link window from another session
link_window() {
target=$(tmux list-windows -a -F '#{session_name}:#{window_index}: #{window_name}' | \
fzf --header='Link window:' \
--preview='tmux list-panes -t {1} -F "Pane #{pane_index}: #{pane_current_command}"')
if [ ! -z "$target" ]; then
source_window=$(echo "$target" | cut -d' ' -f1)
tmux link-window -s "$source_window"
fi
}
# Function to unlink current window
unlink_window() {
tmux unlink-window
echo "Current window unlinked"
}
# Main execution
if [ "$1" == "--menu" ] || [ -z "$1" ]; then
# Show interactive menu
selection=$(show_menu | fzf --header='Tmux Operations:' | cut -d: -f1)
case "$selection" in
"Session") switch_session ;;
"Window") switch_window ;;
"Move Window") move_window ;;
"Move Pane") move_pane ;;
"Swap Window") swap_window ;;
"Rename Window") rename_window ;;
"Rename Session") rename_session ;;
"Kill Window") kill_window ;;
"Kill Session") kill_session ;;
"New Session") new_session ;;
"Link Window") link_window ;;
"Unlink Window") unlink_window ;;
esac
else
# Direct command execution
case "$1" in
session) switch_session ;;
window) switch_window ;;
move-window) move_window ;;
move-pane) move_pane ;;
swap-window) swap_window ;;
rename-window) rename_window ;;
rename-session) rename_session ;;
kill-window) kill_window ;;
kill-session) kill_session ;;
new-session) new_session ;;
link-window) link_window ;;
unlink-window) unlink_window ;;
*) echo "Unknown command: $1" ;;
esac
fi

View File

@@ -108,4 +108,19 @@ bind w display-popup -E "tmux list-windows -F '#{window_index}: #{window_name}'
bind f display-popup -E "fd --type f --hidden --follow --exclude .git | fzf --preview 'bat --color=always --style=numbers --line-range=:500 {}' | xargs -I {} tmux new-window 'vim {}'" bind f display-popup -E "fd --type f --hidden --follow --exclude .git | fzf --preview 'bat --color=always --style=numbers --line-range=:500 {}' | xargs -I {} tmux new-window 'vim {}'"
# Quick directory navigation # Quick directory navigation
bind g display-popup -E "fd --type d --hidden --follow --exclude .git | fzf --preview 'tree -C {} | head -200' | xargs -I {} tmux send-keys 'cd {}' Enter" bind g display-popup -E "fd --type d --hidden --follow --exclude .git | fzf --preview 'tree -C {} | head -200' | xargs -I {} tmux send-keys 'cd {}' Enter"
# Move window to another session with fzf
bind m display-popup -E "bash ~/.config/tmux/move-window.sh"
# Swap windows with fzf
bind M display-popup -E "tmux list-windows -F '#{window_index}: #{window_name}' | fzf --header='Swap current window with:' | cut -d: -f1 | xargs -I {} tmux swap-window -t {}"
# Move pane to another window with fzf
bind p display-popup -E "tmux list-windows -F '#{window_index}: #{window_name}' | fzf --header='Move pane to window:' | cut -d: -f1 | xargs -I {} tmux join-pane -t :{}"
# Break pane into new window
bind B break-pane -d
# Comprehensive tmux operations menu with fzf
bind Space display-popup -E -w 80% -h 80% "bash ~/.config/tmux/tmux-fzf-menu.sh --menu"