雑念日記

主に技術的なことをつらとらと(書ければいいな)。

Javaが書けない僕でもp5に貢献したい!

本投稿はProcessing Advent Calendar 2014の5日目の記事です。

Processing Advent Calendar 2014 : ATND

公私共にほとんど使わないのでJava力が底辺を這いずりまわっている僕ですが、Processingのバグ修正にちょっぴり貢献したので、その顛末を備忘録がてら記録したいと思います。
「これから本格的にProcessingへコントリビュートしたい!でもどうしたらいいかよくわからない!」という方がもしいれば少しでも参考になれば幸いです。
間違ったことを書いていたらご指摘願います。

目次

  • はじまり
  • 発起
  • Processingのソースコードはどこにあるか
  • ビルド環境を用意する
  • バグの原因を見つける
  • バグった経緯を調べる
  • バグを修正してみる
  • pull requestを送る
  • 結果
  • まとめ

はじまり

Processing-2.1のエディタ(PDE)で日本語文字列の表示がおかしいというバグがありました。
僕自身は外部エディタを使っているのですぐには気づかなかったのですが、ブログやTwitterGithubのIssueなどでちょろちょろ話題になっていました。

f:id:hoshi_sano:20141204022939p:plain

↑最初の報告者は中国の方でした。どうもマルチバイト文字だと問題が発生するようでした。
Issueがあがっているならすぐ解決されるか…と思いきや、開発陣には話がイマイチ伝わっていない感じ。
この手の問題はアルファベット圏の方々にはピンとこないかもしれませんね。
しかしこの問題、当時日本人は(少なくとも観測範囲内では)当然みんな嫌がっていて、このバグのためにわざわざ古いバージョン(2.0x系)を使っていた人が少なくなかったと思います。

発起

さて、このバグ、ざっくり言うと半角文字は重ならなくて全角文字は重なっちゃうというものでしたが、どういうコードでバグってるのかなんとなく予想がつきますね?
わりと簡単に修正できそうだけど放置してたらなかなか修正されなさそう、というような状況に見えたので、自分で修正してみようと思いました。
「修正する」というところまでいかずとも「ここがバグの原因だよ!」と誰かに伝えることだけでもできれば!
そんなわけでProcessingの修正作業が始まります。

Processingのソースコードはどこにあるか

ご存知の通り、Processingはオープンソースのプロジェクトなのでソースコードはすべて公開されています。
現在ではGithub上で日々開発が進められていますので、gitGithubが最低限使える必要があります。
git初心者はタイムリーなGit Advent Calendar 2014 初心者がプルリクまでに覚えるべきたった 9つの厳選 Gitコマンド とかを見るべし。


Processing · GitHub

大別すると、Processing本体がprocessing/processingで、リファレンスや公式WEBサイトがprocessing/processing-docsで管理されています。他にもAndroidモードサウンドライブラリなど、コマゴマとした機能毎のリポジトリもあります。

今回のバグはProcessing本体のエディタ(PDE)のバグなので、対象のリポジトリこちら

Githubにログインしている状態で、このリポジトリの「Fork」ボタンをクリックして、自分のアカウント上にprocessingのリポジトリを作成します。

↓これ

f:id:hoshi_sano:20141204023450p:plain

その後、git cloneでforkしたリポジトリを手元にコピーします。

  $ git clone https://github.com/<Githubアカウント名>/processing.git

processingのディレクトリ構成は2014-12-05時点では次のようになっています。

  processing/
  ├── README.md
  ├── app/
  ├── build/
  ├── core/
  ├── done.txt
  ├── java/
  ├── license.txt
  ├── pdex/
  └── todo.txt

それぞれざっくり以下のような感じです。

名前 説明
README.md リポジトリの概要が書かれたファイルです。一読しておきましょう。
app エディタ(PDE)に関するソースのディレクトリです。エディタの挙動を変えたい場合はここをいじります。
build 全体をビルドするために必要な諸々のディレクトリです。
core Processingの仕様に関するソースのディレクトリです。クラスやメソッドの挙動を変えたい場合はここをいじります。
done.txt 完了している機能追加やバグ修正がバージョンごとに一覧で記録してあります。
java 標準添付ライブラリのソースなどが置かれたディレクトリです。
license.txt ライセンス条項です。
pdex PDE Xモードに関するソースのディレクトリです。
todo.txt 今後追加すべき機能や修正すべきバグが一覧で記録してあります。

というわけで、今回のバグの修正対象はappの下の何かです。

ビルド環境を用意する

バグを修正するには自前でprocessingをビルドして挙動を確認できる環境が必要になります。
以下にビルドに関する情報が書かれている(上述のgit cloneの話も含む)ので、それに従いましょう。

2014-12-05現在では以下がインストールされている必要があります。

Antとはビルドツールのことです。 http://ant.apache.org/
@reona396さんの2日目の記事にもちらっと出てきました。

ビルドには、ソースコードや設定ファイルなどの構成要素から実行可能なファイルを生成するまで複雑な手順が必要なのですが、それらを自動化してくれるのがAntなどのビルドツールです。

ここまで用意できたら、あとはcloneしたリポジトリから以下を実行すればビルド開始です。

  $ cd build
  $ ant run

うまくいけばPDEが起動します。
うまくいかない場合は上述のwikiにトラブルシューティング的な記述があるので参考にしましょう。
tyfkdaさん(processingの日本語化をしてくださった方です)の「Processingをビルドする」も参考になるかもです。
Eclipseを使ったビルドについてもwikiに書かれているので、Eclipse使いの人も安心です。

さて、ここまでで修正の準備ができました。

バグの原因を見つける

次は問題となっているコード探しです。
processingのソースコードに精通していて、どのファイルのどのあたりが原因か思い浮かぶ、というのが理想的ですが、ほとんどソースコードを読んだことがない状態だと、問題のあるコードがどこにあるか見当もつきませんね。少なくとも当時の僕はそうでした。

そのため、「全角文字が重なってしまう」というバグを、「文字の横幅の計算がミスってて、配置がおかしくなってる」という現象であるとアタリをつけて(それ以外あまり思い浮かばないですけど)、「font」「char」「width」など関連がありそうな単語でgrepしまくりました。
(今考えるとかなり頭の悪い方法です。もう少し冷静になって、それぞれのファイルが何を担うものかざっくり調べても良かったと思います。)

そして以下のコードにたどり着きました。

https://github.com/processing/processing/blob/processing-0223-2.1/app/src/processing/app/syntax/TextAreaPainter.java#L764-L768

  protected int paintSyntaxLine(Graphics gfx, Segment line, int x, int y, 
                                Token tokens, SyntaxStyle[] styles) {
    ...
      int w = fm.charWidth(' '); // 問題はコレ
      for (int i = 0; i < line.count; i++) {
        gfx.drawChars(line.array, line.offset+i, 1, x, y);
        x += w;
      }
      //x += fm.charsWidth(line.array, line.offset, line.count);
      //x += fm.charWidth(' ') * line.count;
      line.offset += length;

      tokens = tokens.next;
    }

    return x;
  }

文字の幅を一律半角スペースの幅固定にして、配置を決めていました。そりゃあ全角文字は重なっちゃうね。

バグった経緯を調べる

問題がある場所はわかったのはいいですが、以前のバージョンでは問題なかったという点が気になります。
修正方針を決めるためにも、エンバグした経緯を調べる必要がありました。
そんなわけで過去のバージョン、問題なかったという2.03ではどうなっているかを見てみました。git(Github)を使えば過去の変更もわりと簡単に確認できます。

このあたりですね。

javax.swing.text.Utilities.drawTabbedTextに丸投げしていた処理をこのへんのコミットで自前の実装に変更しているみたいでした。
コミットメッセージを見る限り、Eclipseでも問題なく使えるように、ということのようです。

バグを修正してみる

問題点も経緯も判明したので、次はコードの修正です。

バグ自体が難しいものではなく、また周辺に参考となるコードが大量にあるので、以下のような修正でとりあえず想定している通りに動く状態にすることができました。

--- a/app/src/processing/app/syntax/TextAreaPainter.java
+++ b/app/src/processing/app/syntax/TextAreaPainter.java
@@ -761,10 +761,9 @@ public class TextAreaPainter extends JComponent implements TabExpander {
       // doesn't respect mono metrics, insists on spacing w/ fractional or something
 //      x = Utilities.drawTabbedText(line, x, y, gfx, this, 0);
 //      gfx.drawChars(line.array, line.offset, line.count, x, y);
-      int w = fm.charWidth(' ');
       for (int i = 0; i < line.count; i++) {
         gfx.drawChars(line.array, line.offset+i, 1, x, y);
-        x += w;
+        x += fm.charWidth(line.array[line.offset+i]);
       }
       //x += fm.charsWidth(line.array, line.offset, line.count);
       //x += fm.charWidth(' ') * line.count;

文字1個1個に対して幅を計算してるので処理に時間が掛かるのでは、とか、もともと固定幅(半角スペースの幅)で計算していたところが、プロポーショナルフォントの場合は文字毎に幅が違っちゃうけどいいのかな、とかいろいろ疑問に残るところはありましたが、ひとまずここまでで

  • 問題のあるコード
  • 問題の経緯
  • 修正案(あくまで"案")

が用意出来ました。

本当はここで更に単体テストが通るかどうかを確認するのが良いのですが、processingではあまりテストが書かれない傾向があるのと、今最新のリビジョンで試してみたら一部通らないテストがあり、手順が悪いのか手元の環境のせいなのかそもそも今は通らない状態なのかが判別できないため、時間切れで割愛します。進展があったら後日記事にまとめたいと思います。
(どなたか詳細ご存知の方がいたらご教授ください...)

pull requestを送る

ここまできて僕は

  • ソースコードをずっと追いかけた訳ではないのでバックグラウンドを理解していない
  • それに加えてJava力が低いので上記の修正が適切かわからない

という点から若干尻込みして、Issue #2173 に報告するだけで終わりにしようかなーとか思ってました。

しかし「綺麗なpull requestを送るための3つのポイント」という記事の中で「pull requestはラブレター」であるという記述を見て、pull requestを送ることにしました。

こういう意見もありますし。

修正案がイマイチならリジェクトされるだけですし、問題の箇所が伝われば誰かが適切な修正をしてくれますしね。

というわけで送ったpull requestがこちらです。

fix #2173 Multi byte character overlapping by hoshi-sano · Pull Request #2318 · processing/processing · GitHub

残念な英語には目をつむってください。
pull requestの送り方は上記の「綺麗なpull requestを送るための3つのポイント」が参考になります。
また、今回のケースは既にIssueがあることがわかっていましたが、pull requestを送る前に同じ内容に関するIssueやpull requestが既に発行されていないかどうかは確認しておきましょう。

結果

修正箇所が他のpull requestとバッティングしたりとその後も紆余曲折ありましたが、無事修正は取り込まれてバージョン2.2からは日本語が正常に表示されるようになりました。めでたしめでたし。

まとめ

gitとGithubを使えるようになろう

これができないとprocessingの開発の輪には入れません。

antを使えるようになろう

これも現状必須ですね。

英語を読めて、少し書けるようになろう

開発者向けのドキュメントやソースコード中のコメントやIssueを読んだり、バグ報告、Issue内でのやりとりするためには必要です。書く方は多少覚束なくても、コードの断片やキャプチャ画像なんかで補足することは可能です。翻訳サービスも利用しまくりましょう。

Java力は後からついてくる

Java力あるに越したことはないのは当然ですが、今回みたいな瑣末なバグ修正とかならコードがある程度読めてリファレンスを引ける力があればなんとかなるのではないでしょうか。修正や機能追加などの具体的な貢献には至らなくても、興味のある所のコードを読んでみたり、ちょっとお遊びで改造してみたりしていれば力がついていく気がします。

pull requestはラブレター

開発者にとってpull requestは嬉しいもののはずです。僕だったら嬉しいです。心のハードルを下げましょう。
ただしこの言葉を免罪符に、相手の気持ちを考えない無茶苦茶なラブレターを送るようなことはしないようにしましょう。


Processingの作品やライブラリ開発の紹介なんかはよく目にするのですが、Processing本体の開発についての日本語情報はあまり見ないので(僕のアンテナが拾ってないだけですかね...?)自分で書いてみました。
この記事を見て「戦闘力たったの5か...ゴミめ...」と思ったスゴウデProcessingコントリビュータの方々は、開発に関する情報発信をしてくださると僕が喜びます。
Processingの開発に興味を持った方は、まずは以下なんかを読むといいと思います。
https://github.com/processing/processing/wiki#contribute
今後、公式ドキュメントの多言語対応などで日本のP5erの力が発揮できる機会ができることを期待しつつ、おわり。

DXRuby/ruby-processingでローグライクゲーム その1

DXRubyとruby-processingを使ってローグライクゲームを作っています。
大まかなシステムはなんとなーくできてきました。

ですがまだまだ先は長いです。
もしかしたら途中で飽きてしまうかも知れません。

なのでここいらで一旦まとめちゃおう、ということで動画にしました。
動画を作って公開する、というのをモチベーションとして、継続して行けたらなぁと思ったり思わなかったり。

「失踪」タグが付かないよう頑張ります。

SITW24に参加してfluentdについてしゃべりました

去る2014年7月26日(土)、第24回目の山陰ITPro勉強会(SITW)でコンテナとシステム管理者の将来について勉強したあと、fluentdの収集データ可視化について喋ってきました。

ところで fluentd + Elasticsearch + Kibana について解説したムック本が近々出るらしいです。これは注目!

発表スライド

使用したスライドに少々の改変を加えて公開しました。

当日はスライドを表示しつつ口頭とデモでかなり補足しながら喋ったため、そのあたりを全然知らない人が見てもある程度内容がわかるよういろいろ追記しました。それを加味してもスライドの内容ではざっくりしすぎなため、参考リンクなんかも埋め込んでいます。

補足

まだまだ追記したい内容や埋め込みたいリンクがあったのですが、すっかり忘れてそのまま公開してしまったので、この場を借りて更に補足。

Elasticsearchのデモの中で「syslogも取得しましょう」てな感じでさらっと流してしまったあたりは以下にちゃんとしたチュートリアルがあります。

また、「GrowthForecastに送っているfluent-plugin-dstatで取得したデータを、そのままElasticsearchにも送りましょう」みたいな流れにしましたが、実はこれではあまりうまいこといきません。Elasticsearchがdstatの各数値データをString型で保存してしまうため、「そのまま」ではHistgramやSparklinesでグラフを描画することができないのです。(これの追記を忘れてしまったのは悔やまれる...)

それを解消するにはElasticsearchのmappingやtemplateといった機能を使って、数値データがちゃんとfloat型などで保存されるようにする必要があります。以下などを参考にさせていただきました。

当日は後半かなり駆け足になってしまい、ElasticsearchとKibanaについてはかなりアバウトな説明しかできませんでした。スライドに追加したリンク以外にもいろいろ勉強になる情報がウェブ上にありますので、参考にさせていただきましょう。

SITW24の感想など

そもそもなぜ発表したか

この半年強くらい、fluentdを触る機会があり、ソースをそれなりに読んでみたりプルリク(たった1行の修正w)を送ってみたりなどということをしていた背景がありました。SITWスタッフである@sho_hashimotoさんがそんな様子を見ていてくださっており、声を掛けていただいたというのが登壇の経緯となります。そんなこともありつつ、また公の場で喋るのは初めだということもありつつで(社内LTなんかはやっていましたが)、@sho_hashimotoさんには発表当日までいろいろサポートしていただきました。この場を借りてお礼申し上げます。

メインセッション: Linuxコンテナを支える技術とLXC、Dockerのキホン

TenForward(@ten_forward)さんによるセッション。

今話題のコンテナ、LXC、Dockerについてのセッションでした。
コンテナ周りは最近凄い流行り具合で、そのビッグウェーブに乗り遅れまいと自分でもいろいろと調べてみたりするのですが、細部はイマイチよくわからなかったりでした。そんな中で、コンテナ技術の歴史も交えてkernelまわりの目線から話を聞けたり、デモを見せていただいたりというのは大変勉強になり、楽しかったです。これまで不明瞭だったことも、デモで実際に動きを見せていただけるとなんとなくイメージができました。

とはいえ不勉強なものでスライドの中には理解できない話もそれなりに。とりあえず実際に使ってみなきゃ&もっと勉強しなきゃですね。

サブセッション1: これからシステム管理者として生きていくために

あみだく(@amidaku)さんによるセッション。

前半は「これからのシステム管理者」としての心持ちについてなどのお話、後半はシステム管理系の各種ソフトウェアについての横断的・全体概要的なお話でした。スライドは公開しないとのことで、残念。

前半の中で、便利な新しいツールをどんどん試そう!といった旨のお話が出てきました。自分は保守的というかものぐさというか、新しい何かを触る・調べる・使うことに対するハードルがものすごく高いので、実践していかねばなぁと思いました。慣れてしまったものを変えるのは大変だけれど、その方法をいつまでも続けていくこともそれはそれで大変ですし、続けていった結果時代遅れになってしまったタイミングでその時のトレンドに追いつこうとするのはもっと大変ですもんね...(自戒)。

サブセッション2: fluentdとダッシュボードを使った ビジュアルなシステム管理

スライドは上に載せてあります。

対象としてfluentdをほぼ知らない人を想定して資料を作ったため、fluentdの概要と何ができるのかなどといったところにわりと力を割いた内容となりました。(皆さん、もっと深い話が聞きたかったでしょうか...?)
そのせいもあるのでしょうが、後半のダッシュボードまわり(特にElasticsearch+Kibana)がざっくりしすぎてしまったのが少々心残りです。そもそも自分自身そこまでちゃんと使えていないところも多々あったので仕方なしといったところでしょうか。

参加者の方からの発言でもありましたが、ダッシュボードや最先端のストレージを使わなくても、複数ホストからの情報をどこか一箇所のファイルにまとめておく、とかでも十分有用だと思うんですよね、fluentd。そういう緩い使い方も一言挟めたら良かったなあと思いました。

あとは資料やデモの準備に追われて時間配分など到底考えられず、何分で喋り終えたかも把握できていないスピーカー素人っぷりはかなり反省するところです。

まとめ

ウェブ上の情報の寄せ集めみたいなスライド・発表でしたが、ポジティブな感想をいただけたのは本当に良かったです。人と喋ることや人前で喋ることは結構ニガテなんですが、今後また機会があれば何かについて発表していければなと思いました。
懇親会でもいろいろなお話が聞けて楽しかったです。