Using MooX::Options to run a Perl script.

In my last post about using Moo I added some more functionality to my File::Info package. I added some more attributes and some Moo roles. I also updated and ran my test script to ensure that it worked well.

Now I want to put my File::Info class to use.  Normally when I write scripts I like to use configuration files with Config::General and command line options (CLI) with Getopt::Long. These have served me very well in the past. Having seen a post recently on the excellent Perl Maven site about Command Line Scripts With Moo I decided to give MooX::Options a try.

This script accepts one input option,  ‘in_file’. The MooX option attribute takes care of  most of the validation and error handling of the input. It also takes care of displaying ‘–help’ and ‘–man’  documentation based on what is entered into the ‘doc’ and ‘long_doc’ option parameters respectively.

You can even do coercion on the option input just as you would with any Moo attribute. Here I could have coerced the input file into a ‘Path::Tiny’ object if I wished. However this is already taken care of in the File::Info module already.

Even though this is a script, because it uses Moo, you could also create Moo attributes. It really is a neat way to write Perl scripts with input options.


use Moo;
use MooX::Options;
use v5.16;
use FindBin qw/$Bin/;
use lib qq{$Bin/../lib};

use File::Info;

#  Options

option 'in_file' => (
    is       => 'ro',
    format   => 's',
    required => 1,
    short => q{file|i_f},
    doc      => q{The file you wish to examine.},
    long_doc => q{
    The full file path of the file that you would like to get size and age information about.},

#  Functions
sub run_like_the_wind {
    my ($self) = @_;
    say qq{\n};
    say q{Your File: } . $self->in_file;
    say q{=} x (length($self->in_file) + 11);

    my $file_info_obj = File::Info->new( file => $self->in_file );

    say qq{Not so pretty...\n}
      . $file_info_obj->file->stringify . q{ size is }
      . $file_info_obj->size_bytes
      . q{ and it's been }
      . $file_info_obj->seconds_since_mod
      . qq{ seconds since its last modification.};

    say qq{\nA little prettier...\n}
      . $file_info_obj->file->stringify . q{ size is }
      . $file_info_obj->make_file_size_pretty
      . q{ and was last modified on }
      . $file_info_obj->mod_time_moment->strftime(qq{%a %b %e at %I:%M:%S %p})  . q{ local time.};

     say q{That's } .$file_info_obj->time_since_mod_pretty  . qq{ ago!\n};

#--- Run the script

On the first run I forget to enter the ‘in_file’.

Moo > perl bin/ 
in_file is missing
USAGE: [-h] [long options...]

    --in_file: String
        The file you wish to examine.

        show a short help message

    -h --help:
        show a help message

        show the manual

[14:44 - 0.62]
Moo > 

It prints a nice error message with some instructions.  Next time I will get it right.

Moo > perl bin/ --in_file IMAG0029.jpg 

Your File: IMAG0029.jpg
Not so pretty...
IMAG0029.jpg size is 592023 and it's been 78620118 seconds since its last modification.

A little prettier...
IMAG0029.jpg size is 578.15 KB and was last modified on Sat Apr  6 at 04:02:28 PM local time.
That's 129.99 Weeks ago!

[14:57 - 0.04]
[austin@the-general-II 83] Moo > 

There is a lot more that could be added to our File::Info module. It could be subclassed and or given some more Roles to provide some extra functionality.

Here is some more useful links on this topic.

MooX::Options on CPAN

Now I Have Better Options, by Mark Fowler in the Perl Advent Calendar

App::Math::Tutor, by Jens Rehsack , has lots of Moo and Moox::Options examples.