This, from a posting in my blog a few months ago, has gone from being an idea that I thought was cool to one of the best little hacks I've coughed up in recent memory. I quote it in full here:
==================
I spend a lot of time in bash. For the uninitiated, bash is a system that
you'll find on most unix machines and, thankfully, some windows and every
Mac out there. At first blush, it's no more than a command-line interface,
and therefore off the radar of most users who see such things as an anachronism
they'd rather forget.
I do nearly everything in bash. I READ MY EMAIL FROM A COMMAND LINE, which is
why I eschew marked-up email. I navigate directories, edit files, engage in my
daily source code checkout and delivery, search for files, search inside files,
reboot my machine, and even occasionally browse web pages from the command line.
bash is the heart and soul of my digital existence.
The trouble is that I tend to have about 6 bash windows open at a time. At
work today, I had one running a web server, another fiddling with my database,
a third, fourth, and fifth editing different files, while a sixth was grinding
away through my machine trying to record the names of every file on the system.
Why? Because it's handy to be able to search through such an archive if you
want to know where to find an object by filename.
When you do this, you end up with lots of windows in your control bar named
simply, "bash." This is fine if you only have one of them, but its agony when
you have 6 or more.... and two dozen other things going on. I have three
monitors under the simultaneous command of one keyboard/mouse pair and I still
feel the need for more. Each of those windows has several bash terminals open.
So I've plunked this together. First, place these lines in your
.bash_profile:
export PROMPT_COMMAND='export TRIM=`~/bin/trim.pl`'
export PS1="\[\e]0;\$TRIM\a\]\$TRIM> "
trap 'CMD=`history|~/bin/hist.pl`;echo -en "\e]0;$TRIM> $CMD\007"' DEBUG
I went through and wrote dozens of paragraphs on how this all works and exactly
why it is set up the way it is, but you're not really interested. Trust me.
There is an entire chapter of a book in why I did "CMD=...
; echo..." on that
third line. Many people (including bluehost, where my other domain is hosted)
are still using and old version of bash with major bugs in how it handles traps,
so we're stuck with this. You can remove the CMD and replace it with
$BASH_COMMAND if you are current on your bash version and feel like doing the
research.
Anyway, the first script I use is here. It creates a nice prompt that contains
your machine name and directory, chopped down to a reasonable length:
============trim.pl===========
#!/usr/bin/perl
#It seems that my cygwin box doesn't have HOSTNAME available in the
#environment - at least not to scripts - so I'm getting it elsewhere.
open (IN, "/usr/bin/hostname|");
$hostname = <IN>;
close (IN);
$hostname =~ /^([A-Za-z0-9-]*)/;
$host_short = $1;
$preamble = "..." if (length($ENV{"PWD"})>37);
$ENV{"PWD"} =~ /(.{1,37}$)/;
$path_short = $1;
print "$host_short: $preamble$path_short";
==============================
There's a warning at the top of this blog post that you should read now before
you start asking stupid questions like, "Why didn't you just use the HOSTNAME
environment variable via @ENV?" Simple: Because that doesn't work for all the
systems I tried it on.
Now for the really cool bit. Remember line 3 of the .bash_profile addition?
trap 'CMD=`history|~/bin/hist.pl`;echo -en "\e]0;$TRIM> $CMD\007"' DEBUG
It's dumping the trim.pl script output in the same container as before, printing
to both the command prompt and the window title, but this time it's adding the
command that you just typed! This is why you don't want to be doing all
of this in your .bashrc: any script you run (on my machine, man is one of them)
will trigger this thing on every line. man's output gets seriously garbled by
what we're doing here. We're not exactly playing nice with the terminal.
To grab the command you just typed, we take the bash's history and dice it up a
bit:
===========hist.pl============
#!/usr/bin/perl
while (<STDIN>)
{
$line = $_
}
chomp $line;
$line =~ /^.{27}(.*)/;
print $1;
==============================
So now, I have a bazillion windows going and they say things like:
castro: /home/ronb blog
Ron-D630: /C/ronb/rails/depot script/server
Ron-D630: /C/ronb/rails/depot mysql -u ron -p
Ron-D630: /C/ronb/rails/depot find . > /C/ronb/system.map
Ron-D630: /C/ronb/rails/depot vi app/views/cart.html.erb
Ron-D630: /C/perforce/depot/ p4 protect
Ron-D630: /C/perforce/depot/ p4 sync -f
Ron-D630: /C/perforce/depot/
From the happy little bar at the bottom of the screen, I can now tell which is
which at a moment's glance. And because we've set PS1, as soon as a command
finishes executing, the command name is replaced by just the output of trim.pl
again.
UPDATE (same day):
This stuff (the .bash_profile entries) laid all kinds of hell on me when I
tried it in my .bashrc. Your .bashrc is executed by non-interactive scripts
whenever you invoke bash as a language. I hit this when I was trying to use
man. All sorts of garbage (the complete text of my .bashrc, plus escape
charecters) showed up at the top of the man page. I would suggest testing
this gem with a quick 'man man' invocation at the command line once you get
it all together.
I guess it's time for me to pull the custom garbage out of my .bashrc and put
it where it belongs...
Incedentally, I found myself typing 'man trap' at one point in this process.