日本語が使えるirbにしておく

OSXに標準インストールされているirbは、残念ながら日本語が文字化けする。Rubyの方は標準で日本語が使えるようになったのに、何故なんだ?

調べてみると、Ruby自体の日本語処理には問題ないのだけど、irbがコマンド入力を受け取る際に使っているライブラリ(libedit)が日本語に対応していないのが原因らしい。解決策は、日本語対応のライブラリ(readline)に切り替えること。

日本語が使えない環境

  • irbは、"readline"をrequireして、コマンド入力ライブラリを利用している。
  • requireした"readline"はどこにあるのか?
  • irbを起動して、以下のコマンドを入力してみる。
$ irb
irb(main):001:0> puts $LOADED_FEATURES.grep /readline/
/System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/universal-darwin13/readline.bundle
=> nil
irb(main):002:0> exit
  • 上記readline.bundleは、たぶん日本語が使えないlibeditを参照しているはず。
  • readline.bundleが参照しているライブラリは、以下のコマンドで確認できる。
$ otool -L /System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/universal-darwin13/readline.bundle
/System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/universal-darwin13/readline.bundle:
	/System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/libruby.2.0.0.dylib (compatibility version 2.0.0, current version 2.0.0)
	/usr/lib/libedit.3.dylib (compatibility version 2.0.0, current version 3.0.0)
	/usr/lib/libncurses.5.4.dylib (compatibility version 5.4.0, current version 5.4.0)
	/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1197.1.1)
	/usr/lib/libobjc.A.dylib (compatibility version 1.0.0, current version 228.0.0)

コマンド入力ライブラリとは?

  • ターミナルで入力する時に、キー操作に応じて文字の入力を受け取る処理をしているのだ。
  • キー操作は文字入力だけでなく、カーソル移動、削除、control-a・control-eで行頭・行末へ移動するなどの便利な操作環境も提供している。
  • OSX標準では、irbはlibeditを利用している。残念ながら日本語に対応していない...。
  • 一方、readlineというコマンド入力ライブラリもあり、こちらは日本語に対応している。

readlineをインストール

  • readlineはHomebrewで素早くインストールできる。
$ brew install readline
  • あるいは、すでにインストール済みかもしれない。
$ brew list readline | grep libreadline.dylib
/usr/local/Cellar/readline/6.2.4/lib/libreadline.dylib

libeditからreadlineへ切り替え

  • requireしたreadline.bundle、libeditライブラリ、readlineライブラリの正確なファイルパスを取得できたら...
参照しているbundleのパス /System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/universal-darwin13/readline.bundle
  古いライブラリのパス /usr/lib/libedit.3.dylib
 新しいライブラリのパス /usr/local/Cellar/readline/6.2.4/lib/libreadline.dylib
  • 以下のコマンドを使って、readline.bundleが参照するlibeditライブラリを、readlineライブラリへ切り替えるのだ。(管理者権限が必要)
# コマンドの書式:
# install_name_tool -change 古いライブラリのパス 新しいライブラリのパス 参照しているbundleのパス

$ sudo install_name_tool -change "/usr/lib/libedit.3.dylib" "/usr/local/Cellar/readline/6.2.4/lib/libreadline.dylib" "/System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/universal-darwin13/readline.bundle"
BUNDLE=`ruby -r readline -e 'puts $LOADED_FEATURES.grep /readline/'`
OLD=`otool -L $BUNDLE | awk '/libedit/{print $1}'`
NEW=`brew list readline | grep libreadline.dylib`
sudo install_name_tool -change $OLD $NEW $BUNDLE


  • Ruby1.8では、$LOADED_FEATURESにファイル名しか入っていないので、ちょっと工夫が必要。
BUNDLE=$(find `ruby -e 'print $LOAD_PATH[0..-2].join(" ")'` -type f -name readline.bundle 2>/dev/null|sort|uniq)
OLD=`otool -L $BUNDLE | awk '/libedit/{print $1}'`
NEW=`brew list readline | grep libreadline.dylib`
sudo install_name_tool -change $OLD $NEW $BUNDLE


irbで日本語が使えた!

$ irb
irb(main):001:0> puts '日本語'
日本語
=> nil
irb(main):002:0> exit


やったー!