Terminal title / background color under nested tmuxes

this is just so impressively ugly i wanted to share this with you guys.

you know how vim can determine background color under any properly functioning terminal, so it can set bg=dark automatically? well, this doesn’t work out of the box under tmux, but luckily it’s an easy fix:

if exists("$TMUX")
   let &t_RB = "\ePtmux;\e\e]11;?\007\e\\"
endif

this means we wrap the query into a DCS passthrough sequence \ePtmux;PAYLOAD\e\\, so tmux would pass it to the outer terminal. this is documented everywhere and it old news. now, what if we have nested tmuxes? this is where things get ugly:

if exists("$TMUX")
   if exists("$SSH_CONNECTION")
      let &t_RB = "\ePtmux;\e\ePtmux;\e\e\e\e]11;?\007\e\e\\\\\e\\"
   else
      let &t_RB = "\ePtmux;\e\e]11;?\007\e\\"
   endif
endif

note double-escaping of all \es in the encapsulated escaped sequence. this took me a while to figure out. try to imagine how this would look under three tmuxes. :face_with_raised_eyebrow:

i’m assuming here for simplicity that all ssh connections are going from under tmux, i guess we could also SendEnv/AcceptEnv a custom environment variable or something if host terminal has tmux running, but it’s too much effort.

now, what about bash and setting window title with prompt command? the horrors never cease:

case "$TERM" in
   screen*)
      if [ -n "$TMUX" ]; then
         if [ -n "$SSH_CONNECTION" ]; then
            PROMPT_COMMAND='echo -ne "\ePtmux;\e\ePtmux;\e\e\e\e]0;${USER}@${HOSTNAME}: ${PWD}\007\e\e\\\\\e\\"'
         else
            PROMPT_COMMAND='echo -ne "\ePtmux;\e\e]0;${USER}@${HOSTNAME}: ${PWD}\007\e\\"'
         fi
      else
         PROMPT_COMMAND='echo -ne "\033]0;${USER}@${HOSTNAME}: ${PWD}\007"'
      fi

      ;;
   xterm*|rxvt*)
      PROMPT_COMMAND='echo -ne "\033]0;${USER}@${HOSTNAME}: ${PWD}\007"'
      ;;
esac

again, imagine how this would look under three tmuxes, what with quadruple-escaped \es in the payload. :face_vomiting:

anyway, this was one way shell communication to the outer terminal, where we don’t need to wait for a reply, but what if we wanted to?

not only we can do it, we can also not rely on assumptions about ssh connections - at a cost of a slight delay while multiple terminal queries are being sent - while doing so, like this:

   oldstty=$(stty -g)
   stty raw -echo min 0 time 0

   if [ -n "$TMUX" ]; then
      printf "\ePtmux;\e\e]11;?\007\e\\"
      sleep 0.05
      read -r answer
      result=${answer#*;}

      # nested tmux
      if [ -z $result ]; then
         printf "\ePtmux;\e\ePtmux;\e\e\e\e]11;?\007\e\e\\\\\e\\"

         sleep 0.05
         read -r answer
         result=${answer#*;}
      fi
   else
      printf "\e]11;?\007"
      sleep 0.01
      read -r answer
      result=${answer#*;}
   fi

   stty $oldstty

   if [ -n "$result" ]; then
      RGBVAL=$(( 0x$(echo $result | sed 's/[^rgb:0-9a-f/]\+$//' | cut -c 15-16) ))

      # the threshold here is arbitrary i guess, and this method won't work on all background colors
      if [ $RGBVAL -le 100 ]; then
         echo terminal background is dark
      else
         echo terminal background is light
      fi
   fi