I like to find what I need quickly, so I make heavy use of tab completion at the command line. Lately, I’ve been using fzf more and more to do this. It’s a wonderful tool. I won’t go in depth about fzf
here, but if you haven’t checked it out, please do. I think it’s well worth it.
What I want to do today is to explain how to harness the power of fzf
to add tab completion to an arbitrary command line program. In this case, it’s Perl’s prove
, which many of us use when running tests.
Often when running tests, I want the results I’m looking for as fast as possible. So, I’ll want to run one or more files, but not everything in the test suite. Running every test can be slow. Anything that allows my mind to wander is something I want to avoid.
What I want to be able to do is run prove **<tab>
and get a multi-select list. Bonus points if that list can be searched and narrowed down further once it appears.
Enter fzf
.
The bash (and zsh) implementation#
I’m going to assume that you already have fzf
installed and that you’re using the bash
or zsh
shell. In this case, all you need to do is add the following lines to your .bashrc
and then source ~/.bashrc
and you’re ready to go.
_fzf_complete_prove() {
_fzf_complete --reverse --multi --prompt="prove> " -- "$@" < <(
find t | grep .t$
)
}
_fzf_complete_prove_post() {
awk '{print $1}'
}
[ -n "$BASH" ] && complete -F _fzf_complete_prove -o default -o bashdefault prove
Note that if you’re using zsh
you won’t need the last line.
Using fd rather than find#
You’ll note that my solution above uses find
, but nowadays I actually prefer fd. If you also enjoy using fd
, you can do something like:
_fzf_complete_prove() {
_fzf_complete --reverse --multi --prompt="prove> " -- "$@" < <(
fd -e t
)
}
This recursively finds files with the .t
extension. Note that since we haven’t specified a folder here, this will search in t
and xt
, so it will find more test files than the find
command above. Use your favourite tool here and be creative.
Using Your Fancy New CLI#
Now, you can do things like:
prove -lv **<tab>
or just
prove **<tab>
and you’ll be presented with a list of tests to run.
$ prove -lv **
prove>
63/63 (0)
>> t/00-load.t
t/add_header.t
t/aliases.t
t/area_link.t
t/autocheck.t
t/bad-request.t
t/clone.t
t/content.t
t/cookies.t
t/credentials-api.t
t/credentials.t
t/die.t
t/dump.t
t/field.t
t/find_frame.t
You can now start typing to narrow down the list further. You can use your tab key to select multiple files.
$ prove -lv **
prove>
63/63 (3)
>t/00-load.t
t/add_header.t
t/aliases.t
>t/area_link.t
t/autocheck.t
>>>t/bad-request.t
t/clone.t
t/content.t
t/cookies.t
t/credentials-api.t
t/credentials.t
t/die.t
t/dump.t
t/field.t
t/find_frame.t
Once you’re done, just <enter>
and you’ll have a command line that is ready to run your tests:
prove -lv t/00-load.t t/area_link.t t/bad-request.t
That’s it! You can see this in action by clicking the image below.
To take this to the next level with a preview pane, see my next post.
Addendum:#
Thanks to Andy Lester for pointing out that
ack -f --perltest
can also be used to get a list of Perl test files.