Vim Tips: Simple Project Switching with FZF
What
Simply jump between any nested git directory in a root directory using simple linux utilities and FZF.
Type :Project
and pick the project you want to work on next.
Why
The more we move towards microservices, the more repositories you have to jump between every day.
This tip lets you hop between git projects in the same Vim instance. This workflow is much faster than closing the window, jumping to the other directory and starting a new editor instance. In some cases it may also allow re-using plugins like an LSP to reduce use of system resources.
How
First install the fzf
and fzf.vim
plugins by
junegunn
and append the following script to your
~/.vimrc
- vim
- plugins
1 |
|
Explanation
this stack overflow question goes over the most efficient way to query for git
repos.
I used a top answer to construct the following find
command.
- sh
- output
1 |
|
You can run this command yourself, replacing ~/projects
with wherever you
keep your repositories. The output can be seen by clicking output
in the codepane above.
If the command fails because you don’t have find installed you can add it with brew on MacOS with brew install findutils
Using this output we’re able to construct the command we’d
like to execute. tabedit /home/james/projects/guard
causes us to create a new tab if it does not exist, and
select it. Then we are able to call lcd /home/james/projects/guard
which causes vim to change
directory for the current pane to the new project.
lcd
causes all your commands to be executed in the target project directory
and substitutions like %
to return the new directory.
We can’t directly call lcd with the path so we use string interpolation to
evaluate the command like in exec 'lcd '.a:project
a:project
is an argument scoped variable. It is only available in the
function due to it being listing in the arguments
s:change_to_project(project)
.
s:function_name
causes the function to only be available with the script.
This prevents it from polluting the global namespace or being called adhoc
later on.
command! Project ...
defines a new command that you can call with :Project
.
fzf#run(fzf#wrap(...)
allows you to send the results of any shell command
that returns a list of strings to be selected and then operated on by a VimL
function.
You can see that there is a { source: '...command', sink: function('s:change_to_project') }
hash. function('s:change_to_project')
returns a function reference by looking up the passed variable. When the FZF
command completes it will send the single string result to any function that is
passed in the sink
property of the hash.