💾 Archived View for tilde.team › ~m040601 › mirrorz › fzf_wiki › clone_fzf.wiki › Examples-(vim).md captured on 2023-04-26 at 14:29:34.

View Raw

More Information

⬅️ Previous capture (2023-01-29)

-=-=-=-=-=-=-

### `fzf.vim` repository

If you're not familiar with Vimscript or don't have time to write your own
commands, check out [fzf.vim](https://github.com/junegunn/fzf.vim) project
which provides a set of ready-made commands.

### Basic tutorial

See https://github.com/junegunn/fzf/blob/master/README-VIM.md

### `locate` command integration

command! -nargs=1 -bang Locate call fzf#run(fzf#wrap(

\ {'source': 'locate <q-args>', 'options': '-m'}, <bang>0))


`:Locate /` will list every file on the system. So make sure that you're using Go version of fzf which is significantly faster than the old Ruby version.

### Open files in splits



" Open files in horizontal split

nnoremap <silent> <Leader>s :call fzf#run({

\ 'down': '40%',

\ 'sink': 'botright split' })<CR>

" Open files in vertical horizontal split

nnoremap <silent> <Leader>v :call fzf#run({

\ 'right': winwidth('.') / 2,

\ 'sink': 'vertical botright split' })<CR>


### Choose color scheme

nnoremap <silent> <Leader>C :call fzf#run({

\ 'source':

\ map(split(globpath(&rtp, "colors/*.vim"), "\n"),

\ "substitute(fnamemodify(v:val, ':t'), '\\..\\{-} , '', '')"),

\ 'sink': 'colo',

\ 'options': '+m',

\ 'left': 30

\ })<CR>


### Select buffer

function! s:buflist()

redir => ls

silent ls

redir END

return split(ls, '\n')

endfunction

function! s:bufopen(e)

execute 'buffer' matchstr(a:e, '^[ 0-9]*')

endfunction

nnoremap <silent> <Leader><Enter> :call fzf#run({

\ 'source': reverse(<sid>buflist()),

\ 'sink': function('<sid>bufopen'),

\ 'options': '+m',

\ 'down': len(<sid>buflist()) + 2

\ })<CR>


### Simple MRU search

#### `v:oldfiles`

command! FZFMru call fzf#run({

\ 'source': v:oldfiles,

\ 'sink': 'e',

\ 'options': '-m -x +s',

\ 'down': '40%'})


#### Filtered `v:oldfiles` and open buffers

command! FZFMru call fzf#run({

\ 'source': reverse(s:all_files()),

\ 'sink': 'edit',

\ 'options': '-m -x +s',

\ 'down': '40%' })

function! s:all_files()

return extend(

\ filter(copy(v:oldfiles),

\ "v:val !~ 'fugitive:\\|NERD_tree\\|^/tmp/\\|.git/'"),

\ map(filter(range(1, bufnr(' )), 'buflisted(v:val)'), 'bufname(v:val)'))

endfunction


### Jump to tags (simple)

command! -bar Tags if !empty(tagfiles()) | call fzf#run({

\ 'source': "sed '/^\\!/d;s/\t.*//' " . join(tagfiles()) . ' | uniq',

\ 'sink': 'tag',

\ }) | else | echo 'Preparing tags' | call system('ctags -R') | FZFTag | endif


### Jump to tags

This version better handles same tags across different files.

function! s:tags_sink(line)

let parts = split(a:line, '\t\zs')

let excmd = matchstr(parts[2:], '^.*\ze;"\t')

execute 'silent e' parts[1][:-2]

let [magic, &magic] = [&magic, 0]

execute excmd

let &magic = magic

endfunction

function! s:tags()

if empty(tagfiles())

echohl WarningMsg

echom 'Preparing tags'

echohl None

call system('ctags -R')

endif

call fzf#run({

\ 'source': 'cat '.join(map(tagfiles(), 'fnamemodify(v:val, ":S")')).

\ '| grep -v -a ^!',

\ 'options': '+m -d "\t" --with-nth 1,4.. -n 1 --tiebreak=index',

\ 'down': '40%',

\ 'sink': function('s:tags_sink')})

endfunction

command! Tags call s:tags()


### Jump to tags in the current buffer

function! s:align_lists(lists)

let maxes = {}

for list in a:lists

let i = 0

while i < len(list)

let maxes[i] = max([get(maxes, i, 0), len(list[i])])

let i += 1

endwhile

endfor

for list in a:lists

call map(list, "printf('%-'.maxes[v:key].'s', v:val)")

endfor

return a:lists

endfunction

function! s:btags_source()

let lines = map(split(system(printf(

\ 'ctags -f - --sort=no --excmd=number --language-force=%s %s',

\ &filetype, expand('%:S'))), "\n"), 'split(v:val, "\t")')

if v:shell_error

throw 'failed to extract tags'

endif

return map(s:align_lists(lines), 'join(v:val, "\t")')

endfunction

function! s:btags_sink(line)

execute split(a:line, "\t")[2]

endfunction

function! s:btags()

try

call fzf#run({

\ 'source': s:btags_source(),

\ 'options': '+m -d "\t" --with-nth 1,4.. -n 1 --tiebreak=index',

\ 'down': '40%',

\ 'sink': function('s:btags_sink')})

catch

echohl WarningMsg

echom v:exception

echohl None

endtry

endfunction

command! BTags call s:btags()


### Search lines in all open vim buffers
(require `set hidden` to prevent vim unload buffer)

function! s:line_handler(l)

let keys = split(a:l, ':\t')

exec 'buf' keys[0]

exec keys[1]

normal! ^zz

endfunction

function! s:buffer_lines()

let res = []

for b in filter(range(1, bufnr(' )), 'buflisted(v:val)')

call extend(res, map(getbufline(b,0,"$"), 'b . ":\t" . (v:key + 1) . ":\t" . v:val '))

endfor

return res

endfunction

command! FZFLines call fzf#run({

\ 'source': <sid>buffer_lines(),

\ 'sink': function('<sid>line_handler'),

\ 'options': '--extended --nth=3..',

\ 'down': '60%'

\})


### Narrow ag results within vim

- `CTRL-X`, `CTRL-V`, `CTRL-T` to open in a new split, vertical split, tab respectively.
- `CTRL-A` to select all matches and list them in quickfix window
    - `CTRL-D` to deselect all
- `Ag` without argument will list all the lines

function! s:ag_to_qf(line)

let parts = split(a:line, ':')

return {'filename': parts[0], 'lnum': parts[1], 'col': parts[2],

\ 'text': join(parts[3:], ':')}

endfunction

function! s:ag_handler(lines)

if len(a:lines) < 2 | return | endif

let cmd = get({'ctrl-x': 'split',

\ 'ctrl-v': 'vertical split',

\ 'ctrl-t': 'tabe'}, a:lines[0], 'e')

let list = map(a:lines[1:], 's:ag_to_qf(v:val)')

let first = list[0]

execute cmd escape(first.filename, ' %#\')

execute first.lnum

execute 'normal!' first.col.'|zz'

if len(list) > 1

call setqflist(list)

copen

wincmd p

endif

endfunction

command! -nargs=* Ag call fzf#run({

\ 'source': printf('ag --nogroup --column --color "%s"',

\ escape(empty(<q-args>) ? '^(?=.)' : <q-args>, '"\')),

\ 'sink*': function('<sid>ag_handler'),

\ 'options': '--ansi --expect=ctrl-t,ctrl-v,ctrl-x --delimiter : --nth 4.. '.

\ '--multi --bind=ctrl-a:select-all,ctrl-d:deselect-all '.

\ '--color hl:68,hl+:110',

\ 'down': '50%'

\ })


### Fuzzy search files in parent directory of current file

This command is very handy if you want to explore or edit the surrounding/neigbouring files of the file your currently editing. (e.g. files in the same directory)

function! s:fzf_neighbouring_files()

let current_file =expand("%")

let cwd = fnamemodify(current_file, ':p:h')

let command = 'ag -g "" -f ' . cwd . ' --depth 0'

call fzf#run({

\ 'source': command,

\ 'sink': 'e',

\ 'options': '-m -x +s',

\ 'window': 'enew' })

endfunction

command! FZFNeigh call s:fzf_neighbouring_files()


### Fuzzy search the arglist (`:Args`)

command! -bang Args call fzf#run(fzf#wrap('args',

\ {'source': map([argidx()]+(argidx()==0?[]:range(argc())[0:argidx()-1])+range(argc())[argidx()+1:], 'argv(v:val)')}, <bang>0))


### Fuzzy search netrwhist (`:Netrwhist`)

function! MyUniq(lst)

return filter(a:lst, 'count(a:lst, v:val) == 1')

endfunction

command! -bang Netrwhist call fzf#run(fzf#wrap('netrw_dirhist',

\ {'source':

\ !exists('g:netrw_dirhist_cnt')

\ ?"tail -n +3 ".g:netrw_home.".netrwhist | cut -d \"'\" -f2- | rev | cut -d \"'\" -f2- | rev | awk '!seen[$0]++'"

\ :MyUniq(map(range(1,g:netrw_dirhist_cnt), 'g:netrw_dirhist_{v:val}'))

\ }, <bang>0))

This uses the command line tools `tail`, `cut`, `rev`, and `awk` which are most likely available under macOS and Linux.

The default value of `g:netrw_dirhistmax` is 10. You might be interested in increasing this value when you use this feature more often:

let g:netrw_dirhistmax = 1000


### Fuzzy file template search

Say you have a folder with files in it you use for templating, and you want a fzf menu to choose which file will be loaded:

"

" choose from templates and apply to file

"

function! s:read_template_into_buffer(template)

" has to be a function to avoid the extra space fzf#run insers otherwise

execute '0r ~/.vim/templates/'.a:template

endfunction

command! -bang -nargs=* LoadTemplate call fzf#run({

\ 'source': 'ls -1 ~/.config/nvim/templates',

\ 'down': 20,

\ 'sink': function('<sid>read_template_into_buffer')

\ })