From 0db22a9f0c8934f9496072b160d50aaac2acf3ef Mon Sep 17 00:00:00 2001 From: Fabian Ising Date: Mon, 19 Oct 2026 11:14:48 +0200 Subject: [PATCH] [TMUX][ZSH] Label ssh panes with remote title or host alias Co-Authored-By: Claude Opus 5.5 --- tmux/.tmux.conf | 9 ++++++++ zsh/lib/interactive.zsh | 50 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+) diff --git a/tmux/.tmux.conf b/tmux/.tmux.conf index e78c021..25a85e6 100644 --- a/tmux/.tmux.conf +++ b/tmux/.tmux.conf @@ -43,6 +43,15 @@ bind - run-shell 'v="#{@venv}"; d="#{pane_current_path}"; if [ -n "$v" ]; then t # its global env carries one), regardless of what the source pane had. bind c new-window -e VIRTUAL_ENV= +# ssh panes: the shell sets #{@ssh_host} and the pane title to the alias (see +# zsh/lib/interactive.zsh); a remote that sets its own title overrides the +# latter. Label ssh panes by title in the window name and, only in windows with +# an ssh pane, in the pane border. +set -g automatic-rename-format '#{?#{@ssh_host},#{=40:pane_title},#{?pane_in_mode,[tmux],#{pane_current_command}}#{?pane_dead,[dead],}}' +set -g pane-border-format '#{?#{@ssh_host},#[bold] #{=60:pane_title} #[default],}' +set-hook -g window-layout-changed \ + 'if -F "#{P:#{@ssh_host}}" "set -w pane-border-status top" "set -wu pane-border-status"' + # Switch windows bind-key -n M-Left select-window -t -1 bind-key -n M-Right select-window -t +1 diff --git a/zsh/lib/interactive.zsh b/zsh/lib/interactive.zsh index f03bafa..dd1da2e 100644 --- a/zsh/lib/interactive.zsh +++ b/zsh/lib/interactive.zsh @@ -108,3 +108,53 @@ pastefinish() { zstyle :bracketed-paste-magic paste-init pasteinit zstyle :bracketed-paste-magic paste-finish pastefinish ZSH_AUTOSUGGEST_CLEAR_WIDGETS+=(bracketed-paste) + +# Mirror the ssh destination into a per-pane tmux option; .tmux.conf labels ssh +# panes (window name, pane border only in windows with ssh panes) by title. +_ssh_host_tmux() { + local -a set=(set -p -t $TMUX_PANE @ssh_host "$1") + [[ -n $1 ]] || set=(set -pu -t $TMUX_PANE @ssh_host) + tmux $set \; if -F -t $TMUX_PANE '#{P:#{@ssh_host}}' \ + "set -w -t $TMUX_PANE pane-border-status top" \ + "set -wu -t $TMUX_PANE pane-border-status" 2>/dev/null +} +_ssh_host_preexec() { + [[ -n $TMUX ]] || return + local -a w=(${(z)3}) # $2 is size-limited + while [[ $w[1] == *=* || $w[1] == (command|exec|noglob|nocorrect) ]]; do shift w; done + [[ ${w[1]:t} == ssh ]] || return + shift w + local host opt + while (( $#w )); do + case ${(Q)w[1]} in + --) host=${(Q)w[2]}; break ;; + -?*) + # option cluster; stop at the first flag that takes an argument + opt=${(Q)w[1]#-}; shift w + while [[ -n $opt ]]; do + if [[ $opt[1] == [BbcDEeFIiJLlmOoPpRSWw] ]]; then + [[ -n ${opt:1} ]] || shift w + break + fi + opt=${opt:1} + done ;; + *) host=${(Q)w[1]}; break ;; + esac + done + [[ $host == ssh://* ]] && host=${${host#ssh://}%:<->} + host=${host##*@} + [[ -n $host ]] || return + _ssh_host_tmux $host + _ssh_host_set=1 + # pane title starts as the alias; a remote that sets its own title wins. + # Runs after OMZ's preexec, so this replaces its "ssh ..." title. + print -rn -- $'\e]2;'"$host"$'\e\\' +} +_ssh_host_precmd() { + (( ${_ssh_host_set:-0} )) || return + _ssh_host_tmux '' + _ssh_host_set=0 +} +autoload -Uz add-zsh-hook +add-zsh-hook preexec _ssh_host_preexec +add-zsh-hook precmd _ssh_host_precmd