RubyでReadline

RubyはReadlineライブラリに対応しています。代表例としてはirb、その他にもdebug.rbなんかでも使われていますね。Windows環境でも使えるようになっているのですが、実は困った点があります。DOS窓コマンドプロンプト)のサイズを変更すると、表示がぐちゃぐちゃに乱れてしまうのです。

vimirbがメインの開発環境なので、irbが広い画面で使えることは非常に重要になります。RDE、RDT等も開発環境の選択肢としてはあるのですが*1、お手軽さで言えばvimirbははずせません。そんなわけで(仕方なく)調べまくり、1年後に^^;たどりついたのは以下のようにすれば良いという結論でした。

site_ruby/1.8/readline.rb

require 'readline.so'

module Readline
  alias :readline_so :readline
  def readline(*a)
    unless @@rl_prep_called ||= false
      require 'dl'
      DL.dlopen('readline.dll')['rl_prep_terminal', '0I'][1]
      @@rl_prep_called = true
    end
    readline_so(*a)
  end
  module_function :readline_so, :readline
end
  • site_ruby/1.8/readline.rbは上記内容で新しく作ります。このpathにこの名前で置くことが重要です。こうしておくとrequire 'readline'したときにreadline.rbが読み込まれます。
  • そのうえでreadline.rbの中でreadline.soを読み込み、モジュール定義を修正します。aliasとmodule_functionは、モジュール関数を置き換える際の定石のようです。
  • 修正のポイントですが、DLライブラリを使って、readline.dllのrl_prep_terimnalというAPIを呼び出します。readline.dllのソースを追いかけたところ、DOS窓のサイズを取得するコードはここにしかありませんでしたので、直接呼び出すことにしました。

あまり試せていませんが、iar.rbでも動くと思います。

*1:emacsは小指を酷使するので引退なのです…