Paul's Internet Landfill/ 2014/ Better Titles in GNU Screen

Better Titles in GNU Screen

I have been using this trick for years, but I never bothered documenting it. GNU Screen is one of those programs that does not seem like anything special when you first hear about it, and then becomes invaluable once you start using it. I use it to keep large number of terminal sessions open on a host -- some of them sessions parked in different folders, and some running different utilities.

But GNU Screen has a huge problem: the default screen titles are useless. On a default Debian installation, when I hit <ctrl>+a " to see the list of windows I have opened, I see:

0 bash                      $
1 bash                      $

which does not help me keep track of my windows at all. It is possible to set a title manually using <ctrl>+a A, but this is irritating. I want screen to display titles automatically for me. Below are some tricks to make those titles more dynamic and more useful. Upon running certain commands I want to set the title to the command name; otherwise I want to display the current directory.

Set current directory in .bashrc

Add the following snippet to your .bashrc, somewhere after the PS prompt setting:

# Set the screen title
case $TERM in
    screen*)
        # This is the escape sequence ESC k ESC \
        SCREENTITLE='\[\ek\w\e\\\]'
        ;;
    *)
        SCREENTITLE=''
        ;;
esac
PS1="${SCREENTITLE}${PS1}"

The \w sets the current working folder. The rest of the SCREENTITLE line is a magic escape sequence that somehow sets the title for the screen.

Set titles for the root user

I often find myself using sudo -s to get root shells. I want those shells to be distinct from the usual shells. To accomplish this, I put the following stanza in the .bashrc for root:

# Set the screen title
case $TERM in
    screen*)
        # This is the escape sequence ESC k ESC \
        SCREENTITLE='\[\ekroot: \w\e\\\]'
        ;;
    *)
        SCREENTITLE=''
        ;;
esac

# I don't actually have this line in root's .bashrc, because
# I use the prompt below instead
PS1="${SCREENTITLE}${PS1}"

This adds the static text root: before the prompt.

Make root prompt red

This is not directly related to GNU Screen, but I find it helpful to confirm that I am using a root shell and not a regular one. Add the following snippet to the .bashrc for root:

RED='\[\033[0;31m\]'
NOCOLOR='\[\033[0m\]'

export PS1="${SCREENTITLE}${RED}${PS1}${NOCOLOR}"

Now the root prompt will be red. These are more magical escape sequences I don't pretend to understand, but I do know that you can use other colours if you want.

Set title to program names

I could not find a systematic way of doing this, but I have an ad-hoc method that works well enough. For programs I use regularly and leave running for a long time (such as w3m, newsbeuter, mutt, vim, or top) I have a small shell scripts that performs a benevolent Man-in-the-Middle attack: it intercepts the calls to these programs, sets the screen title, and then calls the actual executable. Here is the script, called runwithtitle.sh :

#!/bin/sh


cmd=`basename $0`

#set the screen title
  case $TERM in
      screen*)
          # Escape all whitespace chars (\s : whitespace)
          titletext=`echo "$cmd $@" | sed -e 's/\s/\\ /g'`
          /usr/bin/screen -X title "$titletext"
          ;;
  esac
/usr/bin/$cmd $@

The basename $0 identifies the name of this command. Then the case statement sets the title. Finally, the command name is run, assuming it lives in /usr/bin.

To use this script, I make a symlink to the script with the name of the command I wish to track:

cd ~/bin
ln -s runwithtitle.sh vim
ln -s runwithtitle.sh newsbeuter

Now when I run vim the local copy of the command (in ~/bin/vim) is called.

I have to use different versions of this script sometimes. If the command takes arguments then I copy the runwithtitle.sh script and change the last line to call the command explicitly. One example of this is chromium, which I always want to run with the --incognito switch. Another example is my quick shortcut d, which I use to conduct searches on DuckDuckGo:

#!/bin/bash

# Wow this is fragile. I had better not have any tabs
# in the query.

# putting double-quotes around phrases I want to keep does not
# work unless I single-quote expressions. This is because
# of how Bash parses arguments

changedargs=`echo $@ | sed -e "s/ /+/g"`
newtitleargs=`echo $@ | sed -e "s/ /\\ /g"`
escquotes=`echo $newtitleargs | sed -e 's/"/%22/g'`

#set the screen title
  case $TERM in
      screen*)
          /usr/bin/screen -X title "s $newtitleargs"
          ;;
  esac

/usr/bin/w3m "https://duckduckgo.com/?q=$changedargs"

I also have to be careful because sometimes commands call other commands. For example, w3m uses sensible-editor to edit textfields, which calls vim, which changes the titles (somewhat unhelpfully). So I hardcode /usr/bin/vim as the editor in the w3m options screen instead of trying to fix sensible-editor.

Startup windows

Often, I want a set of screens to start in certain situations. For example, I have a set of screens that I use for taking notes, and one I use when I am at work. To accomplish this I use screenrc files.

For example, when listening to talks I use the following screenrc:

# Allow copy/paste in Vim?
register [ "\033:se paste\015a"
register ] "\033:se nopaste\015a"

# Startup!
chdir /home/pnijjar/personal/talks
screen -t "talks" /usr/bin/hnb talks.hnb
screen -t "extranotes" /usr/bin/hnb extranotes.hnb

chdir
screen 2
select 0

This creates three windows, and selects the first one for use so that I can take notes. Then, I make a ~/bin/talkscreen command to use this screenrc:

#!/bin/bash

/usr/bin/screen -c ~/.talkscreenrc

Similarly, I can make a different screenrc for work, and then have another small command (workscreen) that calls that screenrc.