Reputation: 5
I usually have plenty of files opened in different windows and tabs within vim (or neovim). To jump to the window where the file is open I use :sbuffer. For that, I input the begging of the file name and autocomplete with . I would like to find the name of the file in the way fuzzy search does.
How I see this going, I press , I input a part of the file name, until I see the file found by fuzzy search, then I press . If the file is already opened in a window in any tab, vim moves there rather than opening it in the actual window.
Do you know how to achieve this with any fuzzy search plugin? I'm not worried about the behaviour if the file is not open as usually I take manual care of splits when opening files.
Thanks!
Upvotes: 0
Views: 1287
Reputation: 276
Fzf
is probably one of your best options here.
You'll need both fzf.vim and fzf.
Also, there's a readme for fzf vim in fzf main repo (yeah...).
I can't recall where I found this, but here's a config I copied from Fzf manual somewhere:
let g:fzf_command_prefix = 'Fzf'
let g:fzf_buffers_jump = 1 " [Buffers] to existing split
function! s:build_location_list(lines) abort
call setloclist(0, map(copy(a:lines), '{ "filename": v:val }'))
lopen
endfunction
function! s:build_quickfix_list(lines) abort
call setqflist(map(copy(a:lines), '{ "filename": v:val }'))
copen
endfunction
" An action can be a reference to a function that processes selected lines
let g:fzf_action = {
\ 'ctrl-l': function('s:build_quickfix_list'),
\ 'ctrl-r': function('s:build_location_list'),
\ 'ctrl-t': 'tab split',
\ 'ctrl-x': 'split',
\ 'ctrl-v': 'vsplit'}
" \ 'ctrl-o': '<S-tab>',
" \ 'ctrl-i': 'insert_match',
" function! s:insert_match(lines) abort
" <c-r>=echo('a:lines')<cr>
" endfunction
nnoremap <leader>ff :FzfFiles $HOME<cr>
nnoremap <leader><c-f> :FzfFiles .<cr>
nnoremap <leader>F :FzfFiles /<cr>
nnoremap <leader>fb :FzfBuffers<cr>
nnoremap <leader>b :FzfBuffers<cr>
nnoremap <leader>fw :FzfWindows<cr>
nnoremap <leader>ft :FzfTags<cr>
nnoremap <leader>f<c-t> :FzfBTags<cr>
nnoremap <leader>fc :FzfCommit<cr>
nnoremap <leader>f<c-c> :FzfBCommit<cr>
nnoremap <leader>fg :FzfGFiles?<cr>
nnoremap <leader>f<c-g> :FzfGFiles<cr>
nnoremap <leader>fl :FzfLines<cr>
nnoremap <leader>f<c-l> :FzfBLines<cr>
nnoremap <leader>f; :FzfHistory:<cr>
nnoremap <leader>f/ :FzfHistory/<cr>
nnoremap <leader>fh :FzfHistory<cr>
nnoremap <leader>fm :FzfHelptags<cr>
nnoremap <leader>fs <esc>:FzfSnippets<cr>
nnoremap <leader>fr <esc>:Rg<cr>
inoremap <c-x><c-s> <c-o>:FzfSnippets<cr>
" Enable per-command history.
" CTRL-N and CTRL-P will be automatically bound to next-history and
" previous-history instead of down and up. If you don't like the change,
" explicitly bind the keys to down and up in your $FZF_DEFAULT_OPTS.
let g:fzf_history_dir = '~/.local/share/fzf-history'
let g:fzf_tags_command = 'ctags -R'
" Border color
let g:fzf_layout = {'up':'~90%', 'window': { 'width': 0.8, 'height': 0.8,'yoffset':0.5,'xoffset': 0.5, 'highlight': 'Todo', 'border': 'rounded' } }
let $FZF_DEFAULT_OPTS = '--layout=reverse --info=inline --bind "ctrl-o:toggle+up,ctrl-space:toggle-preview"'
let $FZF_DEFAULT_COMMAND="rg --files --hidden --glob '!.git/**'"
"-g '!{node_modules,.git}'
" Customize fzf colors to match your color scheme
let g:fzf_colors =
\ { 'fg': ['fg', 'Normal'],
\ 'bg': ['bg', 'Normal'],
\ 'gutter': ['bg', 'Normal'],
\ 'hl': ['fg', 'Comment'],
\ 'fg+': ['fg', 'CursorLine', 'CursorColumn', 'Normal'],
\ 'bg+': ['bg', 'Visual', 'CursorColumn'],
\ 'hl+': ['fg', 'Statement'],
\ 'info': ['fg', 'PreProc'],
\ 'border': ['fg', 'vertsplit'],
\ 'prompt': ['fg', 'Conditional'],
\ 'pointer': ['fg', 'Exception'],
\ 'marker': ['fg', 'Keyword'],
\ 'spinner': ['fg', 'Label'],
\ 'header': ['fg', 'Comment'] }
" \ 'border': ['fg', 'Conditional'],
"Get Files
command! -bang -nargs=? -complete=dir Files
\ call fzf#vim#files(<q-args>, fzf#vim#with_preview({'options': ['--layout=reverse', '--info=inline']}), <bang>0)
" Get text in files with Rg
command! -bang -nargs=* Rg
\ call fzf#vim#grep(
\ "rg --column --line-number --no-heading --color=always --smart-case --glob '!.git/**' ".shellescape(<q-args>), 1,
\ fzf#vim#with_preview(), <bang>0)
" Ripgrep advanced
function! RipgrepFzf(query, fullscreen) abort
let command_fmt = 'rg --column --line-number --no-heading --color=always --smart-case %s || true'
let initial_command = printf(command_fmt, shellescape(a:query))
let reload_command = printf(command_fmt, '{q}')
let spec = {'options': ['--phony', '--query', a:query, '--bind', 'change:reload:'.reload_command]}
call fzf#vim#grep(initial_command, 1, fzf#vim#with_preview(spec), a:fullscreen)
endfunction
command! -nargs=* -bang RG call RipgrepFzf(<q-args>, <bang>0)
" Git grep
command! -bang -nargs=* GGrep
\ call fzf#vim#grep(
\ 'git grep --line-number '.shellescape(<q-args>), 0,
\ fzf#vim#with_preview({'dir': systemlist('git rev-parse --show-toplevel')[0]}), <bang>0)
I tweaked it only a tad, but with something you'll probably enjoy because it's fzf paradigm to set switchbuf=usetab
(or useopen). It lets Vim use a window where the buffer is already opened rather than the current.
let g:fzf_buffers_jump = 1 " [Buffers] to existing split
I hope it helps!
Upvotes: 1
Reputation: 792
I'm personnally using the FZF plugin for all my fuzzy searches.
Here's a piece of code archieving what you ask:
set switchbuf=useopen,usetab
function! HandleFZFSink(filename)
echo a:filename
try
exe "sbuffer " . a:filename
catch
exe "edit " . a:filename
endtry
endfunction
function! FZFTmp()
let cmd = 'ls --color=never 2> /dev/null'
silent! exe fzf#run({'source': cmd, 'sink': function('HandleFZFSink'), 'down':'40%'})
endfunction
nnoremap <silent> , :<C-u>call FZFTmp()<CR>
Upvotes: 0