summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJunegunn Choi <junegunn.c@gmail.com>2016-07-26 02:35:40 +0900
committerJunegunn Choi <junegunn.c@gmail.com>2016-07-26 02:37:12 +0900
commitf787f7e65108938fda981abb71f4fdfb08fd9f31 (patch)
tree85131066923318cb13ff4b40c61bbaf46a805307
parenta7c9c08371d27b550f3896ab554f6490871a7a0a (diff)
downloadfzf-f787f7e65108938fda981abb71f4fdfb08fd9f31.tar.gz
[vim] Add fzf#wrap helper function
Close #627
-rw-r--r--README.md17
-rw-r--r--plugin/fzf.vim147
-rw-r--r--test/fzf.vader74
3 files changed, 188 insertions, 50 deletions
diff --git a/README.md b/README.md
index 220a6cb3..5de73037 100644
--- a/README.md
+++ b/README.md
@@ -320,10 +320,10 @@ customization.
[fzf-config]: https://github.com/junegunn/fzf/wiki/Configuring-FZF-command-(vim)
-#### `fzf#run([options])`
+#### `fzf#run`
-For more advanced uses, you can use `fzf#run()` function with the following
-options.
+For more advanced uses, you can use `fzf#run([options])` function with the
+following options.
| Option name | Type | Description |
| -------------------------- | ------------- | ---------------------------------------------------------------- |
@@ -342,6 +342,17 @@ options.
Examples can be found on [the wiki
page](https://github.com/junegunn/fzf/wiki/Examples-(vim)).
+#### `fzf#wrap`
+
+`fzf#wrap(name string, [opts dict, [fullscreen boolean]])` is a helper
+function that decorates the options dictionary so that it understands
+`g:fzf_layout`, `g:fzf_action`, and `g:fzf_history_dir` like `:FZF`.
+
+```vim
+command! -bang MyStuff
+ \ call fzf#run(fzf#wrap('my-stuff', {'dir': '~/my-stuff'}, <bang>0))
+```
+
Tips
----
diff --git a/plugin/fzf.vim b/plugin/fzf.vim
index 668af7d5..53cb4cba 100644
--- a/plugin/fzf.vim
+++ b/plugin/fzf.vim
@@ -22,6 +22,7 @@
" WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
let s:default_layout = { 'down': '~40%' }
+let s:layout_keys = ['window', 'up', 'down', 'left', 'right']
let s:fzf_go = expand('<sfile>:h:h').'/bin/fzf'
let s:install = expand('<sfile>:h:h').'/install'
let s:installed = 0
@@ -104,6 +105,101 @@ function! s:warn(msg)
echohl None
endfunction
+function! s:has_any(dict, keys)
+ for key in a:keys
+ if has_key(a:dict, key)
+ return 1
+ endif
+ endfor
+ return 0
+endfunction
+
+function! s:open(cmd, target)
+ if stridx('edit', a:cmd) == 0 && fnamemodify(a:target, ':p') ==# expand('%:p')
+ return
+ endif
+ execute a:cmd s:escape(a:target)
+endfunction
+
+function! s:common_sink(action, lines) abort
+ if len(a:lines) < 2
+ return
+ endif
+ let key = remove(a:lines, 0)
+ let cmd = get(a:action, key, 'e')
+ if len(a:lines) > 1
+ augroup fzf_swap
+ autocmd SwapExists * let v:swapchoice='o'
+ \| call s:warn('fzf: E325: swap file exists: '.expand('<afile>'))
+ augroup END
+ endif
+ try
+ let empty = empty(expand('%')) && line('$') == 1 && empty(getline(1)) && !&modified
+ let autochdir = &autochdir
+ set noautochdir
+ for item in a:lines
+ if empty
+ execute 'e' s:escape(item)
+ let empty = 0
+ else
+ call s:open(cmd, item)
+ endif
+ if exists('#BufEnter') && isdirectory(item)
+ doautocmd BufEnter
+ endif
+ endfor
+ finally
+ let &autochdir = autochdir
+ silent! autocmd! fzf_swap
+ endtry
+endfunction
+
+" name string, [opts dict, [fullscreen boolean]]
+function! fzf#wrap(name, ...)
+ if type(a:name) != type('')
+ throw 'invalid name type: string expected'
+ endif
+ let opts = copy(get(a:000, 0, {}))
+ let bang = get(a:000, 1, 0)
+
+ " Layout: g:fzf_layout (and deprecated g:fzf_height)
+ if bang
+ for key in s:layout_keys
+ if has_key(opts, key)
+ call remove(opts, key)
+ endif
+ endfor
+ elseif !s:has_any(opts, s:layout_keys)
+ if !exists('g:fzf_layout') && exists('g:fzf_height')
+ let opts.down = g:fzf_height
+ else
+ let opts = extend(opts, get(g:, 'fzf_layout', s:default_layout))
+ endif
+ endif
+
+ " History: g:fzf_history_dir
+ let opts.options = get(opts, 'options', '')
+ if len(get(g:, 'fzf_history_dir', ''))
+ let dir = expand(g:fzf_history_dir)
+ if !isdirectory(dir)
+ call mkdir(dir, 'p')
+ endif
+ let opts.options = join(['--history', s:escape(dir.'/'.a:name), opts.options])
+ endif
+
+ " Action: g:fzf_action
+ if !s:has_any(opts, ['sink', 'sink*'])
+ let opts._action = get(g:, 'fzf_action', s:default_action)
+ let opts.options .= ' --expect='.join(keys(opts._action), ',')
+ function! opts.sink(lines) abort
+ return s:common_sink(self._action, a:lines)
+ endfunction
+ let opts['sink*'] = remove(opts, 'sink')
+ endif
+
+ return opts
+endfunction
+
function! fzf#run(...) abort
try
let oshell = &shell
@@ -137,7 +233,7 @@ try
call writefile(source, temps.input)
let prefix = 'cat '.s:shellesc(temps.input).'|'
else
- throw 'Invalid source type'
+ throw 'invalid source type'
endif
else
let prefix = ''
@@ -435,60 +531,17 @@ function! s:callback(dict, lines) abort
endfunction
let s:default_action = {
- \ 'ctrl-m': 'e',
\ 'ctrl-t': 'tab split',
\ 'ctrl-x': 'split',
\ 'ctrl-v': 'vsplit' }
-function! s:cmd_callback(lines) abort
- if empty(a:lines)
- return
- endif
- let key = remove(a:lines, 0)
- let cmd = get(s:action, key, 'e')
- if len(a:lines) > 1
- augroup fzf_swap
- autocmd SwapExists * let v:swapchoice='o'
- \| call s:warn('fzf: E325: swap file exists: '.expand('<afile>'))
- augroup END
- endif
- try
- let empty = empty(expand('%')) && line('$') == 1 && empty(getline(1)) && !&modified
- let autochdir = &autochdir
- set noautochdir
- for item in a:lines
- if empty
- execute 'e' s:escape(item)
- let empty = 0
- else
- execute cmd s:escape(item)
- endif
- if exists('#BufEnter') && isdirectory(item)
- doautocmd BufEnter
- endif
- endfor
- finally
- let &autochdir = autochdir
- silent! autocmd! fzf_swap
- endtry
-endfunction
-
function! s:cmd(bang, ...) abort
- let s:action = get(g:, 'fzf_action', s:default_action)
- let args = extend(['--expect='.join(keys(s:action), ',')], a:000)
+ let args = copy(a:000)
let opts = {}
- if len(args) > 0 && isdirectory(expand(args[-1]))
+ if len(args) && isdirectory(expand(args[-1]))
let opts.dir = substitute(remove(args, -1), '\\\(["'']\)', '\1', 'g')
endif
- if !a:bang
- " For backward compatibility
- if !exists('g:fzf_layout') && exists('g:fzf_height')
- let opts.down = g:fzf_height
- else
- let opts = extend(opts, get(g:, 'fzf_layout', s:default_layout))
- endif
- endif
- call fzf#run(extend({'options': join(args), 'sink*': function('<sid>cmd_callback')}, opts))
+ call fzf#run(fzf#wrap('FZF', extend({'options': join(args)}, opts), a:bang))
endfunction
command! -nargs=* -complete=dir -bang FZF call s:cmd(<bang>0, <f-args>)
diff --git a/test/fzf.vader b/test/fzf.vader
index 47f2bfcd..bab5c162 100644
--- a/test/fzf.vader
+++ b/test/fzf.vader
@@ -1,5 +1,6 @@
Execute (Setup):
let g:dir = fnamemodify(g:vader_file, ':p:h')
+ unlet! g:fzf_layout g:fzf_action g:fzf_history_dir
Log 'Test directory: ' . g:dir
Save &acd
@@ -69,6 +70,79 @@ Execute (fzf#run with dir option and autochdir when final cwd is same as dir):
" Working directory changed due to &acd
AssertEqual '/', getcwd()
+Execute (fzf#wrap):
+ AssertThrows fzf#wrap({'foo': 'bar'})
+
+ let opts = fzf#wrap('foobar')
+ Log opts
+ AssertEqual '~40%', opts.down
+ Assert opts.options =~ '--expect='
+ Assert !has_key(opts, 'sink')
+ Assert has_key(opts, 'sink*')
+
+ let opts = fzf#wrap('foobar', {}, 0)
+ Log opts
+ AssertEqual '~40%', opts.down
+
+ let opts = fzf#wrap('foobar', {}, 1)
+ Log opts
+ Assert !has_key(opts, 'down')
+
+ let opts = fzf#wrap('foobar', {'down': '50%'})
+ Log opts
+ AssertEqual '50%', opts.down
+
+ let opts = fzf#wrap('foobar', {'down': '50%'}, 1)
+ Log opts
+ Assert !has_key(opts, 'down')
+
+ let opts = fzf#wrap('foobar', {'sink': 'e'})
+ Log opts
+ AssertEqual 'e', opts.sink
+ Assert !has_key(opts, 'sink*')
+
+ let opts = fzf#wrap('foobar', {'options': '--reverse'})
+ Log opts
+ Assert opts.options =~ '--expect='
+ Assert opts.options =~ '--reverse'
+
+ let g:fzf_layout = {'window': 'enew'}
+ let opts = fzf#wrap('foobar')
+ Log opts
+ AssertEqual 'enew', opts.window
+
+ let opts = fzf#wrap('foobar', {}, 1)
+ Log opts
+ Assert !has_key(opts, 'window')
+
+ let opts = fzf#wrap('foobar', {'right': '50%'})
+ Log opts
+ Assert !has_key(opts, 'window')
+ AssertEqual '50%', opts.right
+
+ let opts = fzf#wrap('foobar', {'right': '50%'}, 1)
+ Log opts
+ Assert !has_key(opts, 'window')
+ Assert !has_key(opts, 'right')
+
+ let g:fzf_action = {'a': 'tabe'}
+ let opts = fzf#wrap('foobar')
+ Log opts
+ Assert opts.options =~ '--expect=a'
+ Assert !has_key(opts, 'sink')
+ Assert has_key(opts, 'sink*')
+
+ let opts = fzf#wrap('foobar', {'sink': 'e'})
+ Log opts
+ AssertEqual 'e', opts.sink
+ Assert !has_key(opts, 'sink*')
+
+ let g:fzf_history_dir = '/tmp'
+ let opts = fzf#wrap('foobar', {'options': '--color light'})
+ Log opts
+ Assert opts.options =~ '--history /tmp/foobar'
+ Assert opts.options =~ '--color light'
+
Execute (Cleanup):
unlet g:dir
Restore