Julius Plenz – Blog

debugging a zsh completion function

There's a Perl module threads::shared. However, it won't show up as a completion match to the perldoc command. Why is that?, a colleague asked me. Now, that obviously is a quirk, so let's debug it.

We start at /usr/share/zsh/functions/Completion/Unix/_perldoc, where we find this:

_alternative \
    'modules:module: _perl_modules -tP' \
    'pods:base pod: _perl_basepods' \
    'files:module or .pod file:_files -g "*.(pod|pm)(-.)"' &&
    ret=0

So, go on to _perl_modules: It searches for paths where Perl would store modules and their documentation (line 85):

inc=( $( $perl -e 'print "@INC"' ) )

Then, they do some complicated globbing stuff on the directories (line 104), where a loop iterates over $inc and stores each element in $libdir:

new_pms=( $libdir/{[A-Z]*/***/,}*${~sufpat}~*blib* )

There's the catch: This globbing expression will only recurse into subdirectories that start with an uppercase letter. Lowercase modules on the highest level are okay, though. That's why threads appears (from threads.pm), but threads::shared doesn't (from threads/shared.pm).

The search for all modules that are missed this way will translate to the following Z-Shell command:

$ print -l ${^=$(perl -e 'print "@INC"')}/[a-z]*/***/*.pm(.N)
/usr/lib/perl/5.10/threads/shared.pm
/usr/share/perl/5.10/encoding/warnings.pm
/usr/share/perl/5.10/warnings/register.pm

posted 2011-09-01 tagged zsh and perl

Perl: use feature;

With it's 5.10 version, Perl learned some pretty interesting new features. Some of them modify the syntactic interpretation of Perl code, so to stay backwards-compatible, you have to manually enable them. To do this, add a line like

use feature qw(:5.10);

to your other use declarations. (For one-liners, add the -E command line switch.) The documentation is available via perldoc feature or online.

There's one pretty trivial change that nonetheless has bothered me for a long time already. Why is there no function in Perl to print out some strings, and then finish with a newline? I mean, almost every sane programming language has this, and it helps writing clean code a lot (no fiddling with \n and so on). – Now, they backported the say function from Perl 6, which does just that: add an omplicit newline.

The new concept of state variables is nothing I need for now; however, the feature they strangely call switch (although the actual keywords are given/when) is pretty nice: It's pretty much like what you'd expect with a typical C construct like this:

switch(var) {
    case 1:
        /* do something */
        break;
    ...

    default:
        /* do default thing */
        break;
}

In Perl that's now:

given($var) {
    when(condition1) {
        # do something
    }

    do_other_thing when condition2; # as one-liner

    default {
        # fallthrough case
    }
}

Update: The statement when condition; one-liner doesn't work. Don't know where I got that from.

You can use simple strings (maps to $_ eq "string"), regular expressions (maps to $_ =~ /regex/) or function references like \&myfunc (maps to myfunc($_)).

The best improvement, however, are so-called named captures. (You don't have to enable those specifically.) It allows regexes to contain pairs of parentheses that you can assign a name to later extract the match. That means: no stupid and mind-boggling re-numbering of $2 to $3 etc., just because you added a set of brackets around something you want to extract from a string. Consider this example regex:

my $re = qr/
    (?<user>[^\@\s]+)
    \@
    (?<domain>[^\s">]+)
    /x;

You can now access the user-part of the e-mail address via $+{user}, not necessarily via $1. The immediate gain is obvious: if you add parentheses around the whole expression (to capture the whole e-mail address) the user part is still available via $+{user}. The numbered variable would be $2 now, though.

Another side-effect is that you can test several regexes in a row now, and later extract matching parts from all of these – of course only if you use distinct capture names. Hash entries in %+ will only be updated upon a match (and won't be cleared AFAIK, at least in the lexical scope).

posted 2011-07-02 tagged perl