Vim 8.0 で追加された機能 v_<C-a>/v_<C-x>

カーソル下の数字などをインクリメントする <C-a> が Visual モードでもできるようになりました。
選択した範囲の数字に対してインクリメントをすることが出来ます。

[v_g<C-a>/v_g<C-x>]

これと似た機能で v_g<C-a>/v_g<C-x> というのも追加されました。
これは

1.
1.
1.
1.

というような数字のリストが合った時に 2番めの 1. に移動して、3行を Visual 選択してから g<C-a> を押すと

1.
2.
3.
4.

というようにインクリメントされます。

Vim 8.0 がリリース!!

ついに Vim 8.0 がリリースされました!!!

https://groups.google.com/forum/#!topic/vim_dev/CmiGxtJ7fn4

Vim 7.0 がリリースされたのが 2006年5月になるので、約10年ぶりのメジャーアップデートとなります。
わたしは Vim 7.3 あたりから Vim を使い始めたので今回がはじめてのメジャーアップデートになりますね。
Vim 8.0 の主な新機能は以下になります。

  • Asynchronous I/O support, channels, JSON
  • Jobs
  • Timers
  • Partials, Lambdas and Closures
  • Packages
  • New style testing
  • Viminfo merged by timestamp
  • GTK+ 3 support
  • MS-Windows DirectX support

Vim 8.0 の詳細に関してはこちら を参照してください。
基本的にエンドユーザにはあまり関係がないですが、非同期処理やラムダの実装など、Vim プラグイン製作者に取ってはとても大きな機能が追加されています。
Vim 8.0 がリリースされたのでこれを期にいろんなプラグインが出てくるんじゃないかなーと思います。
何はともあれお疲れさまでした。

Vim 7.4.2304 で Timer のコールバック内で timer_stop() できるようになった

以前、『コールバック関数内で timer_stop() 出来ない』という問題があったんですが、Vim 7.4.2304 でこの問題が修正されました。

function! Test()
    let disp = { "value" : 0 }
    function! disp.call(...)
        echo self.value
        let self.value += 1

        " 5回呼び出されたら止める
        if self.value > 5
            call timer_stop(self.id)
        endif
    endfunction

    " 辞書関数をコールバックとして登録
    let disp.id = timer_start(500, disp.call, { "repeat" : -1 })
endfunction

Ruby の refinements で特異メソッドを定義する時の注意

さて、次のようにクラスオブジェクトに対して特異メソッドを定義するとエラーになります。

module StringEx
  refine String do
    class << self
      def homu
        "homu"
      end
    end
  end
end

using StringEx

# Error: undefined method `homu' for String:Class (NoMethodError)
p String.homu

つい、通常のクラスと同じように class << self を行いたくなるんですが、これでは上手く動作しません。 ここでいう selfstring ではなくて refinement のオブジェクトでラップされた String なので、これでは String に特異メソッドは定義されないからです。

[String.singleton_class を使う]

なので、self ではなくて String.singleton_class を使用すると動作します。

module StringEx
  refine String.singleton_class do
    def homu
      "homu"
    end
  end
end

module M
  using StringEx

  # OK 呼び出せる
  p String.homu
  # => "homu"
end


module M2
  # NG 呼び出せない
  # error: undefined method `homu' for String:Class (NoMethodError)
  p String.homu
end

これでおっけー

Ruby で無名スコープみたいなのを記述する

C++ では {} で任意の箇所に無名スコープをつくることができます。

int value = 10;
{
    int count = 3;

    // スコープの外の変数にアクセスできる
    value += count;
}
// スコープの中で定義した変数はスコープ外でアクセスはできない
// value = count;

Ruby の場合、似たようなきのうに begin 〜 end がありますが、この場合は、

begin
    value = 42
end
# スコープ外からアクセスできる
p value + 10

このようにスコープ外からアクセスする事が出来ます。

[#instance_eval を使う]

このような問題を回避する場合は、#instance_eval を利用する事が出来ます。

value = 10
instance_eval do
    count = 3
    value += count
end

p value
# => 13

# スコープ外からはアクセスできない
# value = count

べんり。

Ruby で動的に refine を定義する

Ruby で refinements を利用すると次のようにクラス拡張を特定の範囲でのみ適用させることができます。

module StringEx
    refine String do
        def twice
            self + self
        end
    end
end

using StringEx

p "homu".twice
# => "homuhomu"

上記の場合は StringEx モジュールを定義してそれを using しているのですが、次のようにして無名モジュールを定義することも出来ます。

using Module.new {
    refine String do
        def twice
            self + self
        end
    end
}

p "homu".twice
# => "homuhomu"

局所的にクラス拡張を行ないたい場合に便利。