Vimのコマンドラインモードでfzfを動かす
Vimのコマンドラインモードでfzfを起動し,選んだ文字を加工した上でコマンドラインモード上にテキストとして挿入する.vimrc
を書きました.
環境
- macOS: 10.15.3 (Catalina)
- vim: 8.0 (2016 Sep 12, compiled Mar 25 2018 03:02:16) (kaoriya-vim)
やりたかったこと
よく使うディレクトリのブックマークをテキストで作成しておいて,
Vimでファイル保存する際などに,コマンドラインモードで:e
と入力した後で,
fzfでそのブックマークを選択してパスを挿入する,ということがやりたくて方法を考えてみました.
ブックマークのファイル
こんな感じで,識別用のラベルとパスを書いています.
$HOME/bookmarks
WIP,$HOME/Desktop/WIP
Projects,$HOME/Documents/projects
MEDIA,/Volumes/MEDIA
シェルでの方法
ちなみにZSH上では次のようなコードを書いて,ZLEでfzfするようにしました.
$HOME/.zshrc
fzf-bookmark() {
local selected
selected=`(cat ~/bookmarks 2>/dev/null) | fzf`
if [ -n "$selected" ]; then
LBUFFER=${LBUFFER}"`awk 'BEGIN{FS=","}{print $2}' <<<"$selected"` "
fi
zle reset-prompt
}
zle -N fzf-bookmark
bindkey '^Xb' fzf-bookmark
Vimでの方法
こんなコードを.vimrc
に書きました.(2021-01-10 修正)
$HOME/.vimrc
function! s:FzfBookmark()
let l:BS = "\u08" " <C-h>
let l:cmdtype = getcmdtype()
let l:args = {
\ 'source': 'cat $HOME/bookmarks',
\ 'sink': { lines -> lines },
\ 'down': '~50%',
\ } " sink does nothing
if l:cmdtype == ':'
let l:list = fzf#run(fzf#wrap(l:args))
if len(list)
return escape(substitute(list[0], '^.\{-,},', '', ''), ' ')
else
return 'a' . l:BS " workaround for redraw problem
endif
endif
endfunction
cnoremap <expr> <C-x>b <SID>FzfBookmark()
fzfの起動はfzf#run()
を使っており,
選択結果を加工して,<C-x>b
にマップされる結果として返しています.
これで,コマンドモードで<C-x>b
をタイプすることでfzfが起動し,
選択したブックマークのパスが挿入されます.