リリカルマジカル13

11時半くらいに会場に着いて、一通り巡った後昼飯のために一旦外に出て、それから14時過ぎくらいまで会場にいた。

サークル一覧見て初めて気になったサークルがいくつかあったんだけど、俺が行った頃にはもう売り切れていたのが多かった…… 今日買えたのはこんなかんじ。

特に気に入ったのは BANDIT さんの BREAKERS!! PORTABLE 4。ちょっとしたシリーズ物で、お話も好きだし服装が見ていて楽しい。

あと昼飯を京急蒲田の商店街でとったんだけど、シャッターが多いように感じた。 主にリリマジ目的で何度か来てるけど、よく行ってた定食屋がなくなっていたりしてなんか一気に飯屋がなくなった気がする。

Haskellでいかにしておっぱい画像をダウンロードするか〜2012 Conduit 編

元ネタはここらしい: いかにしておっぱい画像をダウンロードするか〜2012 - ゆーすけべー日記

D言語でいかにしておっぱい画像をダウンロードするか〜2012 — Gist を見かけたので Haskell 版を書いてみたんだけど、どうやら既にやられてしまっていたようだ…

いかにしておっぱい画像をダウンロードするか~2012 Haskell編 - 厨二病患者のプログラミング入門

まぁ今流行りの(?) Conduit 版だとこんなかんじ、という例として見てもらえれば。今気付いたけど TupleSections は特に有効にする必要なかったな…

映画

昨日、舞台挨拶付きのストライクウィッチーズ劇場版を見てきた。 一部展開が強引に感じられたものの、総じてとてもよくできてると思った。少し間を空けてもう一回は見たい。 お姉ちゃんの登場シーンが多くてうれしいし、貴重な(?)きれいなペリーヌさんを見ることもできるのでおすすめ。

入場のときに Chaos TCG のカードをもらった。下のほうに「NOT FOR SALE」とある。Chaos TCG 的にこのカードがどれくらい良いのかは全然知らない。

魔法少女リリカルなのは The MOVIE 2nd A's の前売券が劇場窓口で売られ始めたので、ストライクウィッチーズを見る前についでに買っておいた。 1st のときに別の劇場でA3ポスター付きの前売券を買ったときは手提げ袋をもらえなくて持ち帰るのに苦労したけど、今回はもらうことができた。 自分と同じ大きな黒いビニールの手提げ袋を持ってストライクウィッチーズのほうの劇場に入ってくる人を何人か見つけられた。

今回の前売券は前回よりもさらに種類が増えている気がしますが、はやてちゃんのものを中心に買っていきたいと思います。

ghcmod.vim と Unite hoogle の組み合わせ

ghcmod.vim でカーソル位置の型を得ることができるため、これを Unite hoogle の入力としてみると便利そうだと思った。

例えば ~/.vim/ftplugin/haskell.vim

nnoremap <buffer> <silent> <Space>o :<C-u>call <SID>unite_hoogle_type()<CR>
function! s:unite_hoogle_type()
  let [_, l:type] = ghcmod#type()
  call ghcmod#type_clear()
  call unite#start(['hoogle'], { 'input': l:type })
endfunction

を追加する。

すると、よくわからない位置に undefined を書いてとりあえずコンパイルは通る状態にした後、

undefined の位置で <Space>o と打鍵すると

こうなる、みたいな使い方がありそう。

まぁ undefined に限らず、型でも検索できる hoogle と、型を得ることができる ghc-mod type の組み合わせは良さそう。

unite-haddock に hoogle の結果を使う source を追加した

以前インストールされているモジュール名を候補とする unite-haddock を書いた が、 それに加えて hoogle がインストールされていれば :Unite hoogle で hoogle の結果を候補として表示できるようにした。 アクションは haddock と同じで、ローカルあるいはリモート (Hackage) のドキュメントをブラウザで開くというもの。

https://github.com/eagletmt/unite-haddock

準備

hoogle が必要。cabal install hoogle でインストールできる。

さらに hoogle のためのデータベースを作る必要がある。 hoogle data で初期化した後、必要に応じて hoogle data $pkgname でデータベースを作って hoogle combine *.hoo で default.hoo を更新していくといいと思う。

使い方

unite.vim のインターフェイスで hoogle による検索結果を見ることができる。

ここから型や関数を選んで、そのドキュメントをブラウザで開くことができる。

:Unite hoogle だけでなく、:UniteWithCursorWord hoogle でカーソル位置にある単語で検索するのも便利かもしれない。

設定

g:unite_source_hoogle_max_candidates に候補として表示する結果の数の最大値を設定できる。 デフォルトでは 200。 これは unite.vim とは独立して (hoogle 側で) 最大値を設定しているため、Unite バッファ上で <Plug>(unite_toggle_max_candidates) を打鍵しても影響が無い点に注意。

また g:unite_source_haddock_browser にドキュメントを見るためのブラウザを設定できる。 多くの環境であれば勝手に適切なコマンドを用いて開いてくれるので設定する必要は無い。 しかし一部の環境では file:///path/to/doc.html#fragment という URI を開く際に /path/to/doc.html#fragment というパスのファイルを開きにいってしまうため、この変数を用意した。 具体的には、awesome のようなマイナーな DE でかつ xdg-open が利用可能なとき、xdg-open がそのような挙動をしてしまう。

他の hoogle を利用しているプラグイン

unite-haskellimportref-hoogle がある。 どちらも ujihisa さんによるもの。

ref-hoogle が機能的に近そうだが、ref-hoogle は単に hoogle での検索結果を表示するだけであり、ドキュメントを開きにいく機能は無い。 あと現状あんまりまともに動いていない気がする……

なぜ自動チェックが嫌いなのか

端的に言うと、自動的にチェッカが実行されている間は Vim への操作がブロックされてしまうから。

自動的に文法のチェックをするようなツールがある。 この手のツールでは Emacs の flymake がたぶん一番有名だけど、Vim にも似た機能をもつプラグインがある。 最近は Syntastic がかなり人気の様子。 デフォルトで多くのツールをサポートし、エラー箇所の表示もかっこいいっぽい。

Syntastic ではどのようにして自動的にチェックしているかというと、BufWritePost (や BufReadPost) のタイミングで文法チェッカを実行し、 結果を location-list に表示したり sign や balloon で強調したりしている。 ここで問題なのは、ファイルへの書き出しの後に文法チェッカが実行されている間は Vim への操作が完全にブロックされてしまう点だ。 ruby -wc のように主に動的型付けなスクリプト言語において本当に文法が正しいかどうかチェックする程度ならば一瞬でチェックが終了するけれども、 g++ -fsyntax-only とか ghc-mod check のようにちょっと一瞬で終わるとは言えないようなチェックが存在する。 そんなチェックをファイルへの書き出しの度に行って、しかもチェックしている間は操作がブロックされるというのはかなりイラつく。 正直、文法エラーを生じるようなプログラムなんてまず書かないし、文法チェック以上のチェック (lint とか型検査とか) こそが役に立つと思うんだけど、 そうなるとチェックに多少時間がかかるようになってブロックされることによるイライラが増す。

外部プロセスとの非同期的なやりとりは vimproc で達成できるので、さらに Vim に setTimeout 的なものがあるといいですね……
Issue #150: タイマーが欲しい · vim-jp/issues

neco-ghc が neocomplcache 無しでも利用できるようになりました

neco-ghc は neocomplcache 専用のプラグインでしたが,構造を変更して neocomplcache 無しでも Vim のオムニ補完の関数として動作できるようにしました. neocomplcache ユーザにとっては表面上の変更点はありません.neocomplcache の有無にかかわらず,補完能力そのものは同じです.

ujihisa/neco-ghc - GitHub

necoghc#omnifunc を 'omnifunc' に設定することで,非 neocomplcache ユーザでも neco-ghc による補完を Vim のオムニ補完として使えます. ~/.vim/ftplugin/haskell.vimsetlocal omnifunc=necoghc#omnifunc と設定すると Haskell のコードを開いたときに自動的に 'omnifunc' に設定できます. そしてインサートモードで C-x C-o とすれば補完できます.

以下は neocomplcache 専用のプラグインから 'omnifunc' としても使えるように書き換えたときにちょっとハマった部分の記録.Vim の補完関数を書いたり,それを neocomplcache からも使えるようにしたい人には参考になるかも.

補完のキャンセル

'omnifunc' の仕様は :help complete-functions にある. a:findstart が 1 のときは補完位置を返すわけだけど,

Return -1 if no completion can be done, the completion will be cancelled with an error message. Return -2 to cancel silently.

と書かれている. これを読んで俺は「-1 を返すと補完はキャンセルされるので a:findstart が 0 で再び呼ばれることはなく,さらに -2 を返すと『パターンは見つかりませんでした』のエラーメッセージも出ない」と解釈した. しかしどうやら,-1 を返したときに関しては a:findstart が 0 で再び呼ばれるのが仕様らしく, そのとき a:base は空文字列になっている. 一方 -2 を返したときは呼ばれない. なので,とりあえず neco-ghc では補完できないときは位置として -1 を返し,a:base が空のときは補完できないものとして空の補完候補を返している.

col('.') の値

a:findstart が 0 で 'omnifunc' が呼ばれたとき,col('.') は「補完位置」を返す. つまり,例えば

foo ba_

において _ の位置でオムニ補完をして,補完位置として ba の先頭を返した場合,補完候補を計算する段階では col('.') の値は 7 ではなく 5 となる.

一方 neocomplcache のプラグインとして動作するとき,s:source.get_complete_words() の内部では col('.') の値は 7 になる. そのかわり(?),s:source.get_complete_words() の第一引数で補完位置として 4 が渡される.