mirror of
https://github.com/junegunn/fzf.git
synced 2026-09-11 01:03:03 +08:00
The window fzf was started from stays visible, and can be used while fzf runs, which a popup inside Vim cannot offer. Only where the pane is not modal, so tmux 3.7 or above, or Zellij 0.44 or above with fzf 0.71.0 or above. A tmux popup from 3.3 to 3.6 cannot be left, and below 3.3 fzf goes through the fzf-tmux script, whose options are spelled differently. Both keep the window inside Vim. An explicit popup layout is unaffected and still works from 3.3. fzf checks tmux before Zellij, so tmux wins when both are set. g:fzf_layout still wins, so anyone who set it sees no change.
256 lines
8.3 KiB
Plaintext
256 lines
8.3 KiB
Plaintext
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
|
|
|
|
" 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 = 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(g:FzfRun({ 'source': 'git ls-files', 'options': '--filter e', 'dir': g:dir }))
|
|
AssertEqual ['fzf.vader'], result
|
|
AssertEqual 1, haslocaldir()
|
|
AssertEqual getcwd(), cwd
|
|
|
|
Execute (fzf#run with Funcref command):
|
|
let g:ret = []
|
|
function! g:FzfTest(e)
|
|
call add(g:ret, a:e)
|
|
endfunction
|
|
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(g:FzfRun({ 'source': 'echo hi', 'options': '-f i' }))
|
|
AssertEqual ['hi'], result
|
|
|
|
Execute (fzf#run with list source):
|
|
let result = sort(g:FzfRun({ 'source': ['hello', 'world'], 'options': '-f e' }))
|
|
AssertEqual ['hello'], result
|
|
let result = sort(g:FzfRun({ 'source': ['hello', 'world'], 'options': '-f o' }))
|
|
AssertEqual ['hello', 'world'], result
|
|
|
|
Execute (fzf#run with string source):
|
|
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 g:FzfRun({'source': ['/foobar'], 'sink': 'e', 'dir': '/tmp', 'options': '-1'})
|
|
" No change in working directory
|
|
AssertEqual cwd, getcwd()
|
|
|
|
call g:FzfRun({'source': ['/foobar'], 'sink': 'tabe', 'dir': '/tmp', 'options': '-1'})
|
|
AssertEqual cwd, getcwd()
|
|
tabclose
|
|
AssertEqual cwd, getcwd()
|
|
|
|
Execute (Incomplete fzf#run with dir option and autochdir):
|
|
set acd
|
|
let cwd = getcwd()
|
|
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 g:FzfRun({'source': ['/foobar'], 'sink': 'e', 'dir': '/tmp', 'options': '-1'})
|
|
" Working directory changed due to &acd
|
|
AssertEqual '/foobar', expand('%')
|
|
AssertEqual '/', getcwd()
|
|
|
|
Execute (fzf#run with dir option and autochdir when final cwd is same as dir):
|
|
set acd
|
|
cd /tmp
|
|
call g:FzfRun({'source': ['/foobar'], 'sink': 'e', 'dir': '/', 'options': '-1'})
|
|
" Working directory changed due to &acd
|
|
AssertEqual '/', getcwd()
|
|
|
|
Execute (Default layout):
|
|
unlet! g:fzf_layout g:fzf_height
|
|
let layout_keys = ['window', 'popup', 'tmux', 'up', 'down', 'left', 'right']
|
|
|
|
let opts = fzf#wrap('foobar')
|
|
Log opts
|
|
let found = filter(copy(layout_keys), 'has_key(opts, v:val)')
|
|
AssertEqual 1, len(found)
|
|
if found[0] ==# 'tmux'
|
|
" Only where fzf opens a floating pane, which can be left while fzf runs
|
|
Assert !empty($TMUX) || !empty($ZELLIJ)
|
|
AssertEqual '90%,60%', opts.tmux
|
|
elseif found[0] ==# 'window'
|
|
AssertEqual 0.9, opts.window.width
|
|
else
|
|
" No popup support in this build
|
|
AssertEqual '~40%', opts.down
|
|
endif
|
|
|
|
" Fullscreen strips it, whichever it was
|
|
let opts = fzf#wrap('foobar', {}, 1)
|
|
Log opts
|
|
AssertEqual [], filter(copy(layout_keys), 'has_key(opts, v:val)')
|
|
|
|
Execute (fzf#wrap):
|
|
AssertThrows fzf#wrap({'foo': 'bar'})
|
|
|
|
" Pin the layout so the assertions do not depend on the environment
|
|
let g:fzf_layout = { 'window': { 'width': 0.9, 'height': 0.6 } }
|
|
|
|
let opts = fzf#wrap('foobar')
|
|
Log opts
|
|
AssertEqual 0.9, opts.window.width
|
|
Assert opts.options =~ '--expect='
|
|
Assert !has_key(opts, 'sink')
|
|
Assert has_key(opts, 'sink*')
|
|
|
|
let opts = fzf#wrap('foobar', {}, 0)
|
|
Log opts
|
|
AssertEqual 0.9, opts.window.width
|
|
|
|
let opts = fzf#wrap('foobar', {}, 1)
|
|
Log opts
|
|
Assert !has_key(opts, 'window')
|
|
|
|
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'
|
|
|
|
let g:fzf_colors = { 'fg': ['fg', 'Error'] }
|
|
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')
|
|
AssertEqual '''""''', fzf#shellescape('""', 'sh')
|
|
AssertEqual '''foobar>''', fzf#shellescape('foobar>', 'sh')
|
|
AssertEqual '''\\\"\\\''', fzf#shellescape('\\\"\\\', 'sh')
|
|
AssertEqual '''echo ''\''''a''\'''' && echo ''\''''b''\''''''', fzf#shellescape('echo ''a'' && echo ''b''', 'sh')
|
|
|
|
Execute (fzf#shellescape with cmd.exe):
|
|
AssertEqual '^"^"', fzf#shellescape('', 'cmd.exe')
|
|
AssertEqual '^"\\^"', fzf#shellescape('\', 'cmd.exe')
|
|
AssertEqual '^"\^"\^"^"', fzf#shellescape('""', 'cmd.exe')
|
|
AssertEqual '^"foobar^>^"', fzf#shellescape('foobar>', 'cmd.exe')
|
|
AssertEqual '^"\\\\\\\^"\\\\\\^"', fzf#shellescape('\\\"\\\', 'cmd.exe')
|
|
AssertEqual '^"echo ''a'' ^&^& echo ''b''^"', fzf#shellescape('echo ''a'' && echo ''b''', 'cmd.exe')
|
|
|
|
AssertEqual '^"C:\Program Files ^(x86^)\\^"', fzf#shellescape('C:\Program Files (x86)\', 'cmd.exe')
|
|
AssertEqual '^"C:/Program Files ^(x86^)/^"', fzf#shellescape('C:/Program Files (x86)/', 'cmd.exe')
|
|
AssertEqual '^"%%USERPROFILE%%^"', fzf#shellescape('%USERPROFILE%', 'cmd.exe')
|
|
|
|
Execute (Cleanup):
|
|
unlet g:dir
|
|
Restore
|