From 0f281ef89410cd581b581fd6087e9edd1832d1e8 Mon Sep 17 00:00:00 2001 From: Junegunn Choi Date: Tue, 12 Jan 2016 01:15:36 +0900 Subject: [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 --- plugin/fzf.vim | 47 ++++++++++++++++++++++++++++------------------- 1 file changed, 28 insertions(+), 19 deletions(-) (limited to 'plugin') diff --git a/plugin/fzf.vim b/plugin/fzf.vim index 8dc5b8a1..f84edfa4 100644 --- a/plugin/fzf.vim +++ b/plugin/fzf.vim @@ -1,4 +1,4 @@ -" Copyright (c) 2015 Junegunn Choi +" Copyright (c) 2016 Junegunn Choi " " MIT License " @@ -139,17 +139,13 @@ try let tmux = !has('nvim') && s:tmux_enabled() && s:splittable(dict) let command = prefix.(tmux ? s:fzf_tmux(dict) : fzf_exec).' '.optstr.' > '.temps.result - try - if tmux - return s:execute_tmux(dict, command, temps) - elseif has('nvim') - return s:execute_term(dict, command, temps) - else - return s:execute(dict, command, temps) - endif - finally - call s:popd(dict) - endtry + if has('nvim') + return s:execute_term(dict, command, temps) + endif + + let ret = tmux ? s:execute_tmux(dict, command, temps) : s:execute(dict, command, temps) + call s:popd(dict, ret) + return ret finally let &shell = oshell endtry @@ -193,16 +189,28 @@ function! s:pushd(dict) return 1 endif 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() return 1 endif return 0 endfunction -function! s:popd(dict) - if has_key(a:dict, 'prev_dir') && getcwd() ==# a:dict.dir - execute 'chdir '.s:escape(remove(a:dict, 'prev_dir')) +function! s:popd(dict, lines) + " Since anything can be done in the sink function, there is no telling that + " 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 endfunction @@ -314,7 +322,6 @@ endfunction function! s:execute_term(dict, command, temps) call s:split(a:dict) - call s:pushd(a:dict) let fzf = { 'buf': bufnr('%'), 'dict': a:dict, 'temps': a:temps, 'name': 'FZF' } let s:command = a:command @@ -338,7 +345,7 @@ function! s:execute_term(dict, command, temps) call s:pushd(self.dict) try - call s:callback(self.dict, self.temps) + let ret = s:callback(self.dict, self.temps) if inplace && bufnr('') == self.buf execute "normal! \" @@ -348,11 +355,13 @@ function! s:execute_term(dict, command, temps) endif endif finally - call s:popd(self.dict) + call s:popd(self.dict, ret) endtry endfunction + call s:pushd(a:dict) call termopen(a:command, fzf) + call s:popd(a:dict, []) setlocal nospell setf fzf startinsert -- cgit v1.2.3