Vim, exit at current files location
Asked Answered
E

2

5

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?

Evergreen answered 28/10, 2022 at 13:14 Comment(3)
For the most part you can't: a child process (vim) cannot modify the working directory of a parent process (the shell from which you started vim).Tilbury
But can I have Vim return a string upon exit, which is the pwd the bash shall is to move itself to?Evergreen
vi.stackexchange.com/a/22949 A very good example on what is going on.Saporous
S
6

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
}
Saporous answered 28/10, 2022 at 14:58 Comment(3)
I took it a bit futher, named the function vim_cd_at_exit. Then if I want to vim, plus cd to where i exit i do "${EDITOR}_cd_at_exit". But if I don't want that i just run vim as before.Evergreen
@Evergreen Up to you. I don't use cd/lcd in vim at all so there is nowhere to cd to. I just wanted to solve an interesting challenge. :-)Saporous
Learn something from this. up voted!Mayflower
M
4

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:

Mayflower answered 28/10, 2022 at 13:14 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.