ProcessingのRubyモードを作り始めた

2014-06-05

グラフィカルプログラミング環境として便利なProcessingのIDE(PDE)で、Rubyの文法でプログラムを書ける、Rubyモードというものを作り始めた。

https://github.com/tyfkda/processing-ruby-mode

まだ作り途中で、アプリケーション起動中にエディタを操作できないとか、標準入出力がエディタのコンソールにリアルタイムで出ないとか、文法エラーのメッセージがちゃんと出ないとか、アプリの起動が遅いとかいろいろあるけど、ひとまず動くようになったので、ブログ記事を書いてみる。

なぜ作ろうかと思ったかというと、もちろんRubyの文法と、Processingの開発環境やAPIの両方が好きだったので、合わせたものがあるといいなという理由。

実はruby-processingという、まさにそういうことができるものがすでにあって、自分でテキストエディタでRubyのプログラムを書いて、コマンドラインから実行することができる。ただ問題があって、PDEから編集・実行できないこと、起動が遅いこと(これは毎回 rp5 run するとであって、rp5 watch を使うと毎回起動せずに済み、ファイルを更新すると自動的にアプリが更新される)、あとMacOSXではインストールが結構面倒だった。これらの問題は初学者なども含めた一般に普及させたいと思った時に問題だと思う。

そこでProcessingのPDE上でRubyを使えるようにしようかと考えた。ArduinoはC言語の文法で開発するようになっていて、その開発環境はProcessingを元にして作られているので、それと同じように自分でProcessingのソースを変更してビルドしてやろうかと思っていた。

しかし最近のProcessingにはモードというものがあり、その中にPythonモードというのがあって、Javaじゃない文法でもProcessingを動かせるようになっているのを見て、同じようにやることにした。モードの追加の仕方は、ドキュメントなどがないので、手探りで調べた(Processingに独自のモードを追加する方法))。

コードの実行はruby-processingを参考に。ruby-processingではJRubyを使っていて、Rubyコードの実行はJRubyに丸投げしている。このJRubyがすごくて、Java↔JRuby間のバインディング、グルーコードを全く書かなくてもお互いに呼び出せて、値も自動的に変換される。さらにJavaで定義されいるクラスをRuby側で継承して、メソッドをオーバーライドできる。すげぇ!

またruby-processingは凝っていて(追記:ruby-processingじゃなくてこれもJRubyだった)、Processing/JavaのAPIやJavaの推奨のコーディング規約はキャメルケースだけど、Rubyっぽく書けるように、対応するスネークケースのAPIを自動的に定義してくれる。カコ(・∀・)イイ!!

しかしRubyモードならではの問題もある。Processing/JavaではwidthmouseXなどといった、一見グローバル変数に見えるProcessingのシステム変数は実はPAppletクラスのメンバ変数になっている。そしてスケッチに書いたソースは全部PAppletの内部メソッドや内部クラスとして定義されるので、それらがどこからでも参照できる。しかしRubyの場合は、mouse_xという名前が変数の場合はローカル変数にしかならないので、自動的に値は入らない。どうしているかというとPAppletクラスのメソッドとして定義してあって、Rubyの文法ではメソッドの呼び出しの括弧を省略できるので変数っぽく見える、という具合になっている。しかしRubyではclassの内部で定義したclassでも外側のインスタンスにはアクセス出来ないので、mouse_xなどは見えない。グローバル変数は$から始まらないといけないので、それもできない。じゃあどうするかというと、$appというグローバル変数があるようなので、それ経由でアクセスする方法になるらしい。残念。そのへんPythonモードではどう解決しているのか不明。

今後の展望は、まともに使えるようにして、最終的に本家のProcessingにリンクしてもらえるようにまでしたい。