Mere Code

Diverse Topics of General Interest to the Practicing Programmer

Undistract me

Here’s a thing that happens a lot to me: I’m doing some work, and as part of that work I need to run a command in my terminal that takes a little while. I run the command, look at it for about a second and then switch to doing something else – checking email, perhaps. I get deeply involved in my email checking, and then about twenty minutes later I switch back to the terminal and see the command has finished. For all I know, it finished nineteen minutes ago, and I was just too engrossed to notice it.

This is a big productivity sink for me, especially if the command happened to fail and need retrying. I’m not disciplined enough to just sit and watch the command, and I’m not prescient enough to add something to each invocation telling me when a command is done. What I want is something that alerts me whenever long running commands finish.

Well, that thing now exists, thanks to glyph’s script that provides precmd and postcmd support to bash and a lot of help from Chris Jones of Terminator.

To use it right now:
 $ bzr co lp:~jml/+junk/shell-tools
 $ . shell-tools/long-running.bash
 $ notify_when_long_running_commands_finish_install

You’ll see that if you run a command that takes over 30 seconds to complete, it will pop up a notification, which should hopefully take you away from whatever it was you are doing and back to the task at hand.

If you look at the code, you’ll see that it installs two hooks: precmd and preexec. preexec runs just before the shell launches a command, and precmd runs just before it prompts for the next command. Our preexec stores when the command was launched and the precmd checks to see if it finished within a certain time frame. If not, it sends out a notification.

Currently, you’ll get a notification when you finish reading a long document, since the command finishes a long time after the command starts. Obviously this isn’t ideal. I think the fix is to only send notifications when the shell doesn’t have focus. Unfortunately, that’s a little tricky and I think is going to be highly terminal specific.

Anyway, I’m a total shell newbie, so I’d love to know if there’s any way this could be done better.  Also let me know if you find this useful, or you know of someone who has already done this.


Martin Lindhe on 2012-01-25 14:56
there is also a util called "zenity" that creates gnome dialogs from the shell
Martin Lindhe on 2012-01-25 14:53
FYI, you could also try the "beep" command to sound the pc speaker from your shell script
jml on 2012-01-24 09:18
@jam A blacklist might not be a bad idea. As it is, I'm not minding the pop ups when focused though.

As for the '; n' thing. I've tried it before. What happens is I tend to forget to put it on, then feel lazy and stupid when I get distracted again.
jam on 2012-01-24 08:44
Why not just have it blacklist specific commands. For example "vi/emacs/less". I don't know specifically how you are looking at text for a long time, but it seems the commands that run are going to be fairly different.

There are also easy things if you know a command is going to be slow, like setting up a shell command to run a sound file/pop up a notification, and alias it to something short like 'n' and then just

command; n

It isn't quite as auto-magical, but it does avoid false positives.
jml on 2012-01-24 00:22
@Steve Terminator has plugins that do that. However, what I wanted was something that I didn't have to enable or disable at all, and something that wouldn't do false positives even if the command spewed stuff all the time.

@Tuure Good point. My hunch is that problem is best solved at the notify-send level.
Tuure Laurinolli on 2012-01-23 22:39
This seems like it would only work on local machine. Something similar for remote machine would have to have a back-channel to your local machine, e.g. with ssh -R. I think I'll hack on something along these lines tomorrow night.
Steve McInerney on 2012-01-23 22:04
Hmm. I'm a loooong time konsole fan, and that functionality is built in. "View; Monitor for Silence" or "Monitor for Activity".
Use it quite a lot for long running commands/rollouts etc.
Used to be better in previous versions, that you could adjust the time before alert; but alas, that's been removed.

I have my layout setup such that the konsole tab bar (at the bottom where it belongs) is *always* visible, so when something changes, it flashes, I see it instantly.
jml on 2012-01-23 18:11
@Daniel_Bo: No reason, just a simple matter of patching GNOME Terminal a DBUS API that lets you ask if the current shell has focus, and getting that patch upstream.

@glyph: Updated.
glyph on 2012-01-23 17:37
Interesting application!

Please update your links, though: that post now lives here. (LiveJournal is dead to me.)
Daniel Bo on 2012-01-23 16:00
Wonderful and extremely useful. Why can't this be modified so the focus issue is solved for GNOME Terminal and then be shipped by default?

It seems like one of those polish features that Ubuntu needs and wants.