Fuzzy search through files in Visual Studio Code

Visual Studio Code already supports searching across all the project files. But let’s make searching inside them even more ergonomic and easier to use. We’ll do it by taking an inspiration in the behavior of the command :RG from Vim plugin junegunn/fzf.vim.

The goal

Check out the Find in files in Visual Studio Code:

Screenshot of the Find in files in Visual Studio Code

As an alternative, we’ll create a custom shell command rgf for fuzzy searching. After we select the result, command rgf will open the file in Visual Studio Code on the correct line. Then we’ll simplify running rgf from Visual Studio Code. We’ll build this new, alternative, flow:

Fuzzy searching in Visual Studio Code

Prerequisites

First, make sure you have these installed and set up so all works as expected:

Now, save this shell environment variable. Probably to $HOME/.bashrc, but it depends on your shell and your setup:

export FZF_DEFAULT_OPTS="--history=$HOME/.fzf-history"

This setting lets fzf load search history from the specified file and update the file on completion. You can then use Ctrl+N and Ctrl+P to go back and forward through search history and Ctrl+H and Ctrl+J or arrow keys and to select the next and previous result.

Install the script for fuzzy searching

Similarly, save the following script to your $PATH and make it executable, so you can run it in your shell:

#!/usr/bin/env bash

##
# Interactive search.
#
[[ -n $1 ]] && cd "$1" # go to provided folder or noop

export FZF_DEFAULT_COMMAND="rg --column --line-number --no-heading --color=always -- ''"
selected=$(
  fzf \
    --ansi \
    --delimiter : \
    --bind "f12:execute-silent:(code -g $PWD/{1..3})" \
    --preview-window 'up,60%,border-bottom,+{2}+3/3,~3' \
    --preview 'bat -f --highlight-line={2} {1}' | cut -d":" -f1,2,3
)

[[ -n $selected ]] && code -g "$PWD"/"$selected"

For example, on macOS, you can copy the script, then run this in your terminal:

pbpaste > ~/bin/rgf # ~/bin is in my $PATH
chmod +x ~/bin/rgf

Having done all this, you can now use rgf to fuzzy search in your shell. Try it!

What does the script do

The script combines fzf, rg, bat, and code to fuzzy search through your code and to open the result in Visual Studio Code. I based it on Using fzf as interactive ripgrep launcher.

Compared to the original, the script behaves like the :RG command in junegunn/fzf.vim. It uses fzf fuzzy searching right away, and it doesn’t pre-filter the results with ripgrep. The script uses ripgrep to list the lines in the project, with path, filename, and line number.

Install fuzzy search command to Visual Studio Code

Next in order, simplify running rgf from Visual Studio Code.

Add this to your Visual Studio Code settings.json:

{
  "command-runner.commands": {
    "rgf": "rgf; exit"
  }
}

After doing this, you can:

Add fuzzy search shortcut

Add this to your Visual Studio Code keybindings.json:

{
  "args": { "command": "rgf" },
  "command": "command-runner.run",
  "key": "cmd+k ."
}

New workflow

After doing this, you can:

Fuzzy searching in Visual Studio Code

How does this differ from the default

I want to avoid writing complicated regular expressions. I prefer not to write out the full names. If I’m looking for the function getSelectedAddressFormValues, I should be able to find it with the search term getseladd.

In comparison with Find in files, you don’t need regex.

One field, nothing more

With Find in files, you have several input fields and extra toggles which you need to keep checking and toggling either with a mouse or complicated shortcuts.

Instead, I want to have one input field where the search term affects almost everything. See how fzf does it. Do you want to use the exact match? ‘wild Do you want to use an inverse match? !wild

Everything is part of the search term.

Limiting the files included in the search is easier

With Find in files, you can limit the files included in your search in at least two ways, but I find neither of them ergonomic enough:

Why do you need to write out the whole path? You can use glob syntax. But you still have to figure out where to put them.

By comparison, what if you could enter the folder/file name right inside the same input field as the search term and use fuzzy matching? You’d find a lot of things faster.

Example

Take the case of finding the word wild inside the folder web-app. The folder web-app is located in ./packages/web-app.

I’d like to use this search term:

web-app wild

Or even this should work:

weba wild # fuzzy matching

Complete search history

Lastly, with Find in files, you can go through previous searches but Visual Studio Code doesn’t remember the switches and files to include field. I’d prefer to have access to the complete search history, with the toggles and other fields as part of it.