Augment fzf#complete interface with reducer option

This commit is contained in:
Junegunn Choi 2015-08-18 18:30:08 +09:00
parent cffb0e0191
commit ca4163b57c
2 changed files with 67 additions and 12 deletions

View file

@ -48,8 +48,7 @@ List of commands
bindings to open in a new tab, a new split, or in a new vertical split. bindings to open in a new tab, a new split, or in a new vertical split.
- Bang-versions of the commands (e.g. `Ag!`) will open fzf in fullscreen - Bang-versions of the commands (e.g. `Ag!`) will open fzf in fullscreen
Customization ### Customization
-------------
```vim ```vim
" This is the default extra key bindings " This is the default extra key bindings
@ -59,6 +58,35 @@ let g:fzf_action = {
\ 'ctrl-v': 'vsplit' } \ 'ctrl-v': 'vsplit' }
``` ```
Fuzzy completion helper
-----------------------
`fzf#complete` is a helper function for creating custom fuzzy completion using
fzf. If the first parameter is a command string or a Vim list, it will be used
as the source.
```vim
" Replace the default dictionary completion with fzf-based fuzzy completion
inoremap <expr> <c-x><c-k> fzf#complete('cat /usr/share/dict/words')
```
For advanced uses, you can pass an options dictionary to the function. The set
of options is almost identical to that for `fzf#run`, except that it takes
`reducer` function instead of `sink` or `sink*`.
```vim
" Reducer function transforms the output of fzf into a single string value
function! FirstLineInUpperCase(lines)
return toupper(a:lines[0])
endfunction
inoremap <expr> <c-x><c-k> fzf#complete({
\ 'source': 'cat /usr/share/dict/words',
\ 'reducer': function('FirstLineInUpperCase'),
\ 'options': '--no-multi --reverse --margin 15%,0',
\ 'left': 20})
```
License License
------- -------

View file

@ -49,8 +49,10 @@ function! s:buflisted()
return filter(range(1, bufnr('$')), 'buflisted(v:val)') return filter(range(1, bufnr('$')), 'buflisted(v:val)')
endfunction endfunction
let s:default_window = {'down': '40%'}
function! s:fzf(opts, bang) function! s:fzf(opts, bang)
return fzf#run(extend(a:opts, a:bang ? {} : get(g:, 'fzf_window', {'down': '40%'}))) return fzf#run(extend(a:opts, a:bang ? {} : get(g:, 'fzf_window', s:default_window)))
endfunction endfunction
let s:default_action = { let s:default_action = {
@ -398,19 +400,36 @@ command! -bang Commands call s:commands(<bang>0)
inoremap <silent> <Plug>(-fzf-complete-trigger) <c-o>:call <sid>complete_trigger()<cr> inoremap <silent> <Plug>(-fzf-complete-trigger) <c-o>:call <sid>complete_trigger()<cr>
function! s:complete_trigger() function! s:complete_trigger()
call s:fzf({ let opts = copy(s:opts)
\ 'source': s:source, let opts.options = printf('+m -q %s %s', shellescape(s:query), get(opts, 'options', ''))
\ 'sink': function('s:complete_insert'), let opts['sink*'] = function('s:complete_insert')
\ 'options': '+m -q '.shellescape(s:query)}, 0) if has_key(opts, 'reducer')
let s:reducer = opts.reducer
call remove(opts, 'reducer')
else
let s:reducer = function('s:first_line')
endif
call fzf#run(opts)
endfunction endfunction
function! s:complete_insert(data) " The default reducer
function! s:first_line(lines)
return a:lines[0]
endfunction
function! s:complete_insert(lines)
if empty(a:lines)
return
endif
let chars = strchars(s:query) let chars = strchars(s:query)
if chars == 0 | let del = '' if chars == 0 | let del = ''
elseif chars == 1 | let del = '"_x' elseif chars == 1 | let del = '"_x'
else | let del = (chars - 1).'"_dvh' else | let del = (chars - 1).'"_dvh'
endif endif
execute 'normal!' (s:eol ? '' : 'h').del.(s:eol ? 'a': 'i').a:data
let data = call(s:reducer, [a:lines])
execute 'normal!' (s:eol ? '' : 'h').del.(s:eol ? 'a': 'i').data
if has('nvim') if has('nvim')
call feedkeys('a') call feedkeys('a')
else else
@ -418,8 +437,16 @@ function! s:complete_insert(data)
endif endif
endfunction endfunction
function! fzf#complete(source) function! fzf#complete(arg)
let s:source = a:source if type(a:arg) == type({})
if has_key(a:arg, 'sink') || has_key(a:arg, 'sink*')
echoerr 'sink not allowed'
return ''
endif
let s:opts = a:arg
else
let s:opts = extend({'source': a:arg}, get(g:, 'fzf_window', s:default_window))
endif
let eol = col('$') let eol = col('$')
let ve = &ve let ve = &ve