To speak to others is to first silence those in whose name we speak. (Callon 1986)

emacs-screen-bash-fu

Today I "wasted" lots of time on a great deal of emacs-screen-bash-fu. It mainly took a lot of time since a lot of the things I did people don't seem to be doing, or if they are they aren't posting it on the net. Thus I'll post the more interesting parts here.

Trying to organize this in a smart way I'll do things file by file. However I will not include the whole files, only the bits and parts containing my new fu.

First lets have a look at .screenrc:

terminfo rxvt-unicode 'Co#256:AB=\E[48;5;%dm:AF=\E[38;5;%dm'
source $HOME/configfiles/.hostspecificscreenrc
setenv LC_SCREEN_RUNNING 1
shelltitle '] |bash'
  1. The first sentence enables 256-color support (since I'm using urxvt). However, this must be combined with the alias mentioned in .bashrc below.
  2. The second sentence includes a separate screen resource file. I've done this because I have my configuration shared between all of my machines using git, but I want a hardstatus string on each host.
  3. The third sentence allows me to detect that screen is running when ssh-ing into a different host from screen. By default (at least on Debian) any environment variables starting with LC_ will be forwarded to the remote host when using SSH.
  4. Last, but not least, the final sentence enables the shell to be able to set the title of the screen-window it is running in. More about that later.

Now we will take a look at .bashrc:

alias screen='/usr/bin/screen -T rxvt-unicode'
alias python='echo -ne "\ekpython\e\\";/usr/bin/python'
alias top='echo -ne "\ektop\e\\";/usr/bin/top'

HNAME=${HOSTNAME}

    if [ "whisky" == "$HOSTNAME" ]; then
    echo 'hardstatus string "%{.Yk} %-w%{.KY} %n %t %{-}%+w %=%{.Yk} %H  %m/%d %C%a \
    "' > $HOME/configfiles/.hostspecificscreenrc
    PROMPT_COLOR="\[\e[33;1m\]"
elif [ "fatboy" == "$HOSTNAME" ]; then
    echo 'hardstatus string "%{.gk} %-w%{.Kg} %n %t %{-}%+w %=%{.gk} %H  %m/%d %C%a \
    "' > $HOME/configfiles/.hostspecificscreenrc
    PROMPT_COLOR="\[\e[33;32m\]"
elif [ "remote.tequila.org" == "$HOSTNAME" ]; then
    echo 'hardstatus string "%{.bW} %-w%{.wB} %n %t %{-}%+w %=%{.bW} %H  %m/%d %C%a \
    "' > $HOME/configfiles/.hostspecificscreenrc
    PROMPT_COLOR="\[\e[1;34m\]"
    HNAME="vanntett"
fi

NAME_COLOR=${PROMPT_COLOR}

    if [ "root" == "$USER" ]; then
    NAME_COLOR="\[\e[1;31m\]"
    ISROOT="root@"
fi

if [ "x" != "x$LC_SCREEN_RUNNING" ]; then
    export PROMPT_COMMAND='echo -ne "\ek${ISROOT}${HNAME}[`basename ${PWD}`]\e\\"'
fi

export PS1="${NAME_COLOR}${debian_chroot:+($debian_chroot)}\u\[\e[1;34m\] \
${PROMPT_COLOR}${HNAME}:\w\$ \[\e[0m\]"
  1. The first alias statement enables the use of 256 colors when running urxvt in screen. This must be combined with the sentence in .screenrc above to work.
  2. The second and third aliases set the title of the screen-window they are run in (if any) before executing the application. So when running python within screen the title of the screen-window it is run in will change to python as long as python is running. For top, it will change to top. These are only two examples. I've created several other aliases also. Keep in mind that this is only useful for applications that don't immediately terminate.
  3. Next we make a variable that contains the host name of the host we are on. I use this later on because for some hosts I want to display their actual host names, for others I want to display a different name.
  4. Next is a three-part if-statement that will run slightly different commands based on what host we are on. Each branch has two commands. The first command creates a hardstatus string and puts it in the host specific screen resource file we talked about earlier. This gives me a different color layout within screen depending upon what host I'm on. The second command sets a variable containing a bash escape sequence representing a color different for each host (we will later use this to have different colored command prompts based on what host we are on). The final branch has an extra statement. The reason is that I don't want to display the standard host name for that host, but rather show the name vanntett.
  5. Next we copy the prompt color variable we created above into a new variable. The reason for this is that we want to use the same color on usernames, unless we are root.
  6. Now we check if we are root. If we are two things are done: First we set the second color variable to red, next we create a new variable containing @root. We do this because when creating screen window names later on we want to add @root to them, if we are root.
  7. Next we check the special LC_-variable we send over ssh. Checking this variable will tell us if we are running under screen or not even if we have ssh-ed in to a remote host. If we are running screen we export the PROMPTCOMMAND-variable. The content of this variable will be run every time a terminal changes (so every time we run a command in a terminal, every time a new terminal is opened and every time we exit an application in a terminal). The command will set the title of the screen window the terminal is running in based on host name, current directory and if we are root or not.
  8. The final command is the command that gives us a different colored command prompt on each host.

Finally we will take a look at .emacs:

(defun set-screen-title ()
  (send-string-to-terminal (concat "\ek"
        "emacs " (buffer-name) "\e\\")))

(let ((term (getenv "TERM")))
  (when (not window-system)
    (add-hook 'window-configuration-change-hook 'set-screen-title)
    (add-hook 'emacs-startup-hook 'set-screen-title)))

This tells emacs to update the screen window name with the name of the buffer we are currently viewing any time emacs is started (in screen running in terminal-mode) and any time we switch buffers.

You might have noticed that I have in no way, shape or form tried to make this a step by step tutorial or explain anything in details. Basically I figure that if you are interested in this stuff you should be able to figure out what is going on. If not, try looking over it again, or send me an angry email complaining about my superior intellect and sarcastic attitude.

Finally I will sum up the fu of these files:

  1. The files are created to work automatically on all of the host I distribute them to.
  2. The color of my command prompt is different depending upon what host I am on. In addition, when logged on as root, the username in the command prompt will be red.
  3. The color of the status bar within screen will also have the same coloration depending on what host I am on
  4. The title of each screen window will be automatically updated in the following ways:
    1. As standard each window will have the title hostname[current working directory], or if the terminal in the screen window is logged on as root root@hostname[current working directory]
    2. The host name will be correct even if one uses ssh from within screen to log on to a remote server
    3. Many programs will update the screen window title as long as they run, such as python. As soon as the programs terminate the title will fall back to the above default.
    4. If emacs is running in terminal-mode within a screen window the title of the screen window will always be the current emacs buffer
  5. All of the above name functions will work both locally and when one ssh-es in on a remote server from within screen.

I hope this inspires you to so similar fu yourself. If you have any ideas about other things that should be done with screen and/or screen and emacs, please drop me a note, I'm itching to do more, but I need some inspiration.

posted on 09 Jun 2010

About me

    • Languages of choice
    • C, python, perl and lisp
    • Current interests
    • GSM-networks and technology, Emacs, Stumpwm, org-mode, philosophy and ethics, microprocessors, Drupal, Latex and writing.