GNU screen の裏にいる Window で完了したコマンドを Growl 通知したい

というようなことをつぶやいていたら、

Twitter / hchbaw: @typester 最近になって screen -Q windows とできるようになってますね。

と教えていただいた。

-Q コマンドというのは -X と同じようなものだけど、コマンド結果を screen 内のステータス領域ではなく標準出力で得ることができる。また、-X はつねに実行時にそれ自体がアクティブな screen セッションになるのに対し -Q はアクティブなセッションにクエリを投げる感じで、セッションが切り替わらない。(この辺は理解が怪しいので突っ込み歓迎)

それでそれを使うと

screen -Q windows

と実行することで :windows で echo されるのとおなじ文字列を標準出力で得ることができる。その出力をパースすれば、自分が screen の裏にいるかどうか判断することができるというわけ。

zsh でコマンド完了時(正確にはプロンプトが表示される直前)に呼ばれるフックは precmd なので以下のように定義:

function precmd() {
    $HOME/bin/precmd.pl `history -n -1 | head -1`
}

シェルスクリプトかけないので Perl に逃げています。 で、precmd.pl は以下のような感じ:

#!/usr/bin/perl

use strict;
use warnings;
use FileHandle;

my $lastcmd = join ' ', @ARGV;

my $window = $ENV{WINDOW};

my $windows = qx{ screen -Q windows } or die "Your screen doesn't support -Q";
qx{ screen -X redisplay };

my $active;
for my $win (split "\x20\x20", $windows) {
    my ($num, $flag, $title) = $win =~ /^(\d+)(.)? (.+)/;

    if ($flag and $flag eq '*') {
        $active = $num;
        last;
    }
}

if ($window != $active) {
    open my $fh, "|/usr/local/bin/growlnotify -t 'GNU screen window $window'" or die $!;
    print $fh sprintf 'command done: "%s"', $lastcmd;
    print $fh "\n";
    close $fh;
}

これで、コマンドが完了した場合にピコーンと通知が来るようになりました。

長い make や wget の時に超絶便利ですね!

書き忘れましたが、現在この機能をつかうためには開発版の screen を使用する必要があります。

by typester / at 2010-03-23T11:22:00 / screen · zsh / Comments(0)