1MooseX::App::Tutorial(3U)ser Contributed Perl DocumentatiMoonoseX::App::Tutorial(3)
2
3
4
6 MooseX::App::Tutorial - getting started with MooseX::App
7
9 To create a simple command-line application with MooseX::App you need
10
11 • A base class
12
13 • Multiple command classes (unless you use MooseX::App::Simple)
14
15 • and an invocation script
16
18 The simplest possible base class just contains a single use statement
19 which loads all roles and metaclasses you need to get started as well
20 as Moose and hence strictures as well as warnings.
21
22 package MyApp;
23 use MooseX::App;
24 1;
25
26 The base class can be customized by
27
28 • adding MooseX-App plugins
29
30 • changing the command-class namespace
31
32 • defining global options/parameters used by all command classes
33 (only if command classes inherit from the base class)
34
35 • add documentation (either POD or via the app_usage and
36 app_description functions)
37
38 • and changing MooseX-App flags (eg. turn fuzzy matching off)
39
40 • Adding Moose attribute documentation and type constraints.
41
42 It is also possible to add global options and parameters to your base
43 class and inherit your command classes from the base class (inheriting
44 your command classes from your base class is purely optional).
45
46 package MyApp;
47 use MooseX::App qw(Config Color); # Loads the Config and Color plugin
48
49 # This attribute will be available at the command line
50 option 'some_global_option' => (
51 is => 'rw',
52 isa => 'Str',
53 required => 1,
54 documentation => q[Some important global option],
55 );
56
57 # This attribute will not be exposed
58 has 'private_option' => (
59 is => 'rw',
60 isa => 'Str',
61 );
62
63 1;
64
65 When adding attributes make sure to include a documentation and
66 possibly a type constraint. MooseX-App will use this information to
67 build a user documentation for each attribute and command. The
68 attribute documentation can be customized by providing additional
69 options (see MooseX::App::Meta::Role::Attribute::Option)
70
72 After you created a base class it is time to create one class for each
73 command you want to provide (unless you are using MooseX::App::Simple).
74 The command classes must reside in the namespace of the base class (eg.
75 'MyApp::SomeCommand'). You can also deeply nest classes in the main
76 namespace to create subcommand. The namespace for the command classes
77 however can be changed via the 'app_namespace' function in the base
78 class, or by simply registering command classes manually via
79 'app_command_register'. Use 'app_exclude' to exclude certain sub
80 namespaces.
81
82 All command classes must use MooseX::App::Command, which will also load
83 Moose.
84
85 package MyApp::SomeCommand;
86 use MooseX::App::Command;
87
88 If you want to use global options defined in the base class you can
89 optionally extend the base class with your command class.
90
91 package MyApp::SomeCommand;
92 use MooseX::App::Command;
93 extends qw(MyApp);
94
95 To provide a description for each command you need to set the
96 "command_short_description", "command_long_description" and optionally
97 "command_usage" information. The command descriptions may contain
98 linebreaks.
99
100 command_short_description q[This command is awesome];
101 command_long_description q[This command is so awesome, yadda yadda yadda];
102
103 If not provided, MooseX-App will try to parse the command description
104 from the POD. The NAME or ABSTRACT section will become the short
105 description and the DESCRIPTION or OVERVIEW section the long
106 description.
107
108 The usage header can either be set by adding "command_usage"
109
110 command_usage q[script some_command --some_option NUMBER];
111
112 or by adding a SYNOPSIS or USAGE section to the module' POD. If neither
113 command_usage nor SYNOPSIS/USAGE are set, then the usage header will be
114 autogenerated.
115
116 Attributes can be documented using the Moose built-in "documentation"
117 option as well as "cmd_tags", "cmd_flag" and "cmd_aliases" which are
118 defined by MooseX-App (see MooseX::App::Meta::Role::Attribute::Option)
119
120 option 'some_option' => (
121 is => 'rw',
122 isa => 'Integer',
123 required => 1,
124 documentation => q[Some important option],
125 cmd_tags => [qw(Important!)], # Extra tags. Displayed in square brackets
126 cmd_aliases => [qw(any)], # Alternative option name
127 cmd_flag => 'some', # Option should be called 'some' instead of 'some_option'
128 );
129
130 It is also possible to define positional parameters with the
131 'parameter' keyword
132
133 # This attribute will become a positional parameter
134 parameter 'id' => (
135 is => 'rw',
136 isa => 'Int',
137 documentation => q[Some ID],
138 required => 1,
139 );
140
141 The help for this command would look something like this (with
142 autogenerated usage headers):
143
144 usage:
145 my_app some_command <ID> [long options...]
146 my_app help
147 my_app some_command --help
148
149 description:
150 This command is awesome, yadda yadda yadda
151
152 parameter:
153 ID Some ID [Integer; Required]
154
155 options:
156 --config Path to command config file
157 --some -s Some important option [Required; Integer; Important!]
158 --help --usage -? Prints this usage information. [Flag]
159
160 In case you want to include an attribute not defined with the 'option'
161 or 'parameter' keyword (eg from a Role) you can use the 'AppOption'
162 trait and 'cmd_type' attribute. (see
163 MooseX::App::Meta::Attribute::Option).
164
165 has 'myoption' => (
166 is => 'rw',
167 traits => ['AppOption'], # only required if not definded in base or command class
168 cmd_type => 'option', # or 'parameter'
169 );
170
171 Finally your command classes will need a method which should be called
172 if the command is invoked by the user.
173
174 sub run {
175 my ($self) = @_;
176 # do something
177 }
178
179 If you need to implement only a single command you should use
180 MooseX::App::Simple instead of MooseX::App, and omit command classes.
181 In this case of course you have to declare all options and implement
182 the application logic in the base class:
183
184 package MyApp;
185 use MooseX::App::Simple qw(Config); # Loads the Config plugin
186
187 option 'some_option' => (
188 is => 'rw',
189 isa => 'Str',
190 documentation => q[Some important option],
191 );
192
193 sub run {
194 my ($self) = @_;
195 # do something
196 }
197
198 1;
199
201 Once you have the base and command classes ready, you need to write a
202 small invocation script:
203
204 #!/usr/bin/env perl
205 use MyApp;
206 MyApp->new_with_command->run();
207
208 "MyApp->new_with_command" will try to instantiate a command class. If
209 it fails it will return a MooseX::App::Message::Envelope object
210 possibly containing an error message and a usage message. Since
211 MooseX::App::Message::Envelope follows the Null object pattern you can
212 call any method on it without checking the object type. Note that
213 MooseX::App::Message::Envelope objects may also have an exitcode set.
214 In this case whenever the object gets stringified, it prints on
215 STDERR/STDOUT and exits the program using the specified exitcode. Don't
216 use the ovleroaded stingification if you don't want this behaviour.
217
218 You can also pass default/fallback values to the constructor
219
220 #!/usr/bin/env perl
221 use MyApp;
222 MyApp->new_with_command( some_global_option => 'something' )->run();
223
224 If using MooseX::App::Simple your invocation script needs some
225 modification and call "new_with_options" instead of "new_with_command".
226
227 #!/usr/bin/env perl
228 use MyApp;
229 MyApp->new_with_options->run();
230
232 Once you have a basic working application you can make it more user
233 friendly by adding documentation (either by using the app_description,
234 app_usage, command_short_description, ... functions or by writing POD),
235 Moose type constraints and additional plugins (eg. colorise the
236 output).
237
238 Make sure to invoke your script with APP_DEVELOPER=1 during
239 development. This will come with a starup penalty but perform
240 additional checks for detecting wrong attribute/type constraint
241 combinations, name clashes, ...
242
243 If you want custom behaviour you could start writing your own
244 MooseX::App::WritingPlugins.
245
246
247
248perl v5.36.0 2023-01-20 MooseX::App::Tutorial(3)