Vim で復活の呪文を使う

Vim Advent Calendar 2011 46日目の記事になります。
特に Vim Advent のネタにする予定もなかったのですが、他に書く人もいなさそうなので、46日目にしました。
こんな感じで書きたいことがあれば各々が好きなように Vim Advent に投稿すればいいと思います。
1人で書き過ぎな気がするので、みなさんももっと参加しましょう!
と、いう事で今回は Vim復活の呪文を唱えたいと思います。

[Vim で復元]

アプリケーションではよく現在の状況を保存し、次回起動時に復元する機能(例えば、バッファであったり、ウィンドウ構成であったり)があると思います。
Vim も例に漏れずに現在の状況を保存し、復元を行う手段が幾つか存在します。

  • session
    • 全てのウィンドウのビューとグローバルな設定を保存し、復元を行う
  • viminfo
    • コマンドや編集情報、検索情報などの履歴を保存し、復元を行う
  • ウィンドウの位置とサイズ


基本的に保存したいデータは上記のようなものになると思います。
さて、上記の機能をそのまま使用しても問題ないのですが、せっかくなので簡単に各処理をまとめた Vim script を書いてみました。
また、session 系のプラグインは既に幾つか存在すると思うので、そちらを調べてみるのもいいかも知れません。

[Vim script]

" ユーザ側が設定するオプション
" 実際にデータが保存されるディレクトリパス
let s:save_point = "c:/save_point"

" session が保存を行うデータオプション
set sessionoptions=blank,curdir,buffers,folds,help,globals,slash,tahpages,winsize,localoptions


" 保存
function! s:save_window(file)
    let options = [
    \ 'set columns=' . &columns,
    \ 'set lines=' . &lines,
    \ 'winpos ' . getwinposx() . ' ' . getwinposy(),
    \ ]
    call writefile(options, a:file)
endfunction

function! s:save_point(dir)
    if !isdirectory(a:dir)
        call mkdir(a:dir)
    endif
    
    " ファイルが存在していないか、書き込み可能の場合のみ
    if !filereadable(a:dir.'/vimwinpos.vim') || filewritable(a:dir.'/vimwinpos.vim')
        if has("gui")
            call s:save_window(a:dir.'/vimwinpos.vim')
        endif
    endif

    if !filereadable(a:dir.'/session.vim') || filewritable(a:dir.'/session.vim')
        execute "mksession! ".a:dir."/session.vim"
    endif

    if !filereadable(a:dir.'/viminfo.vim') || filewritable(a:dir.'/viminfo.vim')
        execute "wviminfo!  ".a:dir."/viminfo.vim"
    endif
endfunction

" 復元
function! s:load_point(dir)
    if filereadable(a:dir."/vimwinpos.vim") && has("gui")
        execute "source ".a:dir."/vimwinpos.vim"
    endif

    if filereadable(a:dir."/session.vim")
        execute "source ".a:dir."/session.vim"
    endif

    if filereadable(a:dir."/viminfo.vim")
        execute "rviminfo ".a:dir."/viminfo.vim"
    endif
endfunction


" 呼び出しを行うコマンド
command! SavePoint :call s:save_point(s:save_point)
command! LoadPoint :call s:load_point(s:save_point)


" 自動的に保存、復元するタイミングを設定
augroup SavePoint
    autocmd!
    autocmd VimLeavePre * SavePoint

    " 自動で保存、復元を行う場合
"   autocmd CursorHold * SavePoint
"   autocmd VimEnter * LoadPoint
augroup END

.vimrc 等にコピーすればすぐに使えるようになると思います。
ざっくりとした実装なので、不都合があればそのまま書き換えてしまえばいいと思います。
(プラットフォームとか全く考えていないので。
また、保存や復元を行うタイミングは autocmd は各自で設定して下さい。
ファイル関連の Vim script はあんまり書いたことがないんですがこんな感じで大丈夫ですかね。

[使い方]

SavePoint 保存
LoadPoint 復元

[オプション]

s:save_point 各データを保存するディレクトリへのパス
sessionoptions session が保存を行うデータの種類


また sessionoptions に設定できるオプションは以下の通りです。

キーワード 復元される項目
blank 空のウィンドウ
buffers ウィンドウに表示されたバッファだけでなく、隠れバッファと、リストに載っているだけで読み込まれていないバッファ
curdir カレントディレクト
folds 手動で作られた折り畳み、折り畳みの開閉の区別、折り畳み関連のローカルなオプション
globals 大文字で始まり、最低1個の小文字を含む名前のグローバル変数。文字列型と数値型の変数のみ保存される。
help ヘルプウィンドウ
localoptions ウィンドウまたはバッファに対してローカルなオプションとマッピング (ローカルなオプションのグローバルな値ではない)
options 全てのオプションとマッピング (ローカルなオプションのグローバルな値も)
resize Vimのウィンドウのサイズ: 'lines' と 'columns' の値
sesdir セッションファイルがおかれているディレクトリが、カレントディレクトリになる (ネットワーク越しに、異なったシステムからアクセスを受けるプロジェクトでは便利である)
slash ファイル名内の '\' がスラッシュに置換される
tabpages 全タブページ。これが含まれていないと、カレントタブページのみが復元される。そのため、タブページごとに別々のセッションを保存することができる。
unix WindowsDOS上でも、Unix形式の end-of-line (1個の) を使う
winpos Vimのウィンドウ全体の位置
winsize ウィンドウサイズ

:help sessionoptions を参照。

[注意]

複数の Vim を起動させている場合は複数の Vim から同じディレクトリへと保存されます。
autocmd CursorHold * SavePoint などを設定する場合は注意て下さい。


そんな感じで4回目の Vim Advent でした。
うーん、そろそろ適当な記事書き過ぎだって怒られそうですね。
…さすがに5回目のネタはまだないですよ?