summaryrefslogtreecommitdiff
path: root/posts/2009-06-22-modules-i-like-getopt-long-and-moosex-getopt.org
blob: 02b090367bd4d9853a2cceac1dc7ca66e6755493 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
** Getopt::Long

[[http://search.cpan.org/perldoc?Getopt::Long][Getopt::long]] is a
useful module to parse command line arguements.

A basic usage is something like this:

#+BEGIN_SRC perl
    #!/usr/bin/perl -w
    use strict;
    use YAML::Syck;
    use Getopt::Long;

    GetOptions('config=s' => \my $cfg_file,);

    my $config = LoadFile $cfg_file
#+END_SRC

In *GetOptions*, we require a value for config with *config=s*. If we
wante an integer, we replace 's' with 'i', and for a floating point,
with 'f'.

Call your script :

#+BEGIN_EXAMPLE
    % script.pl --config=file.yml #this one works
    % script.pl --config file.yml #this one too!
    % script.pl -c file.yml       #and this one too
#+END_EXAMPLE

The three syntaxes are understood.

A good practices is to combine this module with
[[http://search.cpan.org/perldoc?Pod::Usage][Pod::Usage]]. Let's do some
modifications on the example:

#+BEGIN_SRC perl
    #!/usr/bin/perl -w
    use strict;
    use YAML::Syck;
    use Getopt::Long;
    use Pod::Usage;

    GetOptions('config=s' => \my $cfg_file,) or pod2usage(2);
    pod2usage(2) unless @ARGV > 0;

    my $config = LoadFile $cfg_file

    __END__
    =head1 NAME

    uberscript

    =head1 SYNOPSIS

    uberscript [options]

    Options:

        --config  config file

    =head1 Options

    =over 4

    =item B<config>

    Path to the config file
#+END_SRC

then

#+BEGIN_EXAMPLE
    % perl uberscript

    Usage:
        uberscript [options]

        Options:
            --config  config file
#+END_EXAMPLE

From now if we call our script without argument, the POD will be printed
on STDIN.

** MooseX::Getopt

[[http://search.cpan.org/perldoc?MooseX::Getopt][MooseX::Getopt]] is a
Role that add a =new_with_options= to your object. We create a basic
Object :

#+BEGIN_SRC perl
    package OurShinyObject;

    use Moose;
    with qw/MooseX::Getopt/;

    has 'config' => (isa => 'Str', is => 'ro', required => 1);
    has 'context' => (
        isa     => 'HashRef',
        is      => 'rw',
        lazy    => 1,
        traits  => ['NoGetopt'],
        default => sub { LoadFile shift->config }
    );

    ...
#+END_SRC

create a script to call this object

#+BEGIN_SRC perl
    #!/usr/bin/perl -w
    use strict;
    use OurShinyObject;

    my $obj = OurShinyObject->new_from_options();
#+END_SRC

#+BEGIN_SRC sh
    % script.pl --config file.yml
#+END_SRC

The role will set our attribute *context* using the value from the
argument set on the command line.

The =traits => ['NoGetopt']= indicate that this attributes will be not
be read from the command line. An alternate way to do this is to prefix
the attributes with **\_**.

** conclusion (?)

When you write a script, even if you're sure you will never need to have
more than one argument, or that you never will have to update the code,
/please/ consider to use of *Getopt::Long* instead of a =shift @ARGV=,
because we all know that you will at a certain point update this script
and you will more than one argument :).