pericmd 034: More on tab completion (6): Completion modules

In this post we’ll take a tour on what completion modules have been written and how you can write one yourself.

Completing Perl modules and distributions

Complete::Module, previously mentioned, can complete Perl module names. There are some other derivative modules which I wrote which are basically shortcuts for convenience like Complete::Dist::Zilla (for listing modules in the namespace of /^Dist::Zilla::(Plugin,PluginBundle,Role)::/) or Complete::Pod::Weaver (for modules in /^Pod::Weaver::(Role,Plugin,PluginBundle,Section)::/). There is also Complete::Riap which currently only supports local URL (like “/App/fatten/fatten” or “pl:/WWW/PAUSE/Simple/list_files”) and also complete from Perl modules and functions.

Complete::Dist can complete from list of locally installed Perl distributions. I’m using it App::DistUtils (“uninstall-dist <tab>”).

Unix stuffs

Complete::Unix provides several functions for completing Unix-related things like user names, UIDs, group names, GIDs, PIDs, as well as process names. They can be useful for writing Unix or Unix-related utilities. For example, I’m using it for App::ShellCompleter::emacs (“emacs –user <tab>”).

Complete::Man can complete from list of available manpages. So far I haven’t had the need to use it yet though.

Others

complete_prog() from Complete::Util can complete from list of programs available on PATH.

Creating your own completion routine/module

Let’s create an example of completing from the list of time zone names. In a Unix machine, there is usually a directory structure in /usr/share/zoneinfo/ which we can readily use (we just need to filter out some files). Since this is just filesystem path, we can utilize Complete::Util‘s complete_file() for this.

First create a module called Complete::TZ by creating file named “lib/Complete/TZ.pm” with the following content:

package Complete::TZ;

use strict;
use warnings;
use Exporter qw(import);
our @EXPORT_OK = qw(complete_tz);

sub complete_tz {
    require Complete::Util;
    my %args = @_;
    Complete::Util::complete_file(
        starting_path => '/usr/share/zoneinfo',
        handle_tilde => 0,
        allow_dot => 0,
        filter => sub {
            return 0 if $_[0] =~ /\.tab$/;
            1;
        },

        word => $word,
    );
}
1;

Let’s test this module:

% perl -Ilib -MComplete::TZ=complete_tz -MDD -E'dd complete_tz(word=>"asia/j")'
["Asia/Jakarta", "Asia/Jayapura", "Asia/Jerusalem"]

If you later package this module as a proper CPAN module and install it, you’ll be able to use it in your CLI app as with other completion routines, e.g.:

use Complete::TZ qw(complete_tz);

$SPEC{yourapp} = {
    v => 1.1,
    args => {
        tz => {
            summary => 'Select a timezone name',
            schema => 'str*',
            completion => \&complete_tz,
        },
        ...
    },
};
...

When you use your CLI app, you’ll then get a convenience of tab completion for timezone names, e.g.:

% yourapp --tz asia/j<tab><tab>
Asia/Jakarta   Asia/Jayapura   Asia/Jerusalem
Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s