[英]fzf.vim: fuzzy matching with a fall-back source
我想通過以下行為對 select 緩沖區執行 vim 命令:
fzf.vim
提供的:History
命令不同,因為我們僅列出當前目錄中最近使用的緩沖區, fzf.vim 列出所有最近的緩沖區)。 用戶可以搜索他們想要加載的文件名 這是我到目前為止所擁有的(假設已經安裝了junegunn/fzf.vim
):
nnoremap <silent> <space><space> :call <SID>recent_files()<CR>
function! s:recent_files_sink(items)
if len(a:items) == 2
execute "edit" a:items[1]
return
endif
call fzf#vim#files("", {'options': ['--query', a:items[0]]})
endfunction
" deduped is a list of items without duplicates, this
" function inserts elements from items into deduped
function! s:add_unique(deduped, items)
let dict = {}
for item in a:deduped
let dict[item] = ''
endfor
for f in a:items
if has_key(dict, f) | continue | endif
let dict[f] = ''
call add(a:deduped, f)
endfor
return a:deduped
endfunction
function! s:recent_files()
let regex = '^' . fnamemodify(getcwd(), ":p")
let buffers = filter(map(
\ getbufinfo({'buflisted':1}), {_, b -> fnamemodify(b.name, ":p")}),
\ {_, f -> filereadable(f)}
\ )
let recent = filter(
\ map(copy(v:oldfiles), {_, f -> fnamemodify(f, ":p")}),
\ {_, f -> filereadable(f) && f =~# regex})
let combined = s:add_unique(buffers, recent)
call fzf#run(fzf#wrap({
\ 'source': map(combined, {_, f -> fnamemodify(f, ":~:.")}),
\ 'sink*': function('s:recent_files_sink'),
\ 'options': '--print-query --exit-0 --prompt "Recent> "'
\ }))
endfunction
Space Space調用s:recent_files()
列出加載的緩沖區和最近使用的來自 viminfo 的文件。 這里有趣的是調用fzf#run
中的sink*
選項(從底部算起的第 4 行)。 水槽是另一個 function。 如果選擇了文件名,接收器 function 會加載它以進行編輯,否則,它會調用fzf#vim#files
,列出目錄的內容。
這非常接近我想要的,但有幾個問題:
我正在尋找有關如何解決這些問題的建議,尤其是 2 和 3。我也對不完全符合規范但提供良好用戶體驗的解決方案持開放態度。
編輯:我想出了另一種方法來實現這一點,使用它作為 fzf 的源
cat recent_files.txt fifo.txt
其中recent_files.txt
是最近文件的列表, fifo.txt
是使用mkfifo
創建的空 fifo。 可以將映射添加到緩沖區,觸發寫入 fifo 的命令。 這樣,用戶可以使用該映射來包含所有文件的列表,以防他們在最近的文件中找不到匹配項。 如果用戶在最近的文件中找到文件並按 Enter 鍵,這種方法會出現問題。 由於 fzf 直到等待從 fifo 讀取,它不會退出https://github.com/junegunn/fzf/issues/2288
我終於能夠使用 fzf 的reload
功能找到一個非常接近的解決方案。 (感謝junegunn )
事情是這樣的:
nnoremap <silent> <space><space> :call <SID>recent_files()<CR>
" Initialize fzf with a list of loaded buffers and recent files from
" the current directory. If <space> is pressed, we load a list of all
" the files in the current directory
function! s:recent_files()
let regex = '^' . fnamemodify(getcwd(), ":p")
let buffers = filter(map(
\ getbufinfo({'buflisted':1}), {_, b -> fnamemodify(b.name, ":p")}),
\ {_, f -> filereadable(f)}
\ )
let recent = filter(
\ map(copy(v:oldfiles), {_, f -> fnamemodify(f, ":p")}),
\ {_, f -> filereadable(f) && f =~# regex})
let combined = <SID>add_unique(buffers, recent)
"-------------------------------------------
" This is the key piece that makes it work
"-------------------------------------------
let options = [
\ '--bind', 'space:reload:git ls-files',
\ ]
call fzf#run(fzf#wrap({
\ 'source': map(combined, {_, f -> fnamemodify(f, ":~:.")}),
\ 'options': options
\ }))
endfunction
" deduped is a list of items without duplicates, this
" function inserts elements from items into deduped
function! s:add_unique(deduped, items)
let dict = {}
for item in a:deduped
let dict[item] = ''
endfor
for f in a:items
if has_key(dict, f) | continue | endif
let dict[f] = ''
call add(a:deduped, f)
endfor
return a:deduped
endfunction
我使用<space><space>
啟動 FZF。 此 FZF window 僅包含當前目錄中的最新文件。 如果我然后按<space>
,則 FZF window 將使用從git ls-files
獲得的新文件列表進行更新。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.