読者です 読者をやめる 読者になる 読者になる

$shibayu36->blog;

株式会社はてなでエンジニアをしています。プログラミングや読書のことなどについて書いています。

tmuxで裏側のwindowのコマンドが終了したら、Growlに通知する

tech

 GNU screen の裏にいる Window で完了したコマンドを Growl 通知したい - unknownplace.orgのtmux版が欲しかったので作った。もしかしたら他に何かあるかもしれない。

前提

  • Growlのインストールが必要
  • Growlをコマンドラインから叩ける、growlnotifyが必要

tmuxでもWINDOW環境変数を扱えるようにする

 tmuxでコマンドが実行されているwindowの番号を取得する方法がよくわからなかったので、tmuxのwindowを作った時にWINDOW環境変数に突っ込むことにした。tmux で cdd (別の WINDOW のカレントに移動)する - cooldaemonの備忘録を参考にした。

.zshrcに以下を追記しておく。

# tmuxにもWINDOWを設定
if [ "$TMUX" != "" ] ; then
    export WINDOW=`tmux respawn-window 2>&1 > /dev/null | cut -d ':' -f 3`
fi

裏側のwindowで実行されたかどうか調べるスクリプトの作成

 perlで。https://github.com/shibayu36/config-file/blob/master/bin/cmd-exit-notify.pl においてある。tmux list-windowsでwindowの一覧が取得できるので、それをパースすればactiveかどうか分かる。あとは$ENV{WINDOW}と比較してやれば、現在のwindowとコマンドが実行されたwindowが別かどうか分かる。

#!/usr/bin/env perl
use strict;
use warnings;

my $lastcmd = join ' ', @ARGV;

my $current = $ENV{WINDOW};

my $windows = qx{ tmux list-windows };

my $active;
for my $win (split "\n", $windows) {
    if ($win =~ /^(\d+):.*\(active\)$/) {
        $active = $1;
        last;
    }
}

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

zshのprecmdにhookする

 あとはこのスクリプトを使って、precmdにhookしてあげればよい。

autoload -Uz add-zsh-hook
function cmd-exit-notify() {
    $HOME/bin/cmd-exit-notify.pl `history -n -1`
}
add-zsh-hook precmd cmd-exit-notify

その他

  • 出来ればiTermが非アクティブな時は通知するようにしたいけど、どうすればいいかわからない。
  • 僕のいろんな設定ファイルは https://github.com/shibayu36/config-file においてあるので良ければどうぞ