Tea is ready - Command line kitchen timer for OS X Mavericks

OS X のターミナルからコマンドラインで使うタイマーコマンドを作ってみました。 ウィジェットiPhone アプリなど探せばいくらでもあるのでしょうが、たとえばカップ麺を作る時にお湯を入れてから探して起動してセットしたりしていると、それだけで1分近く経っちゃうんですね。

https://github.com/kaz-utashiro/tir

This is the command line kitchen timer for Apple OS X Mavericks. It will show the message on terminal, notification center, and read it out using audible speech. Default message is "Tea is ready" and the word "tea" is replaced by the command argument. If the first argument is number, command wait that time in second. Playing iTunes is paused automatically during speech.

Mavericks では AppleScript から通知センターの機能が利用できるようになったらしいのでそれを使って。 名付けて TIR (Tea Is Ready)。 これなら秒速で実行可能です。 英国文化圏では、お茶はもちろん、ご飯の準備ができたときにも "Tea is ready" と言うのだそうです。

最初は alias だったのが、徐々に複雑になってきたので sh になって、それも破綻してきたので、生まれて初めての bash スクリプトになりました。 というかシェルスクリプトで関数を使ったのが初めてで、関数がコマンドのように振る舞うのも知らなかった。

使い方は簡単で

tir

と実行すると、Tea is ready と表示すると共に、通知センターにメッセージを表示し、ついでに say(1) コマンドを使って内容を読み上げます。

tir 180

とすると180秒待ってからメッセージを表示します。

tir 3m Your ramen

とすると、3分経ってから Your ramen is ready と言ってくれます。

デフォルトの声が気に入らない場合には

tir -v Hysterical

のように声を指定することができて、

tir -r 5min Noodle

と -r オプションを指定すると、毎回ランダムに声を選びます。 スピーカーのボリュームが小さくなっているかもしれない場合は、

tir -V100

のように -V オプションで一時的にボリュームを上げることもできます。 システムの音量を変更するので音楽を再生しているような時には突然大きな音になってしまうので注意が必要です。 iTunes については再生中であれば一時的にポーズするようにしてありますが、それ以外のアプリのことはわかりません。

いつもターミナルを開いている人にだったら結構使えるんじゃないでしょうか。

ロングバージョン

さて、-v オプションで選べる声中には結構面白いものも入っていて、選択リストは

say -v ?

と実行すると見ることができます。

この中の Good News という声を使うとなかなかゴージャスな感じになることを発見しました。 ラーメンが出来上がったことを威風堂々のメロディにのせて歌い上げてくれるので、モチベーションも高まるのではないでしょうか。 こんな風に実行してみます。

tir -w 3min -v good -m 'ramen is ready ee ramen is ready, your ramen is ready ramen is ready'

結果はこうなりますw。 画像は手持ちの写真をテキトーに並べてみました。


Ramen is ready - YouTube

参考

通知センターを利用するのはこの記事が詳しい。

上の記事でも紹介されていますが、コマンドラインから利用するにはこんなツールがある。 大げさなので使ってませんが。

cdif / sdif / watchdiff now runs on Linux

OS X でしか使っていなかったのですが、Linux で実行してみたら使えなかったので修正しました。

  • 端末の幅を取得するのに stty を使っていたが、仕様の違いがあるので tput を使うように変更
  • Text::Glob は標準モジュールだと思っていたが違ったので使わないように変更

また、一時ファイルの取り扱いが変わっています。

  • 従来は /tmp にファイルを作成して使用後に削除していた
  • それを IO::File::new_tmpfile を使うように変更
    • これだとファイルをオープンすると同時に unlink するので削除する必要がない
    • そのため異常終了してもファイルが残らない
  • diff コマンドに与えるパスは /dev/fd/ を使うように変更

追記

会社の FreeBSD で試してみると /dev/fd/3, /dev/fd/4 が開けないといいますね。 CLOSE ON EXEC の解除ができていないのでは疑ったのですが、そうではなくてファイルシステムの問題のようです。 マニュアルを見ると devfs(5) は 0, 1, 2 しか提供しないので、fdescfs(5) を使えと書いてあります。 こういう場合は設定を変えてくださいという方針でいいんでしょうかね。

追記2

sdif, cdif, watchdiff を統合して sdif-tools というリポジトリで管理するようになっています。

CPAN にもリリースしたので、cpanminus でインストールできます。

$ cpanm App::sdif

watchdiff -- cdif wrapper for monitoring command result

最近、gitbub で iij/watch というコマンドがひっそりと公開されました。 管理者の yasuoka 君は以前の同僚で、このコマンドは2000年に一緒の部署で働いていた時にみんなで作ったものですね。 元々は BSD/OSwatch というコマンドがあって、ちょっと拡張しようといじってたら結局作り直しちゃったやつです。 ずっと社内で使っていたものを公開したのには何か理由があるようですが、詳しいことは知りません。

このコマンドの機能は、指定したコマンドを定期的(デフォルトでは2秒おき)に実行して結果を画面に出すだけです。 少し工夫してあって、変更された部分を反転できるようになってたり、 出力が画面に入り切らない時には、スクロールして見ることもできます。

たいしたものではないけど意外と便利で、今でもたまに使ったりします。 たとえば、こんな感じ。

  • WiFi の電波が取れないなー、なんでかな〜てな時

    watch ifconfig -a

  • やっべー、ディスクぎりぎりだよ、足りるかあ〜てな時

    watch df

  • ネットワーク調子悪いなあ、なんか起こってるのかしらん?てな時

    watch netstat -s

まあ、これでもいいんだけど、反転だけではどうも色気がないんですね。 ncurses は色にも対応しているようなので、そういうの使うという手もあるのだけど、変更部分を調べる仕組みが単純に作ってあるので、行が増えたり減ったりすると途端にお手上げなわけです。

だったら、せっかく cdif で色が出るようにしたんだから、それを使えばいいじゃんということで作ってみました。 こんな感じの画面が2秒おきに表示されると考えておくんなさい。 cdif の変更点は、単に余計な部分を表示しないようにしただけです。 あ、実装言語は Perl ですよ。

f:id:uta46:20140215223419p:plain

似たようなツールはほかにもたくさんありそうですけどね。 watchdiff は、デフォルトでは垂れ流しモードなので、画面を書き換えずにスクロールしていきます。 最近はマルチウィンドウ環境が前提なので、その方が案外使いやすい場面も多いのではないかと思います。

しかし、en0 と連動する p2p0 ってインタフェースは一体何なんでしょうか? などという今まで気にもしなかかったことも、ビジュアル化することで気がついたりするわけです。 どうも、AirDrop と関係があるくさいです。

ちなみに watch コマンドで同じような画面を見ると、こうなります。 これでは、どこが変わったのかさっぱりわかりません。 ubuntu にも watch コマンドがあるらしいですが、それだとどう見えるのか気になるところです。

f:id:uta46:20140215232114p:plain

即席なので実装は粗粗、マニュアルテキトー。 特に端末制御周りは手抜きで、OS X 以外で動くかどうかはかなり怪しいです。 何かあったら github の issues でもなんでも適当にどうぞ。

NAME

watchdiff - repeat command and watch the differences

SYNOPSIS

watchdiff option -- command

Options:

    --refresh=#     refresh screen count (default 0)
    --interval=#    interval time between execution in second (default 2)
    --count=#       command repeat count (default 1000)
    --[no]date      show date at the beginning (default on)
    --[no]silent    do not show same result (default off)
    --[no]newline   print newline after command result (default on)
    --exec          set executing commands
    --diff=command  diff command used to compare result

Example:

    watchdiff df

    watchdiff --silent df

    watchdiff --refresh 5 --noclear -- df

    watchdiff --refresh 1 -- netstat -s -p ip

    watchdiff --refresh 1 --exec uptime --exec iostat --exec df

    watchdiff -s --refresh 1 --diff 'sdif --cdif -U100' -- netstat -sp ip

    watchdiff --nodate --nonewline --count=18 --interval=10 date

INSTALL

cpanm App::sdif

AUTHOR

Kazumasa Utashiro

https://github.com/kaz-utashiro/sdif-tools

SEE ALSO

diff(1), cdif(1), sdif(1)

COPYRIGHT

Use and redistribution for ANY PURPOSE are granted as long as all copyright notices are retained. Redistribution with modification is allowed provided that you make your modified version obviously distinguishable from the original one. THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES ARE DISCLAIMED.

ANSI 端末の216色カラーテーブル

あ、それから、なんとなく sdif--colortable というオプションが入ってます。 こんなのね。

最初の列は横縞、2番目の列は縦縞に見えます。 3番目はどっちかなあという感じ。

RGB の値から輝度を計算するのには次の式を使います。 明るさに与える影響は、緑が6割もあるので、緑の変化がはっきり見えるんですね。

輝度 = 0.298912 * R + 0.586611 * G + 0.114478 * B

f:id:uta46:20140201133622p:plain

cdif v2.9 / sdif v2.6 Latin and Russian support

ラテン系の言語とロシア語に対応しました。 タイ語も処理は一応入れてみたけど、ちゃんと表示できません。 例文は質問サイトから拝借。

漢字の連続をひとつの単語として処理するのはやめました。 これで中国語もデフォルトのままで問題ありません。 日本語については若干振る舞いが変わりますが、それほど問題ではないと思うし、ちゃんと見たい時には --mecab オプションを使った方がいいです。

それから、変更部分の背景色を変更しました。 実際に使ってみると、左右が同じ色の方が比較しやすいのと、シアンやマジェンタに赤や青を乗せると判別しにくいからです。

Français / French

f:id:uta46:20140201125506p:plain

Deutsch / German

f:id:uta46:20140201125617p:plain

Русский / Russian

f:id:uta46:20140201125638p:plain

cdif/sdif でいろんな言語を試してみた / multi language trial

Korean

多分大丈夫だろうと思ってはいたが、韓国語はなんの問題もなく処理できる。

As expected, Korean is fine.

f:id:uta46:20140131140507p:plain

Chinese

中国語は、案の定漢字の連続を一単語として処理すると塩梅が悪い。 -B オプションをつけるとうまく行っているような気がする。

Chinese works ok with -B option for cdif.

f:id:uta46:20140131140630p:plain

Arabic

よもやと思ってアラビア語をやってみた。

Arabic doesn't work.

f:id:uta46:20140131140858p:plain

やっぱり駄目だったか...

そもそも、どうしてアラビア語の部分だけではなくて全体が左右反転してしまうのかとか、まったくメカニズムがわからない。

ちなみに、アラビア語はサンプルがみつからなかったので、雪国の冒頭部分の日本語と英訳を Google で翻訳したものである。

cdif/sdif 256色対応

cdif/sdif で ANSI の256色指定ができるようにしてみました。 デフォルトを換えちゃいましたよ。 実際には、6x6x6 の216色です。 うまい指定形式を思いつかないので、24段階のグレースケールには未対応です。 いい考えがあったら教えてください。

ANSI 256 color support

  • Actually 216 colors (6x6x6)
  • Format
    • Foreground / Background
  • Color
    • 000 .. 555
    • 000000 .. FFFFFF

f:id:uta46:20140127131846p:plain