Nested screens

Written at lunch time in English • Tags: ,

Recently I’ve been debugging code on a remote system and ended up opening several ssh connections to it from my screen session. This is suboptimal because each connection in screen just gets labeled with the name of the remote system in my setup. Running a screen session on the system itself would provide me with labels that are more informative (generally: what is running in each shell).

I have resisted running nested screens for a long time, mainly due to the additional complexity of teaching myself two separate command characters for screen, and when to use each one. For example, when copying between inner screen sessions one must use the outer command character. Some display bugs and flow control hickups also show up in the inner screen sessions.

Yesterday I ran across a tmux configuration for nested sessions and started looking into implementing something similar in screen. Migrating to tmux is another thing I’ve been resisting…

Implementing “switching” between nested screen sessions takes advantage of the following screen commands:

  • bindkey for programming the sequences produced by shifted arrow keys.
  • register and process for executing multiple screen commands from a single key press.
  • bind for making the necessary individual commands available from key presses.
  • escape for setting and resetting the command character.
  • hardstatus for indicating which screen is “active” (i.e. receives the “normal” command character).

To switch to the inner screen press Shift + Up Arrow and the following happens:

  1. The outer screen will have its status line color switched to red (C-z V R).
  2. The outer screen will have its command character switched to Control G (C-z V C-g).
  3. The inner screen will have its status line color switched to green (C-z V G).

To switch back to the outer screen press Shift + Down Arrow and the reverse happens:

  1. The inner screen will have its status line color switched to red (C-z V R).
  2. The outer screen will have its command character switched to Control Z (C-g V C-z).
  3. The outer screen will have its status line color switched to green (C-z V G).

Here is the relevant configuration:

# Set command character to C-z, and "C-z z" sends out a C-z character.
escape ^Zz

hardstatus on
hardstatus alwayslastline
hardstatus string "%{.g.} %2n %t%= %H "

bind V command -c nested
bind -c nested G hardstatus string "%{.g.} %2n %t%= %H "
bind -c nested R hardstatus string "%{.R.} %2n %t%= %H "
bind -c nested ^G escape ^Gg
bind -c nested ^Z escape ^Zz

# Shift Up --> Inner
bindkey ^[[1;2A process I
register I ^ZVR^ZV^G^ZVG

# Shift Down --> Outer
bindkey ^[[1;2B process O
register O ^ZVR^GV^Z^ZVG

# Use C-g V V to return to outer screen without commanding the inner one
bind -c nested V process V
register V ^GV^Z^ZVG

Notes:

  • The same configuration is used for both the outer and inner screens.
  • I’m using C-z as my normal command character — you may want something else.

Shortcomings:

  • Detaching from the inner screen is slightly messy:
    • You are left with C-g as the control character of the outer screen.
    • Pressing Shift + Down Arrow results in C-g V R sent to current screen.
    • This can be avoided by using C-g V V instead.
  • Initially the status bar color of the inner screen is “wrong” (green).
    • The situation becomes normal by pressing Shift + Up Arrow.
  • Three copies of the hardstatus string setting have to be maintained.
    • Some additional use of register and process could be used to avoid this.