Wednesday, 26 November 2008

Shell features

Here are two features I would like to see in a Unix shell:
  • Timing: The shell should record how long each command takes. It should be able to show the start and stop times and durations of commands I have run in the past.
  • Finish notifications: When a long-running command finishes, the task bar icon for the shell's terminal window should flash, just as instant messaging programs flash their task bar icon when you receive a message. If the terminal window is tabbed, the tab should be highlighted too.
You can achieve the first with the time command, sure, but sometimes I start a command without knowing in advance that it will be long-running. It's hard to add the timer in afterwards. Also, Bash's time builtin stops working if you suspend a job with Ctrl-Z. It would be simpler if the shell collected this information by default.

The second feature requires some integration between the shell and the terminal. This could be done via some new terminal escape sequence or perhaps using the WINDOWID environment variable that gnome-terminal appears to pass to its subprocesses. But actually, I would prefer if the shell provided its own terminal window. There would be more scope for combining GUI and CLI features that way, such as displaying filename completions or (more usefully) command history in a pop-up window.

I have seen a couple of attempts to do that. Hotwire is one, but it is too different from Bash for my tastes. I would like a GUI shell that initially looks and can be used just like gnome-terminal + Bash. Gsh is closer to what I have in mind, but it is quite old, written in Tcl/Tk and C, and not complete.


zooko said...

I've been using this script to get timing as well as to get a record of the stdout/stderr and what the command-line was. Of course, this script messes up certain issues due to "how many levels of quoting", which is the perennial bane of shell scripting for me.

LOG=zooko.`echo "${CMD}"|tr -Cs [:alnum:] _|cut -d'_' -f-3 2>/dev/null`.log.txt
LOG=`echo ${LOG} | tr -s .`
mv --backup=numbered "${LOG}" "${LOG}-" 2>/dev/null
mv --backup=numbered "${OTHER_LOG_FILE}" "${OTHER_LOG_FILE}-"
echo "$CMD" > "${LOG}"
date >> "${LOG}"
( time eval $CMD ) 2>&1 | tee -a "$LOG"

Mark Seaborn said...

Zooko: is there a reason you do

time eval $CMD

instead of

time "$@"

I suppose the former will handle the environment-setting syntax "VAR=value cmd"; the latter will handle spaces in arguments properly.

Zooko said...

Reason? Probably sheer ignorance. I will try

time "$@"


Wade Simmons said...

I know this post is over a year old, but I thought you might be interested to know about a feature in ZSH that does what you want for automatic timing. If you add the following to your config:


Then anytime you run a command that takes over 2 seconds, it will print the `time` statistics out to the terminal.