App-Skeletor
view release on metacpan or search on metacpan
lib/App/Skeletor.pm view on Meta::CPAN
(map { $_->{name} => $opt->${\$_->{name}} } @{$usage->{options}}),
name => template_as_name($opt->as),
namespace => $opt->as,
project_fullpath => do {my $path = path(split('::', $opt->as)); "$path" },
name_lowercase => lc(template_as_name($opt->as)),
name_lc => lc(template_as_name($opt->as)),
name_lowercase_underscore => do {
my $val = lc(template_as_name($opt->as));
$val=~s/-/_/g; $val;
},
name_lc_underscore => do {
my $val = lc(template_as_name($opt->as));
$val=~s/-/_/g; $val;
},
);
my $tt = Template::Tiny->new(TRIM => 1);
$path_to_share->visit(sub {
my ($path, $stuff) = @_;
return if $path=~m/\.DS_Store/g;
my $expanded_path = $path;
my $target_path = path($opt->directory, $expanded_path->relative($path_to_share));
my (@vars) = ($target_path=~m/__(?:(?![__]_).)+__/g);
foreach my $var(@vars) {
my ($key) = ($var=~m/^__(\w+)__$/);
my $subst = $template_var_names{$key} || die "$key not a defined variable";
$target_path=~s/${var}/$subst/g;
}
$target_path = path($target_path);
if(-e $target_path && !$opt->overwrite) {
print "$target_path exists, skipping (set --overwrite to rebuild)\n";
return;
}
if($expanded_path->is_file) {
$expanded_path->parent->mkpath;
if("$path"=~/\.ttt$/) {
my $data = $expanded_path->slurp;
$tt->process(\$data, \%template_var_names, \my $out);
my ($new_target_path) = ("$target_path" =~m/^(.+)\.ttt$/);
path($new_target_path)->touchpath;
my $fh = path($new_target_path)->openw;
print $fh $out;
close($fh);
path($new_target_path)->chmod($expanded_path->stat->mode);
} else {
$expanded_path->copy($target_path);
}
} elsif($path->is_dir) {
$target_path->mkpath;
} else {
print "Don't know want $path is!";
}
}, {recurse=>1});
}
caller(1) ? 1 : run(@ARGV);
=head1 NAME
App::Skeletor - Bootstrap a new project from a shared template
=head1 SYNOPSIS
From the commandline:
skeletor --template Skeltor::Template::Example \
--as Local::MyApp \
--directory ~/new_projects \
--author 'John Napiorkowski <jjnapiork@cpan.org>' \
--year 2015
Bootstrap from URL hosted version:
curl -L bit.ly/app-skeletor | perl - \
--template Skeletor::Template::Example \
--as Local::MyApp \
--author 'test author'
(Assumes you have `curl` installed, as it is on many modern unix-like systems).
=head1 DESCRIPTION
When initially setting up a project (like a website build using L<Catalyst> or
an application that uses L<DBIx::Class>) there is often a number of boilerplate
files and directories you need to create before beginning the true work of
application building. Additionally, during general development certain types
of repeated tasks may occur which would benefit from automation, such as adding
new controllers to L<Catalyst> or new tables in L<DBIx::Class>. For these types
of activities you may find having a code generator speeds up some of the grunt
work and promotes uniformity of design. L<App::Skeltor> is such a code generator.
The core design is simple. You install L<App::Skeltor> and any of the code
patterns on CPAN that you wish to derive projects from (typically using the
L<Skeltor::Template::*> namespace, but you can use any namespace, and project
patterns can be attached to any arbitirary CPAN module). You then can use the
'skeletor' commandline application to generate code into a target directory,
using expansion variables to customize how the directories and files are created.
For example if you wish to build a new project called C<Local::MyApp> which is
based off the L<Skeletor::Template::Example> project, you'd install that distribution
(via L<cpanminus> or whichever tool you prefer) and then type something like the
following:
skeletor --template Skeltor::Template::Example \
--as Local::MyApp \
--directory ~/new_projects \
--author 'John Napiorkowski <jjnapiork@cpan.org>' \
--year 2015
This would create a new project which consists of directories and files that have been
generated and customized based on the commandline options given.
Alternatively you may use the URL hosted version of L<App::Skeletor> which will always
track the most current release. This allows you to use the tool without installing it
first, making it useful for bootstrapping new development environments:
( run in 2.464 seconds using v1.01-cache-2.11-cpan-5735350b133 )