在当前文件位置退出Vim

5

我经常使用 Vim 并通过快捷键更改当前位置。

然后,当我退出 Vim 时,我希望能在 bash shell 中处于我所在文件的目录。

我该如何实现这个功能?


3
大多数情况下,你不能这样做:子进程(vim)无法修改父进程的工作目录(启动vim的shell)。 - larsks
1
但是我能让Vim在退出时返回一个字符串吗?这个字符串是bash shell要移动到的pwd吗? - john-jones
1
一个非常好的例子,说明了正在发生的事情。 - phd
2个回答

6
在多进程操作系统中,子进程无法更改父进程中的任何内容。但是父进程可以进行协作,因此子进程可以要求父进程为其执行某些操作。在您的情况下,在退出vim时应返回最后工作的目录,并且shell应该转到它。我成功通过以下方式实现了协作:
在~/.vimrc文件中:
call mkdir(expand('~/tmp/vim'), 'p') " create a directory $HOME/tmp/vim
autocmd VimLeave * call writefile([getcwd()], expand('~/tmp/vim/cwd')) " on exit write the CWD to the file

~/.bashrc文件中:
vim() {
    command vim "$@"
    rc=$?
    cd "`cat \"$HOME/tmp/vim/cwd\"`" && rm "$HOME/tmp/vim/cwd" &&
    return $rc
}

我进一步完善了它,将函数命名为vim_cd_at_exit。然后,如果我想要在退出时使用vim,并且切换到退出时的目录,我只需运行"${EDITOR}_cd_at_exit"。但是,如果我不想这样做,我可以像以前一样运行vim。 - john-jones
@john-jones 由你决定。我根本不在vim中使用cd/lcd,所以也没有地方可以cd到。我只是想解决一个有趣的挑战。 :-) - phd
从中学到了一些东西。点赞! - Jetchisel

3

针对未来读者,本文内容参考/借鉴自@phd的回答。

vimrc代码:

augroup auto_cd_at_edit
  autocmd!
  autocmd BufEnter * if expand('%p:h') !~ getcwd() | silent! lcd %:p:h | endif
augroup END

" Pointing rm to `~/` gives me the chills! :-)
" Change the *path_name, file_name according to your own desire.
function! Vim_Cd_At_Exit()
  let l:file_name = 'cwd'
  let l:sub_pathname = 'vim_auto_cd'
  let l:path_name = getenv('TMPDIR') . '/' . l:sub_pathname
  call mkdir(l:path_name, 'p')
  call writefile(['cd -- '  .  shellescape(getcwd())], l:path_name . '/' . l:file_name)
endfunction

augroup Auto_Cd_After_Leave
  autocmd!
  autocmd VimLeave * call Vim_Cd_At_Exit()
augroup END

编写~/.bashrc的代码

##: if `declare -p TMPDIR` has a value, you can skip this part
##: If not make sure your system has `/dev/shm` by default 
##: otherwise use another directory.
export TMPDIR=${TMPDIR:-/dev/shm}

vim() {
  builtin local IFS rc path tmp_file
  tmp_file="$TMPDIR/vim_auto_cd/cwd"
  builtin command vim "$@"
  rc=$?
  if [[ -e "$tmp_file" && -f "$tmp_file" ]]; then
    IFS= builtin read -r path < "$tmp_file"
    [[ -n "$path" && "${path#cd -- }" != "'$PWD'" ]] && {
    builtin source "$tmp_file" || builtin return
    builtin printf '%s\n' "$path"
    ##: Uncomment the line below to delete the "$tmp_file"
    #builtin command rm "$tmp_file"
  }
  fi
  builtin return "$rc"
}

  • 在某些系统上,vivim指向/etc/alternatives,而 shell函数名称只是vim,因此避免这种功能的快速方法就是使用vi。或者使用command vim调用/执行它,参见:help command

上面帖子中的资源:


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接