# Copyright (C) 2008-2009, Sebastian Riedel. package Mojo::Script; use strict; use warnings; use base 'Mojo::Base'; require Carp; require Cwd; require File::Path; require File::Spec; require IO::File; use Mojo::ByteStream; use Mojo::Template; __PACKAGE__->attr( description => (chained => 1, default => 'No description.')); __PACKAGE__->attr(quiet => (chained => 1, default => 0)); __PACKAGE__->attr( renderer => (chained => 1, default => sub { Mojo::Template->new })); sub chmod_file { my ($self, $path, $mod) = @_; # chmod chmod $mod, $path or die qq/Can't chmod path "$path": $!/; $mod = sprintf '%lo', $mod; print " [chmod] $path $mod\n" unless $self->quiet; return $self; } sub chmod_rel_file { my ($self, $path, $mod) = @_; # Path $path = $self->rel_file($path); # chmod $self->chmod_file($path, $mod); } sub class_to_file { my ($self, $class) = @_; # Class to file $class =~ s/:://g; $class = Mojo::ByteStream->new($class)->decamelize->to_string; return $class; } sub class_to_path { my ($self, $class) = @_; # Class to path my $path = join '/', split /::/, $class; return "$path.pm"; } sub create_dir { my ($self, $path) = @_; # Exists if (-d $path) { print " [exist] $path\n" unless $self->quiet; return $self; } # Make File::Path::mkpath($path) or die qq/Can't make directory "$path": $!/; print " [mkdir] $path\n" unless $self->quiet; return $self; } sub create_rel_dir { my ($self, $path) = @_; # Path $path = $self->rel_dir($path); # Create $self->create_dir($path); } sub get_data { my ($self, $data, $class) = @_; $class ||= ref $self; # Cache my $sections = $self->{data}; # Slurp $sections = do { local $/; eval "package $class; "; } unless $sections; $self->{data} ||= $sections; # Split my @data = split /^__(.+)__\r?\n/m, $sections; # Remove split garbage shift @data; # Find data while (@data) { my ($name, $content) = splice @data, 0, 2; return $content if $name eq $data; } return undef; } sub rel_dir { my ($self, $path) = @_; # Parts my @parts = split /\//, $path; # Render return File::Spec->catdir(Cwd::getcwd(), @parts); } sub rel_file { my ($self, $path) = @_; # Parts my @parts = split /\//, $path; # Render return File::Spec->catfile(Cwd::getcwd(), @parts); } sub render_data { my $self = shift; my $data = shift; # Get data my $template = $self->get_data($data); # Render my $output; $self->renderer->render($template, \$output, @_); return $output; } sub render_to_file { my $self = shift; my $data = shift; my $path = shift; # Render my $content = $self->render_data($data, @_); # Write $self->write_file($path, $content); return $self; } sub render_to_rel_file { my $self = shift; my $data = shift; my $path = shift; # Path $path = $self->rel_dir($path); # Render $self->render_to_file($data, $path, @_); } # My cat's breath smells like cat food. sub run { Carp::croak('Method "run" not implemented by subclass') } sub write_file { my ($self, $path, $data) = @_; # Directory my @parts = File::Spec->splitdir($path); pop @parts; my $dir = File::Spec->catdir(@parts); $self->create_dir($dir); # Open file my $file = IO::File->new; $file->open(">$path") or die qq/Can't open file "$path": $!/; # Write unbuffered $file->syswrite($data); print " [write] $path\n" unless $self->quiet; return $self; } sub write_rel_file { my ($self, $path, $data) = @_; # Path $path = $self->rel_file($path); # Write $self->write_file($path, $data); } 1; __END__ =head1 NAME Mojo::Script - Script Base Class =head1 SYNOPSIS use base 'Mojo::Script'; sub run { my $self = shift; $self->render_to_rel_file('foo_bar', 'foo/bar.txt'); } 1; __DATA__ __foo_bar__ % for (1 .. 5) { Hello World! % } =head1 DESCRIPTION L is a base class for scripts. =head1 ATTRIBUTES =head2 C my $description = $script->description; $script = $script->description('Foo!'); =head2 C my $quiet = $script->quiet; $script = $script->quiet(1); =head1 METHODS L inherits all methods from L and implements the following new ones. =head2 C $script = $script->chmod_file('/foo/bar.txt', 0644); =head2 C $script = $script->chmod_rel_file('foo/bar.txt', 0644); =head2 C my $file = $script->class_to_file('Foo::Bar'); =head2 C my $path = $script->class_to_path('Foo::Bar'); =head2 C $script = $script->create_dir('/foo/bar/baz'); =head2 C $script = $script->create_rel_dir('foo/bar/baz'); =head2 C my $data = $script->get_data('foo_bar'); =head2 C my $path = $script->rel_dir('foo/bar'); =head2 C my $path = $script->rel_file('foo/bar.txt'); =head2 C my $data = $script->render_data('foo_bar', @arguments); =head2 C $script = $script->render_to_file('foo_bar', '/foo/bar.txt'); =head2 C $script = $script->render_to_rel_file('foo_bar', 'foo/bar.txt'); $script = $script->render_to_rel_file('foo_bar', 'foo/bar.txt'); =head2 C $script = $script->run(@ARGV); =head2 C $script = $script->write_file('/foo/bar.txt', 'Hello World!'); =head2 C $script = $script->write_rel_file('foo/bar.txt', 'Hello World!'); =cut