Vim, exit at current files location

424 Views Asked by At

I run Vim and change my current location all the time via shortcuts.

Then when I exit Vim, I want to be in the directory of the file I was in, in the bash shell.

How do I go about doing that?

2

There are 2 best solutions below

3
phd On BEST ANSWER

In multiprocess operating systems a subprocess cannot change anything in the parent process. But the parent process can cooperate so a subprocess can ask the parent process to do something for the subprocess. In your case on exit vim should return the last working directory and the shell should cd to it. I managed to implement cooperation this way:

In ~/.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

In ~/.bashrc:

vim() {
    command vim "$@"
    rc=$?
    cd "`cat \"$HOME/tmp/vim/cwd\"`" && rm "$HOME/tmp/vim/cwd" &&
    return $rc
}
0
Jetchisel On

For future readers, Adapted/derived from @phd's answer.

Code for 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

code for ~/.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"
}

  • On some system vi and vim points to say /etc/alternatives and the bash shell function name is just vim, so a quick way to avoid this functionality is just use vi. Either that or invoke/execute it with command vim, see: help command

Resources from above post: