sábado, 18 de julio de 2009

Getopt::Complete. Making your own tab completions

I just discovered a new perl module in cpan called Getopt::Complete.

As all Getopt::* family, it deals with your program flags. But this module takes it a little further.

Those who know me, know I'm a fan of the DWIM philosophy, so I try to automate every single process in my life. Instead of bash, I use zsh for its amazing DWIMy tab completion.

Well, Getopt::Complete lets you write the tab completion function in perl instead of bash.

Here's a modified example from its perldoc:


#!/usr/bin/perl

use Getopt::Complete (
type => ['names','places','things'], #--type has 3 possible completions
instance => sub {
my ($command, $value, $option, $other_opts) = @_;
if ($other_opts->{type} eq 'names') {
system('touch /tmp/fu');
return [qw/larry moe curly/],
}
elsif ($other_opts->{type} eq 'places') {
return [qw/here there everywhere/],
}
elsif ($other_opts->{type} eq 'things') {
return [ query_database_matching("${value}%") ]
}
elsif ($otper_opts->{type} eq 'surprsing') {
# no defined list: take anything typed
return undef;
}
else {
# invalid type: no matches
return []
}
}
);


to enable the completion, you must tell bash, it should ask the same program to complete words in the commandline.

$complete -C /home/kidd/myapp.pl myapp.pl

Then you should make myapp.pl executable

$chmod +x /home/kidd/myapp.pl

and now, you can start testing it.

WARNING!: In the previous example, I've put an extra line that executes a system call. If you try to tab complete 'myapp.pl --type names --instance ' , the system call will be executed and you'll get a 'free' /tmp/fu file.

That's obviously a serious security issue, but if you use it in a wise way, this module can add some quality to your software requiring only a few lines of code.

TODO: I'm looking at enabling this kind of completion in zsh. If anyone knows it, please leave a comment.

That's all for now.