Vimで二重拡張子のファイルのファイルタイプを検出する

Vim で二重拡張子のファイルを編集することが時々ある。例えば *.ext.njk といった末尾の拡張子がある特定の拡張子で、それの手前にある拡張子がファイル本来の種類を表すもの。

こういったファイル名のファイルタイプを指定する場合、愚直に設定を書くのなら以下のようになると思う。

autocmd BufNewFile,BufRead *.html.njk setfiletype html
autocmd BufNewFile,BufRead *.xml.njk setfiletype xml
" ...

上記のような設定をつらつらと記述する面倒は避けたいので、ファイルタイプを自動的に検出するような Vim script を .vimrc に書いた。

function! s:set_filetype() abort
" すでにfiletypeが指定されていたら終了
if did_filetype()
return
endif

let extension = expand('%:r:e')

" 拡張子が取得できなかったら終了
if empty(extension)
return
endif

let filetypes = getcompletion(extension, 'filetype')

" ファイルタイプが存在しなければ終了
if empty(filetypes)
return
endif

execute 'setlocal' 'filetype=' . filetypes[0]
endfunction

if exists('?getcompletion')
autocmd BufNewFile,BufRead *.*.njk call <SID>set_filetype()
endif

getcompletion() という関数を使うと拡張子に対応したファイルタイプの配列が取得できるとのことでこれを使った。

あとは expand() でカレントバッファのファイル名から拡張子を取得して、組み合わせると目的が達成できた。

ファイルを開くたびに手動でファイルタイプを指定していて面倒だったが、これからは苦労せずに済む。

Ref