package Egg::Helper::Plugin::Maker;
#
# Masatoshi Mizuno E<lt>lusheE<64>cpan.orgE<gt>
#
# $Id: Maker.pm 96 2007-05-07 21:31:53Z lushe $
#

=head1 NAME

Egg::Helper::Plugin::Maker - Helper who generates plug-in module.

=head1 SYNOPSIS

The plugin module is generated in the helper script of the project.

  % perl myapp_helper.pl NewPlugin -v 1.00
  
  % ls /path/to/myapp
  ...
  .....
  drwxr-xr-x ..... Egg-Plugin-NewPlugin

An arbitrary perl module is generated.

  % perl /path/to/egg_makemaker.pl MyModules::Tools
  
  % ls
  ...
  .....
  drwxr-xr-x ..... MyModules-Tools

=head1 DESCRIPTION

It is a helper who generates the skeleton of the plugin module.

Can it not be caught in the plugin and the skeleton of an arbitrary 
Perl module be generated by obtaining the module generation script.

Generation is done when starting from the helper script by the name that 
continues the plugin name specified behind Egg::Plugin.

Moreover, the generation place is sure to become the route of the project.
In a word, '-o' option is disregarded.

Generation is done as it is when starting from the module generation script 
by the specified name.

The output destination can be specified by '-o' option and output to the
current directory when omitting it.

=cut
use strict;
use warnings;

our $VERSION = '2.00';

sub _setup_get_options {
	shift->SUPER::_setup_get_options(" v-module_version= ");
}
sub _execute {
	my($self)= @_;
	my $g= $self->global;
	return $self->_output_help if ($g->{help} or ! $g->{any_name});

	if ($g->{project_root}) {
		$g->{output_path}= $g->{project_root};
		$g->{any_name}= "Egg::Plugin::$g->{any_name}"
		                   if $g->{any_name}!~m{^Egg\:\:Plugin};
	}
	my $mod_name= $self->mod_name_resolv($g->{any_name});
	$self->_setup_module_maker( __PACKAGE__ );
	$self->_setup_module_name($mod_name);

	-e $g->{target_path} and die qq{ '$g->{target_path}' already exists. };

	my @files= YAML::Load( join '', <DATA> );
	$self->generate(
	  chdir        => [$g->{target_path}, 1],
	  create_files => \@files,
	  complete_msg => "# + module generate is completed.\n",
	  makemaker_ok => 1,
	  errors       => { rmdir=> [$g->{target_path}] },
	  ) || return 0;

	print <<END_INFO;

output PATH: $g->{target_path}

END_INFO
}
sub _output_help {
	my($self)= @_;
	my $cmdline= $self->global->{project_root} ? do {
		my $pname= lc($self->project_name);
		"perl ${pname}_helper.pl Plugin:Maker [NEW_PLUGIN_NAME] [OPTION]";
	  }: do {
		"perl egg_makemaker.pl [NEW_PLUGIN_NAME] [OPTION]";
	  };

	print <<END_HELP;

Usage: ${cmdline}

  OPTION  -v ... Version of generated module.
          -o ... At the output destination of the module complete set.
                 * Invalid when starting from the helper of project.
          -h ... help.

* Method of generating module maker script.

  % perl -MEgg::Helper::Plugin::Maker \\
      -e "Egg::Helper::Plugin::Maker-out" > /path/to/egg_makemaker.pl

END_HELP
}

=head1 METHODS

=head2 out

The module generation script is output to STDOUT.

Please do as follows and develop with the file.

  % perl -MEgg::Helper::Plugin::Maker \
       -e "Egg::Helper::Plugin::Maker-out" > /path/to/egg_makemaker.pl

* It might be convenient to grant the execution permission arbitrarily.

=cut
sub out {
	require Egg::Helper;
	my $perlpath= Egg::Helper->perl_path;
	print <<SCRIPT;
#!$perlpath
use Egg::Helper;
Egg::Helper->run('Plugin:Maker');
SCRIPT
}

=head1 MAKING GUIDE of PLUGIN

It is information that becomes the hint of making the plugin.

=head2 About the dispatching priority of the plugin

Egg operates @ISA as succeeded to to the project that does include. 
At this time, the loaded each plug-in is sequentially added to @ISA, and Egg
is added at the end.

Therefore, dispatching priority is as follows.

  1. Controller of project.
  2. Order by which plugin is loaded.
  3. Egg.

And, each method call from Egg executes the module of the @ISA registration
by L<Class::C3> going it.

For instance, if it wants to put interrupt by the scene that Egg calls 
the method of '_prepare', it is described that the method of '_prepare' is
prepared in the made plug-in, necessary processing is made, and processing is
passed to the following module.

  sub _prepare {
    my($e)= @_;
    .... ban, ba, ba, ban.
    $e->next::method;
  }

* The call ends by the module if it forgets to describe $e->next::method.

=head2 About the call of each method of Egg.

The method call is being written in the document of L<Egg>, and refer to
that, please.

=over 4

=item * _setup

It is a call for the setup when processing begins.

It moves only once at the start when operating as a perpetuity object such
as mod_perl and FastCGI.
Therefore, when it uses it for no efficiency code, checking the configuration,
and operating every time are effective.

  sub _setup {
    my($e)= @_;
    my $conf= $e->config->{plugin_orign} ||= {};
    $conf->{foo} ||= 'default';
    $e->next::method;
  }

=item * _prepare

It is the first call called after the object of the project is generated.

It might be good to write the code related to a prior preparation beforehand
when it is preferable to generate the object etc.

  sub _prepare {
    my($e)= @_;
    $e->my_accessor( MyPlugin::handler->new($e) );
    $e->next::method;
  }

=item * _dispatch_start

It is originally a call of dispatch to process the first movement.

Wanting to process it from which plugin by '_prepare' at the end are more
certain to put interrupt here.

  sub _dispatch_start
    my($e)= @_;
    ... delay code.
    $e->next::method;
  }

=item * _dispatch_action

It is originally a call to execute the action matched with dispatch.

I think processing by the behavior situation of dispatch in '_dispatch_start'
might become a done code.

  sub _dispatch_action {
    my($e)= @_;
    ... ban, bo, bo, bon.
    $e->next::method;
  }

=item * _dispatch_finish

It is originally a call to process dispatch after the fact.

It is more certain to put interrupt on here when there is processing 
that wants to do earlier than the plugin that operates by the following
'_finalize'.

  sub _dispatch_finish {
    my($e)= $e->next::method;
    ... ban, bo, bo, bon.
    $e;
  }

=item * _finalize

It is a call for the processing that wants to do before outputting contents.

  sub _finalize {
    my($e)= @_;
    ... finalize code.
    $e->next::method;
  }

=item * _finalize_output

It is originally a call to output contents.

It is more certain to put interrupt on here to process it from which 
plug-in that operates by '_finalize' at the end.

  sub _finalize_output {
    my($e)= @_;
    ... finalize code.
    $e->next::method;
  }

After contents are output when making it as follows, it will process it.

  sub _finalize_output {
    my($e)= $e->next::method;
    ... finalize code.
    $e;
  }

=item * _finalize_error

When the error occurs, it is called.

  sub _finalize_error {
    my($e)= @_;
    ... finalize code.
    $e->next::method;
  }

After the error screen is output when making it as follows, it will process it.

  sub _finalize_error {
    my($e)= $e->next::method;
    ... finalize code.
    $e;
  }

=item * _finalize_result

It is originally a call to return the result code after contents are output.

Perhaps, even whenever the error occurs, it is called.

Please put interrupt on here only when there is processing that wants to do
at the end by all means.

However, the error here is fatal because it has already come off the error trap.

=back

=head1 SEE ALSO

L<Egg::Helper>,
L<Egg::Release>,

=head1 AUTHOR

Masatoshi Mizuno E<lt>lusheE<64>cpan.orgE<gt>

=head1 COPYRIGHT

Copyright (C) 2007 by Bee Flag, Corp. E<lt>L<http://egg.bomcity.com/>E<gt>, All Rights Reserved.

This library is free software; you can redistribute it and/or modify
it under the same terms as Perl itself, either Perl version 5.8.6 or,
at your option, any later version of Perl 5 you may have available.

=cut

1;

__DATA__
---
filename: Makefile.PL
value: |
  use inc::Module::Install;
  
  name         '<$e.module_name>';
  all_from     'lib/<$e.module_filename>';
  version_from 'lib/<$e.module_filename>';
  author       '<$e.author>';
  license      '<$e.license>';
  
  requires 'Egg::Release' => 2.00;
  
  build_requires 'Test::More';
  build_requires 'Test::Pod';
  # build_requires 'Test::Perl::Critic';
  # build_requires 'Test::Pod::Coverage';
  
  use_test_base;
  auto_include;
  WriteAll;
---
filename: Build.PL
filetype: module
value: |
  use Module::Build;
  
  my $builder = Module::Build->new(
  
    module_name       => '<$e.module_distname>',
    dist_version_from => 'lib/<$e.module_filename>',
    dist_author       => '<$e.author>',
    license           => '<$e.license>',
  
    requires => {
  
      'Egg::Release'         => 2.00,
  
      'Test::More'           => 0,
      'Test::Pod'            => 0,
  #    'Test::Perl::Critic'  => 0,
  #    'Test::Pod::Coverage' => 0,
      },
  
    );
  
  $builder->create_build_script();
---
filename: lib/<$e.module_filename>
filetype: module
value: |
  package <$e.module_distname>;
  #
  # Copyright (C) <$e.year> <$e.headcopy>, All Rights Reserved.
  # <$e.author>
  #
  # <$e.revision>
  #
  use strict;
  use warnings;
  
  our $VERSION = '<$e.module_version>';
  
  # ... Let's write the perl code here.
  
  # Please refer to L<Egg::Helper::Plugin::Maker> for hook of Egg.
  
  1;
  
  __END__
  <$e.document>
---
filename: t/00_use.t
value: |
  # Before `make install' is performed this script should be runnable with
  # `make test'. After `make install' it should work as `perl test.t'
  
  #########################
  
  # change 'tests => 1' to 'tests => last_test_to_print';
  
  use Test::More tests => 1;
  BEGIN { use_ok('<$e.module_distname>') };
  
  #########################
  
  # Insert your test code below, the Test::More module is use()ed here so read
  # its man page ( perldoc Test::More ) for help writing this test script.
---
filename: t/89_pod.t
value: |
  use Test::More;
  eval "use Test::Pod 1.00";
  plan skip_all => "Test::Pod 1.00 required for testing POD" if $@;
  all_pod_files_ok();
---
filename: t/98_perlcritic.t
value: |
  use strict;
  use Test::More;
  eval q{ use Test::Perl::Critic };
  plan skip_all => "Test::Perl::Critic is not installed." if $@;
  all_critic_ok("lib");
---
filename: t/99_pod_coverage.t~
value: |
  use Test::More;
  eval "use Test::Pod::Coverage 1.00";
  plan skip_all => "Test::Pod::Coverage 1.00 required for testing POD coverage" if $@;
  all_pod_coverage_ok();
---
filename: Changes
value: |
  Revision history for Perl extension <$e.distname>.
  
  <$e.module_version>  <$e.gmtime_string>
  	- original version; created by <$e.created>
  	   with module name <$e.module_distname>
---
filename: README
value: |
  <$e.module_distname>.
  =================================================
  
  The README is used to introduce the module and provide instructions on
  how to install the module, any machine dependencies it may have (for
  example C compilers and installed libraries) and any other information
  that should be provided before the module is installed.
  
  A README file is required for CPAN modules since CPAN extracts the
  README file from a module distribution so that people browsing the
  archive can use it get an idea of the modules uses. It is usually a
  good idea to provide version information here so that people can
  decide whether fixes for the module are worth downloading.
  
  INSTALLATION
  
  To install this module type the following:
  
     perl Makefile.PL
     make
     make test
     make install
  
     or
  
     perl Build.PL
     ./Build
     ./Build test
     ./Build install
  
  AUTHOR
  
  <$e.author>
  
  COPYRIGHT AND LICENCE
  
  Put the correct copyright and licence information here.
  
  Copyright (C) <$e.year> by <$e.copyright>, All Rights Reserved.
  
  This library is free software; you can redistribute it and/or modify
  it under the same terms as Perl itself, either Perl version 5.8.6 or,
  at your option, any later version of Perl 5 you may have available.
---
filename: MANIFEST.SKIP
value: |
  \bRCS\b
  \bCVS\b
  ^inc/
  ^blib/
  ^_build/
  ^MANIFEST\.
  ^Makefile$
  ^pm_to_blib
  ^MakeMaker-\d
  ^t/9\d+_.*\.t
  Build$
  \.cvsignore
  \.?svn*
  ^\%
  (~|\-|\.(old|save|back|gz))$
