Skip to content
Snippets Groups Projects
Commit e7439ce1 authored by Junegunn Choi's avatar Junegunn Choi
Browse files

Major update to Vim plugin

parent b8e438b6
No related branches found
No related tags found
No related merge requests found
......@@ -290,7 +290,9 @@ TODO :smiley:
Usage as Vim plugin
-------------------
If you install fzf as a Vim plugin, `:FZF` command will be added.
### `:FZF`
If you have set up fzf as a Vim plugin, `:FZF` command will be added.
```vim
" Look for files under current directory
......@@ -303,27 +305,76 @@ If you install fzf as a Vim plugin, `:FZF` command will be added.
:FZF --no-sort -m /tmp
```
You can override the source command which produces input to fzf.
Note that environment variables `FZF_DEFAULT_COMMAND` and `FZF_DEFAULT_OPTS`
also apply here.
### `fzf#run([options])`
For more advanced uses, you can call `fzf#run()` function which returns the list
of the selected items.
`fzf#run()` may take an options-dictionary:
| Option name | Type | Description |
| ----------- | ------- | ---------------------------------------------------------- |
| `source` | string | External command to generate input to fzf (e.g. `find .`) |
| `source` | list | Vim list as input to fzf |
| `sink` | string | Vim command to handle the selected item (e.g. `e`, `tabe`) |
| `sink` | funcref | Reference to function to process each selected item |
| `options` | string | Options to fzf |
| `dir` | string | Working directory |
#### Examples
If `sink` option is not given, `fzf#run` will simply return the list.
```vim
let g:fzf_source = 'find . -type f'
let items = fzf#run({ 'options': '-m +c', 'dir': '~', 'source': 'ls' })
```
And you can predefine default options to fzf command.
But if `sink` is given as a string, the command will be executed for each
selected item.
```vim
let g:fzf_options = '--no-color --extended'
" Each selected item will be opened in a new tab
let items = fzf#run({ 'sink': 'tabe', 'options': '-m +c', 'dir': '~', 'source': 'ls' })
```
For more advanced uses, you can call `fzf#run` function as follows.
We can also use a Vim list as the source as follows:
```vim
:call fzf#run('tabedit', '-m +c')
" Choose a color scheme with fzf
call fzf#run({
\ 'source':
\ map(split(globpath(&rtp, "colors/*.vim"), "\n"),
\ "substitute(fnamemodify(v:val, ':t'), '\\..\\{-}$', '', '')"),
\ 'sink': 'colo',
\ 'options': '+m'
\ })
```
Most of the time, you will prefer native Vim plugins with better integration
with Vim. The only reason one might consider using fzf in Vim is its speed. For
a very large list of files, fzf is significantly faster and it does not block.
`sink` option can be a function reference. The following example creates a
handy mapping that selects an open buffer.
```vim
" List of buffers
function! g:buflist()
redir => ls
silent ls
redir END
return split(ls, '\n')
endfunction
function! g:bufopen(e)
execute 'buffer '. matchstr(a:e, '^[ 0-9]*')
endfunction
nnoremap <Leader><Enter> :call fzf#run({
\ 'source': g:buflist(),
\ 'sink': function('g:bufopen'),
\ 'options': '+m +s',
\ })<CR>
```
Tips
----
......
" Copyright (c) 2013 Junegunn Choi
" Copyright (c) 2014 Junegunn Choi
"
" MIT License
"
......@@ -21,6 +21,9 @@
" OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
" WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
let s:cpo_save = &cpo
set cpo&vim
call system('type fzf')
if v:shell_error
let s:fzf_rb = expand('<sfile>:h:h').'/fzf'
......@@ -38,32 +41,73 @@ function! s:escape(path)
return substitute(a:path, ' ', '\\ ', 'g')
endfunction
function! fzf#run(command, ...)
let cwd = getcwd()
function! fzf#run(...) abort
let dict = exists('a:1') ? a:1 : {}
let temps = [tempname()]
let result = temps[0]
let optstr = get(dict, 'options', '')
let cd = has_key(dict, 'dir')
if has_key(dict, 'source')
let source = dict.source
let type = type(source)
if type == 1
let prefix = source.'|'
elseif type == 3
let input = add(temps, tempname())[-1]
call writefile(source, input)
let prefix = 'cat '.s:escape(input).'|'
else
throw 'Invalid source type'
endif
else
let prefix = ''
endif
try
let args = copy(a:000)
if len(args) > 0 && isdirectory(expand(args[-1]))
let dir = remove(args, -1)
execute 'chdir '.s:escape(dir)
if cd
let cwd = getcwd()
execute 'chdir '.s:escape(dict.dir)
endif
execute 'silent !'.prefix.s:exec.' '.optstr.' > '.result
redraw!
if v:shell_error
return []
endif
let argstr = join(args)
let tf = tempname()
let prefix = exists('g:fzf_source') ? g:fzf_source.'|' : ''
let options = empty(argstr) ? get(g:, 'fzf_options', '') : argstr
execute 'silent !'.prefix.s:exec.' '.options.' > '.tf
if !v:shell_error
for line in readfile(tf)
if !empty(line)
execute a:command.' '.s:escape(line)
let lines = readfile(result)
if has_key(dict, 'sink')
for line in lines
if type(dict.sink) == 2
call dict.sink(line)
else
execute dict.sink.' '.s:escape(line)
endif
endfor
endif
return lines
finally
execute 'chdir '.s:escape(cwd)
redraw!
silent! call delete(tf)
if cd
execute 'chdir '.s:escape(cwd)
endif
for tf in temps
silent! call delete(tf)
endfor
endtry
endfunction
command! -nargs=* -complete=dir FZF call fzf#run('silent e', <f-args>)
function! s:cmd(...)
let args = copy(a:000)
let opts = {}
if len(args) > 0 && isdirectory(expand(args[-1]))
let opts.dir = remove(args, -1)
endif
call fzf#run(extend({ 'sink': 'e', 'options': join(args) }, opts))
endfunction
command! -nargs=* -complete=dir FZF call s:cmd(<f-args>)
let &cpo = s:cpo_save
unlet s:cpo_save
Execute (Setup):
let g:dir = fnamemodify(g:vader_file, ':p:h')
Log 'Test directory: ' . g:dir
Execute (fzf#run with dir option):
let result = fzf#run({ 'options': '--filter=vdr', 'dir': g:dir })
AssertEqual ['fzf.vader'], result
let result = sort(fzf#run({ 'options': '--filter e', 'dir': g:dir }))
AssertEqual ['fzf.vader', 'test_fzf.rb'], result
Execute (fzf#run with Funcref command):
let g:ret = []
function! g:proc(e)
call add(g:ret, a:e)
endfunction
let result = sort(fzf#run({ 'sink': function('g:proc'), 'options': '--filter e', 'dir': g:dir }))
AssertEqual ['fzf.vader', 'test_fzf.rb'], result
AssertEqual ['fzf.vader', 'test_fzf.rb'], sort(g:ret)
Execute (fzf#run with string source):
let result = sort(fzf#run({ 'source': 'echo hi', 'options': '-f i' }))
AssertEqual ['hi'], result
Execute (fzf#run with list source):
let result = sort(fzf#run({ 'source': ['hello', 'world'], 'options': '-f e' }))
AssertEqual ['hello'], result
let result = sort(fzf#run({ 'source': ['hello', 'world'], 'options': '-f o' }))
AssertEqual ['hello', 'world'], result
Execute (fzf#run with string source):
let result = sort(fzf#run({ 'source': 'echo hi', 'options': '-f i' }))
AssertEqual ['hi'], result
Execute (Cleanup):
unlet g:dir
Restore
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment