Vim: Working Directory Autocompletion and File Finding from Project Root
When working with Vim, I open the editor from the project root. This is the parent directory which also contains the
For file navigation, I heavily rely on fzf.vim. Opening Vim from the root directory means that I have access to all project files via FZF. I mapped the command to
<ctrl> + p (VS Code) and can find the file I would like to edit.
For autocompletion, I use different plugins. One of them is VimCompletesMe, a minimalist tab-completion plugin for Vim.
Let's say we have a standard Create-React-App project structure:
MyApp/ -- client/ --src/ --components/ --Header.js --App.js -- README.md -- package.json
I open Vim from the root folder:
With FZF I can now open different files from this directory.
But when I'm in
App.js and I want to import something, tab autocompletion starts from
MyApp instead of
App.js (which is already nested deeply in the project structure).
// client/src/components/App.js import React from 'react' import Header from '. ' /* <- here autocompletion goes wrong and starts suggesting files and folders relative to the parent directory */
This can get confusing.
One solution is to set the working directory to the current file.
I used this snippet in my
autocmd BufEnter * silent! lcd %:p:h
This autocmd changes the window-local current directory to be the same as the directory of the current file. It fails silently to prevent error messages when you edit files via ftp or new files.
This "breaks" FZF file searching. FZF will now search for files in the current directory instead of the parent/root folder.
What if we could tell FZF to search from the project folder instead?
function! s:find_git_root() return system('git rev-parse --show-toplevel 2> /dev/null')[:-2] endfunction command! ProjectFiles execute 'Files' s:find_git_root()
This assumes that you have a
.git folder in your parent directory.
Alternatively, you can use a plugin like ProjectRoot. It tries to guess the main folder and offers simple mappings and commands.
Now, remap your current keybinding for FZF to use the function above. For example:
nnoremap <c-p> :<c-u>ProjectFiles<cr>
If you would like to use
rg for finding text within files (instead of
grep), you can also adjust the command to search from the project root. I couldn't get it working with the function above. But it works with ProjectRoot.
call minpac#add('dbakker/vim-projectroot') " install the plugin nnoremap <Leader>rg :<C-u>ProjectRootExe Rg<CR> " key mapping for Rg