Artificial Simon
Artificial Simon

Reputation: 5

vim sbuffer with fuzzy search

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

Answers (2)

Biggybi
Biggybi

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

Zorzi
Zorzi

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

Related Questions