2011年7月31日日曜日

Rubyのio/consoleを試す

Rubyでコンソールアプリケーションを作成する際に、 標準のIOではうまくいかない問題がある。 例えば...

  • リアルタイム入力
  • パスワード入力時等に文字のエコーを停止
  • 端末のサイズを取得
等がある。これはcursesなどを用いれば解決できるが、パスワード入力のみで必要な場合等 cursesでは大げさすぎると感じる場合もある。

そこで、次のruby(1.9.3?)あたりに標準で付属されるらしい、 io/consoleというライブラリを使ってみる。

導入

今回は、rubyのリポジトリから最新開発版を入手し、ビルドする。RVMを用いてもよい。

miku@hatsune% svn co http://svn.ruby-lang.org/repos/ruby/trunk ruby19-svn
miku@hatsune% cd ruby19-svn
miku@hatsune% autoconf
miku@hatsune% ./configure --prefix=/usr/ruby19-svn --program-suffix=19-svn
miku@hatsune% make
miku@hatsune% sudo make install

lib/ruby/1.9.1/x86_64-linux/io/console.so がio/console用のライブラリらしい。

使ってみる

リファレンスなんて無いので、ソース(ext/io/console/console.c) を読みながらとりあえず叩いてみる。 IOクラスに追加されるメソッドは、以下のとおり...らしい。

  • IO.console #=> IO for console device
  • IO#raw
  • IO#raw!
  • IO#getch
  • IO#echo=
  • IO#echo?
  • IO#noecho
  • IO#winsize
  • IO#winsize=
  • IO#iflush
  • IO#oflush
  • IO#ioflush

実際にirbで叩いてみると分かるが、getchでは入力した瞬間にその入力した文字が返される。 また、winsizeではその瞬間のコンソールサイズが配列として返される。 その他のメソッドも、だいたい名前のままな動作をする模様。

irb(main):012:0> IO.console
=> #

irb(main):011:0> IO.console.getch
=> "m"

irb(main):013:0> IO.console.noecho{|io| p io.getch}
"a"
=> "a"

irb(main):014:0> IO.console.winsize
=> [55, 139]

改行の問題

io/consoleで入力を受け付けながら出力すると、 "\n"で正しく改行ができなくなることがある模様。 例えば以下のように書いた場合、LFのみが行われCRが行われず、 行は変わるものの開始位置がおかしくなる。

Thread.start(){
  loop {IO.console.getch}
}

IO.console.noecho{|io|
  loop{
   io.printf("%d\n", rand(1024))
  sleep 0.1
  }
}

これは、"\n"を"\r\n"に変えてやれば解決する。 今後修正されるかもしれないが、一応。

0 件のコメント:

コメントを投稿