Browse Source

Prevent orphan tmux sessions when closing terminal windows

  * Unless you want that.  To persist a tmux session turn on the
    status bar or open more than one window.
master
Peter J. Jones 1 year ago
parent
commit
3d6a8406a7
Signed by: Peter Jones <pjones@devalot.com> GPG Key ID: 9DAFAA8D01941E49
2 changed files with 90 additions and 35 deletions
  1. 80
    18
      bin/tmux-new-terminal
  2. 10
    17
      config/tmux.conf

+ 80
- 18
bin/tmux-new-terminal View File

@@ -1,4 +1,4 @@
#!/bin/sh -eu
#!/usr/bin/env bash

################################################################################
# This file is part of the tmuxrc package. It is subject to the
@@ -9,12 +9,25 @@
# in the LICENSE file.

################################################################################
# This script is an overly complex way of hiding tmux in a terminal
# emulator. Each new terminal that is opened has a unique tmux
# session associated with it. However, all terminals from the same
# desktop are grouped together using a session name prefix.
#
# Closing the only tmux window or the terminal will terminate the
# current session. Turning on the tmux status bar will tell this
# script that you want the session to persist.

################################################################################
SESSION_GROUP=""
SESSION_NAME=""
TTY_NUMBER=`tty | cut -d/ -f4`
TTY_NUMBER=$(tty | cut -d/ -f4)
TERM_CLOSED=0

################################################################################
# Some environment variables for the new session:
export GPG_TTY=`tty`
GPG_TTY=$(tty)
export GPG_TTY

################################################################################
usage () {
@@ -22,17 +35,21 @@ cat <<EOF
Usage: tmux-new-terminal [options]

-h This message
-s NAME Set the session name
-g NAME Set the session group name
-s NAME Set the target session name
EOF
}

################################################################################
while getopts "hs:" o; do
while getopts "hg:s:" o; do
case "${o}" in
h) usage
exit
;;

g) SESSION_GROUP=$OPTARG
;;

s) SESSION_NAME=$OPTARG
;;

@@ -44,22 +61,67 @@ done
shift $((OPTIND-1))

################################################################################
# Take the session name from the current workspace name.
if [ -z "$SESSION_NAME" -a -n "$DISPLAY" ]; then
SESSION_NAME=`wmctrl -d | awk '($2 ~ /\*/) {print $NF}'`
fi
# Find a session in the current group that has no clients.
find_inactive_sessions() {
local format='#{session_name}|#{session_attached}'

# Failing that, set it to something generic.
[ -z "$SESSION_NAME" ] && SESSION_NAME=scratch
(tmux list-sessions -F "$format" || :) | \
(grep --fixed-strings "/${SESSION_GROUP}|0" || :) | \
cut -d'|' -f1
}

################################################################################
# When the parent terminal closes, figure out what to do with tmux.
terminal_window_closed() {
if [ "$TERM_CLOSED" -eq 1 ]; then return; fi
TERM_CLOSED=1

trap "" SIGHUP # Don't re-enter this function
trap "" SIGPIPE # Don't die on writes to the terminal

status=$(tmux show-options -t "$SESSION_NAME" -v status)
windows=$(tmux list-windows -t "$SESSION_NAME" | wc -l)

if [ "$status" = "on" ] || [ "$windows" -gt 1 ]; then
# Help tmux know the session is detached. Without this it will
# still display the session as attached.
tmux detach-client -s "$SESSION_NAME"
else
# Kill the session and its windows.
tmux kill-session -t "$SESSION_NAME"
fi
}

################################################################################
# Make sure the target session exists.
if ! tmux has-session -t "$SESSION_NAME" 2> /dev/null; then
tmux new-session -s "$SESSION_NAME" -d
# Create a new session and group it with $SESSION_GROUP.
join_session() {
local other_session
other_session=$(find_inactive_sessions | sort | head -1)

# Deal with the outer terminal window closing.
trap terminal_window_closed SIGHUP

# Start tmux.
if [ -n "$other_session" ]; then
tmux attach-session -t "$other_session"
else
tmux new-session -A -s "$SESSION_NAME"
fi
}

################################################################################
# Take the session group from the current workspace name.
if [ -z "$SESSION_GROUP" ] && [ -n "$DISPLAY" ]; then
SESSION_GROUP=$(wmctrl -d | awk '($2 ~ /\*/) {print $NF}')
fi

# Create a new session and group it with $SESSION_NAME.
# Failing that, set it to something generic.
[ -z "$SESSION_GROUP" ] && SESSION_GROUP=scratch

# Take the session name from the group and current TTY.
# (The $TTY_NUMBER is used to ensure the session name is unique.)
exec tmux \
new-session -A -t "$SESSION_NAME" -s "$SESSION_NAME"/$TTY_NUMBER \; \
new-window "${SHELL:-zsh}; tmux detach-client"
if [ -z "$SESSION_NAME" ]; then
SESSION_NAME="$SESSION_GROUP/$TTY_NUMBER"
fi

join_session

+ 10
- 17
config/tmux.conf View File

@@ -1,10 +1,3 @@
# Reminders:
#
# Colors: black, red, green, yellow, blue, magenta, cyan, white (and
# bright variants)
#
# Attrs: none, bold, dim, underscore, blink, reverse, hidden, italics.

# Use C-t as the prefix key
unbind C-b
set -g prefix C-t
@@ -24,7 +17,7 @@ set -g base-index 1

# Since I start tmux from a systemd service I need to update
# environment variables when I attach.
set -g update-environment "DISPLAY XAUTHORITY SSH_AUTH_SOCK GPG_TTY"
set -g update-environment "SHELL DISPLAY XAUTHORITY SSH_AUTH_SOCK GPG_TTY"

# How tmux interacts with the terminal
set -g default-terminal "screen-256color"
@@ -35,22 +28,22 @@ set-window-option -g aggressive-resize on
# Status Line
bind-key S set status # Toggle status line
set -g status off # And start with it off
set -g status-bg black
set -g status-bg colour8
set -g status-fg white
set -g status-left ""
set -g status-right " #S "
set -g status-right-bg black
set -g status-right-fg green
set -g status-right-attr bold
set -g status-right " #{session_name} "
set -g status-right-bg colour8
set -g status-right-fg colour15
set -g status-right-attr none
set -g status-justify centre
set -g message-bg magenta
set -g message-fg black
set -g message-command-bg black
set -g message-command-bg colour8
set -g message-command-fg white
set -g window-status-attr dim
set -g window-status-attr none
set -g window-status-current-attr bold
set -g window-status-format "#[fg=white]#[bg=black]#I:#W#F"
set -g window-status-current-format "#[fg=#002b36]#[bg=#9396c4] #I #[fg=#002b36]#[bg=#6c71c4] #W "
set -g window-status-format " #[fg=#999999]#[bg=#515151] #I #[fg=#000000]#[bg=#999999] #W#F "
set -g window-status-current-format " #[fg=#002b36]#[bg=#9396c4] #I #[fg=#ffffff]#[bg=#6c71c4] #W "
set -g window-status-activity-style "bg=magenta,bold"
set -g window-status-bell-style "bg=magenta,bold"


Loading…
Cancel
Save