Linuxカーネルのmakeとか、実行に時間のかかるコマンドを実行して、終わるのを待って眺めるのは辛い。でもその隙に別のことをやると、そのまま完了を待っているのを忘れてしまって時間を無駄にした気持ちになって辛い。 && growlnotify
とかコマンドの後につけるのを忘れたことに気がついて、Ctrl-Cで一旦止めるかどうか悩むのが辛い。
というわけで
zshのフックを適当に使って、普通にzshでコマンドを叩くだけで、閾値以上の時間がかかるコマンドが終わると通知してくれる設定を考えてみた。
- MacのGrowl 対応 ( growlnotify 必須 )
- Linuxのデスクトップ通知対応 ( notify-send 必須 )
- SSH接続先ではトリガ用文字列を出力するので、iTerm2などを使うと通知可能
- トリガ設定はコメント参照
- iTerm2の設定→ Mac - iTerm2で特定文字列をハイライトやGrowl通知する - Qiita [キータ]
.zshrc
などに追加するだけで動くはず。
__timetrack_threshold
に設定する秒数で、通知の閾値を設定できる。デフォルトは20秒。
実行に時間がかかっても通知されたくないコマンド(vimでのファイル編集とかsshとか)を __timetrack_ignore_progs
に列挙すると、それらは通知されなくなる。
ちょっと書き換えれば、メール通知とかも一応出来ると思うけどやらないほうが地球にやさしいと思う。
autoload -U add-zsh-hook 2>/dev/null || return
#
# Notification of local host command
# ----------------------------------
#
# Automatic notification via growlnotify / notify-send
#
#
# Notification of remote host command
# -----------------------------------
#
# "==ZSH LONGRUN COMMAND TRACKER==" is printed after long run command execution
# You can utilize it as a trigger
#
# ## Example: iTerm2 trigger( http://qiita.com/yaotti/items/3764572ea1e1972ba928 )
#
# * Trigger regex: ==ZSH LONGRUN COMMAND TRACKER==(.*)
# * Parameters: \1
#
__timetrack_threshold=20 # seconds
read -r -d '' __timetrack_ignore_progs <<EOF
less
emacs vi vim
ssh mosh telnet nc netcat
gdb
EOF
export __timetrack_threshold
export __timetrack_ignore_progs
function __my_preexec_start_timetrack() {
local command=$1
export __timetrack_start=`date +%s`
export __timetrack_command="$command"
}
function __my_preexec_end_timetrack() {
local exec_time
local command=$__timetrack_command
local prog=$(echo $command|awk '{print $1}')
local notify_method
local message
export __timetrack_end=`date +%s`
if test -n "${REMOTEHOST}${SSH_CONNECTION}"; then
notify_method="remotehost"
elif which growlnotify >/dev/null 2>&1; then
notify_method="growlnotify"
elif which notify-send >/dev/null 2>&1; then
notify_method="notify-send"
else
return
fi
if [ -z "$__timetrack_start" ] || [ -z "$__timetrack_threshold" ]; then
return
fi
for ignore_prog in $(echo $__timetrack_ignore_progs); do
[ "$prog" = "$ignore_prog" ] && return
done
exec_time=$((__timetrack_end-__timetrack_start))
if [ -z "$command" ]; then
command="<UNKNOWN>"
fi
message="Command finished!\nTime: $exec_time seconds\nCOMMAND: $command"
if [ "$exec_time" -ge "$__timetrack_threshold" ]; then
case $notify_method in
"remotehost" )
# show trigger string
echo -e "\e[0;30m==ZSH LONGRUN COMMAND TRACKER==$(hostname -s): $command ($exec_time seconds)\e[m"
sleep 1
# wait 1 sec, and then delete trigger string
echo -e "\e[1A\e[2K"
;;
"growlnotify" )
echo "$message" | growlnotify -n "ZSH timetracker" --appIcon Terminal
;;
"notify-send" )
notify-send "ZSH timetracker" "$message"
;;
esac
fi
unset __timetrack_start
unset __timetrack_command
}
if which growlnotify >/dev/null 2>&1 ||
which notify-send >/dev/null 2>&1 ||
test -n "${REMOTEHOST}${SSH_CONNECTION}"; then
add-zsh-hook preexec __my_preexec_start_timetrack
add-zsh-hook precmd __my_preexec_end_timetrack
fi