Derived cows!
This commit is contained in:
parent
38fed456fa
commit
2069267e70
36
cows/DragonAndCow.pm
Normal file
36
cows/DragonAndCow.pm
Normal file
@ -0,0 +1,36 @@
|
||||
package Acme::Cow::DragonAndCow;
|
||||
use strict;
|
||||
use Acme::Cow;
|
||||
@Acme::Cow::DragonAndCow::ISA = qw(Acme::Cow);
|
||||
my $dragon_and_cow = <<'EOC';
|
||||
{$balloon}
|
||||
{$tl} ^ /^
|
||||
{$tl} / \ // \
|
||||
{$tl} |\___/| / \// .\
|
||||
{$tl} /O O \__ / // | \ \ *----*
|
||||
/ / \/_/ // | \ \ \ |
|
||||
@___@` \/_ // | \ \ \/\ \
|
||||
0/0/| \/_ // | \ \ \ \
|
||||
0/0/0/0/| \/// | \ \ | |
|
||||
0/0/0/0/0/_|_ / ( // | \ _\ | /
|
||||
0/0/0/0/0/0/`/,_ _ _/ ) ; -. | _ _\.-~ / /
|
||||
,-\} _ *-.|.-~-. .~ ~
|
||||
\ \__/ `/\ / ~-. _ .-~ /
|
||||
\____({$el}{$er}) *. \} \{ /
|
||||
( (--) .----~-.\ \-` .~
|
||||
//__\\ \__ Ack! ///.----..< \ _ -~
|
||||
// \\ ///-._ _ _ _ _ _ _\{^ - - - - ~
|
||||
EOC
|
||||
sub new
|
||||
{
|
||||
my $proto = shift;
|
||||
my $class = ref $proto || $proto;
|
||||
my $self = $class->SUPER::new();
|
||||
return bless $self, $class;
|
||||
}
|
||||
|
||||
sub as_string
|
||||
{
|
||||
my $self = shift;
|
||||
return $self->SUPER::as_string($dragon_and_cow);
|
||||
}
|
149
cows/Example.pm
Normal file
149
cows/Example.pm
Normal file
@ -0,0 +1,149 @@
|
||||
package Acme::Cow::Example;
|
||||
|
||||
use strict;
|
||||
|
||||
use Acme::Cow;
|
||||
|
||||
@Acme::Cow::Example::ISA = qw(Acme::Cow);
|
||||
|
||||
my $generic_ascii_art = <<'EOC';
|
||||
{$balloon}
|
||||
{$tr}
|
||||
{$el}{$er} {$tr}
|
||||
___________________
|
||||
/ Insert cute ASCII \
|
||||
\ artwork here. /
|
||||
-------------------
|
||||
{$U}
|
||||
EOC
|
||||
|
||||
sub new
|
||||
{
|
||||
my $proto = shift;
|
||||
my $class = ref $proto || $proto;
|
||||
my $self = $class->SUPER::new();
|
||||
$self->over(24);
|
||||
return $self;
|
||||
}
|
||||
|
||||
sub as_string
|
||||
{
|
||||
my $self = shift;
|
||||
return $self->SUPER::as_string($generic_ascii_art);
|
||||
}
|
||||
|
||||
1;
|
||||
__END__
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Acme::Cow::Example - How to write a "derived cow"
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
package Acme::Cow::MyCow;
|
||||
use Acme::Cow;
|
||||
@Acme::Cow::MyCow::ISA = qw(Acme::Cow);
|
||||
|
||||
my $my_cow = <<'EOC';
|
||||
... template goes here ...
|
||||
EOC
|
||||
|
||||
sub new { ... }
|
||||
|
||||
sub as_string { ... }
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
First, put together your template as described in L<Acme::Cow>,
|
||||
using L<Text::Template> as a reference. It is recommended that
|
||||
you store this template in a variable in your package's namespace.
|
||||
B<Your template should not have tab characters in it.> This will
|
||||
cause ugly things to happen.
|
||||
|
||||
Your C<new> method will likely want to look a lot like this:
|
||||
|
||||
sub new
|
||||
{
|
||||
my $proto = shift;
|
||||
my $class = ref $proto || $proto;
|
||||
my $self = $class->SUPER::new();
|
||||
return $self;
|
||||
}
|
||||
|
||||
Assuming you stored the template as C<$my_cow> then
|
||||
your C<as_string> method will likely want to be like this:
|
||||
|
||||
sub as_string
|
||||
{
|
||||
my $self = shift;
|
||||
return $self->SUPER::as_string($my_cow);
|
||||
}
|
||||
|
||||
Below, we present the actual code in this module, so you can see
|
||||
it in action. Yes, you can use this module to produce ASCII art.
|
||||
No, it won't be very exciting.
|
||||
|
||||
=head1 Acme::Cow::Example code
|
||||
|
||||
package Acme::Cow::Example;
|
||||
|
||||
use strict;
|
||||
|
||||
use Acme::Cow;
|
||||
|
||||
@Acme::Cow::Example::ISA = qw(Acme::Cow);
|
||||
|
||||
my $generic_ascii_art = <<'EOC';
|
||||
{$balloon}
|
||||
{$tr}
|
||||
{$el}{$er} {$tr}
|
||||
___________________
|
||||
/ Insert cute ASCII \
|
||||
\ artwork here. /
|
||||
-------------------
|
||||
{$U}
|
||||
EOC
|
||||
|
||||
sub new
|
||||
{
|
||||
my $proto = shift;
|
||||
my $class = ref $proto || $proto;
|
||||
my $self = $class->SUPER::new();
|
||||
$self->over(24);
|
||||
return $self;
|
||||
}
|
||||
|
||||
sub as_string
|
||||
{
|
||||
my $self = shift;
|
||||
return $self->SUPER::as_string($generic_ascii_art);
|
||||
}
|
||||
|
||||
=head1 HIGHLIGHTS
|
||||
|
||||
The C<{$balloon}> directive is flush left, but due to the call to
|
||||
C<over()> in the C<new()> method, it will be shoved over 24 spaces
|
||||
to the right, to line up with the thought/speech lines (represented
|
||||
by C<{$tr}>).
|
||||
|
||||
=head1 SAVING WORK
|
||||
|
||||
Included with the C<Acme::Cow> distribution is a short program
|
||||
called C<cowpm> which takes care of most of the boilerplate stuff
|
||||
for you. It's almost as simple as I<just add ASCII art> but there's
|
||||
still a bit that you have to fill in. It has its own documentation;
|
||||
you should peruse L<cowpm>.
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
L<Acme::Cow>, L<cowpm>
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Tony Monroe <tmonroe plus perl at nog dot net>
|
||||
|
||||
=head1 BUGS
|
||||
|
||||
Very few.
|
35
cows/Frogs.pm
Normal file
35
cows/Frogs.pm
Normal file
@ -0,0 +1,35 @@
|
||||
package Acme::Cow::Frogs;
|
||||
|
||||
use strict;
|
||||
|
||||
use Acme::Cow;
|
||||
|
||||
@Acme::Cow::Frogs::ISA = qw(Acme::Cow);
|
||||
|
||||
my $frogs = <<'EOC';
|
||||
{$balloon}
|
||||
{$tr}
|
||||
{$tr}
|
||||
oO)-. .-(Oo
|
||||
/__ _\ /_ __\
|
||||
\ \( | ()~() | )/ /
|
||||
\__|\ | (-___-) | /|__/
|
||||
' '--' ==`-'== '--' '
|
||||
EOC
|
||||
|
||||
sub new
|
||||
{
|
||||
my $proto = shift;
|
||||
my $class = ref $proto || $proto;
|
||||
my $self = $class->SUPER::new();
|
||||
$self->over(46);
|
||||
return bless $self, $class;
|
||||
}
|
||||
|
||||
sub as_string
|
||||
{
|
||||
my $self = shift;
|
||||
return $self->SUPER::as_string($frogs);
|
||||
}
|
||||
|
||||
1;
|
40
cows/MechAndCow.pm
Normal file
40
cows/MechAndCow.pm
Normal file
@ -0,0 +1,40 @@
|
||||
package Acme::Cow::MechAndCow;
|
||||
use strict;
|
||||
use Acme::Cow;
|
||||
@Acme::Cow::MechAndCow::ISA = qw(Acme::Cow);
|
||||
my $mech_and_cow = <<'EOC';
|
||||
{$balloon}
|
||||
{$tl} ,-----.
|
||||
{$tl} | |
|
||||
{$tl} ,--| |-.
|
||||
__,----| | | |
|
||||
,;:: | `_____' |
|
||||
`._______| i^i |
|
||||
`----| |---'| .
|
||||
,-------._| |== ||//
|
||||
| |_|P`. /'/
|
||||
`-------' 'Y Y/'/'
|
||||
.==\ /_\
|
||||
^__^ / /'| `i
|
||||
({$el}{$er})\_______ /' / | |
|
||||
(__)\ )\/\ /' / | `i
|
||||
{$U} ||----w | ___,;`----'.___L_,-'`\__
|
||||
|| || i_____;----\.____i""\____\
|
||||
EOC
|
||||
|
||||
sub new
|
||||
{
|
||||
my $proto = shift;
|
||||
my $class = ref $proto || $proto;
|
||||
my $self = $class->SUPER::new();
|
||||
$self->over(10);
|
||||
return bless $self, $class;
|
||||
}
|
||||
|
||||
sub as_string
|
||||
{
|
||||
my $self = shift;
|
||||
return $self->SUPER::as_string($mech_and_cow);
|
||||
}
|
||||
|
||||
1;
|
38
cows/Stegosaurus.pm
Normal file
38
cows/Stegosaurus.pm
Normal file
@ -0,0 +1,38 @@
|
||||
package Acme::Cow::Stegosaurus;
|
||||
use strict;
|
||||
use Acme::Cow;
|
||||
@Acme::Cow::Stegosaurus::ISA = qw(Acme::Cow);
|
||||
my $stegosaurus = <<'EOC';
|
||||
{$balloon}
|
||||
{$tr} . .
|
||||
{$tr} / `. .' "
|
||||
{$tr} .---. < > < > .---.
|
||||
| \ \ - ~ ~ - / / |
|
||||
_____ ..-~ ~-..-~
|
||||
| | \~~~\.' `./~~~/
|
||||
--------- \__/ \__/
|
||||
.' O \ / / \ "
|
||||
(_____, `._.' | \} \/~~~/
|
||||
`----. / \} | / \__/
|
||||
`-. | / | / `. ,~~|
|
||||
~-.__| /_ - ~ ^| /- _ `..-'
|
||||
| / | / ~-. `-. _ _ _
|
||||
|_____| |_____| ~ - . _ _ _ _ _>
|
||||
EOC
|
||||
|
||||
sub new
|
||||
{
|
||||
my $proto = shift;
|
||||
my $class = ref $proto || $proto;
|
||||
my $self = $class->SUPER::new();
|
||||
$self->over(20);
|
||||
return bless $self, $class;
|
||||
}
|
||||
|
||||
sub as_string
|
||||
{
|
||||
my $self = shift;
|
||||
return $self->SUPER::as_string($stegosaurus);
|
||||
}
|
||||
|
||||
1;
|
207
cows/TextBalloon.pm
Normal file
207
cows/TextBalloon.pm
Normal file
@ -0,0 +1,207 @@
|
||||
package Acme::Cow::TextBalloon;
|
||||
|
||||
use strict;
|
||||
|
||||
my $rcs_id = q$Id$;
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
Acme::Cow::TextBalloon - A balloon of text
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
use Acme::Cow::TextBalloon;
|
||||
|
||||
$x = new Acme::Cow::TextBalloon;
|
||||
$x->add("bunch of text");
|
||||
$x->wrapcolumn(29);
|
||||
|
||||
$y = new Acme::Cow::TextBalloon;
|
||||
$y->adjust(0);
|
||||
$y->add("more text");
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
C<Acme::Cow::TextBalloon> Creates and manipulates balloons of text,
|
||||
optionally printing them. One may notice that the methods in this
|
||||
module are named very similarly to those in C<Acme::Cow>; that's
|
||||
because most of them have to do with the balloon rather than the
|
||||
cow.
|
||||
|
||||
=cut
|
||||
|
||||
use Text::Tabs;
|
||||
use Text::Wrap;
|
||||
|
||||
|
||||
sub new
|
||||
{
|
||||
my $proto = shift;
|
||||
my $class = ref $proto || $proto;
|
||||
my $self = {
|
||||
fill => 1,
|
||||
mode => 'say',
|
||||
over => 0,
|
||||
text => [ ],
|
||||
wrap => 40,
|
||||
};
|
||||
return bless $self, $class;
|
||||
}
|
||||
|
||||
sub wrapcolumn
|
||||
{
|
||||
my $self = shift;
|
||||
if (@_) {
|
||||
$self->{'wrap'} = $_[0];
|
||||
}
|
||||
return $self->{'wrap'};
|
||||
}
|
||||
|
||||
sub mode
|
||||
{
|
||||
my $self = shift;
|
||||
return $self->{'mode'};
|
||||
}
|
||||
|
||||
sub think
|
||||
{
|
||||
my $self = shift;
|
||||
$self->{'mode'} = "think";
|
||||
}
|
||||
|
||||
sub say
|
||||
{
|
||||
my $self = shift;
|
||||
$self->{'mode'} = "say";
|
||||
}
|
||||
|
||||
sub print
|
||||
{
|
||||
my $self = shift;
|
||||
$self->{'mode'} = "think";
|
||||
}
|
||||
|
||||
sub adjust
|
||||
{
|
||||
my $self = shift;
|
||||
if (@_) {
|
||||
$self->{'fill'} = $_[0];
|
||||
}
|
||||
return $self->{'fill'};
|
||||
}
|
||||
|
||||
sub over
|
||||
{
|
||||
my $self = shift;
|
||||
if (@_) {
|
||||
$self->{'over'} = $_[0];
|
||||
}
|
||||
return $self->{'over'};
|
||||
}
|
||||
|
||||
sub as_list
|
||||
{
|
||||
my $self = shift;
|
||||
return $self->_construct();
|
||||
}
|
||||
|
||||
sub as_string
|
||||
{
|
||||
my $self = shift;
|
||||
return join('', $self->_construct());
|
||||
}
|
||||
|
||||
sub add
|
||||
{
|
||||
my $self = shift;
|
||||
push @{$self->{'text'}}, @_;
|
||||
return $self->{'text'};
|
||||
}
|
||||
|
||||
sub text
|
||||
{
|
||||
my $self = shift;
|
||||
if (@_) {
|
||||
my @l = @_;
|
||||
$self->{'text'} = \@l;
|
||||
}
|
||||
return $self->{'text'};
|
||||
}
|
||||
|
||||
sub _maxlength
|
||||
{
|
||||
my ($len, $max);
|
||||
$max = -1;
|
||||
for my $i (@_) {
|
||||
$len = length $i;
|
||||
$max = $len if ($len > $max);
|
||||
}
|
||||
return $max;
|
||||
}
|
||||
|
||||
sub _fill_text
|
||||
{
|
||||
my $self = shift;
|
||||
for my $i (@{$self->{'text'}}) {
|
||||
$i =~ s/\s+$//;
|
||||
}
|
||||
$Text::Tabs::tabstop = 8;
|
||||
my @expanded = Text::Tabs::expand(@{$self->{'text'}});
|
||||
unless ($self->{'fill'}) {
|
||||
return @expanded;
|
||||
}
|
||||
$Text::Wrap::columns = $self->{'wrap'};
|
||||
my @filled = split("\n", Text::Wrap::wrap("", "", @expanded));
|
||||
$Text::Tabs::tabstop = 2; # Defeat a dumb heuristic.
|
||||
my @final = expand(@filled);
|
||||
return @final;
|
||||
}
|
||||
|
||||
sub _construct
|
||||
{
|
||||
my $self = shift;
|
||||
my $mode = $self->{'mode'};
|
||||
my @message = $self->_fill_text();
|
||||
my $max = _maxlength(@message);
|
||||
my $max2 = $max + 2; ## border space fudge.
|
||||
my @border; ## up-left, up-right, down-left, down-right, left, right
|
||||
my @balloon_lines = ();
|
||||
my $shove = " " x $self->{'over'};
|
||||
my $format = "$shove%s %-${max}s %s\n";
|
||||
if ($mode eq think) {
|
||||
@border = qw[ ( ) ( ) ( ) ];
|
||||
} elsif (@message < 2) {
|
||||
@border = qw[ < > ];
|
||||
} else {
|
||||
@border = ( "/", "\\", "\\", "/", "|", "|" );
|
||||
}
|
||||
push(@balloon_lines,
|
||||
"$shove " . ("_" x $max2) . "\n" ,
|
||||
sprintf($format, $border[0], $message[0], $border[1]),
|
||||
(@message < 2 ? "" :
|
||||
map { sprintf($format, $border[4], $_, $border[5]) }
|
||||
@message[1 .. $#message - 1]),
|
||||
(@message < 2 ? "" :
|
||||
sprintf($format, $border[2], $message[$#message], $border[3])),
|
||||
"$shove " . ("-" x $max2) . "\n"
|
||||
);
|
||||
return @balloon_lines;
|
||||
}
|
||||
|
||||
|
||||
=pod
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Tony Monroe E<lt>tmonroe+perl@nog.netE<gt>
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
L<Acme::Cow>
|
||||
|
||||
=cut
|
||||
|
||||
1;
|
||||
__END__
|
43
cows/TuxStab.pm
Normal file
43
cows/TuxStab.pm
Normal file
@ -0,0 +1,43 @@
|
||||
package Acme::Cow::TuxStab;
|
||||
use strict;
|
||||
use Acme::Cow;
|
||||
@Acme::Cow::TuxStab::ISA = qw(Acme::Cow);
|
||||
my $tux_being_stabbed = <<'EOC';
|
||||
{$balloon}
|
||||
{$tl} , ,
|
||||
{$tl} /( )`
|
||||
{$tl} \ \___ / |
|
||||
/- _ `-/ '
|
||||
(/\/ \ \ /\
|
||||
/ / | ` \
|
||||
O O ) / |
|
||||
`-^--'`< '
|
||||
.--. (_.) _ ) /
|
||||
|o_o | `.___/` /
|
||||
|:_/ | `-----' /
|
||||
//<- \ \----. __ / __ \
|
||||
(| <- | )---|====O)))==) \) /====
|
||||
/'\ <- _/`\---' `--' `.__,' \
|
||||
\___)=(___/ | |
|
||||
\ /
|
||||
______( (_ / \______
|
||||
,' ,-----' | \
|
||||
`--\{__________) \/
|
||||
EOC
|
||||
|
||||
sub new
|
||||
{
|
||||
my $proto = shift;
|
||||
my $class = ref $proto || $proto;
|
||||
my $self = $class->SUPER::new();
|
||||
$self->over(8);
|
||||
return bless $self, $class;
|
||||
}
|
||||
|
||||
sub as_string
|
||||
{
|
||||
my $self = shift;
|
||||
return $self->SUPER::as_string($tux_being_stabbed);
|
||||
}
|
||||
|
||||
1;
|
Loading…
Reference in New Issue
Block a user