.\" Automatically generated by Pod::Man 4.09 (Pod::Simple 3.35) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .if !\nF .nr F 0 .if \nF>0 \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} .\} .\" ======================================================================== .\" .IX Title "MooseX::App::Tutorial 3pm" .TH MooseX::App::Tutorial 3pm "2017-10-02" "perl v5.26.0" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" MooseX::App::Tutorial \- getting started with MooseX::App .SH "GETTING STARTED" .IX Header "GETTING STARTED" To create a simple command-line application with MooseX::App you need .IP "\(bu" 4 A base class .IP "\(bu" 4 Multiple command classes (unless you use MooseX::App::Simple) .IP "\(bu" 4 and an invocation script .SH "BASE CLASS" .IX Header "BASE CLASS" The simplest possible base class just contains a single use statement which loads all roles and metaclasses you need to get started as well as Moose. .PP .Vb 3 \& package MyApp; \& use MooseX::App; \& 1; .Ve .PP The base class can be customized by .IP "\(bu" 4 adding MooseX-App plugins .IP "\(bu" 4 changing the command-class namespace .IP "\(bu" 4 defining global options/parameters used by all command classes (only if command classes inherit from the base class) .IP "\(bu" 4 add documentation (either \s-1POD\s0 or via the app_usage and app_description functions) .IP "\(bu" 4 and changing MooseX-App flags (eg. turn fuzzy matching off) .IP "\(bu" 4 Adding Moose attribute documentation and type constraints. .PP It is also possible to add global options and parameters to your base class and inherit your command classes from the base class (inheriting your command classes from your base class is purely optional). .PP .Vb 2 \& package MyApp; \& use MooseX::App qw(Config Color); # Loads the Config and Color plugin \& \& # This attribute will be available at the command line \& option \*(Aqsome_global_option\*(Aq => ( \& is => \*(Aqrw\*(Aq, \& isa => \*(AqStr\*(Aq, \& required => 1, \& documentation => q[Some important global option], \& ); \& \& # This attribute will not be exposed \& has \*(Aqprivate_option\*(Aq => ( \& is => \*(Aqrw\*(Aq, \& isa => \*(AqStr\*(Aq, \& ); \& \& 1; .Ve .PP When adding attributes make sure to include a documentation and possibly a type constraint. MooseX-App will use this information to build a user documentation for each attribute and command. The attribute documentation can be customized by providing additional options (see MooseX::App::Meta::Role::Attribute::Option) .SH "COMMAND CLASSES" .IX Header "COMMAND CLASSES" After you created a base class it is time to create one class for each command you want to provide (unless you are using MooseX::App::Simple). The command classes must reside in the namespace of the base class (eg. 'MyApp::SomeCommand'). You can also deeply nest classes in the main namespace to create subcommand. The namespace for the command classes however can be changed via the \&'app_namespace' function in the base class, or by simply registering command classes manually via 'app_command_register'. Use 'app_exclude' to exclude certain sub namespaces. .PP All command classes must use MooseX::App::Command, which will also load Moose. .PP .Vb 2 \& package MyApp::SomeCommand; \& use MooseX::App::Command; .Ve .PP If you want to use global options defined in the base class you can optionally extend the base class with your command class. .PP .Vb 3 \& package MyApp::SomeCommand; \& use MooseX::App::Command; \& extends qw(MyApp); .Ve .PP To provide a description for each command you need to set the \&\f(CW\*(C`command_short_description\*(C'\fR, \f(CW\*(C`command_long_description\*(C'\fR and optionally \f(CW\*(C`command_usage\*(C'\fR information. The command descriptions may contain linebreaks. .PP .Vb 2 \& command_short_description q[This command is awesome]; \& command_long_description q[This command is so awesome, yadda yadda yadda]; .Ve .PP If not provided, MooseX-App will try to parse the command description from the \s-1POD.\s0 The \s-1NAME\s0 or \s-1ABSTRACT\s0 section will become the short description and the \s-1DESCRIPTION\s0 or \s-1OVERVIEW\s0 section the long description. .PP The usage header can either be set by adding \f(CW\*(C`command_usage\*(C'\fR .PP .Vb 1 \& command_usage q[script some_command \-\-some_option NUMBER]; .Ve .PP or by adding a \s-1SYNOPSIS\s0 or \s-1USAGE\s0 section to the module' \s-1POD.\s0 If neither command_usage nor \s-1SYNOPSIS/USAGE\s0 are set, then the usage header will be autogenerated. .PP Attributes can be documented using the Moose built-in \f(CW\*(C`documentation\*(C'\fR option as well as \f(CW\*(C`cmd_tags\*(C'\fR, \f(CW\*(C`cmd_flag\*(C'\fR and \f(CW\*(C`cmd_aliases\*(C'\fR which are defined by MooseX-App (see MooseX::App::Meta::Role::Attribute::Option) .PP .Vb 9 \& option \*(Aqsome_option\*(Aq => ( \& is => \*(Aqrw\*(Aq, \& isa => \*(AqInteger\*(Aq, \& required => 1, \& documentation => q[Some important option], \& cmd_tags => [qw(Important!)], # Extra tags. Displayed in square brackets \& cmd_aliases => [qw(s)], # Alternative option name \& cmd_flag => \*(Aqsome\*(Aq, # Option should be called \*(Aqsome\*(Aq instead of \*(Aqsome_option\*(Aq \& ); .Ve .PP It is also possible to define positional parameters with the 'parameter' keyword .PP .Vb 7 \& # This attribute will become a positional parameter \& parameter \*(Aqid\*(Aq => ( \& is => \*(Aqrw\*(Aq, \& isa => \*(AqInt\*(Aq, \& documentation => q[Some ID], \& required => 1, \& ); .Ve .PP The help for this command would look something like this (with autogenerated usage headers): .PP .Vb 4 \& usage: \& my_app some_command [long options...] \& my_app help \& my_app some_command \-\-help \& \& description: \& This command is awesome, yadda yadda yadda \& \& parameter: \& ID Some ID [Integer; Required] \& \& options: \& \-\-config Path to command config file \& \-\-some \-s Some important option [Required; Integer; Important!] \& \-\-help \-\-usage \-? Prints this usage information. [Flag] .Ve .PP In case you want to include an attribute not defined with the 'option' or \&'parameter' keyword you can use the 'AppOption' trait and 'cmd_type' attribute. (see MooseX::App::Meta::Attribute::Option). .PP .Vb 5 \& has \*(Aqmyoption\*(Aq => ( \& is => \*(Aqrw\*(Aq, \& traits => [\*(AqAppOption\*(Aq], # only required if not definded in base or command class \& cmd_type => \*(Aqoption\*(Aq, # or \*(Aqparameter\*(Aq \& ); .Ve .PP Finally your command classes will need a method which should be called if the command is invoked by the user. .PP .Vb 4 \& sub run { \& my ($self) = @_; \& # do something \& } .Ve .PP If you need to implement only a single command you should use MooseX::App::Simple instead of MooseX::App, and omit command classes. In this case of course you have to declare all options and implement the application logic in the base class: .PP .Vb 2 \& package MyApp; \& use MooseX::App::Simple qw(Config); # Loads the Config plugin \& \& option \*(Aqsome_global_option\*(Aq => ( \& is => \*(Aqrw\*(Aq, \& isa => \*(AqStr\*(Aq, \& documentation => q[Some important global option], \& ); \& \& sub run { \& my ($self) = @_; \& # do something \& } \& \& 1; .Ve .SH "INVOCATION SCRIPT" .IX Header "INVOCATION SCRIPT" Once you have the base and command classes ready, you need to write a small invocation script: .PP .Vb 3 \& #!/usr/bin/env perl \& use MyApp; \& MyApp\->new_with_command\->run(); .Ve .PP \&\f(CW\*(C`MyApp\->new_with_command\*(C'\fR will try to instantiate a command class. If it fails it will return a MooseX::App::Message::Envelope object possibly containing an error message and a usage message. Since MooseX::App::Message::Envelope follows the Null object pattern you can call any method on it without checking the object type. Note that MooseX::App::Message::Envelope objects may also have an exitcode set. In this case whenever the object gets stringified, it prints on \s-1STDERR/STDOUT\s0 and exits the program using the specified exitcode. Don't use the ovleroaded stingification if you don't want this behaviour. .PP You can also pass default/fallback values to the constructor .PP .Vb 3 \& #!/usr/bin/env perl \& use MyApp; \& MyApp\->new_with_command( some_global_option => \*(Aqsomething\*(Aq )\->run(); .Ve .PP If using MooseX::App::Simple your invocation script needs some modification and call \f(CW\*(C`new_with_options\*(C'\fR instead of \f(CW\*(C`new_with_command\*(C'\fR. .PP .Vb 3 \& #!/usr/bin/env perl \& use MyApp; \& MyApp\->new_with_options\->run(); .Ve .SH "HOW TO CONTINUE" .IX Header "HOW TO CONTINUE" Once you have a basic working application you can make it more user friendly by adding documentation (either by using the app_description, app_usage, command_short_description, ... functions or by writing \s-1POD\s0), Moose type constraints and additional plugins (eg. colorise the output). .PP Make sure to invoke your script with APP_DEVELOPER=1 during development. This will perform additional checks for detecting wrong attribute/type constraint combinations, name clashes, ... .PP If you want custom behaviour you could start writing your own MooseX::App::WritingPlugins. .PP Make sure to run your application in the APP_DEVELOPER=1 environment. In this mode additional sanity checks will be performed upon startup.