I find that the easiest way to work with Bazel is with fzf.
If you haven’t already discovered fzf, it’s great. It’s a command-line fuzzy finder, which means you can use it to replace tab completion at the command line with a fuzzy drop-down picker. It’s straight magic, it’s quick to set up, and you’re in for a treat.
One of the best parts of fzf is that you can script it.Fun fzf tip: the kill
command is already configured using this completion API: try typing kill -p **<TAB>
and you’ll never see kill
the same way again 🙂
In the screen cast above, you see how I’m using **<TAB>
to trigger fzf to list all bazel targets. It uses the Custom fuzzy completion API to register a shell function to run on TAB
.
Here’s the code you can add to your config files (like your ~/.zshrc
):
Note: zsh automatically discovers these functions based on their name. But if you’re using Bash, you need a few extra lines to register these functions.
At its core, these functions invoke bazel query
to list all the targets, and then pass the output to fzf
so they can be filtered.
There’s special handling for bazel
(which is usually bazel build
) as well as bazel test
(which limits the output to only test
and test_suite
targets).
You can see one caveat in the comment there:If you have a solution to this, please let me know!
it doesn’t do all that well at finding every external target. For example, the Sorbet repo has a bunch of :ruby.tar.gz
defined in various external (@
-prefixed) repository rules, but since Bazel doesn’t have an easy way to list all those external repos, and because they’re not transitive deps of anything in //...
, they don’t show up in the output.
One last trick: I have a ton of bazel shell aliases. Because of how zsh auto-discovers these two _fzf_complete_*
functions, using if the first token isn’t literally bazel
then zsh won’t find the right methods.
That’s easy enough to fix: just have one more function per alias:
And that about sums it up. If you have tips for how I could improve these functions, please let me know!