File finder and project search in Vim without any plugins
You don't need Ctrl-P
I used ctrlp for a long time but now I use a self-made version with just a few lines on my vimrc.
Personally I like to use fd within the CLI because it's really fast. So to make this command work we need to know what command do we want to run. In my case is a simple
fd -t f <search>. This is not enough as we want the output to be like any vim's quickfix window, so we need to format it like:
fd -t f <search> | xargs file | cut -d' ' -f1 | sed "s/:/:1:/"
Basically, this command produces this output:
$ fd -t f layout | xargs file | cut -d' ' -f1 | sed "s/:/:1:/" components/skeleton/withLayout.tsx:1: components/cms/CMSLayout.tsx:1:
Just the path of the matching files and a
1 to tell quickfix to go to the first line of that file.
Now that we can populate a window with the results, we need a quick way of triggering this search. As I used CtrlP for a while, I'll make
c-p trigger this. First, I make a function with all the code I need:
function! FindFiles(filename) let error_file = tempname() silent exe '!fd -t f '.a:filename.' | xargs file | sed "s/:/:1:/" > '.error_file set errorformat=%f:%l:%m exe "cfile ". error_file copen endfunction
Basically this will create a new "error file" to include the results and show it in the quickfix window. It silently executes
fd and populates this window with the
cfile command. At the end, it opens the window with
Now it's easy to map control+P to use this function:
command! -nargs=1 Find call FindFiles(<q-args>) nmap <c-p> :Find<space>
This code just creates a command from the previous function and maps
c-p to that command. Notice there's a space character after the mapping: that means when we press control+P it will write :Find followed by a space in command mode so you can start typing the query you want to search for.
If you wanna use this exact same code you can use my plugin better-find.vim. Notice you need to have the
fd command available.
The power of vimgrep
To search for a term in all of our project files, vim already comes with a great tool:
:vimgrep. It also includes a
:grep command that we can customize to use an external tool to search in our projects. In my case I use ripgrep.
Let's go straight to the code:
set grepprg=rg\ --vimgrep function! Grep(...) return system(join([&grepprg] + a:000), ' ') endfunction
As you can see, this is less code than before but a bit more confusing. Without going into much details, the function we created,
:Grep, takes the query as the arguments and passes that to ripgrep. Now we also create a command to use the function, and map it to control+F:
command! -nargs=+ -complete=file_in_path -bar Grep cgetexpr Grep(<f-args>) nmap <c-f> :Grep<space>
And here's the result:
Of course I also made it available on github if you want to use it: better-grep.vim.