'TMUX pane tabs, or 'locking/freezing' pane splits in place

When using tmux, I generally have an editor open in a split on top, and a shell at the bottom. Right now, I'm writing a python script, and on the bottom half of the split I can't find a way to toggle back and forth between ipython and bash: the best I can do is create a nested split between those two, sharing the bottom half of the screen. Right now this looks something like the following.

Is there something like tabs within a pane, so I can switch back and forth between bash/ipython while keeping the editor locked/frozen in place at the top? It's not ideal right now to have to choose between switching to a new tab for one of the shell prompts or using these tiny splits. Tmux is so flexible it seems like there'd be a way to do this straightforward pane-lock. Thanks bottom split



Solution 1:[1]

Resolved using nested tmux sessions. I based my solution on a much-stripped down version of nested-tmux. I launch a nested session and then use tabs within that nested session. To launch a nested session, I use the following script tmux-nested.sh (adapted from the nested-tmux repo):

#!/bin/sh

TMUX_PARENT=$(basename "$TMUX")
TMUX_PARENT="${TMUX_PARENT%%,*}"
export TMUX_PARENT
_SOCK="r$RANDOM"
tmux -L "$_SOCK" new-session -s "$_SOCK"

This creates a nested session with socket given a random filename (a hardcoded value wouldn't permit multiple nested sessions, say in different tabs in the parent session).

In my .tmux.conf file, I add the following line on startup to change the tmux prefix for nested sessions:

# nested session logic
if-shell '! [ -z "$TMUX_PARENT" ]' 'set-option -g prefix C-b'

(where my normal prefix is a backtick)

EDIT: I expanded this function into a much more robust implementation, which can be found below:

# Nest tmux sessions
tmux_nested() {
    local usagestring='usage: tmux-nested [-n | -a nested-session-# | -l]'
    if [[ -z $TMUX ]]; then
        # ensure invoked within active session
        echo "'tmux_nested' should be invoked inside an active tmux session"
        return 1
    fi

    # read flags and check for number of existing nested sessions
    local nested session_name
    nested=$(tmux list-sessions -F '#{session_name}' | \
             ggrep -P '^nested[\d]+' --color=never | sort -V)
    while getopts ':lna:' opt; do
        case $opt in
            l)
                [[ -z $nested ]] && nested="No nested sessions running"
                echo "$nested" && return 0;;
            n)
                # if new session requested: create, set <C-b> tmux prefix, and attach
                for (( i = 1;; i++ )); do
                    # get lowest available numeric value for new session name
                    if ! tmux has-session -t "nested$i" 2> /dev/null; then
                        session_name="nested$i" && break
                    fi
                done
                tmux new-session -ds "$session_name"
                tmux send-keys -t "$session_name" \
                                  "tmux set prefix C-b" ENTER "clear" ENTER
                env TMUX='' tmux attach -t "$session_name"
                return $?;;
            a)
                # attach to specified session if requested
                session_name="nested${OPTARG}"
                if ! env TMUX='' tmux attach -t "$session_name"; then
                    echo "Try 'tmux_nested -l'?" && return 1
                fi;;
            *) echo "$usagestring" && return 1;;
        esac
    done

    # incorrect invocation, report incorrect invocation and exit
    echo "$usagestring" && return 1
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1