mirror of
https://github.com/junegunn/fzf.git
synced 2026-08-22 23:56:51 +08:00
Run fzf asynchronously in the Vim plugin
Popup mode held the fzf process with system(), which froze Vim until fzf exited. fzf in a popup draws in a pane of its own, so that process only waits for it and does not need a window. Hold it with a job instead and Vim keeps processing its event loop, which is what a live preview needs. Nothing is displayed for the job. Falls back to the blocking path when the job cannot start, so the sink still runs and temp files are removed. - job_start() sets $TERM=dumb and the popup inherits the environment, so fzf dropped to its 16-color scheme. Restore it via 'env', or in the command itself before 8.0.902, when 'env' was added - Fullscreen now uses a terminal buffer in a new tab on Vim too. use_term lacked parentheses, so && bound tighter than || and the layout test was dead on Neovim, which already behaved this way - fzf#run returns an empty list in these modes. Callers use sink, sinklist or exit, and the vader specs now wait for completion - Append --no-tmux only when the spec asks for a Vim window, so --popup in $FZF_DEFAULT_OPTS survives a spec with no layout option Accept popup as a synonym of the tmux layout key, matching --popup being the name of --tmux. popup wins when both are given. s:tmux_enabled(): - Accept $ZELLIJ, which --popup covers as well - Parse tmux -V with matchstr and compare with s:compare_versions. The old string comparison against 'tmux 1.7' misreads 10.0 - Drop the fzf-tmux requirement on tmux 3.3 or above, where --tmux needs no script. Removing the script silently disabled popups entirely - Resolve the script where it is used, and anchor the legacy test to ^- so a --tmux value containing a dash, as in 90%,60%,border-native, is not mistaken for a legacy flag
This commit is contained in:
+65
-12
@@ -4,15 +4,44 @@ Execute (Setup):
|
||||
Log 'Test directory: ' . g:dir
|
||||
Save &acd
|
||||
|
||||
" fzf#run runs fzf in a terminal buffer and returns immediately, so the
|
||||
" assertions have to wait for the run to finish. 'exit' is called from the
|
||||
" same handler that runs the sink, just before it, so once it has fired the
|
||||
" sink has run too. It also fires when nothing is selected, unlike the sink.
|
||||
function! g:FzfExit(code)
|
||||
let g:fzf_done = 1
|
||||
endfunction
|
||||
|
||||
" Collects the output without displacing a 'sink' the spec already has.
|
||||
" s:callback runs both
|
||||
function! g:FzfCollect(lines)
|
||||
call extend(g:fzf_lines, a:lines)
|
||||
endfunction
|
||||
|
||||
function! g:FzfRun(spec) abort
|
||||
let g:fzf_done = 0
|
||||
let g:fzf_lines = []
|
||||
call fzf#run(extend(copy(a:spec),
|
||||
\ { 'exit': function('g:FzfExit'), 'sinklist': function('g:FzfCollect') }))
|
||||
let started = reltime()
|
||||
while !g:fzf_done && reltimefloat(reltime(started)) < 10
|
||||
sleep 10m
|
||||
endwhile
|
||||
if !g:fzf_done
|
||||
throw 'Timed out waiting for fzf#run'
|
||||
endif
|
||||
return g:fzf_lines
|
||||
endfunction
|
||||
|
||||
Execute (fzf#run with dir option):
|
||||
let cwd = getcwd()
|
||||
let result = fzf#run({ 'source': 'git ls-files', 'options': '--filter=vdr', 'dir': g:dir })
|
||||
let result = g:FzfRun({ 'source': 'git ls-files', 'options': '--filter=vdr', 'dir': g:dir })
|
||||
AssertEqual ['fzf.vader'], result
|
||||
AssertEqual 0, haslocaldir()
|
||||
AssertEqual getcwd(), cwd
|
||||
|
||||
execute 'lcd' fnameescape(cwd)
|
||||
let result = sort(fzf#run({ 'source': 'git ls-files', 'options': '--filter e', 'dir': g:dir }))
|
||||
let result = sort(g:FzfRun({ 'source': 'git ls-files', 'options': '--filter e', 'dir': g:dir }))
|
||||
AssertEqual ['fzf.vader'], result
|
||||
AssertEqual 1, haslocaldir()
|
||||
AssertEqual getcwd(), cwd
|
||||
@@ -22,32 +51,32 @@ Execute (fzf#run with Funcref command):
|
||||
function! g:FzfTest(e)
|
||||
call add(g:ret, a:e)
|
||||
endfunction
|
||||
let result = sort(fzf#run({ 'source': 'git ls-files', 'sink': function('g:FzfTest'), 'options': '--filter e', 'dir': g:dir }))
|
||||
let result = sort(g:FzfRun({ 'source': 'git ls-files', 'sink': function('g:FzfTest'), 'options': '--filter e', 'dir': g:dir }))
|
||||
AssertEqual ['fzf.vader'], result
|
||||
AssertEqual ['fzf.vader'], sort(g:ret)
|
||||
|
||||
Execute (fzf#run with string source):
|
||||
let result = sort(fzf#run({ 'source': 'echo hi', 'options': '-f i' }))
|
||||
let result = sort(g:FzfRun({ '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' }))
|
||||
let result = sort(g:FzfRun({ 'source': ['hello', 'world'], 'options': '-f e' }))
|
||||
AssertEqual ['hello'], result
|
||||
let result = sort(fzf#run({ 'source': ['hello', 'world'], 'options': '-f o' }))
|
||||
let result = sort(g:FzfRun({ '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' }))
|
||||
let result = sort(g:FzfRun({ 'source': 'echo hi', 'options': '-f i' }))
|
||||
AssertEqual ['hi'], result
|
||||
|
||||
Execute (fzf#run with dir option and noautochdir):
|
||||
set noacd
|
||||
let cwd = getcwd()
|
||||
call fzf#run({'source': ['/foobar'], 'sink': 'e', 'dir': '/tmp', 'options': '-1'})
|
||||
call g:FzfRun({'source': ['/foobar'], 'sink': 'e', 'dir': '/tmp', 'options': '-1'})
|
||||
" No change in working directory
|
||||
AssertEqual cwd, getcwd()
|
||||
|
||||
call fzf#run({'source': ['/foobar'], 'sink': 'tabe', 'dir': '/tmp', 'options': '-1'})
|
||||
call g:FzfRun({'source': ['/foobar'], 'sink': 'tabe', 'dir': '/tmp', 'options': '-1'})
|
||||
AssertEqual cwd, getcwd()
|
||||
tabclose
|
||||
AssertEqual cwd, getcwd()
|
||||
@@ -55,13 +84,13 @@ Execute (fzf#run with dir option and noautochdir):
|
||||
Execute (Incomplete fzf#run with dir option and autochdir):
|
||||
set acd
|
||||
let cwd = getcwd()
|
||||
call fzf#run({'source': [], 'sink': 'e', 'dir': '/tmp', 'options': '-0'})
|
||||
call g:FzfRun({'source': [], 'sink': 'e', 'dir': '/tmp', 'options': '-0'})
|
||||
" No change in working directory even if &acd is set
|
||||
AssertEqual cwd, getcwd()
|
||||
|
||||
Execute (FIXME: fzf#run with dir option and autochdir):
|
||||
set acd
|
||||
call fzf#run({'source': ['/foobar'], 'sink': 'e', 'dir': '/tmp', 'options': '-1'})
|
||||
call g:FzfRun({'source': ['/foobar'], 'sink': 'e', 'dir': '/tmp', 'options': '-1'})
|
||||
" Working directory changed due to &acd
|
||||
AssertEqual '/foobar', expand('%')
|
||||
AssertEqual '/', getcwd()
|
||||
@@ -69,7 +98,7 @@ Execute (FIXME: fzf#run with dir option and autochdir):
|
||||
Execute (fzf#run with dir option and autochdir when final cwd is same as dir):
|
||||
set acd
|
||||
cd /tmp
|
||||
call fzf#run({'source': ['/foobar'], 'sink': 'e', 'dir': '/', 'options': '-1'})
|
||||
call g:FzfRun({'source': ['/foobar'], 'sink': 'e', 'dir': '/', 'options': '-1'})
|
||||
" Working directory changed due to &acd
|
||||
AssertEqual '/', getcwd()
|
||||
|
||||
@@ -150,6 +179,30 @@ Execute (fzf#wrap):
|
||||
let opts = fzf#wrap({})
|
||||
Assert opts.options =~ '--color=fg:'
|
||||
|
||||
Execute (popup is a synonym of tmux):
|
||||
unlet! g:fzf_layout
|
||||
|
||||
" Treated as a layout option, so g:fzf_layout is not applied on top
|
||||
let opts = fzf#wrap('foobar', {'popup': '90%,70%'})
|
||||
AssertEqual '90%,70%', opts.popup
|
||||
Assert !has_key(opts, 'window')
|
||||
|
||||
" And stripped in fullscreen, like the others
|
||||
let opts = fzf#wrap('foobar', {'popup': '90%,70%'}, 1)
|
||||
Assert !has_key(opts, 'popup')
|
||||
|
||||
" Accepted in g:fzf_layout
|
||||
let g:fzf_layout = {'popup': '90%,70%'}
|
||||
let opts = fzf#wrap('foobar')
|
||||
AssertEqual '90%,70%', opts.popup
|
||||
unlet g:fzf_layout
|
||||
|
||||
" Listed as a valid key
|
||||
let g:fzf_layout = {'bogus': 1}
|
||||
AssertThrows call fzf#wrap('foobar')
|
||||
Assert g:vader_exception =~ 'popup'
|
||||
unlet g:fzf_layout
|
||||
|
||||
Execute (fzf#shellescape with sh):
|
||||
AssertEqual '''''', fzf#shellescape('', 'sh')
|
||||
AssertEqual '''\''', fzf#shellescape('\', 'sh')
|
||||
|
||||
Reference in New Issue
Block a user