Hatena::ブログ(Diary)

Alone Like a Rhinoceros Horn

2012-02-21

unite-outline の近況: 次期バージョンの開発

昨年の秋頃から目立った変化のない unite-outline ですが、開発が停滞しているとか、作者のやる気がなくなった*1とかではなく、「今年の抱負 - Vimプラギン編」で述べた通り、次期バージョンの開発(準備)を少しずつ進めています。

ある程度形になったら別ブランチを切って push しようと思ってますが、まだ仕様をあれこれ考えたり非同期実行のやり方を模索している段階で、ものは全然できておりません(汗 まあ、上半期のうちに最初のバージョンを push できたらいいな、ぐらいの見込みです。*2

大きな変更が必要になるついでに、「もうこの際、たまった負債を全部返済してやる!」みたいな意気込みでして、プラグインの構成上前から気になっていた点や、作者がまずいと思っている outline info の仕様など、全面的に見直してドカンと刷新する予定です。(というか、そうせざるを得ないのです…… 詳細は以下を参照)

で、その次期バージョンですが、青写真は以下の通りです。

NuOutline(仮)

アウトライン解析部を独立したプラグイン(NuOutline(仮))として切り出し、unite-outline をそのフロントエンドとして添付するという構成をとります。

プラグインの構成上一番大きな変更点がこれです。

「unite.vim の source として unite-outline は大き過ぎる」、「アウトライン解析を行うプラグインに unite-outline を添付すべきでは?*3」という指摘は以前から何度かあり、自分でも気になっていました。また、

  • autoload/unite/sources/outline/ 以下のディレクトリ階層の深い位置にファイルがごちゃごちゃと多過ぎる。
  • その結果、オートロード関数の名前がやたら長くなる。
  • また、動作が複雑になってオプション変数も増えたが、unite.vim の source のそれはやはり名前が長くなる。
  • unite.vim の source とアウトライン解析部が渾然一体、なんだかなー

といったこともあり、アウトライン解析を行う部分を独立したプラグインとして切り出し、プラグイン全体の構成を仕切り直すことにしました。図で示すと以下のようになります。

f:id:h1mesuke:20120221221020p:image

きれいに 3層に分離しました。3者の役割分担は Webアプリケーションなどでおなじみの MVCパターンでとらえると理解しやすいです。アウトライン表示のインターフェースを提供してくれる unite.vim がビュー、見出し抽出のロジックを持っている NuOutline がモデル、両者の間に入ってあれこれと調停をし、見出しの自動更新のための面倒をみたりする unite-outline がコントローラというわけですね。

V, C は交換可能(にしたい)

NuOutline は(頑張って)unite.vim, unite-outline と密に結合させないで作ろうと思っています。unite-outline はあくまでフロントエンドのデフォルト実装として NuOutline に添付されているもの、という位置付けにして、第三者が別のフロントエンドを提供できる余地を残しておきます。(そんな人が現れるかは別にして ;-) )

が、リポジトリは unite-outline のままで!

どちらかというと unite-outline の方が NuOutline のオマケ的な存在なのですが、Vundle や neobundle.vim 全盛(?)の昨今、リポジトリURL が変わるというのは致命的だと思うので、開発は引き続き、現行の unite-outline のリポジトリで行います。まあ、使うだけなら NuOutline は unite-outline の影に隠れて見えませんし、ユーザーが使うのはあくまで unite.vim を通してですからね。

というわけでなんと、unite-outline という unite.vim の source に、プラグインがまるまる1個付いてくるということになります(笑)

オプション変数名が変化

「unite.vim上でどう表示するか」に関する設定を除き、オプション変数の所管が NuOutline の方へ移るので変数の名前が変わってしまいます。しばらくは古い変数の方も見るようにしたいところですが……

outline info → parser

unite.vim の source である unite-outline の source……的な存在であった outline info は所管が NuOutline の方へ移ります。それにともない名称も outline info から parser に変更し、配置場所も

  • autoload/nuoutline/parsers/

とします。*4unite.vim における sources, kinds, filters などと同様の位置付けになります。

DRY でない create_heading() よ消え去れ!

outline info の仕様には(今となっては)気に入らない部分がたくさんあり、その最たるものが見出し抽出のためのパターンが複雑になると create_heading() の中身が DRY でなくなるというものです。例えば、

'^\s*\(foo\|bar\|baz\|fizz\|buzz\)\>'

のようなパターンを設定したとして、マッチングが行われ、マッチが見つかって create_heading() が呼び出されたとします。その場合、マッチしたサブマッチがどれかによって処理を分けなければならないことがほとんどで、現行の outline info ではマッチした文字列に対して再度マッチングを試み、サブマッチのうちのどれに実際にマッチしたのかを判定するような DRY でないコードが氾濫しています。

これは outline info を書く側の問題ではなくて、そのようにしか書けなくしている outline info の仕様の方に問題があるのです。

「こんなことでは outline info を書いてみようと思ってくれた人も離れていくわ!」

と強く思った私は、outline info の所管が NuOutline へ移るこのタイミングで、その仕様を刷新することにしました。

まだ仕様を練っている段階ですが、

let s:parser.foo_pattern = "foo's pattern"
function! s:parser.create_foo_heading()
endfunction

let s:parser.bar_pattern = "bar's pattern"
function! s:parser.create_bar_heading()
endfunction

let s:parser.baz_pattern = "baz's pattern"
function! s:parser.create_baz_heading()
endfunction

こんな風に、見出しの種類ごとに個別にパターンを設定できるようにし、「どのパターンにマッチしたか」の判定までを本体側の責任として、適切なコールバックが呼び出されるようにします。parser側では見出し(辞書)の作成に専念できるようになるので、パターンマッチ方式の parser を作るための敷居はかなり下がるはずです。

構文解析が必要になるケースのサポート

create_heading() について力説した直後にアレですが、「正規表現によるパターンマッチ → create_heading() 」というやり方で見出しが拾えるファイルタイプは実は少なく、ほとんどのプログラミング言語では見出しを「ちゃんと」拾うのに構文解析が必要になります。

具体的に言うと、ctags などの外部の構文解析プログラムを呼び出し、その出力を解析して見出しの木を parser が自前で作る必要があります。

今後、対応ファイルタイプを増やしていくためにも、その辺の処理が書きやすくなるようなユーティリティコードの充実やドキュメントの整備などが必要と考えています。

まとめ

最初からちゃんと設計しとけや! ヽ(*`Д´)ノゴルァ

うう、当初は「正規表現でマッチさせて拾うだけやん」程度の軽いノリで作り始めたのでございます。最初にコミットされたバージョンの素朴さがすべてを物語っている……

しかし、まあ、ここまできたらプラグインとしてちゃんとしたものにしたいですね!

*1:むしろ逆で、変なブーストが入ったw

*2:今年の抱負ということになってるので、遅くとも年内にはw

*3:alignta に unite-alignta が同梱されているのがこの構成ですね。

*4:outline info は autoload/outline/ に配置してもよいことになっていましたが、これは autoload/unite/sources/outline/ が自作の outline info を配置する場所として位置が深すぎるだろうとの配慮からでした。通常、autoload/ に何かを配置させるにあたっては、プラグイン名できちんと名前空間を切るべきです。

2011-10-10

unite-outline の近況: C のマクロがどう展開されるかを表示するようにした

C のマクロが展開されてどうなるかを => の後に表示するようにしてみた。

Before:

f:id:h1mesuke:20111010163037p:image

 ↓

After:

f:id:h1mesuke:20111010163030p:image

上の画像より空間の利用効率が上がって情報量が増えたのがわかると思う。

do { ... } while(0) のような複数行に渡るものは最初の数行分しか表示できないけど、アウトラインってことならこんなもんで十分だろう。詳細はプレビューするなりジャンプするなりすれば確認できるわけだし。

2011-01-31

unite-outline まとめ

unite-outline の関連エントリが増えてきたのでまとめ。自演乙。*1

*1:ちなみに、私は長島☆自演乙☆雄一郎選手のファンです ( ̄ー ̄)bグッ!

2010-11-07

unite.vim で簡易アウトライン機能

ここでいう「アウトライン機能」とは、極々大雑把に、「ファイルの見出し一覧的なものを表示する機能」および、「見出し一覧から項目を選択することで該当個所へジャンプできる機能」、ぐらいの意味です。(世間一般において「アウトライン機能」といった場合にこれで通用するのかは自信がないので、そこは適当に)

ファイルタイプごとに設定されたパターンにもとづいて見出しを抽出し、それでファイルのアウトライン表示をやる機能を前々から欲しいと思っていて、はてさてプラグインを探そうか、それとも :grep でやろうか*1と思っていたところ、id:thincaさんによる以下のエントリがタイムリーヒット。

ここから簡易的なアウトライン機能までもう少しですよね。ここに、ファイルタイプごとに設定されたパターンにもとづく見出し行の抽出(フィルタ)を加えて候補を絞り込めば、unite のインターフェースを使って見出し一覧の表示と各見出しへのジャンプ機能が実現できてしまいます。

というか、やってみたらそれらしいものができたのでした↓

unite-outline

自分の vimrc で使ってみるとこんな感じ

f:id:h1mesuke:20110816233246p:image

なかなかいい感じ。

後は対応するファイルタイプを増やしていって、見出し抽出用のパターンをチューンしていけば、「アウトライン機能」としてちゃんと使える source にできそうではないですか。おおー。

source を書いて夢がひろがりんぐな unite面白いです。*2

スクリーンショット

対応ファイルタイプもちょっとずつ増えてきたので、見出し一覧のスクリーンショットをいろいろ掲載してみる。(2010-12-16)

C

f:id:h1mesuke:20111011140636p:image

C++

f:id:h1mesuke:20111011140634p:image

HTML

f:id:h1mesuke:20110816233728p:image

Java

f:id:h1mesuke:20110816233729p:image

JavaScript

f:id:h1mesuke:20111011140722p:image

Markdown

f:id:h1mesuke:20111011140721p:image


汎用のマークアップ言語としては Markdown の他に

  • reStructuredText
  • ReVIEW
  • Textile

にも対応している。

Perl

f:id:h1mesuke:20110816233730p:image

PHP

f:id:h1mesuke:20110816233731p:image

Python

f:id:h1mesuke:20110816233732p:image

Ruby

f:id:h1mesuke:20110816234413p:image

Shell script

f:id:h1mesuke:20111011140521p:image

Vim Help

f:id:h1mesuke:20111011140555p:image

Vim script

f:id:h1mesuke:20110816233246p:image

対応しているファイルタイプ一覧

後書き

unite.vim のヘルプを読んで source を自作できると知った多くの人(自分含め)が最初に作ろうとするのがこの見出し抽出タイプではないでしょうか。なので、似たような source を自分の vimrc に書いている人は多そうですね (^^;

追記

GitHub にリポジトリを作ってみました。
ちょっとずつ対応ファイルタイプを充実させていく予定 (2010-11-08)

*1::grep を使って見出しを抽出して quickfix list でアウトラインを表示させている vimrc を最近見た。ほー、そんな使い方もあるんだなあと感心。

*2:名前に偽りなし。本当にいろんなプラグインに分散されていた機能を統合(unite)してしまって、一体いくつのプラグインをお払い箱にすれば気が済むのかという感じ。