The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
=pod

=head1 NAME

MooseX::App::Tutorial - getting started with MooseX::App

=head1 GETTING STARTED

To create a simple command-line application with MooseX::App you need

=over

=item * A base class

=item * Multiple command classes (unless you use L<MooseX::App::Simple>)

=item * and an invocation script

=back

=head1 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.

  package MyApp;
  use MooseX::App;
  1;

The base class can be customized by

=over

=item * adding MooseX-App plugins

=item * Changing the command-class namespace

=item * and defining global attributes used by all command classes

=item * setting MooseX-App flags/options

=back

  package MyApp;
  use MooseX::App qw(Config); # Loads the Config plugin
  
  # This attribute will be available at the command-line
  option 'some_global_option' => (
      is                => 'rw',
      isa               => 'Str',
      documentation     => q[Some important global option],
  );
  
  # This attribute  will not be exposed
  has 'private_option' => (
      is              => 'rw',
      isa             => 'Str',
  ); 
  
  1;

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.

=head1 COMMAND CLASSES

After you have created a base class it is time to create one class for each 
command you want to provide (unless you are using L<MooseX::App::Simple>). 
The command classes must reside in the namespace of the base class 
(eg. 'MyApp::SomeCommand'). The namespace for the command classes however can 
be changed via the 'app_namespace' function in the base class.

All command classes must load MooseX::App::Command.

  package MyApp::SomeCommand;
  use MooseX::App::Command;

If you want to use global options defined in the base class you can optionally
extend the base class with your command class.

  package MyApp::SomeCommand;
  use MooseX::App::Command;
  extends qw(MyApp);

To provide a description for each command you need to add 
C<command_short_description> and C<command_long_description>
information. The command descriptions may contain linebreaks.

 command_short_description q[This command is awesome];
 command_long_description q[This command is awesome, yadda yadda yadda];

If not provided, MooseX-App will try to parse the command description from 
the POD. The NAME section will become the short description and the 
DESCRIPTION or OVERVIEW section the long description. If your class has no
POD, MooseX-App will look for the DistZilla abstract tag.

The usage header can either be set by adding C<command_usage>

 command_usage q[script some_command --some_option NUMBER];

or by adding a SYNOPSIS or USAGE section to the module' POD. If neither
command_usage nor SYNOPSIS/USAGE are set, then the usage header will
be autogenerated.

Attributes can be documented using the Moose built-in C<documentation> option
as well as C<cmd_tags> which is defined by MooseX-App. Additionally the
C<cmd_flag> and C<cmd_aliases> attributes defined in 
L<MooseX::Getopt::Meta::Attribute::Trait> are also honoured.

  option 'some_option' => (
      is                => 'rw',
      isa               => 'Integer',
      required          => 1,
      documentation     => q[Some important option],
      cmd_tags          => [qw(Important!)],
      cmd_aliases       => [qw(so)], # From MooseX::Getopt
  );

The help for this command would look something like this (with autogenerated
usage header):

  usage:
    my_app some_command [long options...]
    my_app help
    my_app some_command --help
  
  description:
    This command is awesome, yadda yadda yadda
  
  options:
    --config           Path to command config file
    --some_option --so Some important option [Required; Integer; Important!]
    --help --usage -?  Prints this usage information. [Flag]

In case you want to include an attribute not defined with the 'option' 
keyword you can use the 'AppOption' trait 
(L<MooseX::App::Meta::Attribute::Option>).

  has 'myoption' => (
      is                => 'rw',
      traits            => ['AppOption'],
  );

Finally your command classes will need a method which should be called
if the command is invoked by the user.

 sub run {
    my ($self) = @_;
    # do something
 }

If you need to implement only a single command you should use
L<MooseX::App::Simple> instead of L<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:

  package MyApp;
  use MooseX::App::Simple qw(Config); # Loads the Config plugin
  
  option 'some_global_option' => (
      is                => 'rw',
      isa               => 'Str',
      documentation     => q[Some important global option],
  );
  
  sub run {
     my ($self) = @_;
     # do something
  }
  
  1;

=head1 INVOCATION SCRIPT

Once you have the base and command classes ready, you need to write a small
invocation script:
 
 #!/usr/bin/env perl
 use MyApp;
 MyApp->new_with_command->run();

C<MyApp-E<gt>new_with_command> will try to instantiate a command class. If it
fails it will return a L<MooseX::App::Message::Envelope> object possibly
containing an error message and a user help message. Since 
L<MooseX::App::Message::Envelope> follows the null object pattern you can 
call any method on it without checking the object type.

If using L<MooseX::App::Simple> your invocation script needs some 
modification.

 #!/usr/bin/env perl
 use MyApp;
 MyApp->new_with_options->run();