#!/usr/bin/env perl use strict; use warnings; use Pod::Usage; use Getopt::Long; use Path::Class qw/file dir/; use Template; use YAML; my @render_options = qw/json db email cache/ GetOptions( \my %opt, qw/help new/, @render_options, ); pod2usage(0) if $opt{help}; require Catalyst; require Catalyst::Utils; # dependency check require Catalyst::Helper::Lighty; require Catalyst::Helper::Schema::Dumper; require Catalyst::View::TT; require Catalyst::View::JSON; require JSON::XS; pod2usage(2) unless @ARGV >= 1; my $module = shift @ARGV; # from pmsetup # $module = "Foo::Bar" # $dist = "Foo-Bar" # $path = "Foo/Bar.pm" my @pkg = split /::/, $module; my $dist = join "-", @pkg; my $path = join( "/", @pkg ) . ".pm"; my $appprefix = Catalyst::Utils::appprefix($module); my %templates; my %chunks = grep { $_ } split /(?:^\s*)?=== (\w+) ===/sm, do { local $/; }; while (my ($key, $chunk) = each %chunks) { for my $text (grep /\S+/, split /^---/m, $chunk) { my $obj; eval { $obj = YAML::Load( $text ); }; if ($@) { warn $@; next; } if ($obj->{file}) { $obj->{file} = eval "qq{$obj->{file}}" or die $@; } push @{ $templates{$key} }, $obj; } } sub render { my $name = shift; my $templates = $templates{$name}; my $base_dir = dir( $dist ); my $tt = Template->new; my $vars = { module => $module, pkg => \@pkg, dist => $dist, path => $path, appprefix => $appprefix, }; for my $t (@$templates) { my $file; if ($t->{file}) { $file = $base_dir->file( $t->{file} ); } elsif ($t->{component}) { (my $p = $path) =~ s/\.pm$//; $file = $base_dir->file( 'lib', $p, $t->{component} ); } next unless $file; $tt->process( \$t->{template}, $vars, \my $content ); my $op = '>'; if ( ($t->{type} || '') eq 'append' ) { $op = '>>'; } print $op eq '>>' ? "Updating $file\n" : "Creating $file\n"; if (!-d $file->parent) { $file->parent->mkpath or die $!; } open my $out, $op, $file or die "$file: $!"; print $out $content; close $out; } } if ( $opt{new} ) { !system "catalyst.pl $module" or die $?; !system "rm -rf $dist/root/*" or die $?; !system "mkdir $dist/tmp" or die $?; !system "mkdir $dist/templates" or die $?; render('core'); !system "./$dist/script/$appprefix\_create.pl Lighty" or die $?; !system "./$dist/script/$appprefix\_create.pl view TT TT" or die $?; } elsif ( !-d $dist ) { warn qq{No such directory "$dist". Please run "catsterter.pl $dist -new" first.\n}; exit; } for my $option (@render_options) { if ($option eq 'json') { !system "./$dist/script/$appprefix\_create.pl view JSON JSON" or die $?; } if ($option eq 'db') { !system "./$dist/script/$appprefix\_create.pl model DBIC DBIC::Schema $module\::Schema" or die $?; !system "./$dist/script/$appprefix\_create.pl Schema::Dumper" or die $?; !system "mkdir ./$dist/schema" or die $?; } render($option); } __DATA__ === core === --- file: 'lib/$path' template: | package [% module %]; use strict; use warnings; use Catalyst::Runtime '5.70'; use Catalyst qw/ConfigLoader/; our $VERSION = '0.01'; __PACKAGE__->setup; 1; --- file: '$appprefix.yml' template: | --- name: [% module %] default_view: TT View::TT: INCLUDE_PATH: __path_to(templates)__ # WRAPPER: common/wrapper.tt --- component: Controller/Root.pm template: | package [% module %]::Controller::Root; use strict; use warnings; use base 'Catalyst::Controller'; __PACKAGE__->config->{namespace} = ''; sub default :Private { my ($self, $c) = @_; $c->res->status(404); $c->stash->{template} = 'errors/404.tt'; } sub index :Private { my ($self, $c) = @_; } sub end :ActionClass('RenderView') { my ($self, $c) = @_; $c->res->header( 'Cache-Control' => 'private' ); } 1; === json === --- file: '$appprefix.yml' type: append template: |+2 View::JSON: expose_stash: 'json' json_driver: XS no_x_json_header: 1 --- component: Controller/API.pm template: | package [% module %]::Controller::API; use strict; use warnings; use base 'Catalyst::Controller'; sub end :Private { my ($self, $c) = @_; my $json = $c->stash->{json} ||= {}; $json->{id} = $c->req->param('id'); $json->{result} ||= '' unless defined $json->{result}; $json->{error} ||= '' unless defined $json->{error}; $c->stash->{fillform} = 0; $c->forward( $c->view('JSON') ); } 1; === db === --- file: '$appprefix.yml' type: append template: |+2 Model::DBIC: connect_info: - dbi:mysql:[% appprefix %] - root - on_connect_do: - SET NAMES utf8 === email === --- file: '$appprefix.yml' type: append template: |+2 email: TmplOptions: INCLUDE_PATH: __path_to(templates)__ # ForceUTF8: 1 mailroute: via: sendmail command: /usr/sbin/sendmail From: noreply@example.com === cache === --- file: '$appprefix.yml' type: append template: |+2 cache: backend: store: FastMmap share_file: __path_to(tmp/cache)__