Skip to content

Add support for session switching#27

Draft
deathbeam wants to merge 1 commit intocrigler:masterfrom
deathbeam:session-switcher
Draft

Add support for session switching#27
deathbeam wants to merge 1 commit intocrigler:masterfrom
deathbeam:session-switcher

Conversation

@deathbeam
Copy link

This adds support for switching dtach sessions by pressing a key configured via the DTACH_SWITCH_KEY environment variable. When pressed, an external command specified by DTACH_SWITCH_CMD is run, and the first line of its output is used as the new socket path to attach to.

This is mostly proof of concept, the env variables are used just for simplicity and the implementation can possibly be better. But basically what this allows to do is for example having key that will for example trigger fzf listing sessions based on whatever user wants, picking one and switching to it. Without worrying about stuff like nesting etc. The cmd can also just be simple echo to switch to some predefined session ofc.

This adds support for switching dtach sessions by pressing a key
configured via the DTACH_SWITCH_KEY environment variable. When pressed,
an external command specified by DTACH_SWITCH_CMD is run, and the first
line of its output is used as the new socket path to attach to.
@deathbeam
Copy link
Author

deathbeam commented Aug 10, 2025

Example on how I would use it:

export DTACH_SWITCH_KEY=$'\x18'
export DTACH_SWITCH_CMD="~/switch-session-dtach.sh"

~/switch-session-dtach.sh

#!/usr/bin/env bash

dtach_sessions=$(find /tmp -maxdepth 1 -type s -name 'dtach-*' 2>/dev/null | sed 's|/tmp/dtach-||')
project_directories=$(find ~/git -mindepth 1 -maxdepth 1 -type d ; find ~ -mindepth 1 -maxdepth 1 -type d -name '[A-Z]*')

function session_name() {
    basename "$1" | tr . _
}

function directory_name() {
    basename "$1" | tr _ .
}

function get_marked_sessions() {
    # Sessions not matching a directory
    while IFS= read -r session; do
        dir_name="$(directory_name "$session")"
        if ! echo "$project_directories" | grep -q "$dir_name"; then
            echo -e "\033[0;36m$session\033[0m"
        fi
    done <<< "$dtach_sessions"

    # Directories, mark those with active sessions
    while IFS= read -r directory; do
        sess_name="$(session_name "$directory")"
        if echo "$dtach_sessions" | grep -q "^${sess_name}$"; then
            echo -e "\033[0;36m$directory\033[0m"
        else
            echo "$directory"
        fi
    done <<< "$project_directories"
}

selected_project=$(get_marked_sessions | sort | fzf \
    --ansi -m --reverse \
    --prompt='Open session > ' \
    --bind="ctrl-s:print-query" \
    --header='<ctrl-s> to use query' \
    --preview='
        session_name=$(basename {} | tr . _)
        if [ -e /tmp/dtach-$session_name ]; then
            echo "Active dtach session: $session_name"
        else
            ls --group-directories-first --color=always -lahG {}
        fi
    ')

if [[ -z $selected_project ]]; then
    exit 0
fi

selected_name=$(session_name "$selected_project")
socket="/tmp/dtach-$selected_name"

if [[ ! -e $socket ]]; then
    dtach -n "$socket" -r winch $SHELL -c "cd '$selected_project'; exec $SHELL"
fi

echo $socket

# exec dtach -A "$socket" -r winch $SHELL -c "cd '$selected_project'; exec $SHELL"

Then I can press C-X to list sessions/create new ones and switch to them without nesting (the last commented line is implementation without this patch and causes issues)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant