Vim でオレオレ :tab drop

この記事は Vim Advent Calendar 2012 251日目の記事になります。


Vim でタブページを多用している場合、:tab drop はとても便利なコマンドです。
しかし、:tab drop を使用した事がある方はわかると思いますが、このコマンドを実行した際に各タブページが1つずつ開かれて行く為、視覚的にとても煩わしいです。
これを解決するためにオレオレ :tab drop コマンドを定義してみました。

function! s:to_fullpath(filename)
    let name = substitute(fnamemodify(a:filename, ":p"), '\', '/', "g")
    if filereadable(name)
        return name
    else
        return a:filename
    endif
endfunction

function! s:tabwinnr(filename)
    let filename = s:to_fullpath(a:filename)
    let list = map(range(1, tabpagenr("$")), "map(tabpagebuflist(v:val), 's:to_fullpath(bufname(v:val)) == filename ? [' . (v:key+1) . ', v:key+1] : []')")
    let list = filter(eval(join(list, '+')), "!empty(v:val)")
    return list
endfunction


function! Tabdrop(filename)
    let result = s:tabwinnr(a:filename)
    if empty(result)
        execute "tabnew" a:filename
        return
    endif
    let [tabnr, winnr] = get(result, 0)
    execute "tabnext" tabnr
    execute winnr . "wincmd w"
endfunction


command! -complete=file -nargs=1
\   Tabdrop call Tabdrop(<q-args>)

" 使い方
" :Tabdrop {filename}


" unite-action
let s:action = {
\    'description' : 'my tab drop',
\    'is_selectable' : 1,
\    "is_tab" : 1,
\ }

function! s:action.func(candidates)
    let bufpath = unite#util#substitute_path_separator(expand('%:p'))
    for candidate in a:candidates
        if bufpath !=# candidate.action__path
            call Tabdrop(candidate.action__path)
            call unite#remove_previewed_buffer_list(bufnr(unite#util#escape_file_searching(candidate.action__path)))
        endif
        call unite#take_action('open', candidate)
        normal zz;
    endfor
endfunction

" kind-file の tabdrop に置き換える
call unite#custom_action('file', 'tabdrop', s:action)
unlet s:action


これで視覚的にも優しくなり(:tab drop より)処理も高速化します。