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>
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})"
}
10 comments:
This is extremely cool. Thanks. (Now I have my GNU SCREEN title and my XTERM title set together using readable commands, rather than using screen's terribly conceived auto-titles)
Glad you enjoyed it. Spread the word! I have been looking for a way to do this in bash for years, and others looking for a similar hack will likely have a hard time finding it from google... (how did you run across it, anyway?)
I googled for preexec() bash
because I had seen the zsh preexec example in the Screen infodocs, and I didn't see any good reason why that hadn't been ported to bash. I was about to install the patch when I found your post.
Cool news cool ideas! and cool you also
bembo is my host, by the way, not the random product of subtly interacting escape codes.
Thanks for a great hack to bash!
I've tried to use the precmd & preexec functions used at the bottom of your script, but it seems that I need to setup the variables $SCREEN_RUN_HOST and $SCREEN_HOST somewhere in my .bashrc to get it work correctly.
Could you please share what how you set up those?
TIA
/LM
Oh. That's unfortunate. Those variables are part of some pretty gratuitous hacks in my overall setup; I'll try to correct this "module" so that it doesn't require them.
If possible if you could just share the info on how you set them. I use a setup with a couple of nested screens myself, and if I can read your script correctly, I like the idea how it presents itself.
no not cool
plain f**king awesome!
this should totally be incorporated into bash by a patch instead of hack
but meanwhile
thanks for the hack! ;)
cool trick with the LC_ vars to shorten the prompts, too!
I'm late to the party, but anyway: Thanks for this - I've been looking for a way to keep track of when I started a command. Using PS1 to get the current time in the prompt is not really a solution as others have noted. But using preexec I can get the time in the terminal window title, without messing with the messages from the running program.
One small problem I noted: If one has HISTTIMEFORMAT set, the 'history-piped-through-sed' removes the history index, but the timestamp is still there. Adding 'local HISTTIMEFORMAT=""' before fixes this without interfering with the user's setting of HISTTIMEFORMAT.
(If you're wondering why I want to remove the history timestamp when my goal was to keep track of when a command started: I want to use different time formats, so my preexec function contains a call to 'date +someotherformat')
Post a Comment