2026年2月2日月曜日

ファイル名補完を「カレントディレクトリから」ではなく「開いているファイルのディレクトリから」にしたい

この記事はVim駅伝の2026-2-2 の記事です。

Vim では <C-x><C-f> で、「カレントディレクトリからのファイル名補完」ができます。

Markdown などで資料を書いていると、リンク先の記述をするために「そのファイルのディレクトリからのファイル補完」がしたくなることがあります。

ただ、資料のビルドなどがあるためカレントディレクトリは docroot から動かしたくありません。

そんな願いをかなえるスクリプトを作ったので共有します。

やり方としては、「補完開始直前に lcd でカレントディレクトリを動かして、補完完了後に元に戻す」という感じです。

同じ挙動が良いという方は以下スクリプトを使ってみてください。

" カレントディレクトリを開いているファイルのディレクトリへ移動
function! file_complete_extension#start_lcd_for_insert_completion() abort
  if exists('b:_saved_lcd')
    return ''
  endif

  " 現在のウィンドウの cwd を保存
  let b:_saved_lcd = getcwd(-1)

  " 開いているファイルのディレクトリへ移動
  let l:dir = expand('%:p:h')
  if !empty(l:dir)
    execute 'lcd' fnameescape(l:dir)
  endif
  return ''
endfunction

" CompleteDone で restore_lcd を発火させる
augroup restore_lcd_after_completion
  autocmd!
  autocmd CompleteDone * call file_complete_extension#restore_lcd()
augroup END

" b:_saved_lcd に戻る
function! file_complete_extension#restore_lcd() abort
  " b:_saved_lcd があればそこに戻る
  if exists('b:_saved_lcd') && !empty(b:_saved_lcd)
    execute 'lcd' fnameescape(b:_saved_lcd)
    " 後始末、 b:_saved_lcd を unlet
    unlet b:_saved_lcd
  endif
endfunction

inoremap <expr> <C-x><C-f>
      \ file_complete_extension#start_lcd_for_insert_completion() . "\<C-x>\<C-f>"

0 件のコメント:

コメントを投稿