[vim] Try to make 'dir' option compatible with &autochdir
When 'dir' option is passed to fzf#run(), the current working directory is temporarily changed to the given directory, and restored at the end. However, this behavior is not compatible with &autochdir. This commit introduces a heuristic to determine whether or not to restore the previous working directory. Related: https://github.com/junegunn/fzf.vim/issues/70
This commit is contained in:
parent
b18db4733c
commit
0f281ef894
@ -1,4 +1,4 @@
|
|||||||
" Copyright (c) 2015 Junegunn Choi
|
" Copyright (c) 2016 Junegunn Choi
|
||||||
"
|
"
|
||||||
" MIT License
|
" MIT License
|
||||||
"
|
"
|
||||||
@ -139,17 +139,13 @@ try
|
|||||||
let tmux = !has('nvim') && s:tmux_enabled() && s:splittable(dict)
|
let tmux = !has('nvim') && s:tmux_enabled() && s:splittable(dict)
|
||||||
let command = prefix.(tmux ? s:fzf_tmux(dict) : fzf_exec).' '.optstr.' > '.temps.result
|
let command = prefix.(tmux ? s:fzf_tmux(dict) : fzf_exec).' '.optstr.' > '.temps.result
|
||||||
|
|
||||||
try
|
if has('nvim')
|
||||||
if tmux
|
|
||||||
return s:execute_tmux(dict, command, temps)
|
|
||||||
elseif has('nvim')
|
|
||||||
return s:execute_term(dict, command, temps)
|
return s:execute_term(dict, command, temps)
|
||||||
else
|
|
||||||
return s:execute(dict, command, temps)
|
|
||||||
endif
|
endif
|
||||||
finally
|
|
||||||
call s:popd(dict)
|
let ret = tmux ? s:execute_tmux(dict, command, temps) : s:execute(dict, command, temps)
|
||||||
endtry
|
call s:popd(dict, ret)
|
||||||
|
return ret
|
||||||
finally
|
finally
|
||||||
let &shell = oshell
|
let &shell = oshell
|
||||||
endtry
|
endtry
|
||||||
@ -193,16 +189,28 @@ function! s:pushd(dict)
|
|||||||
return 1
|
return 1
|
||||||
endif
|
endif
|
||||||
let a:dict.prev_dir = cwd
|
let a:dict.prev_dir = cwd
|
||||||
execute 'chdir '.s:escape(a:dict.dir)
|
execute 'chdir' s:escape(a:dict.dir)
|
||||||
let a:dict.dir = getcwd()
|
let a:dict.dir = getcwd()
|
||||||
return 1
|
return 1
|
||||||
endif
|
endif
|
||||||
return 0
|
return 0
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
function! s:popd(dict)
|
function! s:popd(dict, lines)
|
||||||
if has_key(a:dict, 'prev_dir') && getcwd() ==# a:dict.dir
|
" Since anything can be done in the sink function, there is no telling that
|
||||||
execute 'chdir '.s:escape(remove(a:dict, 'prev_dir'))
|
" the change of the working directory was made by &autochdir setting.
|
||||||
|
"
|
||||||
|
" We use the following heuristic to determine whether to restore CWD:
|
||||||
|
" - Always restore the current directory when &autochdir is disabled.
|
||||||
|
" FIXME This makes it impossible to change directory from inside the sink
|
||||||
|
" function when &autochdir is not used.
|
||||||
|
" - In case of an error or an interrupt, a:lines will be empty.
|
||||||
|
" And it will be an array of a single empty string when fzf was finished
|
||||||
|
" without a match. In these cases, we presume that the change of the
|
||||||
|
" directory is not expected and should be undone.
|
||||||
|
if has_key(a:dict, 'prev_dir') &&
|
||||||
|
\ (!&autochdir || (empty(a:lines) || len(a:lines) == 1 && empty(a:lines[0])))
|
||||||
|
execute 'chdir' s:escape(remove(a:dict, 'prev_dir'))
|
||||||
endif
|
endif
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
@ -314,7 +322,6 @@ endfunction
|
|||||||
|
|
||||||
function! s:execute_term(dict, command, temps)
|
function! s:execute_term(dict, command, temps)
|
||||||
call s:split(a:dict)
|
call s:split(a:dict)
|
||||||
call s:pushd(a:dict)
|
|
||||||
|
|
||||||
let fzf = { 'buf': bufnr('%'), 'dict': a:dict, 'temps': a:temps, 'name': 'FZF' }
|
let fzf = { 'buf': bufnr('%'), 'dict': a:dict, 'temps': a:temps, 'name': 'FZF' }
|
||||||
let s:command = a:command
|
let s:command = a:command
|
||||||
@ -338,7 +345,7 @@ function! s:execute_term(dict, command, temps)
|
|||||||
|
|
||||||
call s:pushd(self.dict)
|
call s:pushd(self.dict)
|
||||||
try
|
try
|
||||||
call s:callback(self.dict, self.temps)
|
let ret = s:callback(self.dict, self.temps)
|
||||||
|
|
||||||
if inplace && bufnr('') == self.buf
|
if inplace && bufnr('') == self.buf
|
||||||
execute "normal! \<c-^>"
|
execute "normal! \<c-^>"
|
||||||
@ -348,11 +355,13 @@ function! s:execute_term(dict, command, temps)
|
|||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
finally
|
finally
|
||||||
call s:popd(self.dict)
|
call s:popd(self.dict, ret)
|
||||||
endtry
|
endtry
|
||||||
endfunction
|
endfunction
|
||||||
|
|
||||||
|
call s:pushd(a:dict)
|
||||||
call termopen(a:command, fzf)
|
call termopen(a:command, fzf)
|
||||||
|
call s:popd(a:dict, [])
|
||||||
setlocal nospell
|
setlocal nospell
|
||||||
setf fzf
|
setf fzf
|
||||||
startinsert
|
startinsert
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
Execute (Setup):
|
Execute (Setup):
|
||||||
let g:dir = fnamemodify(g:vader_file, ':p:h')
|
let g:dir = fnamemodify(g:vader_file, ':p:h')
|
||||||
Log 'Test directory: ' . g:dir
|
Log 'Test directory: ' . g:dir
|
||||||
|
Save &acd
|
||||||
|
|
||||||
Execute (fzf#run with dir option):
|
Execute (fzf#run with dir option):
|
||||||
let cwd = getcwd()
|
let cwd = getcwd()
|
||||||
@ -35,6 +36,34 @@ Execute (fzf#run with string source):
|
|||||||
let result = sort(fzf#run({ 'source': 'echo hi', 'options': '-f i' }))
|
let result = sort(fzf#run({ 'source': 'echo hi', 'options': '-f i' }))
|
||||||
AssertEqual ['hi'], result
|
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'})
|
||||||
|
" No change in working directory
|
||||||
|
AssertEqual cwd, getcwd()
|
||||||
|
|
||||||
|
Execute (Incomplete fzf#run with dir option and autochdir):
|
||||||
|
set acd
|
||||||
|
let cwd = getcwd()
|
||||||
|
call fzf#run({'source': [], 'sink': 'e', 'dir': '/tmp', 'options': '-0'})
|
||||||
|
" No change in working directory even if &acd is set
|
||||||
|
AssertEqual cwd, getcwd()
|
||||||
|
|
||||||
|
Execute (fzf#run with dir option and autochdir):
|
||||||
|
set acd
|
||||||
|
let cwd = getcwd()
|
||||||
|
call fzf#run({'source': ['/foobar'], 'sink': 'e', 'dir': '/tmp', 'options': '-1'})
|
||||||
|
" Working directory changed due to &acd
|
||||||
|
AssertEqual '/', getcwd()
|
||||||
|
|
||||||
|
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'})
|
||||||
|
" Working directory changed due to &acd
|
||||||
|
AssertEqual '/', getcwd()
|
||||||
|
|
||||||
Execute (Cleanup):
|
Execute (Cleanup):
|
||||||
unlet g:dir
|
unlet g:dir
|
||||||
Restore
|
Restore
|
||||||
|
Loading…
Reference in New Issue
Block a user