Skip to content

Instantly share code, notes, and snippets.

@ujihisa
Created January 6, 2014 23:47
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ujihisa/8292163 to your computer and use it in GitHub Desktop.
Save ujihisa/8292163 to your computer and use it in GitHub Desktop.

unite-include-reversed

やばいやばい、VACの執筆予定日がもっと後だと思っていて、穴をあけてしまいました・・・本当に申し訳ないです。

今後はitchyny/calendar.vimで予定を角煮するようにします。

unite-include-reversed

unite-include-reversedというunite sourceとしてのVim pluginの実装を先日開始しました。(*1)

このプラギンは背景を説明するのが難しいと考え、そのために専用の記事を設けることにしました。それがこの記事です。

Vimがもつ"include"という概念について

C言語に#include、Clojureにimport/require/use、Haskellにimport、Rubyにrequireなど、各プログラミング用語ごとに「他のファイルから何かをもってくる」という機能が存在します。ここではこれらすべてを総称してincludeと呼ぶことにしましょう。

Vimはincludeに対する様々な機能を提供しています。

  • [I (後述)
  • <C-x><C-i> (insert mode) によるインクルード補完
    • neocomplete利用で自動化
    • :NeoCompleteIncludeMakeCacheでキャッシュ作成
  • gf (include専用ではないけど)
  • :checkpath! includeしてるファイルを再帰的に網羅
[I			Display all lines that contain the keyword under the
			cursor.  Filenames and line numbers are displayed
			for the found lines.  The search starts at the
			beginning of the file.  {not in Vi}

試しに以下のようなコードを書き、:checkpath!してみましょう。

a.c (保存する必要はありません)

#include <stdio.h>
int main(int argc, char const* argv[])
{
  puts("hello, world!");
  return 0;
}
:checkpath!

:checkpath!

stdio.hとその依存先をすべて検索していることがわかります。

つづいて先ほどのputsのところにカーソルを移動し、[Iと打鍵しましょう。

puts

いまC言語で試しましたが、他のfiletypeでも正しく設定が行われていれば利用できます。 設定はftpluginで行います。たとえばscalaのためのプラギンvim-scalaでは、Scalaのimport文に対してVimのincludeに関する諸機能が利用可能になります。(*2) https://github.com/derekwyatt/vim-scala/blob/master/ftplugin/scala.vim#L2

逆引き

ちょっと名前と機能で整理してみましょう。

  • :checkpath!
    • そのファイル内でincludeしてるものすべてを一欄する。再帰的にincludeをたどりつづけて木にする。
  • [i
    • カーソル位置のidentifierが最初に定義された行を表示。include先も辿る。
  • [I
    • カーソル位置のidentifierが登場するすべての行をファイル名とともに表示。include先も辿る。
  • gf
    • カーソル位置がincludeのpathっぽいもののとき、そのファイルそのものを開く

ところで著者は以下のような機能も欲しいです。

  • ???
    • 「カーソル位置がincludeのとき、そのincludeからもってきたidentifierを使っている行をすべて表示する。include先を辿らない」

つまり、前述の4つを順引とみたときの、逆引きが欲しいのです。

この逆引き機能は、ざっと考えてみたところ、以下のようにして実現できそうです。

  • :checkpath!などで、includeしているファイル一覧を先に生成しておく
  • ファイル先頭からidentifier単位で移動し、各identifier上で[Iし、includeしているファイル名を辞書に保持する
  • 最後まで探索が終わったところで、その辞書をもとに、includeしているファイル名からidentifierを一覧する。

副作用のかたまりですね。

これはあきらかにuniteのsourceにするのがよさそうな例です。 というわけでプラギン名はuniteのsourceでかつincludeを逆引きするもの、つまりunite-include-reversedという名前にしました。

レポジトリはありますが、まだ動作するレベルにはなっていません。 https://github.com/ujihisa/unite-include-reversed

これを実装するために、vital.vimに[Iを関数として使えるようにした Vim.Search.finddef() を実装しました。 これを用いると[Iの結果のようなものをパースした辞書が得られます。

脚注

  • *1 諸事情であれからずっと停滞しています。やばい
  • *2 この設定はujihisaさんがpullreqしました。
  • *3 インクルード補完とそのための設定について詳しくはコチラも参照のこと http://d.hatena.ne.jp/thinca/20091026/1256569191
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment