11

In Vim, when I am in insert mode, and I want to use file-name completion, I want the search path to be relative to the current file, not the current working directory. For instance, if in insert mode I type the following:

./^X^F

The completion menu is showing me files in the :pwd, but I would rather see the files in %:p:h listed.

Is there an option that I can set to fix this, and if not what do you suggest as a workaround?

3 Answers 3

14

If you

:set autochdir

you'll get the behavior you desire. However, if you need to keep the working directory (e.g. to easily open other project files), you'd have to save / restore the CWD with autocmds:

:autocmd InsertEnter * let save_cwd = getcwd() | set autochdir
:autocmd InsertLeave * set noautochdir | execute 'cd' fnameescape(save_cwd)
1
  • 2
    Thank you! autochdir was great for C-X, C-F, but annoying when I'm 4 levels deep in a project and I want to :tabe May 28, 2015 at 10:15
5

@Ingo Karkat's answer is nice, but I am a little hesitant to put that in my vimrc, because even the help page for 'autochdir' gives a note that it's useage will break some plugins.

I have come up with my own solution which may be very niche to my use-cases:

inoremap ./<C-X><C-F> <C-O>:lcd %:p:h<CR><C-X><C-F>

I plan on extracting it out into a function and setting a variable for the pwd before the lcs command is issued and then resetting it at some point in time. It would be nice if there was a menu autocmd.

I may or may not use this, but I thought I would throw out another solution.

1
  • It's implied in your answer but please note that this has the side effect of changing the current working directory for the current window.
    – sitaktif
    Apr 3, 2020 at 7:05
1

I have this in my .vimrc:

" [relative autocomplete]
" ==============================================================================
" Vim's file autocomplete (C-X C-F) works only in an absolute path (using the
" current working directory) as base. But in most languages, you want to use
" relative imports, and file autocomplete doesn't work there. For that, I use
" <C-X><C-X><C-F>:

function! s:EnableRelativeAutocomplete() abort
  let b:relative_autocomplete_cleanup_pending = 1
  lcd %:p:h
endfunction

function! s:DisableRelativeAutocomplete() abort
  if exists('b:relative_autocomplete_cleanup_pending') && b:relative_autocomplete_cleanup_pending
    lcd -
    let b:relative_autocomplete_cleanup_pending = 0
  endif
endfunction

inoremap <C-x><C-x><C-f> <C-o>:call <SID>EnableRelativeAutocomplete()<CR><C-x><C-f>

augroup relative_file_autocomplete
  autocmd!
  autocmd InsertLeave * call s:DisableRelativeAutocomplete()
augroup END

It will change the working directory to the current file's when using <C-x><C-x><C-f> and back to the previous directory when leaving insert mode, if needed.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .