ymsr送別会を終えて

年末のjava-ja忘年会に出た時にyamashiroさんの訃報を聞いて、訳の分からないまま飲み明かした日から1ヶ月半、今日はyamashiroさんの送別会に参加してきました。
その送別会でyamashiroさんを送るための花火が上がりました。
自分がいきなりこの世から居なくなった時に、花火を上げてまで馬鹿騒ぎしてくれる友人が居る彼を心から尊敬します。


今日LTしていた皆さんほどyamashiroさんと付き合いがあったわけではなく、ちゃんと話をする機会があったのは2013年になってからでした。何度か勉強会の懇親会で喋って、やっと顔見知りぐらいになったぐらいです。
多分、最後に会ったのはこわいscala勉強会の受付の時だったかな。
あの時、体調が良くなかったので、本編が終わった後にすぐ帰ってしまったのが悔やまれます。


java-jaの忘年会の日、訃報を聞いて何が何だか良く分かりませんでした。
人の死に触れたことが無いわけじゃないけど、自分より少し年上ぐらいの人間が死ぬなんて事はまだまだ遠い話だと思っていました。今でも良く分からない。
ただその日は忘年会で、自分よりももっと親しかった人達が、とにかく楽しく飲むのが供養だと言っていたので、ひたすら酒を飲んで楽しく過ごそうとしていました。
朝方まで飲んで、一人で帰る時、通勤のためのサラリーマンが溢れる銀座線の中で号泣してました。
友人と言える程の関係性も無かったけど、尊敬してるエンジニアが急に居なくなった事が、とにかく悲しかった。


ところで、先日自分は逆襲のシャアを肴に酒を飲んで語りあう会というイベントを立てました。開催はちょうど明々後日です。
そして今日、ymsr送別会で遺品を巡るゲーム大会で貰ったものに入っていたものが逆襲のシャアブルーレイディスクでした。
こんな出来過ぎた事があるのかと。
これは確実に、どっかで見てるなと思いました。yamashiroさん本当にすげえわ。
ありがとうございます、本当に嬉しいプレゼントでした、大事にします!
後、自分もカラオケが好きなので生きてる間に一度、一緒にカラオケに行きたかった所ですが叶いませんでした。
とても残念なので、来世かあの世的な所で是非一緒に歌い明かしましょう!

世界を変えたいとか思わない俺と、ヒーローになりたい俺

この記事は闇 Advent Calendar 2013 - Adventarの19日目です。


なんか前回の記事を書いたjugyoさんが非常にインパクトの強い話をぶち込んできたおかげで、次の俺どうしようかって感じで困ってますが、私は普通に鬱屈してる感情を書くだけなんで、そんな面白い話は無いです。自分語りのオナニーをして終わりです。
変な期待をしてる人が居るかもしれませんが、私はマジで何も関わってないのでコメントのしようが無いし。

俺の経緯

私は大学生になるぐらいまで、ただPCでゲームして、エロ動画を見て2chを眺めているだけだった。
貧乏だったので、バイトして金溜めてPCを新調した時、古いPCを活用する方法を考えて、Linuxルーターを作る事にした。
そこからLAMP構成ってやつでプログラミングの真似事をやりだした。

実際の所、私はエロ動画及び画像の収集と管理を楽にするためにプログラミングやHTTPの仕組みを覚えた。
Referercookieを偽装したり正規表現スクレイピングライブラリで頑張ってHTMLからURLを切り出した。
ファイルからサムネイルを作ったりファイル名とパスをDBに突っ込んでブラウザから検索できるようにした。

今でも新しい言語で何かする時には、とりあえずエロ動画を整理するためのアプリケーションを書く。
作り慣れてるし、自分の役に立つからモチベーションが続きやすい。


その後、自作のカラオケ動画やニコ動に上がっているカラオケ動画を使ってPCでカラオケをする、という行為を効率化するシステムを作り始めた。
実は、これもエロ動画の管理の応用で作り始めたものだ。
要は動画を検索し、それを変換しキューイングし自動で再生するという処理を作れば良かった。
エロで蓄えた知識を趣味のカラオケに適用しただけだ。

このシステムをRailsで何回か作り直してたら、Railsである程度のアプリケーションが作れるようになった。


法律家になるつもりで入った法学部に全然向いてなかった事が分かったので、なんとなくやれそうなIT系に向きを変えて適当に就活をし、でかいSIerに入った。
そして余りのつまらなさに絶望した。
仕事の大半はメールで誰かをせっつくか、机上の空論に無理やり理屈を付けることだった。

とにかく社外に出ないと話にならんと思い、社外の勉強会に参加しまくるようになった。
Rubyコミュニティで何とか居場所を見つけられたので、継続的に参加するようになった。

そうこうしている内に辞めたさが限界に達して、もう駄目だって時に今の会社に声をかけられたので、渡りに船な感じで転職した。
まあ、そんなに悪い会社ではない。俺はそれなりに楽しく開発できてるし待遇も悪くはないと思う。
Twitterなんかに対する露出の仕方については、個人的には余り好きじゃないし、しばしば良く分からんと思うことはあるけど。

世界なんて変えられない

さて、何とか大手エンプラの世界から転職したのだが、要は嫌なことから逃げたのだ。
このつまらん会社を変えようなんて端から考えていなかった。
どうせ俺が何を言っても周りには伝わらないし、あのでかい組織で権限を獲得するころには自分自身が腐ってそして年老いていることは間違いないと思っていた。
だからさっさと逃げた。


最終的に自分が雇ってもらえて何とか自分の好きなRubyで開発が出来てるので、今はそれなりに何とかなっている。
Rubyと触れ、コミュニティと関わっていたおかげで、Rubyの本を書かせてもらえたりもした。
しかし、未来に対する不安感というのは余り消えてくれないものだ。
根本的に自分は働くのに向いていない。
朝は起きれないし、良く体調を崩す。正直、週に5日も働いていると月に1,2回は限界が来る。
そもそも仕事なんて、できればしたくないのだ。

いつまで経っても自分がしょうもない人間なのは、やりたくない事は沢山あるがやりたい事はさして無いからだ。
今もってなお、自分が作ろうと思えるものは、エロ動画の管理とカラオケを効率化するためのシステムぐらいだ。
世の中を変えたいなんて全然思ってないし、誰にも負けない程開発が好きというわけでもない。
結局の所中途半端なのだ。
エクセル方眼紙とそびえ立つクソを売って金に変えるような世界に嫌気がさして逃げてきた割に、じゃあ俺は何がしたいんだ?って考えると特に何も持っていない。


実際他の人がどうか分からないが、外から見てると皆熱意溢れる人に見える。
人生のリソースを開発者として生きることにちゃんと費しているように見える。
そんなに熱意を持って仕事しなきゃならんのか。
皆、意識が高過ぎるんだよ。開発による自己表現って何だよ。
そういうのが全然分からん。表現したい意思とか特にねえよ。
現場を変えるとか価値の提供とか、本当の所良く分からん。
無駄なことばっかやってたらつまらんってだけじゃないのか。
つまらないことで時間を無駄にしたくないだけなんだよ。


どうも俺は他人の幸せに対する想像力が無いらしい。
何に困っているかということに対する想像力が無いらしい。
見知らぬ他人を幸せにするために頑張ったりできない。
自分とタイプが異なる人間のために何かする気にはなれない。

厨二病としての俺

基本的に私は自堕落に生きていきたいただの駄目人間なのだが、一方でこじらせた厨二病患者でもある。
厨二というのはそう悪いものではないと思う。
エンジニアなんてものは、厨二でないと駄目だとさえ言える。
自分の中で厨二であることが一つの良心として働いている。


私にとって、カッコよさというものの基準は少年マンガや特撮ヒーローなのだ。それは今も変わっていない。
普段ギャグキャラだがやる時はビシっと決める男がカッコいいと思う。
誰からも省みられることもなく、己の正義のために孤独に戦うヒーローの姿に憧れる。
突然学校にやってきたテロリストを咄嗟の機転で冷静に撃退したいと思っている。


ダラダラと過ごしていきたい自堕落な自分が居る一方で、そんなことでグダグダやってるのは漢のやる事じゃねえ!と思う自分も居る。
正義の味方になりたい。誰よりも自分に対してカッコつけたい。
お前は、いつもジョジョを好きだと言いながら、誇り高き人間の魂に背を向けていられるのかと。


人間、自分の心の中には闇の自分と光の自分が居るものだと思う。
常にどちらが主導権を握るかで争いあっている。大体、闇側が優勢なんだけど。
でも、ギリギリのラインで自分の中の正義が発動して、何とか人間で居られているような気がする。


厨二病気質の人の中には、何かしらその当人にしか分からない憧れや正義があるんじゃないかと私は思っている。
だから、正しいことをやれる人は多分厨二病の一種なんだ。


今の所プログラミングをして何かを開発するという行為は楽しいと思っている。
見知らぬ他人のことは分からんが、近くの誰かの役に立てることは嬉しいと思う。
いつどうなるか分からんけど、出来るだけ楽しいと思えることで食っていきたい。
そして、普段腐ってても何かの拍子に自分の中の正義が発動した時に、それが阻まれないような環境が欲しい。
なので、零細企業でプログラマーをやっている。
別に大層な事はやってない。数百万の人が楽しめるサービスを作ってるわけじゃないし、生活の価値観が一変するような新しいサービスを生み出しているわけでもない。
近くにいるやりたい事がある人の手助けをしているだけだ。
それでも、前よりは楽しく生きている気がする。


後は、自分がコードを書いて開発するということに対して飽きないことを祈るのみ。
そうなったら、もう死ぬしかないような気がする。
自分の興味が続くかどうか、それがもっとも怖い問題だ。
他にも文系コンプレックスとか、数学が分からんとか、英語が喋れんとか、もうすぐ30だけどどうすんだとか、色々怖い問題あるけど…。


さて、プログラマーになっていよいよ3年目に突入する。
色々考えてしまったが、来年も程々にゆるく生きていこうと思う。

webapi-vimとBufWriteCmdでWeb上のリソースをVimで編集する

この記事はVim Advent Calendar 2013の14日目です。
前の記事はVim on Android | 高級粗茶2。でした。


Vimを使っているとWeb上に存在するリソースもVimで扱いたくなることがあります。
そんな時の強力なお供がmattnさん作のwebapi-vimです。
webapi-vimを利用することで簡単にWeb上のリソースをvimに取り込むことができます。

let res = webapi#http#get(s:pull_request_list_url(a:repo), {}, s:github_request_header)

if res.status !~ "^2.*"
  return ['error', 'Failed to fetch pull request list']
endif

let content = webapi#json#decode(res.content)

こんな感じで webapi#http#getやwebapi#http#postを呼び出すことでcurlで通信した結果を取得できます。
JSONを返すAPIであれば、webapi#json#decodeを呼び出すことでvim scriptのディクショナリやリストにデータを変換してくれます。


Web上のリソースを扱う時、保存方法に良く使うテクニックがbuftypeオプションとBufWriteCmdです。

setlocal buftype=acwrite

autocmd BufWriteCmd <buffer> call s:post_comment()

function! s:post_comment()
  let body = join(getline(1, "$"), "\n")
  let b:comment_info.body = body
  if pull_request#post_review_comment(b:repo, b:number, b:comment_info)
    setlocal nomodified
    bd!
  endif
endfunction

buftypeをacwriteに指定する事で、:writeコマンドの実行時に発生するBufWriteCmdイベントでファイルを書き込む処理を行うことができます。
後は任意のvim scriptで書いた関数を呼び出せばオーケーです。
そこでwebapi-vimを使えば、Web上に何かを投稿するような処理をVimで普通に編集して保存するような感覚で利用できます。
autocmdでコマンドを定義する時にはバッファローカルにしておかないと暴発するので注意しましょう。
BufWriteCmdからファイルを書き込む時には、ちゃんとmodified状態を無効にする処理を書いておく必要があります。
普段の:writeコマンドと違って自動では処理してくれません。


最近、このwebapi-vimを利用してPluginを作ったので紹介しておきます。

GitHub - joker1007/unite-pull-request: unite-pull-request is a unite.vim plugin for Viewing GitHub pull request.

uniteでgithubのpull requestの一覧を参照したり、変更されたファイルのdiffをvim上で表示するプラグインです。
githubのWeb UIで見るよりvimで見た方がファイルの差分を確認しやすいのでは?と思って作りました。
また、Vimからレビューコメントを送信することができます。

差分表示画面でEnterを押すと新しくコメント用のバッファが開くので、そこにコメントを書いて普通に保存するように:writeを実行すると、Enterを押したカーソルの行に対してレビューコメントが送信できます。
vim上の表示とgithubのコメント対象行を一致させるのが困難だったので、既に存在するファイルを編集した差分の場合は、下部に表示されているdiffデータのバッファからしかコメントが投稿できないのが難点の一つです。
他にもページネーションを考慮してないのでpull requestの一覧を最新30件しか取得できないとか、まだまだ機能不足な点がありますが興味があったら使ってみてください。

余りvim scriptに詳しくなくても、webapi-vimのおかげで比較的簡単にvimからWeb上のリソースを編集することができるようになります。
webapi-vimで良く利用するWebサービスVimから扱う快感に酔いしれましょう。

ジョジョAdvent Calendar 7日目 ジョジョが教えてくれたこと

この記事はジョジョの奇妙な冒険 Advent Calendar 2013 - Adventarの7日目です。

土曜日中に書くつもりだったのが日曜日になってしまった…。
まあ、最終的に書けばよかろうなのだァーッ!ってことで。
ドイツ軍人は締め切りを過ぎてもうろたえないッ!


最近のジョジョでグッときたところは常秀のスタンド「ナット・キング・コール」とカツアゲロードの「オータム・リーブ」ですね。狙い過ぎ感があって、ニヤっとしてしまった。
やっぱ枯葉と言えば、ナット・キング・コールです。
ジョジョリオンスティール・ボール・ランより好きかもしれない。
やっぱ杜王町は良い。


さて、エンジニアはジョジョを読んだ方が良いと思う理由について、ちょっと書いてみようと思う。
一言でまとめて言うなら、エンジニアが持つべき精神というものと非常に親和性が高いからだ。


ジョジョの登場人物は基本的に前向きであり、過去の自分や運命を乗り越える事を非常に重視している。
これは性質が悪だろうが善だろうが変化ない。
自分自身の現状を認識し、迫ってくる運命を自分の意思で乗り越えることが重要だと表現されている。
問題があった時、それを乗り越えられるかどうかは最終的に自分の意思であり覚悟なのだ。
成長する気の無い奴は何も変わらないし何も掴めない。
成長する意思、乗り越える意思の大切さをジョジョは教えてくれるのだ。
日々、新しい技術をキャッチアップして成長し続けていかなければならないエンジニアにぴったりですね!


そして、ジョジョにおいて勝敗を決定付けるのは観察力や応用力だったりする所に、自分は面白さを感じている。
自分の能力が限られたものでも、得意とするフィールドに持ち込んだり、相手の心のスキを突くことで状況を打開する。
自分の出来ることを最大限に活かすことが大事であり、そのためには自分をちゃんと知ること、そして物事を良く観察し理解すること、それが重要であることをジョジョは教えてくれる。
エンジニアも応用の効く能力を身に付けるということが大事だということが良く分かります。


特にエンジニアにオススメしたいのは五部だ。
少人数のチームで成果を挙げるためのリーダーの在り方、自分が正しさに向かいたいという意思を持ち続けることの重要さを教えてくれる。
特に五部は台詞がカッコいい!

「覚悟はいいか?オレはできてる」
「『言葉』ではなく『心』で理解できた!」
「『覚悟』とは!!暗闇の荒野に!!進むべき道を切り開くことだッ!」
「オレは「正しい」と思ったからやったんだ。後悔はない…こんな世界とはいえ オレは自分の『信じられる道』を歩いていたい!」

そう、SIerでエクセルと格闘して悶々とした日々を過ごしていた時、「信じられる道」を歩いていける自分になりたい、とそう思ってもっとプログラマーとして生きていける道を探すことが出来たのは、ジョジョを読んでいたからと言っても過言では無いかもしれないw

周りがユニットテスト書かないとかメンバーが新しい技術に興味が無いとかウォーターフォール至上主義の上司とか、中々正しいと思う事が出来ないって話を良く聞く業界ですが、正しさに向かう意思を失ったら辿り着く可能性は失われてしまう。
自分が信じられる道を歩くこと、歩こうとすることを止めないで居たいものです。

というわけで、無理にとは言いませんが、興味はあるけどまだ読んでないよーって人は五部までは読んでみることをオススメします。


次のジョジョ Advent Calendarはjune29さんです。

「我が心と行動に一点の曇りなし。全てが正義だ…」
To be continued...

パーフェクトRubyの心残り

この記事はパーフェクトRuby Advent Calendar 2013 - Adventarの6日目です。

Rubyサポーターズの一員としてパーフェクトRubyという本を執筆する幸運に恵まれました、joker1007です。
そもそもはryopekoさんに指名していただいて途中からの協力者という形で参加しました。
私が主に担当してたのは、12章から14章までの、Rubyの周辺ツールやgem周りの部分です。

原稿が揃うまでは、仕事終わってから夜中に黙々と格闘する日々が結構多くて、中々辛いこともありましたが、形に残るアウトプットが出せたことを非常に嬉しく思っています。声をかけていただいて本当にありがとうございました!


さて、こうして世に出たパーフェクトRubyなんですが、技術書の常というか既に古くなってる情報がそれなりに存在します。
特に、発売した後になってふざけんなよ!と言いたくなるぐらいがっつり変わった代物が一つありまして…。

皆様ご存知のGitHub - capistrano/capistrano: Remote multi-server automation toolという奴です。

Capistranoの記事書くの本当に大変だったんですよ。
良く使われてるツールの割にドキュメント少ないし、技術書に動かないサンプル載せるとまずいからって、ちゃんとVMにノード3つぐらい作って一つ一つ実行して結果を確認しているわけです。時間も大分かかったと思う。

それなのにCapistrano3ですよ。
今までと全然互換性無いわ、Rails向けの機能は分離されるわ、そもそもコマンドも変わってるわで、本当ふざけんなよ!ですよ。

えー、あんだけ頑張って書いたのに、もう期限切れかよー…。と嘆き悲しみました。
マジ辛い…。
せめて、1年早く3を出しておいてくれれば…。
まあ、まだ2系は結構現役で活用されてると思うので、全く無用になったわけでは無いと思いますが。

というわけで、Capistranoについて参考にする場合には、バージョンに注意してくださいね。


後、もう一つギリギリのタイミングで載せられなかったのがGitHub - deivid-rodriguez/byebug: Debugging in Ruby 2についてです。
Ruby-2.0.0時代のデバッガーとして最近主流になってきているbyebugですが、パーフェクトRubyを執筆し終わった時点ではまだ存在を知らなかったため、デバッガーについて書いたコラムで紹介し損ねてしまいました。
そして、入稿が終わって発売までのタイムラグの中でbyebugについて知りました。
byebugを利用し始めたのはそれなりに早い方でしたが、後1ヶ月早く知ってればなあ、と思ったものです。

2.0系のRubyを使っていてデバッガーを探している方は、まずbyebugを使ってみるのが良いと思います。


心残りを吐露する機会があって、少し気が済んだかなw
次のAdvent Calendarはyui-knkさんです。よろしくお願いします。

[Ruby][Redis]オブジェクトをredisにキャッシュしたり検索したりするConcernを表現するgemを作った
Concernスタイルなモジュールを作ってみたかったので、Redisのキャッシュ機構をActiveSupport::Concernを使ってそれっぽくなるように書いてみた。
元々仕事で書いたコードだったけどちょっと直せば汎用化できそうだったので、夜なべしてgem化してみた。

GitHub - joker1007/redis-cacheable: It is concern style redis caching helper. It makes very easy to cache object.

使い方はこんな感じ

class MyObject
  include RedisCacheable

  attr_reader :id, :name

  redis_key   :id          # optional (default: :id)
  redis_attrs :id, :name # method names

  def initialize(attributes)
    @id = attributes[:id]
    @name = attributes[:name]
  end
end

class ProcObject < MyObject
  redis_attrs ->(obj) { obj.id * 10 } # can give proc
end
my_object = MyObject.new(id: 1, name: "my_object")
my_object.cache_to_redis # KEY = my_object.id, VALUE = MultiJson.dump({"id" => my_object.id, "name" => my_object.name})

MyObject.find_from_redis(1) # => {"id" => 1, "name" => "my_object"}

proc_object = ProcObject.new(id: 1, name: "proc_object")
proc_object.cache_to_redis # different namespace with MyObject
ProcObject.find_from_redis(1) # => 10

もし、どこかで使えそうな機会があったら検討してみてください。

デフォルトでは新しくredisのコネクションプールを生成しますが、既にredisのコネクションが存在するならそれを再利用することができます。

RedisCacheable::Connectable.redis_connection = $redis # $redis is Redis instance or ConnectionPool

Vimにmrubyインターフェースを組み込んでみた

週末の遊びとして、Vimにmrubyインターフェースを組込む実験をしてみた。
ほとんどCで書いた経験が無いので、出来るかわからんなーと思っていたが、構文を実行するだけなら何とか実現できたので、とりあえずまとめておく。
ほとんどmrubyというよりVimの話なんだけど。

mrubyについて調べる

流石にもう試してる人は結構居るみたいなので、mrubyをCのプログラムから実行して結果を取得するのはすぐに分かった。
しかし、なんかいくつかパターンがあるっぽいので繰り返し実行するのに良さそうなのをチョイス。
実行方法の違いが良く分かってない。

#include <mruby.h>
#include <mruby/compile.h>
#include <stdio.h>

int main() {
  mrb_state *mrb;
  mrbc_context *cxt;

  mrb = mrb_open();

  if (mrb == NULL) {
    printf("Error\n");
  }

  cxt = mrbc_context_new(mrb);
  mrb_load_string_cxt(mrb, "puts \"Hello, world\"", cxt);

  mrbc_context_free(mrb, cxt);
  mrb_close(mrb);
  return 0;
}

Vimのif_ruby.cを読む

RubyのコードをCに組込む方法はある程度知っているので、Vimがどういう作法でそれを読んでいるのかを調べる。
マルチプラットフォームな分岐が混じっていて非常に読みづらかったが、要はensure_ruby_initializedという関数で、ruby_init_stack()とruby_init()を読んで、load_pathを設定し、vimとやりとりするオブジェクトを仕込んでいるらしい。
そして、呼び出しのキック元はex_ruby()とかex_rubydo()とかの関数で、それぞれがVimの:rubyコマンド等に対応している。
その対応関係は、ex_docmd.cとかex_cmds.hあたりで定義されている。


ensure_ruby_initializedはこんな感じの関数。

static int ensure_ruby_initialized(void)
{
    if (!ruby_initialized)
    {
#ifdef DYNAMIC_RUBY
	if (ruby_enabled(TRUE))
	{
#endif
#ifdef _WIN32
	    /* suggested by Ariya Mizutani */
	    int argc = 1;
	    char *argv[] = {"gvim.exe"};
	    NtInitialize(&argc, &argv);
#endif
	    {
#if defined(RUBY19_OR_LATER) || defined(RUBY_INIT_STACK)
		ruby_init_stack(ruby_stack_start);
#endif
		ruby_init();
	    }
#ifdef RUBY19_OR_LATER
	    {
		int dummy_argc = 2;
		char *dummy_argv[] = {"vim-ruby", "-e0"};
		ruby_process_options(dummy_argc, dummy_argv);
	    }
	    ruby_script("vim-ruby");
#else
	    ruby_init_loadpath();
#endif
	    ruby_io_init();
	    ruby_vim_init();
	    ruby_initialized = 1;
#ifdef DYNAMIC_RUBY
	}
	else
	{
	    EMSG(_("E266: Sorry, this command is disabled, the Ruby library could not be loaded."));
	    return 0;
	}
#endif
    }
    return ruby_initialized;
}

:mrubyコマンドを動かせるようにする

マルチプラットフォームとかはとりあえずスルー。
Vimとのデータのやり取りも置いといて、:mrubyコマンドで構文を実行する所までを目指す。

#ifdef HAVE_CONFIG_H
# include "auto/config.h"
#endif

#include <stdio.h>
#include <string.h>

#include <mruby.h>
#include <mruby/proc.h>
#include <mruby/compile.h>

#include "vim.h"
#include "version.h"

static int mruby_initialized = 0;
static int ensure_mruby_initialized(void);
static mrb_state* vimMrb;

void ex_mruby(exarg_T *eap)
{
    char *script = NULL;
    mrbc_context *cxt;

    script = (char *)script_get(eap, eap->arg);
    if (!eap->skip && ensure_mruby_initialized())
    {
      cxt = mrbc_context_new(vimMrb);
      if (script == NULL) {
        puts((char *)eap->arg);
        mrb_load_string_cxt(vimMrb, (char *)eap->arg, cxt);
        mrbc_context_free(vimMrb, cxt);
      } else {
        EMSG(_("no mruby script"));
      }
    }
    vim_free(script);
}

static int ensure_mruby_initialized(void)
{
  if (!mruby_initialized)
  {
    vimMrb = mrb_open();
    mruby_initialized = 1;
    return mruby_initialized;
  } else {
    return mruby_initialized;
  }
}

void mruby_end()
{
  mrb_close(vimMrb);
}


非常に適当だが、とりあえずif_ruby.cからコードの構造をパクってきてでっち上げた。


続いて、ex_cmds.hとex_docmd.cを弄る。

diff -r f6cacdc34495 src/ex_cmds.h
--- a/src/ex_cmds.h	Wed Aug 07 21:13:23 2013 +0200
+++ b/src/ex_cmds.h	Sun Aug 11 16:00:41 2013 +0900
@@ -785,6 +785,8 @@
 			NEEDARG|EXTRA|NOTRLCOM),
 EX(CMD_runtime,		"runtime",	ex_runtime,
 			BANG|NEEDARG|FILES|TRLBAR|SBOXOK|CMDWIN),
+EX(CMD_mruby,		"mruby",		ex_mruby,
+			RANGE|EXTRA|NEEDARG|CMDWIN),
 EX(CMD_ruby,		"ruby",		ex_ruby,
 			RANGE|EXTRA|NEEDARG|CMDWIN),
 EX(CMD_rubydo,		"rubydo",	ex_rubydo,
diff -r f6cacdc34495 src/ex_docmd.c
--- a/src/ex_docmd.c	Wed Aug 07 21:13:23 2013 +0200
+++ b/src/ex_docmd.c	Sun Aug 11 16:00:41 2013 +0900
@@ -289,6 +289,9 @@
 # define ex_rubydo		ex_ni
 # define ex_rubyfile		ex_ni
 #endif
+#ifndef FEAT_MRUBY
+# define ex_mruby		ex_script_ni
+#endif
 #ifndef FEAT_SNIFF
 # define ex_sniff		ex_ni
 #endif


mrubyをちゃんと片付けられるように、mruby_endの呼び出しをmain.cに加える。

diff -r f6cacdc34495 src/main.c
--- a/src/main.c	Wed Aug 07 21:13:23 2013 +0200
+++ b/src/main.c	Sun Aug 11 16:00:41 2013 +0900
@@ -1478,6 +1478,9 @@
 #ifdef FEAT_RUBY
     ruby_end();
 #endif
+#ifdef FEAT_MRUBY
+    mruby_end();
+#endif
 #ifdef FEAT_PYTHON
     python_end();
 #endif


関数のプロトタイプ宣言を追加するために、proto/if_mruby.proを作成。

diff -r f6cacdc34495 src/proto/if_mruby.pro
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/proto/if_mruby.pro	Sun Aug 11 16:00:41 2013 +0900
@@ -0,0 +1,4 @@
+/* if_mruby.c */
+void mruby_end __ARGS((void));
+void ex_mruby __ARGS((exarg_T *eap));
+/* vim: set ft=c : */


ヘッダの読み込みを追加する。

diff -r f6cacdc34495 src/proto.h
--- a/src/proto.h	Wed Aug 07 21:13:23 2013 +0200
+++ b/src/proto.h	Sun Aug 11 16:00:41 2013 +0900
@@ -196,6 +196,9 @@
 # ifdef FEAT_RUBY
 #  include "if_ruby.pro"
 # endif
+# ifdef FEAT_MRUBY
+#  include "if_mruby.pro"
+# endif
 
 /* Ugly solution for "BalloonEval" not being defined while it's used in some
  * .pro files. */


後はせっせとautoconfのスクリプトを弄って、--enable-mrubyinterpみたいなオプション足したり、FEAT_MRUBYを定義したり、って感じでコンパイルをでっち上げる。


実際には、autoconfを弄る前に手動でMakefileを直で弄ってコンパイル通らねー、と頭を悩ませたりしてた。
一通り通って動かせるようになってからautoconfを弄っている。


結果、こんな感じでconfigureしてコンパイルすれば動くようになった。

% ./configure --with-features=huge --enable-multibyte --enable-luainterp=yes --with-luajit --with-lua-prefix=/usr/local --enable-rubyinterp=yes --enable-mrubyinterp=yes --with-libmruby=/Users/joker/mruby/build/host/lib/libmruby.a --with-mruby-include=/Users/joker/mruby/include
% make




なんか表示が狂ってておかしいけど、とりあえず実行出来てるっぽい。
パっと見:rubyコマンドと何も変わらないので、少し寂しいが結構楽しかった。


出力はさておき、Vim側とのインターフェースをちゃんと書けば、mrubyでvimプラグインとか書けるかもしれないし、mrbgemsの資産使えたりするんじゃね?とちょっと思っている。
が、そこまでやる気が続くかは分からないw
正直、C書いたりautoconf弄ったりするの辛い…。LLerには厳しい世界であった。
ぬるま湯最高!


編集差分のgistは → https://gist.github.com/joker1007/6203801