Home > Raku > Fuzzy commands

Fuzzy commands

Reading can make one learned. Today I had a peak into lizmat´s new module shorten-sub-commands and learned about Parameter.constraint_list. We need this method to introspect a routines literal parameters.

use MONKEY-TYPING;
augment class Parameter {
    method literal {
        !self.name && !self.named && self.type ~~ Str|Numeric && self.constraint_list == 1
            ?? self.constraint_list.head
            !! Nil
    }
}

multi sub foo('literal', 42) { }
multi sub foo($not-a-literal, 42) { }
.say for &foo.candidates».signature».params».literal;

# OUTOUT: (literal 42)
#         (Nil 42)

We can generalise lizmat´s idea of transforming command line arguments.

multi sub MAIN('foo', |c) { say 'foo', @*ARGS[0] }
multi sub MAIN('Barbara', |c) { say ['bar', @*ARGS[0]] }

sub transform-first-arg(Mu:D $test is raw, &mapper) {
    &MAIN.add_dispatchee: sub (Str:D $subcommand, |c) is hidden-from-USAGE {
        my &this-candidate := &?ROUTINE;
        my @real-subcommands = &MAIN.candidates.grep(* !=:= &this-candidate)».signature».params».[0]».literal;
        if $subcommand ~~ $test {
            MAIN(mapper($subcommand), |c)
        }
    }
}

transform-first-arg({ .lc.contains(<fo ba>.any) }, { .trans: ['fo', /:i ba.*/] => ['foo', 'Barbara'] });

This program is now very generous when it comes to it’s first argument. Even !./% bAR will result in the right MAIN-candidate to be called.

I used augment because this doesn’t feel like an ENODOC. One needs to know quite a lot of the internal workings of Parameter to make use of method constraint_list. We may have to support more then just string and numeral literals in the future. So maybe there is a PR in order.

Categories: Raku