ちなみに

火曜日の空は僕を押しつぶした。

blink(1) でテストの結果を表示するようにした話

追記: Gem にしたのでご活用ください: http://rubygems.org/gems/guard-notifier-blink1

blink(1)id:hxmasaki から1台譲ってもらったので Guard で走らせているテストの結果を通知するようにした。(一ヶ月くらい放置してしまってたのを今日やっと触れた。)

すでにやっている人がいるだろうと探してみると、一応 guard-blink1 という Gem があった。しかし、これはただ blink1-tool を呼び出す部分をラップしてだけで、結果をファイルに書きだしてそれをさらにウォッチして通知のコードを呼び出すように自分で書かないといけない。つまり結果が出てからちょっとだけ遅延が発生する。これはすごい勢いでコードを書いているときにはどのテストの結果なのか分からないことがあってつらい。

仕方ないので自分で書くことにした。Guard は guard-rspec 使ってるだけでぜんぜん詳しくなかったので、どうやって通知をやっているのかを調べた。結果、Guard の Notifier は独自のものを追加する仕組みがなさそうで、無理やり追加することになった。

Guard::Notifer::Base を継承したクラスを作って、Guard::Notifier::NOTIFIERS という定数に無理やり突っ込むと使えるようになる。

available?(opts = {}) というクラスメソッドと、notify(message, opts = {}) というインスタンスメソッドを実装すれば良さそう。

blink1-tool--rgb=r,g,b というオプションを取るのだけれど、0-255 で指定するので、CSSスタイルで書けるように Colorable という Gem を使った。HEX <-> RGB <-> HSB する Gem は何がデファクトなのかよく分からなかった。

以下のようになった。

module ::Guard
  module Notifier
    class Blink1Notifier < Base
      require "colorable"

      DEFAULT_COLORS = {
        success: "#005000",
        pending: "#505000",
        failed:  "#500000",
        notify:  "#000050",
      }.freeze

      DEFAULT_COUNT = 3

      def self.available?(opts = {})
        super && command?("blink1-tool")
      end

      def notify(message, opts = {})
        super
        type = opts[:type]
        colors = opts[:colors] || {}
        color = colors[type] || DEFAULT_COLORS[type]
        count = opts[:count] || DEFAULT_COUNT
        glimmer color, count
      end

      private
      def glimmer(color, count)
        color = color.to_color.rgb.join(",")
        system "blink1-tool", "--rgb=#{color}", "--glimmer=#{count}"
      end

      def self.command?(name)
        system "type #{name} > /dev/null 2>&1"
      end
    end

    NOTIFIERS << {blink1: Blink1Notifier}
  end
end

これをめんどうくさいので Guardfile に書いてしまって、notification で指定してやる。僕の場合は TerminalNotifier も使っているので以下のようにしている。なんか2つも通知されると過剰な気がするし外しても良さそうな気もしてきているけれど。

notification :terminal_notifier
notification :blink1

これで無事にテストの結果によって色分けして光るようになった。

もちろん Windows では type コマンドが全く違う用途になっているので動かない。