blogに引っ越しました。3.2の予定をご覧ください。3.2がリリースできることを大変嬉しく思います。これも今まで支えてくださった皆さんのあれだと思います。ありがとうございます、これからもmikutterをよろしくお願いします。今回は前から気になってた、プラグイン開発者として俺が触りたいのに外からではどうしようもない部分を改善しました。動かなくなっているので今からpull-reqを送ってきます。シムシティみたいなものなんですよね。それ以外はとくに大きな問題はないでしょう。画像まわりの使い勝手は個人的には気に入ってます。ダウンロード機能も付けたかったのですが実装が間に合わず今回はペンディングとしました。画像をブラウザで開くのがツールバーになっているのは、ここにそういった他の機能が乗るためです。稀に画像のロードに失敗するとか、不具合が取りきれていないことがわかっているのが現状です。品質を疎かにしてまで日を合わせやがったとは思わないでいただきたい。バグを分かっててリリースするのと、知らずにリリースすることに本質的な違いなどありません。それにね、よく考えてもみてください。3.2だ、とか言っているmikutterユーザの人生に含まれる不具合のほうが深刻です。かたや画像たまに表示できない問題なんてもう一回開けばいいだけです。考えると、リリースに踏み切ったことにも納得できますね。ごめんなさいちょくちょく修正していきます。本日はmikutterだけではなく、Rubyのお誕生日でもあります。mikutterの検証をしていませんが、概ね問題がないらしいです。今回の変更ではmikutterの動作速度が上がることに期待できそうです。今のところRubyの進化の恩恵を毎回受けることができているので、今回も楽しみです。最後に宣伝ですが、コミックマーケット87の3日目(12/30)に、mikutterの薄い本vol.7が頒布されます。詳しい情報についてはリンク先を見ていただけば良いのですが、私も寄稿しているmikutterの薄い本が、金さえ出せば買えるまたとないチャンスです。十分な部数があるようなので、ゆっくり来てください。当日は私もブースにいることが多いと思うので、握手しましょう。同ブースに私の個人サークル「アトリエとしぁ」の初の画集を1部のみ委託します。12枚か13枚くらい、全て私が描いた絵です。無印で買った無地の絵本に描いただけなので、世界に一部しかない、非常に貴重な作品です。これがなんとたったの400円!mikutterの薄い本のたった200%の値段でお求め頂けます!無印の絵本が315円なので、ほとんど利益はございません!これは私が会場に着くまで買うことができませんので、購入できるかどうかは完全に運です。3.2で新しく追加されたプラグインの機能拡張について、一通り見てみましょう。画像サービスに対応するtwitpicやinstagramみたいな画像をアップロードすることを主とするサービスや、d250g2.comのような画像の提供が主となるサービス(便宜上まとめて画像サービスと呼びます)を、画像プレビューのウィンドウで表示できるようになりました。ルールを追加してみる今まで、画像を開くのはopenimgというプラグインが担当していました。プラグインが担うことになります。プラグインを見ると、どうやって画像を開くのかわかると思います。これはTwitpicのルールです。オーソドックスなルールを持っています。今までのopenimgは、openimgプラグインに付属しているJSONファイルを編集してルールを追加していたので、サードパーティプラグインから追加する方法はありませんでした。openimg自体も正規表現を駆使して画像を探すなど素晴らしい実装になっており、今回openimgを作りなおすに当たっては本当に難儀しました。数年前に自分が書いた、正規表現をゴリゴリ使ってスクレイピングするコードをメンテナンスするってなかなかつらいものがあるんだなあ。今回このように一つひとつの画像サービスに対するルールをコードで現すようにした経緯は前のエントリで説明しましたが、もともと3年くらい前は全部のルールをコードで書いていました。それをやめた時の反省をせず戻すわけにはいきません。JSONのようなデータ構造を採用したのは以下のような問題を解決するためであって画像サービスってちょいちょいルールが変わるので、バージョンアップしなくてもルール配信できるようにしたい!まとめないとコードが恐ろしいサイズになるそれぞれ以下のように解決しました画像サービスはTwitterに死刑宣告されたからか、もう頻繁にDOM構造が変わることがなくなった。そもそも利用頻度が低い(今回この改修をしてるときにyfrogが見れなくなっていることに気づいたが、誰からも報告が来てなかった)。自分のプラグインから画像を開こうこの変更でユーザが新しくできるようになったことで一番重要なのは、自分のプラグインからopenimgを利用できるようになったことです。'http://twitpic.com/d250g2/')画像のURLをクリックした時と同じように、画像が表示されたと思います。ただのイベントですから、あなたのプラグインからも同じ方法で画像を表示できるのです。注目すべきは、URLから画像を探しだし、それを表示したということです。他のプラグインで定義されたルールがこの時に使われます。mikutterを起動する度に同じ画像を勝手に開くことも可能です。3.1までは他のプラグインからこのようなことは出来ませんでした。画像をダウンロードしよう次は画像自体をダウンロードしてみます。次のコードを実行してみましょう。画像をダウンロードするのでちょっと時間がかかるかもしれません。いうファイルができていると思うので見てみましょう。燃えているのではないでしょうか。使うと、URLをダウンロードした結果が流れてくるIOオブジェクトが第二引数に渡されます。受け取れば、画像のダウンロード完了です。これもちゃんと画像サービスのURLから実際の画像を探してダウンロードしていますね。それがなければ、このフィルタの存在する意味がないんですが。終わっているのが気になった人がいるかもしれませんね。あの戻り値が、このフィルタのIOです。何が言いたいかというと、ダウンロードが終わったら、そのIOは、フィルタを呼び出した側がcloseしてください、ということです。GC時に自動的にファイルディスクリプタは開放されると理解してるんですが、IO閉じないのって他のオブジェクトより罪悪感があって...抽出タブの抽出対象うまく伝わるタイトルは思いつかないのですが、要するにこれを増やす機能です。標準では、ユーザ名・本文・Twitterクライアント名を使用できますが、もっとほかのことを基準に抽出したい!ということがままあったので追加できるようにしちゃいました。はい、こんな感じのコードで追加できます。2.0から使えるキーワード引数を使っているという意味でも面白い例です。ブースに来てください。私も行くので、本物のmikutterをお見せしましょう。1)などと書いていますが、これは見て分かる通りbioで抽出するやつを追加します。上のスクショのコンボボックスに表示する名前ですね。operatorとargsはおまじないです。...と言っても、敬虔なmikutterユーザ諸君は「おまじない」では納得できないでしょう。ブースに来てください。私も行くので、本物のmikutterをお見せしましょう。あとはブロックの方がキーワード引数を要求してますね。スクショで言うところの右のテキストボックスに書かれた内容です。その条件でうまい具合に比較してくれる奴です。1ツイート毎に1回このブロックは実行されるので、ここではあまり重い処理をやるとロクなことがなさそうです。実際には、重い処理はどんな場所でも大抵ろくなことになりません。現実は厳しい!社会は厳しい!それで、コメントになっている部分ですが、これはそのすぐ下のシステムメッセージを抽出するための条件と同じものです。システムメッセージは二つ見どころがあって、ひとつは引数や比較方法がない条件だということ、もうひとつは、defextractconditionにはS式も渡せるということです。コメントアウトしてる部分は、ブロックがなくなり、こんな引数が追加されていますね。message)")これをmikutter上で実行すると、以下のような値が返って来ます。:message))そのまんまですね。mikutterの抽出タブの条件がS式になっていることは有名ですが、まさか抽出対象がS式でも渡せるとは...たまげたなあ。これは闇が深いのでこれ以上掘り下げることはしません。S式にすることの意味は速度・メモリの効率です。抽出対象をS式で指定すれば、マクロみたいな雰囲気で全体の条件の中に展開されるので、単一のRubyコードに変換されます。一方で、ブロックだとブロックを呼び出す準備で余計な処理が入ります。ブロック呼び出し自体もありますし。確かにこちらのほうが速度的には有利になりますが、実際計測してみると思った程でもありませんでした。ラピュタに突っ込む気でいるなら気になるかもしれませんが、毎秒2,3ツイート程度ならどうでもいいんじゃないでしょうか。mikutterも悪ノリみたいなものなので、抽出タブの条件周りはmikutterの本質のひとつなのだと思います。ブースに来てください。私も行くので、本物のmikutterをお見せしましょう。デコにとんでもないものをくっつけてお待ちしております。あとがきサードパーティプラグインがどのような恩恵を受けられるのか、という観点からmikutter3.2で行われた変更を見てみました。どちらもコア機能の変更はとくになく、表層的な変更ですが、そんなに需要はないと思います。需要はほとんど気にしていないので、こういうこともあるよなあといった感じです。内容に関してはもっと具体的に掘り下げても良かったんですが、なかなかこういう記事では難しいものですね。pluginとは別に、やりたいことからリファレンス的に引けるドキュメントを考えてるしそっちで補えたらなーとか思いつつ、そもそも書けるのかとか、うーん。mikutterアドベントカレンダーの最終日・mikutter5周年ということで、今年一年のmikutterについて振り返ろうかなとも思ったのですが、ここ数年は、正月に一切のタスクから開放された状態でゆっくり書く感じだったので、今年もそんな感じで行きたいと思います。そんなわけで簡単に、mikutter、誕生日おめでとう。来年もよろしくお願いします。3.2がリリースされますね(棒)。3.2についての私の記事が掲載されていますね(棒)。3.2を12/25にリリースすれば何も問題ないはずですよね。3.2では何をする予定なのかを確認してみましょう。アイコンテーマ(仮称)mikutterのUIのアイコン郡を差し替える機能です。アイコンをまとめたファイルを所定の位置に置いて、設定画面でどれを使うか設定すると、mikutterが用意しているアイコンを別のものに置き換えることができます。ユーザとしては、使用しているWMのテーマにあったアイコンを選ぶ・作ることができるようになります。DSLメソッドを使えば、画像ファイルの指定をより簡潔にできるというメリットがあります。この変更はまだ試験的な機能です。3.3で大幅に変わる可能性があります。2トトリちゃんの画像を楽しめるWebサービスhttp://totori.dip.jpを表示したところ。イワシがいっぱいだあ。openimgプラグインは画像の表示機能を提供していますが、使い勝手が微妙に悪いところがありました。最近サードパーティの画像アップロードサービスがいまいち息をしていないとか、開発当初からとりまく環境が大きく変わってしまったプラグインでもあります。単なる画像取得の手段としてサードパーティプラグインと連携openimgは、d250g2、地獄のミサワなどさまざまなサービスに対応した強力な画像取得ルーティンをもっていますが、このインターフェイスはプラグインの中に閉じてしまっていていました。openimgの画像取得部分を公開することで、画像を扱うプラグインはそれを利用できるようになります。従来は、openimgプラグインに付属しているJSONファイルに、例えばtwitpicの画像を取得するためのルールが書いてありました。この方法では、openimgが想定しないような複雑な方法を使ったルールでの取得が出来ず、実用的には無理が出てくる場合がありました。現実に、いくつかの写真アップロードサービスについては、openimgに別途コードを書いて対応しているような状況がありました。そこで、いっそのことURLを画像URLに展開するようなフィルタを用意して、写真アップロードサービス毎にリスナを登録するアプローチに変更することにしました。することで、openimgプラグイン以外から、画像取得ルールを登録できるようになりますし、ルールがJSONファイルとRubyコードに散らばらなくなりました。一方で、毎回コードを書くとなると、メンテナンス性が問題になってきます。これはスクレイピングの部分にNokogiriを使用することで、コードを単純にしました。mikutterからWebページをスクレイピングするようなプラグインなんて普通書かないと思いますが(棒)、これからは標準プラグインが要求するので気兼ねなくNokogiriを使えますね。振る舞い画面をクリックでブラウザを開いてウィンドウを閉じるという挙動がなくなりました。閉じるにはウィンドウマネージャの閉じる機能を使ってください(ここにもmikutterコマンドを割り当てたかった)。ブラウザで開くには、ツールバーに投げやりな感じのアイコンがあるのでそれを押します(mikutterコマンドry)。ここに入れたい機能がほかにもいくつかあるのですが(mikutterコry)。画像の表示部分も書きなおして、画像のダウンロードが終わったところから表示されていくようになりました。画像プラグイン→メディアプラグイン?今までopenimgは画像に拘ってきましたが、最近のTwitter全体の動向を見ていると、動画なんかも気軽に投稿できるようになってきています。動画に対応する予定は今のところありませんが、今回の変更は、そういった将来の変更も見据えてのものです。抽出対象とは、抽出条件の「名前」「本文」などのことです。これには他に、Twitterクライアントでフィルタしたいという要求もあったので、一応それも入ってはいます。使っているぶんにはこれで足りるかもしれませんが、もっと高度な条件を指定したいかもしれません。多くの条件になりうるメソッドが実装されていますが、今使っているのはそのほんの一部であるというのが現状なわけです。現状だとコードを書いて自力でフィルタしたものをデータソースとして提供するという方法もあり、実際に鍵垢のツイートだけ流れてくるデータソースというものも提供されています。抽出対象の拡張ができるようになることで、こういった要望について、より自然に答えられる場合が出てきます。まとめ3.1からあんまり空いてませんが、期間のわりにはいろいろできたみたいです。詰め過ぎた感じもしますが、来年はまた4月までほとんど動けないことを考えると、差し引き調度良い感じかもしれません。実は今alpha1を上げました。いくつか既知のバグがあるので25日まではそれを取って、25日のどこかで正式な不安定版としてリリースします。数年ぶりのクリスマスリリースになりそうです。大体年末は仕事はたいしたことなくてmikutterでてんてこ舞いなのですが、今年は会社が大型案件をぶつけてくれたので泣いています。最低限思ってたことはやりきれそうなのでよしとしましょう。2014怒られました。2014どうも自動であひる焼きに反応するmikutterプラグインを書いたようです。mikutterプラグインを書きたいと言っている人は基本的に書かないので無害ですが、何も言わずにふっとプラグインを生み出す人間にろくな人は今まで居ませんでした。あひるさんもろくな人間ではないのでしょう。https://github.com/Na0ki/ahiru_yakunaうわぁ...。今見たらyamlファイルに反応バリエーションが出してあるし...。順調に腕を上げてますね。pull-reqも受け取って比較的活発に開発しているようなので、こういう人は早めに潰しておかなければなりません。作った帰ってきたあひる焼きゲーム!https://github.com/toshia/ahiruyakiあひる焼きをソーシャルゲームにしました。mikutterの機能をフル活用してあひる焼きを楽しみます。フロント側の機能はREADMEに書いているので、裏で何をしているかちょっと紹介します。RANK_TABLEあひる焼きランクは、経験値を溜めると上がっていきます。経験値は減ることはありません。次のランクに上がるために必要な経験値をグラフ化してみました。途中からやたら経験値が要るようになりますね。計算式は謎めいたものを使っていますが、深い意味はありません。詳しくはソースの6行目あたりからですが、無駄にEnumeratorを使用しているのがポイントですね。ある経験値だとランクいくつになるか、というのがわりと直感的に書けます。1だからどうした感が半端ない。効率はメモ化した再帰関数のほうが良さそうですが、一方でどう見てもボトルネックになるような処理ではありません。スタミナソーシャルゲームならスタミナがなければいけません。スタミナはランクアップで全回復して、行動によって消費し、時間経過で全回復します。スタミナには最大値があります。これはランクアップで上がっていくので、ランクから計算できます。ゲームを遊んだ時はスタミナが最大になっているというのもポイントです。今回はスタミナを数値で保持せず、スタミナが全回復する時刻を保持して、そこから現在のスタミナ値を決定しています。この方法のメリットは、スタミナ回復のことを常に考える必要がないことです。戻り値を代入すれば即時回復できますし、mikutterを終了している間もスタミナが回復します。スタミナを消費した時は全回復時刻に加算すればいいだけですし、次回のスタミナ回復時刻が10秒後という時にスタミナを消費した時に、5分にリセットされるとかいうこともありません。これはいい方法ですね。良い方法なので、多分本物のソーシャルゲームもだいたいこうなっているんじゃないか、という多分一生役に立たない知見を得ることができました。いや、思っただけなので知見でもないですね。本当に得るものがない。いうメソッドは、消費スタミナ値を引数にとり、そのぶんだけスタミナを消費してブロックを実行します。スタミナが足りなければブロックが実行されないし、ブロックの処理途中で例外などで抜けたらスタミナが減らないので便利です。今回このプラグインを書くにあたっては、イベントをできるだけ使うようにしました。イベントが呼ばれます。最大スタミナ値などほとんどのものはランクから自動計算しているので、経験値が上がった瞬間自動的に上がりますが、スタミナの回復だけは処理してやらないといけないので、このイベントをキャッチすることで行ってます。イベントはどのプラグインでも受け取ることができるため、あひる焼きゲームはMODの開発が簡単です。スタミナが全快した時に発生するイベントは、全快したら自動であひるを焼くなど、さまざまな用途に使えそうです。いうことをしておくと、ユーザは予想外の意味不明な拡張をしてくるものです。mikutterで何度もそういうことを経験しました。何だよ、あひる焼くなプラグインって。終わりに結局、焼きあひるに油を注ぐ結果になっている感じがしてなりません。ゲームのアップデートもしたいのですが、忙しい時期なので、ほかのタスクに圧されて手がついていない状態です。いう役に立たないものを書くと心がやすらぎますし、いろんなものを得た気になれるので(実際はそんなことはほぼない)、皆さんもやったら良いと思います。ネタができたので書こうと思います。本日はmikutter-modeのある開発環境についてです。mikutter-modeとはEmacsでmikutter開発/mikutterプラグイン開発をするためのelispです。Lispというのは...Emacsでないと意味のない内容なのかそうではありません。Vimmerと呼ばれる人々は、Emacsでできることを大抵Vim上で実現してしまう習性を持っています。いった記事をたまに書くことで、他のエディタ/IDEからやばいプラグインが生えてくるのは珍しいことではありません。これについては触れています。この記事は2012年夏に公開されたもので、その後の変化についてはとくに触れられていないので、あれからやったことを中心に書いていきます。インストールこのあたりは特に変わってないのでざっと。以下とかそういうところに設置します。ロードするようにしましょう。一応、私はこんな感じのことを書いてます。mikutter.rbが入っているディレクトリを指定しましょうね。使うと、以下のような画面になって良い感じです。いうディレクトリがあります。これがEmacsと連携するためのmikutter側のプラグインです。実行すると、mikutterがデバッグモードで起動します。デバッグ出力が参照できます。コード実行ここからはmikutter-modeを導入しているmikutterなら、Emacsから起動されたものでなくても良いです。入力すると、mikutterに今表示している内容でプラグインがインストールされます。使った場合、Emacsからすぐに実行できることに加え、実行前にプラグインをmikutterから除去してくれるので、イベントハンドラが無限増殖しないといったメリットがあります。押すと、バッファ全体ではなく選択したコードがmikutterで実行されます。この場合はプラグインが一度除去されるようなことはありません。