Skip to main content

Adding Tab Completion to Your Favourite CLI Programs

·544 words·3 mins·
perl Programming testing tab completion fzf prove fd
Table of Contents
❤️ It's great to see you here! I'm currently available on evenings and weekends for consulting and freelance work. Let's chat about how I can help you achieve your goals.

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.

asciicast

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.


Related

Introducing LWP::ConsoleLogger::Everywhere
·157 words·1 min
perl LWP::ConsoleLogger LWP::ConsoleLogger::Everywhere
The Perl QA Hackathon is still looking for Sponsors
·310 words·2 mins
CPAN metacpan perl QA Hackathon
MetaCPAN Welcomes Panopta as a Sponsor
·355 words·2 mins
CPAN metacpan perl sponsor