Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Idiomatic way to implement standard Unix behaviour of using STDIN if no files are specified on the command line?

Tags:

raku

Is there a more elegant way of processing input coming from either the command line arguments or STDIN if no files were given on the command line? I'm currently doing it like this:

sub MAIN(*@opt-files, Bool :$debug, ... other named options ...) {
    # note that parentheses are mandatory here for some reason
    my $input = @opt-files ?? ([~] .IO.slurp for @opt-files) !! $*IN.slurp;

    ... process $input ...
}

and it's not too bad, but I wonder if I'm missing some simpler way of doing it?

like image 551
VZ. Avatar asked Aug 30 '20 13:08

VZ.


2 Answers

I would probably go for a multi sub MAIN, something like:

multi sub MAIN(Bool :$debug)
{
    process-input($*IN.slurp);
}

multi sub MAIN(*@opt-files, Bool :$debug)
{
    process-input($_.IO.slurp) for @opt-files;
}
like image 173
mscha Avatar answered Sep 22 '22 08:09

mscha


I'd probably do two things to change this. I'd break up the ?? !! onto different lines, and I'd go for a full method chain:

sub MAIN(*@opt-files, Bool :$debug, ... other named options ...) {
    my $input = @opt-files 
                  ?? @opt-files».IO».slurp.join
                  !! $*IN.slurp;

    ... process $input ...
}

You can also map it by using @opt-files.map(*.IO.slurp).join

Edit: building on ugexe's answer, you could do

sub MAIN(*@opt-files, Bool :$debug, ... other named options ...) {

    # Default to $*IN if not files
    @opt-files ||= '-';

    my $input = @opt-files».IO».slurp.join

    ... process $input ...

}
like image 33
user0721090601 Avatar answered Sep 20 '22 08:09

user0721090601