Acme-EyeDrops
view release on metacpan or search on metacpan
lib/Acme/EyeDrops.pm view on Meta::CPAN
=head1 SYNOPSIS
use Acme::EyeDrops qw(sightly);
print sightly( { Shape => 'camel',
SourceFile => 'eyesore.pl' } );
=head1 DESCRIPTION
C<Acme::EyeDrops> converts a Perl program into an equivalent one,
but without all those unsightly letters and numbers.
In a Visual Programming breakthrough, EyeDrops allows you to pour
the generated program into various shapes, such as UML diagrams,
enabling you to instantly understand how the program works just
by glancing at its new and improved visual representation.
Unlike C<Acme::Bleach> and C<Acme::Buffy>, the generated program runs
without requiring that C<Acme::EyeDrops> be installed on the target
system.
=head1 EXAMPLES
=head2 Getting Started
Suppose you have a program, F<helloworld.pl>, consisting of:
print "hello world\n";
To convert this little program into an equivalent camel-shaped one,
create F<cvt.pl> as follows:
# cvt.pl. Convert helloworld.pl into a camel shape.
use Acme::EyeDrops qw(sightly);
print sightly( { Shape => 'camel',
SourceFile => 'helloworld.pl',
Regex => 1 } );
Then run it like this:
perl cvt.pl >new.pl
After inspecting the newly created program, F<new.pl>, to verify that
it does indeed resemble a camel, run it:
perl new.pl
to confirm it behaves identically to the original F<helloworld.pl>.
Instead of using the API, as shown above, you may find it more
convenient to use the F<sightly.pl> command in the F<demo> directory:
sightly.pl -h (for help)
sightly.pl -s camel -f helloworld.pl -r 1 >new.pl
cat new.pl (should look like a camel)
perl new.pl (should print "hello world" as before)
Notice that the shape C<'camel'> is just the file F<camel.eye> in
the F<EyeDrops> sub-directory underneath where F<EyeDrops.pm> is located,
so you are free to add your own new shapes as required.
For the meaning of Regex => 1 above, see the I<Just another Perl hacker>
section below.
=head2 Making Your Programs Easier to Understand
If your boss demands a UML diagram describing your program, you
can give him this:
print sightly( { Shape => 'uml',
SourceFile => 'helloworld.pl',
Regex => 1 } );
If it is a Windows program, you can indicate that too, by
combining shapes:
print sightly( { Shape => 'uml,window',
Gap => 1,
SourceFile => 'helloworld.pl',
Regex => 1 } );
producing this improved visual representation:
''=~('('.'?'.'{'.('`'|'%').('['^'-').(
( (
( (
( (
( (
( (
'`'))))))))))|'!').('`'|',').'"'.('['^
(
( (
( (
'+'))))
)
)
.('['^')').('`'|')').('`'|'.').(('[')^
( (
( (
'/'))))).('{'^'[').'\\'.('"').( '`'|'(').('`'|'%').('`'|"\,").(
( ( ( (
( ( ( (
( ( ( (
( ( ( (
( ( ( (
'`'))))))))))))))))))))|"\,").( '`'|'/').('{'^'[').('['^"\,").(
'`'|'/').('['^')').('`'|',').('`'|'$').'\\'.'\\'
.('`'|'.').'\\'.'"'.';'.('!'^'+').'"'.'}'."\)");
$:='.'^'~';$~='@'|'(';$^=')'^'[';$/='`'|"\.";$,=
"\("^ (( '}'))
;($\) =( '`')|
"\!"; $: =')'^
"\}"; $~ ='*'|
"\`"; $^ ='+'^
"\_"; $/ ='&'|
"\@"; $, ='['&
"\~"; $\ =','^
"\|"; $: ='.'^
"\~"; $~ ='@'|
lib/Acme/EyeDrops.pm view on Meta::CPAN
'`'|'#').( ('`')| '+').( '`'|'%')
.('['^')') .(( ',' )). '"' .('}').
"\)");$:= ('.')^ ( "\~"); $~='@'|
('(');$^= (( ')' )) ^ (( '[' )) ;($/)=
'`'|'.'; $,='('^'}' ; $\='`'|'!' ;($:)
=(')')^ ( '}'
);($~) = '*'
|'`'; ( ( ( $^)
) )= ( ( ( '+'
) ) ) ^ ( ( ( '_'
) ) ) ; ( ( ( $/
) ) ) =
( ( ( (
( ( ( (
( '&')))))))))|'@' ; ( (
( ( ( ( ( $,
) ) ) ) ) ))
= ( (( (( ( (
( ( ( (( ( (
( ( '[')) ) )
) ) ) )
) ) ) )
) ) )
) & (
( ( (
( ( (
( (
( (
'~' ))
)))))))))
=head2 Buffy Looking in the Mirror
Because the I<sightly> encoding is not very compact, you sometimes
find yourself playing a surreal form of I<Perl Golf>, where
the winner is the one with the smallest F<f.tmp> in:
sightly.pl -r 1 -f program_to_be_converted >f.tmp
Apart from reducing the (key-)stroke count, you must avoid regexes
and strive to replace alphanumeric characters with sightly ones,
which do not require sightly encoding.
To illustrate, consider the intriguing problem of creating
I<Buffy looking in the mirror>. Let's start with F<k.pl>:
open$[;chop,($==y===c)>$-&&($-=$=)for@:=<0>;
print$"x-(y---c-$-).reverse.$/for@:
Notice that EyeDrops-generated programs, by default, contain no
trailing spaces, which complicates the above program.
Buffy looking in the mirror can now be created with:
sightly.pl -r 1 -f k.pl -s buffy2 >b.pl
cat b.pl (should show Buffy's face)
perl b.pl (should show Buffy looking in the mirror)
Drat. This requires two I<buffy2> shapes. What to do?
Well, you could use the C<TrailingSpaces> attribute
(C<-T> switch to F<sightly.pl>) to append the required
number of trailing spaces to each line, allowing you to
write a briefer F<kk.pl>:
open$%;chop,print+reverse.$/for<0>
and finally produce I<Buffy looking in the mirror> with:
sightly.pl -T -r 1 -f kk.pl -s buffy2 >bb.pl
Alternatively, the C<Compact> attribute (C<-m> switch to
F<sightly.pl>) could be used to produce a solution free
of any trailing spaces:
sightly.pl -m -r 1 -f k.pl -s buffy2 >buffy.pl
cat buffy.pl (should show Buffy's face)
perl buffy.pl (should show Buffy looking in the mirror)
producing F<buffy.pl>:
''=~('(?{'.(
'`'|'%').('['^'-'
).('`'|'!').('`'|','
).+ ( '"'
).( ( '`'
)|+ ( '/'
)). ( '['
^(( ( '+'
))) ).('`' |((
'%' ))). ( '`'
|(( '.') ) ).+
((( (( ( (((
((( ( ( (((
((( ( '\\')))
))) ) ) ) )
) )))) )))))) .'$[;' . (
( ( (( ( (
( ( ( (( ( ( (( ( ( (
( ( '`') )))) ) )
) ) ))) )
) ))) ) )
)| ( ( ( ( ((
'#' ) ) ) )))
).(('`')| ('(')).(
'`'|'/'). ('['^'+') .',(\\$'
.'=='.('[' ^'"') . '==='.+(
'`'|'#').')' . '>\\$-'
.'&&(\\$-=\\' . '$=)'.(
'`'|'&').('`' | ( '/')).(
'['^')').'\\' . '@:=<' .
('^'^(('`')| "\.")). (
'>').(';').( '!'^'+' )
.('['^'+'). ('['^')' ).('`'|
')').("\`"| "\.").( ( ('['))^
"\/").'\\$\\"'.( ( "\[")^ ( (
( ( "\#"))))). ( ( '-')) . (
( ( ('(')))).( ( ( '[')) ^ (
( '"'))).'--' . '-'. ( (
( '`'))|'#'). ( ( (
( '-')))). ( ( (
( ( '\\' ) )
lib/Acme/EyeDrops.pm view on Meta::CPAN
Invert => 1,
BorderWidth => 1,
SourceFile => 'helloworld.pl',
Regex => 1 } );
producing:
''=~('('.'?'.'{'.('`'|('%')).(
'['^"\-").( '`'|'!').('`'|','
).'"'.('[' ^'+').('['^')').(
'`'|')'). ('`'|'.').('['^'/'
).("\{"^ '[').'\\'.'"'.('`'|
"\(").( (( '`'))|'%').('`'|
',') .( '`'|',').("\`"|
'/' ).( '{'^'[').("\["^
(( ',') )).('`'|"\/").(
( (( '[')))^')').(
(( ( '`')))|',').(
'`' | '$').'\\'.''.
'\\' .('`'|"\.").
'\\'. (( '"'))."\;".(
'!'^"\+"). '"'.'}'.')')
;$:=('.')^ '~';$~="\@"|
'(';$^=')' ^'[';$/='`'|
('.');$,= '('^'}';$\=
'`'|'!'; $:=')'^'}'
;$~='*' |"\`";$^=
'+' ^+ ( '_');$/=
'&'| '@'; $,='['&
'~'; $\=',' ^"\|";
($:)= ('.')^ "\~";
$~='@'| "\("; ($^)
=')'^'[';$/ =('`')| '.'
;$,='('^'}' ;$\=('`')| (
'!');$:=')' ^'}';$~='*'| ((
'`'));$^='+'^'_';$/='&'|'@';#;
=head2 Snowflakes
The C<Text> and C<TextFiller> attributes (C<-t>/C<-u> switches
to F<sightly.pl>) are handy when you simply want to pour
some I<unsightly> text into a shape.
To illustrate, consider an entry in the I<Cam.pm> 2002 Christmas
programming contest, F<snowing.pl>:
$_=q~vZvZ&%('$&"'"&(&"&$&"'"&$Z$#$$$#$%$&"'"&(&#
%$&"'"&#Z#$$$#%#%$%$%$%(%%%#%$%$%#Z"%*#$%$%$%$%(%%%#%$%$
%#Z"%,($%$%$%(%%%#%$%$%#Z"%*%"%$%$%$%(%%%#%$%$%#Z#%%"#%#%
$%$%$%$##&#%$%$%$%#Z$&""$%"&$%$%$%#%"%"&%%$%$%#Z%&%&#
%"'"'"'###%*'"'"'"ZT%?ZT%?ZS'>Zv~;
s;\s;;g;
$;='@,=map{$.=$";join"",map((($.^=O)x(-33+ord)),/./g),$/}split+Z;
s/./(rand)<.2?"o":$"/egfor@;=((5x84).$/)x30;map{
system$^O=~W?CLS:"clear";print@;;splice@;,-$_,2,pop@,;
@;=($/,@;);sleep!$%}2..17';
$;=~s;\s;;g;eval$;
The rules of this contest state that the program source code must fit
precisely into the provided snowflake shape. To comply, you can pour
the above program into the required shape with:
sightly.pl -s snow -f snowing.pl -t -u# -n1 >snowflake.pl
or equivalently (using the API instead of F<sightly.pl>):
print sightly( { Shape => 'snow',
SourceFile => 'snowing.pl',
Text => 1,
TextFiller => '#',
Indent => 1 } );
producing a valid entry, F<snowflake.pl>:
$_= q~v
ZvZ&%(' $&"'"&(
&"& $&"' "&$Z$#$$$#$%$& "'"& (&#
%$&"'"&#Z#$$ $#%# %$%$%$%(%%%#
%$%$%#Z"%*#$ %$%$ %$%(%%%#%$%$
%# Z"%, ($% $% $%( %%%# %$
%$% #Z" %*%" %$ %$%$ %(% %%#
%$%$%# Z#%%"#%#%$ %$ %$%$##&#%$ %$%$%#
Z$ &""$%"&$%$%$%#%"%"&%%$%$%#Z%&% &#
%"'"'"'###%*'"'"'"ZT%?ZT%?ZS'>Zv~;s;\s;;g;$;='@,=map
{$.= $";join"" ,map((($ .^=O)x(- 33+ord)), /./g
),$ /}split +Z;s/. /(rand )<.2?"o ":$
"/eg for@;=((5 x84).$/) x30;map{ system$^O =~W?
CLS:"clear";print@;;splice@;,-$_,2,pop@,;@;=($/,@;);
sl eep!$%}2..17';$;=~s;\s;;g;eval $;
###### ########## ## ########## ######
### ### #### ## #### ### ###
## #### ### ## ### #### ##
############ #### ############
############ #### ############
### #### ############## #### ###
####### #######
### ###
Running F<snowflake.pl> produces a pretty C<cam.pm> snow-scape.
The leftover space at the bottom could be used to add a snowman:
$_= q~v
ZvZ&%(' $&"'"&(
&"& $&"' "&$Z$#$$$#$%$& "'"& (&#
%$&"'"&#Z#$$ $#%# %$%$%$%(%%%#
%$%$%#Z"%*#$ %$%$ %$%(%%%#%$%$
%# Z"%, ($% $% $%( %%%# %$
%$% #Z" %*%" %$ %$%$ %(% %%#
%$%$%# Z#%%"#%#%$ %$ %$%$##&#%$ %$%$%#
Z$ &""$%"&$%$%$%#%"%"&%%$%$%#Z%&% &#
%"'"'"'###%*'"'"'"ZT%?ZT%?ZS'>Zv~;s;\s;;g;$~=q~ZZZJ_
#_ZH /'\\ZG|#o #o#|ZG|$ <%|ZH\\" \\!_!_!/" /ZG/
)\\ ZF/+\\Z E|-|ZE |-|ZE| -|ZF\\+ /ZG
\\)/ ~;;@x=@,= +map{$.= $";;join "",map((( $.^=
O)x(-33+ord)),/./g)}split+Z;$~=~s~\s~~g;;s;.;(rand)<
.2 ?"o":$";egxfor@;=(5x84)x30;map {#
system $^O=~W?CLS :+ "clear";;; ;print
$_. $/, ,for $_ -18? @;: ###
(( map{ $|= 1; ;;; join ""
,map($|--?$" x(-3 *11+ord):$_,
/./g)}split+ Z,$~ ),@x);splice
lib/Acme/EyeDrops.pm view on Meta::CPAN
Next, a 'eye' shape (.eye file in the
get_eye_dir() directory unless overridden
by the EyeDir attribute) is looked for.
Finally, a file name is looked for.
ShapeString Describes the shape you want.
This time you specify a shape string.
SourceFile The source file name to convert.
SourceHandle Specify a file handle instead of a file name.
SourceString Specify a string instead of a file name.
BannerString String to use with built-in Shape 'banner'.
Regex Regex can take the following values:
0: do not embed source program in a regex
If Regex is positive, embed the program in a regex and:
1: add a leading "use re 'eval';" for Perl 5.18+ only
2: do not add a leading "use re 'eval';"
3: add a leading "use re 'eval';"
Do not set this flag when converting complex programs.
Compact Boolean. If set, use compact sightly encoding.
Print Boolean. If set, use a print statement instead
of the default eval statement. Set this flag
when converting text files (not programs).
Binary Boolean. Set if encoding a binary file.
Text Boolean. Set if pouring unsightly text.
TextFiller Filler string used with Text attribute.
For example, TextFiller => '#'.
Gap The number of lines between successive shapes.
Rotate Rotate the shape clockwise 90, 180 or 270 degrees.
RotateType 0 = big rotated shape,
1 = small rotated shape,
2 = squashed rotated shape.
RotateFlip Boolean. Set if want to flip (reflect) the shape
in addition to rotating it.
Reflect Boolean. Reflect the shape.
Reduce Reduce the size of the shape.
Expand Expand the size of the shape.
Invert Boolean. Invert the shape.
Indent Indent the shape. The number of spaces to indent.
TrailingSpaces Boolean. Ensure all lines of the shape are of equal
length, adding trailing spaces if required.
RemoveNewlines Boolean. Remove all newlines from the source before
conversion.
BorderGap Put a border around the shape. Gap between border
and the shape.
BorderGapLeft,BorderGapRight,BorderGapTop,BorderGapBottom
You can override BorderGap with one or more from
the above.
BorderWidth Put a border around the shape. Width of border.
BorderWidthLeft,BorderWidthRight,BorderWidthTop,BorderWidthBottom
You can override BorderWidth with one or more from
the above.
Width Ignored for .eye file shapes. For built-in shapes,
interpreted appropriately for the shape, typically the
shape width in characters. If no shape is specified,
a rectangular block of Width characters is generated.
EyeDir Normally .eye files are got from the EyeDrops
directory underneath where EyeDrops.pm is located.
You can override that by specifying a directory
containing the .eye shape files.
InformHandler By default, sightly prints status of what it is
doing to STDERR; you can override this by providing
a subroutine reference taking a single inform string
argument. To shut it up, set to sub {}.
TrapEvalDie Boolean.
Add closing 'die $@ if $@' to generated program.
When an eval code block calls the die function,
the program does not die; instead the die string
is returned to eval in $@. Using this flag allows
you to convert programs that call die.
TrapWarn Boolean.
Add leading 'local $SIG{__WARN__}=sub{};' to
generated program. This shuts up some warnings.
Use this option if generated program emits
'No such signal: SIGHUP at ...' when run with
warnings enabled.
FillerVar Reference to a list of 'filler variables'.
A filler variable is a Perl variable consisting
of two characters: $ and a punctuation character.
For example, FillerVar => [ '$:', '$^' ].
Do not use $; or $" or $_ as filler variables.
Alternatively, you may set this to '' if you don't
want any filler, or to a string (e.g. '#' or ';'
or ';#') to use instead of filler variables to
fill the leftover part of the last shape with.
=back
=head2 Specifying a Shape
( run in 2.269 seconds using v1.01-cache-2.11-cpan-8f98c5d2c55 )