Created
March 29, 2026 16:07
-
-
Save kesor/38960b1a7c0480e87dcaf9f83f0265b8 to your computer and use it in GitHub Desktop.
single key click session switcher
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env bash | |
| fetch_tmux_sessions() { | |
| # list session ids and names, each on a new line, ordered by session_id | |
| tmux list-sessions -F "#{session_id} #{session_name}" | sort -n | |
| } | |
| # read tmux sessions into an array | |
| mapfile -t SESSIONS < <(fetch_tmux_sessions) | |
| declare -A KEY_SESSION_ID_MAP | |
| declare -a SHORTCUT_KEYS=( 1 2 3 4 5 6 7 8 9 0 '!' '@' '#' '$' '%' '^' '&' '\*' '(' ')' '-' '=' \\ '`' '_' '+' '|' '~' ) | |
| FZF_LINES="" | |
| FZF_KEYS="" | |
| fzf_map_keys_to_sessions() { | |
| for (( i=0; i<${#SESSIONS[@]}; i++ )); do | |
| if [ $i -lt "${#SHORTCUT_KEYS[@]}" ]; then | |
| session_id="${SESSIONS[$i]%% *}" | |
| session_name="${SESSIONS[$i]#* }" | |
| # session_id="${session_line%% *}" | |
| # session_name="${session_line#* }" | |
| key="${SHORTCUT_KEYS[$i]}" | |
| KEY_SESSION_ID_MAP["$key"]="$session_id" | |
| FZF_LINES+="$key: $session_id $session_name"$'\n' | |
| FZF_KEYS+="$key," | |
| else | |
| FZF_LINES+=" $session_id $session_name"$'\n' | |
| fi | |
| # i=$((i+1)) | |
| done | |
| FZF_KEYS+="N" # new session key. | |
| # remove trailing empty line | |
| FZF_LINES=$(echo "$FZF_LINES" | sed '/^$/d') | |
| } | |
| fzf_display_sessions() { | |
| # display sessions with fzf | |
| echo "$FZF_LINES" | fzf --reverse \ | |
| --prompt="Select tmux session: " \ | |
| --scrollbar='' \ | |
| --expect="${FZF_KEYS}" \ | |
| --preview-window=bottom:50%:wrap:border-top \ | |
| --preview=' | |
| session_id=''{}'' | |
| session_id="${session_id#*: }" | |
| session_id="${session_id%% *}" | |
| tmux list-windows -t "${session_id}" -F "#{window_index}" \ | |
| | while read window; do | |
| tmux capture-pane -t "${session_id}:${window}" -p | |
| echo "-------" | |
| done | |
| ' | |
| } | |
| handle_fzf_output() { | |
| # Check if any selection was made | |
| if [[ "${#FZF_OUTPUT[@]}" -le 0 ]]; then | |
| tmux display-message "No session selected." | |
| exit 0 | |
| fi | |
| if [[ "${#FZF_OUTPUT[@]}" -eq 1 ]]; then | |
| # a result has been selected using <enter> | |
| session_id="${FZF_OUTPUT[0]#*: }" | |
| session_id="${session_id%% *}" | |
| else | |
| # a result has been selected using an expected key | |
| expected_key="${FZF_OUTPUT[0]}" | |
| session_id="${KEY_SESSION_ID_MAP["$expected_key"]}" | |
| fi | |
| # Add: handle Shift-N (new session) | |
| if [[ "$expected_key" == "N" ]]; then | |
| read -rp "New session name: " new_session_name | |
| if [[ -n "$new_session_name" ]]; then | |
| tmux new-session -d -s "$new_session_name" | |
| tmux switch-client -t "$new_session_name" | |
| fi | |
| exit 0 | |
| fi | |
| echo >&2 | |
| for key in "${!KEY_SESSION_ID_MAP[@]}"; do | |
| echo "key: $key, value: ${KEY_SESSION_ID_MAP["$key"]}" >&2 | |
| done | |
| echo >&2 | |
| echo "expected_key: _${expected_key}_ ; session_id: _${session_id}_ ; fzf_output: _${FZF_OUTPUT[*]}_" >&2 | |
| # If a session was selected, switch to it | |
| if [ -n "$session_id" ]; then | |
| tmux switch-client -t "$session_id" | |
| else | |
| tmux display-message "No session selected." | |
| fi | |
| } | |
| fzf_session_selector() { | |
| if [ "${#SESSIONS[@]}" -le 0 ]; then | |
| tmux display-message "No tmux sessions found." | |
| exit 1 | |
| fi | |
| fzf_map_keys_to_sessions | |
| IFS=$'\n' read -r -d '' -a FZF_OUTPUT <<< "$(fzf_display_sessions)" | |
| handle_fzf_output "$FZF_OUTPUT" | |
| } | |
| # Invoke the selector in a tmux popup window | |
| if [[ "$1" == "popup" ]]; then | |
| tmux popup -E -h 80% "$(readlink -f "${BASH_SOURCE[0]}")" | |
| else | |
| fzf_session_selector | |
| fi |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment