📑
Vimで最近閉じたファイルを開こう
Vim のタブ機能
Vim でたくさんのファイルを閲覧したい時、みなさんはどうしますか? バッファーに開いておいて切り替える人もいれば、タブをたくさん開いて順繰り見ていく人もいるかと思います。私は後者のタブ派です。
例えば、git で管理しているファイルをパーっと概観したくなった時には
vim -p $(git ls-files)
と実行すれば Vim のタブで全て開くことができます。[1]
このような使い方をしていると、うっかり必要なタブを閉じてしまったりすることがあるんです。そんな時に便利な機能を作ってみました。
閉じたタブの管理
まずはコード
nnoremap <leader>p <Cmd>call ShowMostRecentlyClosedTabs()<CR>
noremap <C-Up> :if len(g:most_recently_closed) > 0 \|
\ execute ':tabnew ' .. remove(g:most_recently_closed, 0) \|
\ endif<CR>
if !exists('g:most_recently_closed')
let g:most_recently_closed = []
endif
augroup MostRecentlyClosedTabs
autocmd!
autocmd BufWinLeave * if expand('<amatch>') != '' | call insert(g:most_recently_closed, expand('<amatch>')) | endif
augroup END
function! ShowMostRecentlyClosedTabs() abort
new
set bufhidden=hide
call append(0, g:most_recently_closed)
$delete
autocmd WinClosed <buffer> bwipeout!
nnoremap <buffer> q <Cmd>bwipeout!<CR>
nnoremap <buffer> <ESC> <Cmd>bwipeout!<CR>
nnoremap <buffer> dd <Cmd>call remove(g:most_recently_closed, line('.') - 1) | delete<CR>
nnoremap <buffer> <CR> <Cmd>execute 'tabnew ' .. remove(g:most_recently_closed, line('.') - 1)<CR>
endfunction
何してるの?
autocmd BufWinLeave * if expand('<amatch>') != '' | call insert(g:most_recently_closed, expand('<amatch>')) | endif
↑の処理で、ウィンドウからバッファーが削除される時に、そのファイル名をg:most_recently_closed
に追加しています。
noremap <C-Up> :if len(g:most_recently_closed) > 0 \|
\ execute ':tabnew ' .. remove(g:most_recently_closed, 0) \|
\ endif<CR>
そして、直近に閉じたファイル名をg:most_recently_closed
から取得して新しいタブで開くようにマッピングしています。
これだけで、「間違って閉じちゃった!」という時に即座に開きなおすことができます。
おまけでShowMostRecentlyClosedTabs()
という関数を定義しました。この関数を実行するとg:most_recently_closed
を新しいバッファーで開いて、g:most_recently_closed
の任意のパスを削除したり任意のパスに移動したりできるようにしています。[2](冒頭の gif を参照)
おまけ
私のタブ関連のキーバインド。
よくタブを開くのでタブの操作に関する設定が多くなっています。
noremap <Tab> <Cmd>tabnext<CR><C-G>
noremap <S-Tab> <Cmd>tabprevious<CR><C-G>
noremap <C-Right> <Cmd>tabnext<CR><C-G>
noremap <C-Left> <Cmd>tabprevious<CR><C-G>
noremap <C-Up> <Cmd>if len(g:most_recently_closed) > 0 \|
\ execute ':tabnew ' .. remove(g:most_recently_closed, 0) \|
\ endif<CR>
noremap <C-Down> <Cmd>q<CR><C-G>
noremap <expr> <C-lt> ':tabmove -' .. v:count1 .. '<CR>'
noremap <expr> <C->> ':tabmove +' .. v:count1 .. '<CR>'
nnoremap gr <Cmd>tabnext<CR><C-G>
nnoremap gR <Cmd>tabprevious<CR><C-G>
" 変更の無いタブとウィンドウを全て閉じる
cabbr qa tabdo windo if !&modified \| try \| close \| catch \| quit \| endtry \| endif
" 開いているタブとウィンドウを問答無用で閉じる
cabbr qq tabdo windo try \| close \| catch \| quit! \| endtry
おわり
それでは良い Vim ライフを!
Discussion