VimのソースコードをVimで解析しよう(Part1-1)

Vimはご存知の通りC言語で書かれています。
ちょっと解析してみましょう。
題材はvim-jpIssue#94 相対行表示にするとカーソルの表示位置がずれるで。
現象はMacOSXで発生してますが、持ってないので作業はlinux(fedora)でやります。
(追記)本来は先ず現象の発生した環境(OS, Vim ver., etc...)で現象の再現手順を確立すべきです。今回のアプローチはイレギュラーです><。

Vimソースコードの取得

Vim本家を参考にしてゲットします。(詳細は割愛)

下準備

.vimrc

" <C-]>でタグジャンプ時にタグが複数あったらリスト表示。カーソルがウィンドウの中心行になるようにジャンプ
nnoremap <C-]> g<C-]>zz
" タグファイルはカレントファイルのパスを基準に上向き検索
set tags=./tags;
" grepは再帰検索、行番号表示あり、バイナリファイルは対象外、マッチ毎にファイル名表示する
"       .hgフォルダとtagsファイルは対象外
set grepprg=grep\ -rnIH\ --exclude-dir=.hg\ --exclude=tags
" (l以外で始まる)QuickFixコマンドの実行が終わったらQuickFixウィンドウを開く
autocmd QuickfixCmdPost [^l]* copen

Bash

$ cd vimソースをゲットしたディレクトリ/src
$ ctags -R -I __ARGS
$ vim

※以後の操作はすべてVimからおこないます。

解析の取っ掛かり

「カーソル位置による相対行番号の描画データ設定処理」から「カーソル描画処理」の間にカーソル位置が変更されていると考えられます。もしそうであればその処理間にカーソル位置が変更されないような仕組みを入れれば解決できるかも。
まずは各処理をやっている場所を特定しましょう。

カーソル位置による相対行番号の描画データ設定処理

キーワードは'relativenumber'オプションですからそれを検索してみましょう。

:grep relativenumber .


option.cの2069行がオプションテーブルのデータっぽいんですけど、同7527行、7528行の If 'number' is set, reset 'relativenumber'. がすごく気になります。もろにオプション変数を弄ってそうなので。

" カレントウィンドウを次ウィンドウ(==Quickfixウィンドウ)に移動。
<C-W><C-W>
" カーソルを最下行(./option.c|7528|〜)に移動
L
" カーソル行のQuickFix情報にジャンプ
<CR>


どうやら w_p_nu が 'number'オプションのBOOL値で、w_p_rnu が 'relativenumber'オプションのBOOL値のようです。ということは w_p_rnu でgrepすれば「カーソル位置による相対行番号の描画データ設定処理」に近づけそうです。

" カーソルを2行下の最初の非空白文字に移動
2<CR>
" カーソルを右側の最初の _ へ移動
f_
" カーソル下の単語をgrep
:grep <C-R><C-W> .


〜試行錯誤〜

描画処理は screen.c でおこなわれていると思われますのでその辺を見ていきましょう。

" カレントウィンドウを次ウィンドウ(==Quickfixウィンドウ)に移動。
<C-W><C-W>
" 「screen.c」を検索
/screen\.c
" カーソル行のQuickFix情報にジャンプ
<CR>

./screen.c|433| w_redr_typeの値をセットするだけの判定なのでスルー。

" 次のQuickFix情報にジャンプ
:cn

./screen.c|950| w_nrwidth絡みの処理っぽいのでスルー。

:cn

./screen.c|3459| おおっ、ここっぽい!一応関数名確認。

" 1桁目が '{' で始まる所へ後方(↑)ジャンプ (== 後方のC関数の定義冒頭部へジャンプ)
[[
" ウィンドウを1ページ後方(↑)スクロール
<C-B>

fold_line()!?コメントも Display one folded line. って書いてるからfolding機能用だな。残念。スルー。

:cn

./screen.c|3459| うーん。。

" QuickFixウィンドウを閉じる
:ccl
" ウィンドウを1ページ前方(↓)スクロール
<C-F>


!!ここだ!関数名も win_line() だし、関数のコメントもそれっぽい!
(w_p_nu でgrepした方が良かったっぽいけど見つかったからOK)


今回はここまで。
次回は「カーソル描画処理」を探します。よろしくどうぞ。
(Part1-2)へ