NAME
Acme::EyeDrops - Visual Programming in Perl
SYNOPSIS
use Acme::EyeDrops qw(sightly);
print sightly( { Shape => 'camel',
SourceFile => 'myprog.pl' } );
DESCRIPTION
Acme::EyeDrops
converts a Perl program into an equivalent one, but without all those unsightly letters and numbers.
It supports Visual Programming by allowing you to pour the generated program into various shapes, such as UML diagrams, enabling you to instantly understand how the program works by glancing at its new and improved visual representation.
Like Acme::Smirch
, but unlike Acme::Bleach
and Acme::Buffy
, the generated program runs without requiring that Acme::EyeDrops
be installed on the target system.
EXAMPLES
Suppose you have a program, helloworld.pl, consisting of:
print "hello world\n";
You can make this program look like a camel with:
print sightly( { Shape => 'camel',
SourceFile => 'helloworld.pl',
Regex => 1 } );
Instead of using the API above, you may find it more convenient to use the sightly.pl command in the demo directory:
sightly.pl -h (for help)
sightly.pl -s camel -f helloworld.pl -r >new.pl
cat new.pl
perl new.pl (should "print hello" world as before)
Notice that the shape 'camel' is just the file 'camel.eye' in the same directory as EyeDrops.pm, so you are free to add your own new shapes as required.
If your boss demands a UML diagram describing the 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',
SourceFile => 'helloworld.pl',
Regex => 1 } );
producing this improved visual representation:
''=~('('.'?'.'{'.('`'|'%').('['^'-').(
( (
( (
( (
( (
( (
'`'))))))))))|'!').('`'|',').'"'.('['^
(
( (
( (
'+'))))
)
)
.('['^')').('`'|')').('`'|'.').(('[')^
( (
( (
'/'))))).('{'^'[').'\\'.('"').( '`'|'(').('`'|'%').('`'|"\,").(
( ( ( (
( ( ( (
( ( ( (
( ( ( (
( ( ( (
'`'))))))))))))))))))))|"\,").( '`'|'/').('{'^'[').('['^"\,").(
'`'|'/').('['^')').('`'|',').('`'|'$').('\\').
'\\'.('`'|'.').'\\'.'"'.';'.('!'^'+').'"'.'}'.
')');$:='"'|'#';$:='?'&'!';$:='*'|'~';$:="\%"&
'$'; $: ='"'
|'#' ;( $:)=
'?'& (( '!')
);$: =( '*')
|'~' ;( $:)=
'%'& (( '$')
);$: =( '"')
|'#' ;( $:)=
'?'& (( '!')
);$: =( '*')
|'~' ;( $:)=
'%'&'$';$:='"'|'#';$:='?'&'!';$:='*'|('~');$:=
'%'& (( '$')
);$: =( '"')
|'#' ;( $:)=
'?'& (( '!')
);$: =( '*')
|'~' ;( $:)=
'%'& (( '$')
);$: =( '"')
|'#' ;( $:)=
'?'& (( '!')
);$: =( '*')
|'~';$:='%'&'$';$:='"'|'#';$:='?'&'!';$:="\*"|
'~';$:='%'&'$';$:='"'|'#';$:='?'&'!';$:=('*')|
'~';$:='%'&'$';$:='"'|'#';$:='?'&'!';$:=('*');
This is a Visual Programming breakthrough in that you can tell that it is a Windows program and see its UML structure too, just by glancing at the code.
For Linux-only, you can use its /usr/games/banner command like this:
print sightly( { Shape => 'srcbanner',
Width => 70,
SourceFile => 'helloworld.pl',
Regex => 1 } );
The generated program, shown below, is easier to understand than the original because its characters are bigger and easier to read:
'' =~
+( ((
'(')).'?'.'{'.('`'|'%').('['^'-').('`'|'!').
('`'|',').'"'.('['^'+').('['^')').('`'|')').
('`'|'.').('['^'/').('{'^'[').'\\'.'"'.('`'|
'(').('`'|'%').('`'|',').('`'|',').('`'|'/')
.+( ((
'{' ))
^(( '['
)) ).(
'[' ^((
',') )).
('`' |'/')
.(('[')^ (')')).(
'`'|',').('`'|'$').'\\'.
'\\'.('`'|"\.").'\\'.
'"'.';'.('!'^'+'
).+ ((
'"' ))
.'}'.')');$:='"'|'#';$:="\?"&
'!';$:='*'|'~';$:='%'&'$';$:=
'"'|'#';$:='?'&'!';$:='*'|'~'
;$:='%'&'$';$:='"'|'#';$:='?'
&(( '!'
));
$:=
'*'|
"\~";
$:=('%')&
'$';$:='"'
|('#');$:=
'?'&"\!";
($:)
=(( ((
'*' )) ))|
'~';$:='%'&'$';$:='"'|'#';$:= ('?')&
'!';$:='*'|'~';$:='%'&'$';$:= '"'|'#';
$:='?'&'!';$:='*'|'~';$:='%'& '$';$:
='"'|'#';$:='?'&'!';$:=('*')| '~'
;$:
=(( ((
'%' ))
))&'$';$:='"'|'#';$:='?'&'!';
$:='*'|'~';$:='%'&'$';$:='"'|
'#';$:='?'&'!';$:='*'|'~';$:=
'%'&'$';$:='"'|'#';$:='?'&'!'
;$: =(
((
'*')
))|+
'~';
$:= "\%"&
'$';$:='"'|'#';$:='?'&'!';$:=
'*'|'~';$:='%'&'$';$:='"'|'#'
;$:='?'&'!';$:='*'|"\~";$:=
'%'&'$';$:='"'|'#';$:='?'
&((
((
((
'!'))))));$:='*'|'~';$:=('%')&
'$';$:='"'|'#';$:='?'&'!';$:='*'|
'~';$:='%'&'$';$:='"'|'#';$:=('?')&
'!';$:='*'|'~';$:='%'&'$';$:='"'|'#'
;($:)= ((
'?')) &+
'!'
;$:
=(
'*')|
'~';$:=
'%'&"\$";$:=
'"'|'#'
;($:)
=(( ((
'?' ))
))&'!';$:='*'|'~';$:='%'&'$';$:='"'|'#';$:=('?')&
'!';$:='*'|'~';$:='%'&'$';$:='"'|'#';$:='?'&"\!";
$:='*'|'~';$:='%'&'$';$:='"'|'#';$:='?'&('!');$:=
'*'|'~';$:='%'&'$';$:='"'|'#';$:='?'&'!';$:="\*"|
'~' ;(
$:
)=((
'%')
)&((
'$' ));$:
='"'|'#';$:='?'&'!';$:=('*')|
'~';$:='%'&'$';$:='"'|'#';$:=
'?'&'!';$:='*'|'~';$:="\%"&
'$';$:='"'|'#';$:='?'&'!'
;$:
='*'|'~';
$:='%'&"\$";$:=
'"'|'#';$:='?'&'!';
$:='*'|'~';$:='%'&"\$";
$:='"'| (( '#'));
($:) =( '?')
&(( (( '!'
))) ); $:
=(( (( ((
'*' )) ))
)) |+ '~'
;( $: )=((
(( (( '%')))
))) &'$';$:='"'|
(( "\#"));$:=
'?'&'!';
$:= ((
'*' ))
|'~';$:='%'&'$';$:='"'|'#';$:='?'&'!';$:='*'|'~';
$:='%'&'$';$:='"'|'#';$:='?'&'!';$:='*'|('~');$:=
'%'&'$';$:='"'|'#';$:='?'&'!';$:='*'|'~';$:="\%"&
'$';$:='"'|'#';$:='?'&'!';$:='*'|'~';$:='%'&"\$";
$:=
'"' |+
'#' ;(
$:)='?'&'!';$:='*'|'~';$:='%'&'$';$:='"'|"\#";$:=
'?'&'!';$:='*'|'~';$:='%'&'$';$:='"'|'#';$:="\?"&
'!';$:='*'|'~';$:='%'&'$';$:='"'|'#';$:='?'&"\!";
$:='*'|'~';$:='%'&'$';$:='"'|'#';$:='?'&('!');$:=
'*'
|"\~";$:=
'%'&'$';$:='"'|
'#';$:='?'&"\!";$:=
'*'|'~';$:='%'&"\$";$:=
'"'|'#' ;($:)=
'?'& '!';
$:= '*'
|(( ((
'~' ))
)); $:
=(( '%'
))& '$';
($:)= "\""|
'#';$:='?'&'!';$:=('*')|
'~';$:='%'&'$';$:='"'
|'#';$:='?'&"\!";
$:=('*')|
((
((
'~'))
));$:='%'&
'$';$:=('"')|
'#';$:='?'&'!';$:
='*'|'~';$:="\%"& ((
'$'));$:='"'|'#';
$:='?'&'!';$:='*'
|'~';$:="\%"&
'$';$:
=('"')|
'#';$:='?'&'!';
$:='*'|'~';$:='%'
&'$';$:="\""|
'#';$:
="\?"&
'!';$:=
'*'|'~' ;(
$:)="\%"&
"\$";
$:
=(
'"')|'#';
$:='?'&"\!";$:=
'*'|'~';$:='%'&'$';
$:='"'|'#';$:='?'&"\!";
$:='*'| '~';$:
='%' &'$'
;$: =((
'"' ))
|(( ((
'#' ))
)); $:=
'?' &'!'
;($:) ='*'|
'~';$:='%'&'$';$:=('"')|
'#';$:='?'&'!';$:='*'
|'~';$:='%'&"\$";
$:=('"')|
'#' ;(
$:) =(
'?')&'!';$:='*'|'~';$:=('%')&
'$';$:='"'|'#';$:='?'&'!';$:=
'*'|'~';$:='%'&'$';$:='"'|'#'
;$:='?'&'!';$:='*'|'~';$:='%'
&(( '$'
));
$:=
'"'|
"\#";
$:=('?')&
'!';$:='*'
|('~');$:=
'%'&"\$";
($:)
=(( ((
'"' ))
))|'#';$:='?'&'!';$:='*'|'~';$:='%'&'$';$:=('"')|
'#';$:='?'&'!';$:='*'|'~';$:='%'&'$';$:='"'|"\#";
$:='?'&'!';$:='*'|'~';$:='%'&'$';$:='"'|('#');$:=
'?'&'!';$:='*'|'~';$:='%'&'$';$:='"'|'#';$:="\?"&
'!'
;$:='*'|'~';
$:='%'&('$');$:=
'"'|'#';$:='?'&'!';$:
='*'|'~';$:='%'&"\$";$:=
'"'|'#'; $:="\?"&
'!'; ($:)=
'*'| '~'
;$: =((
(( '%'
))) )&+
'$' ;(
$:) =( ((
'"')))|'#';$:='?'&'!';$:='*'|'~';$:='%'&('$');$:=
'"'|'#';$:='?'&'!';$:='*'|'~';$:='%'&'$';$:="\""|
'#';$:='?'&'!';$:='*'|'~';$:='%'&'$';$:='"'|"\#";
$:='?'&'!';$:='*'|'~';$:='%'&'$';$:='"'|('#');$:=
'?'
&((
'!')
);$:=
"\*"|
'~';$:
='%'&
"\$";
($:)=
"\""|
"\#";
($:)=
"\?"&
'!';$:
="\*"|
"\~";
($:)=
'%'&
'$' ;(
$:) =(
'"')|'#';$:='?'&'!';$:=('*')|
'~';$:='%'&'$';$:='"'|'#';$:=
'?'&'!';$:='*'|'~';$:='%'&'$'
;$:='"'|'#';$:='?'&'!';$:='*'
|(( ((
((
'~')
))))
);$:
=(( '%'))
&'$';$:='"'|'#';$:='?'&'!';$:
='*'|'~';$:='%'&'$';$:=('"')|
'#';$:='?'&'!';$:='*'|"\~";
$:='%'&'$';$:='"'|'#';$:=
'?'
&'!';
$:='*'|
'~';$:="\%"&
'$';$:=
"\""|
'#' ;$:
="\?"& "\!";
$:="\*"| '~';$:=
'%'&"\$";$:= '"'|'#'
;$:='?'& "\!";
The shapes 'bleach' and 'buffy' are also provided to aid folks migrating from Acme::Bleach and Acme::Buffy.
Let's get more ambitious and create a big JAPH.
my $src = <<'PROG';
open 0;
$/ = undef;
$x = <0>;
close 0;
$x =~ tr/!-~/#/;
print $x;
PROG
print sightly({ Shape => 'japh',
SourceString => $src,
Regex => 1 } );
This works. However, if we were to change:
$x =~ tr/!-~/#/;
to:
$x =~ s/\S/#/g;
the generated program would malfunction in strange ways because it is running inside a regular expression and Perl's regex engine is not reentrant. In this case, we must resort to:
print sightly({ Shape => 'japh',
SourceString => $src,
Regex => 0 } );
which runs the generated sightly program via eval instead.
EyeDrops can also convert plain text:
print sightly({ Shape => 'window',
SourceString => "Bill Gates is a pest!\n",
Regex => 1,
Print => 1 } );
In this example, the generated program will print the SourceString above.
But wait, there's more. You can encode binary files too.
print sightly({ Shape => 'camel,japh,camel',
SourceFile => 'some_binary_file',
Binary => 1,
Print => 1,
Gap => 5 } );
This is prettier than uuencode/uudecode. Here is how you do it with sightly.pl:
sightly.pl -g5 -bps camel,japh,camel -f some_binary_file >fred
To decode:
perl fred >f.tmp
To verify it worked:
cmp f.tmp some_binary_file
The sightly-encoding engine is implemented in the functions ascii_to_sightly
and sightly_to_ascii
.
BUGS
A really diabolical shape with lots of single character lines will defeat the shape-pouring algorithm.
In the general case, all unsightly alphanumerics are not eliminated because of the need for a leading eval.
AUTHOR
Andrew Savige <andrew.savige@ir.com>
SEE ALSO
Acme::Bleach Acme::Smirch Acme::Buffy
CREDITS
I blame Japhy and Ronald J Kimball and others on the fwp mailing list for exposing the ''=~ trick and Jas Nagra for explaining his Acme::Smirch module.
COPYRIGHT
Copyright (c) 2001 Andrew Savige. All rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.