📿

Vimの起動時に現在のリポジトリで直前に使ったファイルを開く

2022/08/14に公開
1

Vimには:oldfilesというコマンド(およびv:oldfilesという変数)があり、過去に開いたファイルを一覧することができます。
この番号は#<0というフォーマットで選択することができ、例えば:editコマンドなどに渡すことができます。

これを利用し、Vim起動時にvim -c 'edit #<0'と指定すれば、ファイルパスを指定せずとも直前に使ったファイルを開くことができます。

ただし、v:oldfilesには「過去に開いたファイル」がすべて入っているため、直前の終了状況によっては、以下のようなファイルが対象になってしまうこともあります。

  • 現在のディレクトリとは別リポジトリのファイル
  • .git/COMMIT_EDITMSGなどの.git内のファイル
  • 以前編集したが、その後削除したファイル
  • プラグインによって開かれた一時的なファイル
  • ヘルプファイル

(状況にもよりますが)基本的にこれらは「直前のファイル」の対象にしたくありません。

ということで、oldfilesをフィルタする関数を作成しました。
以下を設定ファイルに記載してください。

.vimrc or init.vim
" {{{ EditProjectMru()
function! EditProjectMru() abort
  let cmd = 'git rev-parse --show-superproject-working-tree --show-toplevel 2>/dev/null | head -1'
  let root = system(cmd)->trim()->expand()

  " not in git project
  if !isdirectory(root)
    edit #<1
    return
  endif

  " filter oldfiles
  for file in v:oldfiles
    let file = expand(file)
    if file =~ root .. '/' && file !~ '\.git/' && filereadable(file)
      execute 'edit' file
      return
    endif
  endfor
endfunction

" remove function because it is only for `$ vim -c 'call EditProjectMru()'`
autocmd VimEnter * ++once delfunction! EditProjectMru
" }}}

これをvim -c 'call EditProjectMru()'のように起動時に呼び出すことで、「現在のプロジェクトで最近使ったファイル」を開くことができます。
内部では、「現在のgitプロジェクト」かつ「.git/内ではない」かつ「読み込み可能」なファイルを選択する条件を設定しています。
また、起動後に使用することはない想定なので、VimEnterのタイミングで関数を削除しています。

これと:h restore-cursorのテクニックを組み合わせると、直前のファイルを開いて編集に戻るのが楽になります。
毎回-c 'call EditProjectMru()'を打ち込むのも億劫なので、エイリアスに登録しておくのがおすすめです。

git rootの検出は以下の記事でも使用しています。
https://zenn.dev/kawarimidoll/articles/30693f48096eb1

Discussion

yutkatyutkat

たぶんセッション使ったほうが直前の閉じた状態を楽に再現できる気がします