"This bash shell is now fully operational!"

Wednesday November 29, 2006

For many years, I have been a fan of the Z shell. In particular, I loved its programmable completion and many hookable interactive events.

As the years have gone by, however, Bash has slowly re-taken the ground that ZSH originally claimed. Programmable completion, ever more elaborate prompts, and so on became as commonplace in bash configurations as in ZSH. In addition, Bash has had better Unicode support for a long time. The one thing that left ZSH on top of the heap for me was the presence of two hookable events: "precmd" and "preexec", which allowed me to set the title of a ZSH terminal window to be whatever command was currently running. For a variety of reasons, this ability to quickly identify windows has long been immensely useful to me and I was reluctant to give it up.

However, one night a few weeks ago, I was haplessly tab-completing some heinous unicode filename and ... something happened. I'm not really sure what - it may even have been my own fault. However, rm -fr é¢ñ/<tab> somehow became "rm -fr \x00 \x00 \x00 ~" (or something along those lines) and only a very quick control-C saved my home directory.

Knowing that Bash would have Done The Right Thing in this situation thanks to Readline's UTF-8 input support, It was finally time for me to make the switch. I just needed to see if there was any hope of saving my beloved xterm titles on my way over there.

It turns out, there is. Submitted for your approval: zsh-compatible precmd and postcmd support in PURE BASH!

There was apparently a problematic patch to bash at one time which provided similar functionality, but it isn't necessary! You can have zsh-style custom xterm titles in versions of bash all the way back to 2.05b with the above file.

Here's a simple example, which you can use with the above script:

set_xterm_title () {
local title="$1"
echo -ne "\e]0;$title\007"

precmd () {
set_xterm_title "${TERM} - ${USER}@${HOSTNAME} `dirs -0` $PROMPTCHAR"

preexec () {
set_xterm_title "${TERM} - $1 {`dirs -0`} (${USER}@${HOSTNAME})"