__END__

=head1 NAME

Module::Generate - Assisting with module generation.

=head1 VERSION

Version 0.28

=cut

=head1 SYNOPSIS

	use Module::Generate;

	Module::Generate->dist('Planes')
		->author('LNATION')
		->email('email@lnation.org')
		->version('0.01')
		->class('Planes')
			->abstract('Over my head.')
			->our('$type')
			->begin(sub {
				$type = 'boeing';
			})
			->new
				->pod('Instantiate a new plane.')
				->example('my $plane = Planes->new')
			->accessor('airline')
			->sub('type')
				->code(sub { $type })
				->pod('Returns the type of plane.')
				->example('$plane->type')
			->sub('altitude')
				->code(sub {
					$_[1] / $_[2];
					...
				})
				->pod('Discover the altitude of the plane.')
				->example('$plane->altitude(100, 100)')
		->generate;

	...

	Module::Generate->dist('Holiday')
		->author('LNATION')
		->email('email@lnation.org')
		->version('0.01')
		->class('Feed::Data')
			->use('Data::LnArray')
			->our('$holiday')
			->begin(sub {
				$holiday = Data::LnArray->new;
			})
			->sub('parse')
			->sub('write')
			->sub('render')
			->sub('generate')
			->sub('_raw')
			->sub('_text')
			->sub('_json')
		->generate;

=head1 SUBROUTINES/METHODS

=head2 start

Instantiate a new Module::Generate object.

	my $mg = Module::Generate->start;	


=head2 dist

Provide a name for the distribution.

	my $dist = Module::Generate->dist('Planes');

=cut

=head2 lib

Provide a path where the generated files will be compiled.

	my $module = Module::Generate->lib('./path/to/lib');

=cut

=head2 tlib

Provide a path where the generated test will be compiled.

	my $module = Module::Generate->tlib('./path/to/t');

=cut

=head2 author

The author of the distribution/module.

	my $module = Module::Generate->author('LNATION');

=cut

=head2 email

The authors email of the distribution/module.

	my $module = Module::Generate->email('email@lnation.org');

=cut

=head2 version

The version number of the distribution/module.

	my $version = Module::Generate->version('0.01');

=cut

=head2 class

Start a new class/package/module..
	
	my $class = Module::Generate->class('Planes');

=cut

=head2 abstract

Provide abstract text for the class.

	$class->abstract('Over my head.');

=head2 synopsis

Provide a synopsis for the class.

	$class->synopsis('...');

=cut

=head2 no_strict

Disable strict by flag.

	$class->no_strict('refs');

=cut

=head2 no_warnings

Disable warnings by flag.

	$class->no_warnings('reserved');

=cut

=head2 use

Declare modules that should be included in the class.

	$class->use(qw/Moo MooX::LazierAttributes/);

=cut

=head2 base

Establish an ISA relationship with base classes at compile time. 

Unless you are using the fields pragma, consider this discouraged in favor of the lighter-weight parent.

	$class->base(qw/Foo Bar/);

=cut

=head2 parent

Establish an ISA relationship with base classes at compile time. 

	$class->parent(qw/Foo Bar/);

=cut

=head2 require

Require library files to be included if they have not already been included.

	$class->require(qw/Foo Bar/);

=cut

=head2 our

Declare variable of the same name in the current package for use within the lexical scope.

	$class->our(qw/$one $two/);

=cut

=head2 begin

Define a code block is executed as soon as possible.

	$class->begin(sub {
		...
	});

=cut

=head2 unitcheck

Define a code block that is executed just after the unit which defined them has been compiled.

	$class->unitcheck(sub {
		...
	});

=cut

=head2 check

Define a code block that is executed just after the initial Perl compile phase ends and before the run time begins.

	$class->check(sub {
		...
	});

=cut

=head2 init

Define a code block that is executed just before the Perl runtime begins execution.

	$class->init(sub {
		...
	});

=cut

=head2 end

Define a code block is executed as late as possible.

	$class->end(sub {
		...
	});

=cut

=head2 new

Define an object constructor.

	$class->new;

equivalent to:

	sub new {
		my ($cls, %args) = (shift, scalar @_ == 1 ? %{$_[0]} : @_);
		bless \%args, $cls;	
	}

optionally you can pass your own sub routine.

	$class->new(sub { ... });

=head2 accessor

Define a accessor.

	$class->accessor('test');

equivalent to:

	sub test {	
		my ($self, $value) = @_;
		if ($value) {
			$self->{$sub} = $value;
		}
		return $self->{$sub}
	}";

=head2 sub

Define a sub routine/method.
	
	my $sub = $class->sub('name');

=cut

=head2 code

Define the code that will be run for the sub.

	$sub->code(sub {
		return 'Robert';
	});

=cut

=head2 pod

Provide pod text that describes the sub.

	$sub->pod('What is my name?');

=cut

=head2 example

Provide a code example which will be suffixed to the pod definition.

	$sub->example('$foo->name');

=cut

=head2 test

Provide tests for the sub.

	$sub->test(['is', '$obj->name', q|'test'|], [ ... ], ...)

=cut

=head2 macro 

Implement a macro that can be inserted across classes.

	my $mg = Module::Generate->author('LNATION')
		->email('email@lnation.org')
		->version('0.01');
	$mg->macro('self', sub {
		my ($self, $value) = @_;
	});
	my $class = $mg->class('Foo');
	$class->sub('bar')
		->code(sub { &self; $value; });
	$mg->generate;

	###

	package Foo;
	use strict;
	use warnings;
	our $VERSION = 0.01;

	sub bar {
		my ( $self, $value ) = @_;

		$value;
	}

	1;

	__END__

=head2 keyword

Implement a keyword that can be used accross classes.


	my $mg = Module::Generate
		->author('LNATION')
		->email('email@lnation.org');
	$mg->keyword('with', sub {
		my ($meta) = @_;
		return qq|with $meta->{with};|;
	});

	$mg->keyword('has',
		CODE => sub {
			my ($meta) = @_;
			$meta->{is} ||= q|'ro'|;
			my $attributes = join ', ', map {
				($meta->{$_} ? (sprintf "%s => %s", $_, $meta->{$_}) : ())
			} qw/is required/;
			my $code = qq|
				has $meta->{has} => ( $attributes );|;
			return $code;
		},
		KEYWORDS => [qw/is required/],
		POD_TITLE => 'ATTRIBUTES',
		POD_POD => 'get or set $keyword',
		POD_EXAMPLE => "\$obj->\$keyword;\n\n\t\$obj->\$keyword(\$value);"
	);

	$mg->class('Keyword')
		->use('Moo')
		->with(qw/'Keyword::Role'/)
			->test(
				['ok', q|my $obj = Keyword->new( thing => 'abc', test => 'def' )|],
				['is', q|$obj->test|, q|'def'|]
			)
		->has('thing')->required(1)
			->test(
				['ok', q|my $obj = Keyword->new( thing => 'abc' )|],
				['is', q|$obj->thing|, q|'abc'|],
				['eval', q|$obj = Keyword->new()|, 'required']
			);

	$mg->class('Keyword::Role')
		->use('Moo::Role')
		->has('test')->is(q|'rw'|)
			->test(
				['ok', q|my $obj = do { eval q{
					package FooBar;
					use Moo;
					with 'Keyword::Role';
					1;
				}; 1; } && FooBar->new| ],
				['is', q|$obj->test|, q|undef|],
				['ok', q|$obj->test('abc')|],
				['is', q|$obj->test|, q|'abc'|]
			);

=head2 generate

Compile the code.
	
	$sub->generate();

=cut

=head1 AUTHOR

LNATION, C<< <email at lnation.org> >>

=head1 BUGS

Please report any bugs or feature requests to C<bug-module-generate at rt.cpan.org>, or through
the web interface at L<https://rt.cpan.org/NoAuth/ReportBug.html?Queue=Module-Generate>.  I will be notified, and then you'll
automatically be notified of progress on your bug as I make changes.

=head1 SUPPORT

You can find documentation for this module with the perldoc command.

    perldoc Module::Generate

You can also look for information at:

=over 4

=item * RT: CPAN's request tracker (report bugs here)

L<https://rt.cpan.org/NoAuth/Bugs.html?Dist=Module-Generate>

=item * AnnoCPAN: Annotated CPAN documentation

L<http://annocpan.org/dist/Module-Generate>

=item * CPAN Ratings

L<https://cpanratings.perl.org/d/Module-Generate>

=item * Search CPAN

L<https://metacpan.org/release/Module-Generate>

=back

=head1 ACKNOWLEDGEMENTS

=head1 LICENSE AND COPYRIGHT

This software is Copyright (c) 2020 by LNATION.

This is free software, licensed under:

  The Artistic License 2.0 (GPL Compatible)

=cut

1; # End of Module::Generate
