The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.

NAME

Acme::EyeDrops - Visual Programming in Perl

SYNOPSIS

use Acme::EyeDrops qw(sightly);

print sightly( { Shape       => 'camel',
                 SourceFile  => 'eyesore.pl' } );

DESCRIPTION

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.

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              (should look like a camel)
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.

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:

               ''=~('('.'?'.'{'.('`'|'%').('['^'-').(
               (                                    (
               (                                    (
               (                                    (
               (                                    (
               (                                    (
               '`'))))))))))|'!').('`'|',').'"'.('['^
                                 (
                                ( (
                               (   (
                              '+'))))
                                 )
                                 )
               .('['^')').('`'|')').('`'|'.').(('[')^
               (                                    (
               (                                    (
'/'))))).('{'^'[').'\\'.('"').(      '`'|'(').('`'|'%').('`'|"\,").(
(                             (      (                             (
(                             (      (                             (
(                             (      (                             (
(                             (      (                             (
(                             (      (                             (
'`'))))))))))))))))))))|"\,").(      '`'|'/').('{'^'[').('['^"\,").(

'`'|'/').('['^')').('`'|',').('`'|'$').'\\'.'\\'
.('`'|'.').'\\'.'"'.';'.('!'^'+').'"'.'}'."\)");
$:='.'^'~';$~='@'|'(';$^=')'^'[';$/='`'|"\.";$_=
"\("^                  ((                  '}'))
;($,)                  =(                  '`')|
"\!";                  $\                  =')'^
"\}";                  $:                  ='.'^
"\~";                  $~                  ='@'|
"\(";                  $^                  =')'^
"\[";                  $/                  ='`'|
"\.";                  $_                  ='('^
"\}";                  $,                  ='`'|
"\!";                  $\                  =')'^
"\}";                  $:                  ='.'^
'~';$~='@'|'(';$^=')'^'[';$/='`'|'.';$_='('^'}';
($,)=                  ((                  '`'))
|'!';                  $\                  =')'^
"\}";                  $:                  ='.'^
"\~";                  $~                  ='@'|
"\(";                  $^                  =')'^
"\[";                  $/                  ='`'|
"\.";                  $_                  ='('^
"\}";                  $,                  ='`'|
"\!";                  $\                  =')'^
"\}";                  $:                  ='.'^
"\~";                  $~                  ='@'|
'(';$^=')'^'[';$/='`'|'.';$_='('^'}';$,='`'|'!';
$\=')'^'}';$:='.'^'~';$~='@'|'(';$^=')'^"\[";$/=
'`'|'.';$_='('^'}';$,='`'|'!';$\=')'^'}';$:='.';

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 apply its /usr/games/banner command to the program's source text:

print sightly( { Shape       => 'srcbanner',
                 Width       => 70,
                 SourceFile  => 'helloworld.pl',
                 Regex       => 1 } );

The generated program is easier to understand than the original because its characters are bigger and easier to read.

Converting from Perl 5 to Perl 6

You can convert Perl 5 programs to Perl 6 simply by arranging for them to impersonate the Perl 6 maestros, Larry Wall and Damian Conway:

print sightly( { Shape       => 'larry,damian',
                 Gap         => 2,
                 SourceFile  => 'helloworld.pl',
                 Regex       => 1 } );

producing:

                         ''=~('('.'?'.'{'
                      .('`'|'%').('['^"\-").(
                 '`'|'!').('`'|',').'"'.(('[')^
               '+').                         ('['
             ^')'                              ).(
           '`'|                                  ')'
         ).+(                                   (  '`'
        )|((                                    (   '.'
       ))))                                  .(  (    '['
     )^((                                   (     (    '/'
   )))                                    ))       .(   '{'
  ^((                                   ((           (   '['
 )))                                ))).              (   (((
(((                             '\\'                   )   )))
)))                         .'"'                        .   (((
'`'                ))|'(').(                            (   '`'
)|+              ((                                     (    ((
'%'             ))                                       )   ))
).(            (                                         (   ((
'`'            )                                          )))|+
','           )                                              .(
'`'           |          ',').('`'|'/').('{'^'[').('['^(',')).(
'`'           |'/').("\["^    "\)").(    (    (   "\`"))|     (
','           )          ) .+(  '`'  |+  (    ( ((  '$'  )))  )
).+           (          ( '\\')).'\\'.  (    ( '`')|('.')).  (
(((           (          (               (    (               (
((   (((     (           (               (    ((              (
((   (  '\\')            )               )     ))             )
))   )                   )               )     ) )            )
))   )  )))               ))).'"'.(';').(       ( '!')^('+')).
((    (                              (          (          (
 (     (                            (          (           (
  (     (                            ( '"'    )            )
   )      )))                              ))             )
    )       )                  ))).'}'.')');$:="\."^      (
     (      (                '~')));$~='@'|'(';$^=')'     ^
      (     (               '['));$/='`'|'.';$_=('(')^   (
       (   (                '}'))  );$,='`'|"\!";  ($\)  =
        ( (                 ')')  )              ^  '}' ;
         $:                 =((   '.'))^'~';$~='@'   |((
          (                                            (
          (                                           (
          (                                          (
         (       (                                  (
         (        (                                (
         (          (                             (
         (            (                          (
        (               (                       (   (
        (                 (                    (     (
       (                    '('              ))       )
      )                          )))))))))))            )


                  )))))))))))));(
                $^)=')'^'[';$/="\`"|
              '.';$_='('^'}';$,='`'|'!'
            ;$\=                     ')'^
          '}';                         ($:)
        ='.'                             ^'~'
       ;$~=                                 '@'|
      '(';                                   ($^)
     =')'                                     ^'['
    ;$/=                                       '`'|
   '.';                                         $_=
   '('^                                         '}';
  ($,)                                    ="\`"| '!';
  ($\)                                =')'     ^  '}'
  ;$:    =((                  ('.')))^          (  '~'
 );(     (  $~))           =((                  (  '@'
)))      |      '(';$^=')'^                     (  '['
);(      (                                      (  $/)
))=      (                                      (  '`'
))|      (                                       ( '.'
));     (                                        ( $_)
 )=(    (                                        ( '('
 ))     )                                        ^ '}'
; $,    =                                        ( ((
(  ((  (                                         ( ((
(   '`')       )))))))))              )|'!';     $\=
(    ')'    )^+         '}'        ;$:      =((  '.'
) )^  ((        '~'));$~             =('@')|      ((
( (   ((      ((  '(')  ))    )    )) ));(  $^    )
= (  ')'       )^"\[";$/=     (    '`')|'.';$_    =
(  (  ((                      (                  (
 (    ((                      (                 ((
 (    '('                     )                 ))
  )   )))                     )                )))
   ))^'}';                    (                $,)
     ='`'|              (     (    (          '!'
     )));(              (     (    (          $\)
     )))=((             ')'))^'}';$:         ='.'
     ^"\~";                                  ($~)
     =('@')|         '(';$^=')'^"\[";$/=    '`'|
      "\.";$_=    '('^'}';$,='`'|('!');$\= ')'^
       "\}";$:=  ((                     "\."))^
       '~';$~="\@"|  '(';$^=')'^'[';$/=  ('`')|
        '.';$_='('      ^'}';$,="\`"|    "\!";
         $\=')'^'}'                    ;($:)=
          '.'^('~');$~=            '@'|"\(";
           $^=')'^'[';$/='`'|'.';$_='('^'}'
           ;$,='`'|'!';$\=')'^'}';$:=('.')^
            '~';$~='@'|'(';$^=')'^('[');$/=
             '`'|'.';$_='('^'}';$,='`'|'!';
              $\=')'^'}';$:='.'^'~';$~='@'
                |'(';$^=')'^'[';$/=('`')|
                 '.';$_='('^'}';$,="\`"|
                   '!';$\=')'^('}');$:=
                     '.'^'~';$~=('@')|
                        '(';$^=')';

If you sincerely idolize Larry, you might put a picture frame around him:

print sightly( { Shape       => 'larry2',
                 BorderGap   => 3,
                 BorderWidth => 2,
                 SourceFile  => 'helloworld.pl',
                 Regex       => 1 } );

where the shape larry2 is a caricature contributed by Ryan King:

''=~('('.'?'.'{'.('`'|'%').('['^'-').('`'|'!').("\`"|
',').'"'.('['^'+').('['^')').('`'|')').('`'|'.').('['
^+                                                 ((
((                                                 ((
((                                                 ((
((                 '/')))))))))))                  ))
.(             '{'^'[').'\\'.'"'.('`'              |+
((            '('))).('`'|'%').('`'|','            ).
+(          '`'|(',')).( '`'|'/'). ('{'^           ((
((         '['))))).('['  ^',').(  ((  '`'         ))
|+        '/' ).('['^')') .("\`"|  (    ','        ))
.(       '`' |"\$").'\\'.  '\\'.  (      '`'       |+
((       '.' ))).('\\').   '"'.  (        ((       ((
((      ';') )))))).''.   ('!'             ^       ((
((     '+'))) )). '"'    . (             ((        ((
((    '}')))))) )      . (    (    (     ((        ((
((    ')')))))) ))));    $:='.'^'~';$~=('@')|      ((
((    '(')))); $^  ="\)"^      (( ((    (  ((      ((
((     '[')))))     )))         ) )     )   ;(     $/
)=    '`'|'.';       $_       = ( ( (    (  ((     ((
((     '('))))       ))         ) )      )  )^     ((
((      '}')))        );       $,  =(     '`'      )|
((       "\!"));  (    $\)=')'^     '}'; $:        =(
((        '.')))^ (        '~'); ($~)= ( ((        ((
((         '@'))))))      )|"\(";  $^=')'^'['      ;(
$/           )="\`"|   '.';$_='('   ^'}';$,='`'    |+
((            '!')) ; $\=(')')^        (  "\}");   $:
=(                (  '.'))      ^'~'     ;  ($~)   =(
((              ( (   '@'               )    )))   )|
((           '(' )    );  (            (     $^    ))
=(         ((  (       (    "\)")))))^       (     ((
((      '['     ))           )                     ))
;(     (         $/           ))                   =(
((   (             ((        (   (                 ((
((                   '`')))))     )                ))
))                                                 ))
|+                                                 ((
((                                                 ((
'.'))))));$_='('^'}';$,='`'|'!';$\=')'^'}';$:='.'^'~'
;$~='@'|'(';$^=')'^'[';$/='`'|'.';$_='('^'}';$,="\`";

Just another Perl hacker

Let's get more ambitious and create a big self-printing 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. If you want to use Regex => 1, ensure that the program to be converted does not use any regular expressions (and is careful with use of $_).

To produce a JAPH that resembles the original Just another Perl hacker, aka Randal L Schwartz, try this:

print sightly({ Shape        => 'merlyn',
                SourceString => 'Just another Perl hacker,',
                Regex        => 1,
                Print        => 1 } );

producing:

                      ''=~('('.'?'.'{'.('['
                   ^'+').('['^')').('`'|')').(
                '`'|'.').('['^'/').'"'.('`'^'*')
             .('['                          ^'.')
           .('['                              ^'(')
          .('['                                ^'/')
        .('{'^                                 '[').(
       "\`"|                                    '!').(
      '`'|                                      '.').(
     '`'|          (                (           '/'))).
   ('['            ^              ( (          '/'))).(
  '`'|           (              (  (         ( '('))))).
 ('`'|         (              (    (        (  '%'))))).
 ('['^       (              (    (        (    ')'))))).
 ('{'^      '[')        .(      (      ((      ('{'))))^
 '+').     (    '`'|'%'       ).("\["^         ')').('`'
|',').('{'^                                    '[').('`'
|'(').('`'                                      |"\!").(
'`'|'#').(        ('`')|             '+').(     '`'|'%')
.('['^')')     .((      ','       )).      '"'   .('}').
"\)");$:=         ('.')^       (     "\~");      $~='@'|
('(');$^=       (( ')'  ))     ^   (( '['  ))     ;($/)=
 '`'|'.';       $_='('^'}'     ;   $,='`'|'!'      ;($\)
 =(')')^                       (                    '}'
  );($:)                       =                    '.'
   ^'~';                     ( ( (                  $~)
   )  )=                    (  (  (                 '@'
   )   )                   ) | ( ( (               '('
   )   )                   ) ; ( ( (               $^
   )   )                                          ) =
    (  (                                         ( (
     ( (                                         ( (
      (               ')')))))))))^'['     ;    # ;
       #        ;    #                ;    #    ;#
       ;        #     ;              #    ;    #;
       #        ;      #;          #;    #    ;
       #        ;        #       ;#      ;   #
       ;        #          ;#;#;        #   ;
        #        ;                     #   ;
        #        ;                    #   ;
         #        ;                      #
          ;       #                     ;
           #      ;                    #
            ;      #                  ;
             #                      ;
               #                  ;
                 #;#           ;#
                     ;#;#;#;#;

Buffy Looking in the Mirror

Because the sightly encoding is not very compact, you sometimes find yourself playing a surreal form of Perl Golf, where the winner is the one with the smallest f.tmp in:

sightly.pl -r -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 Buffy looking in the mirror. Let's start with k.pl:

open$[;chop,($==y===c)>$-&&($-=$=)for@:=<0>;
print$"x-(y---c-$-).reverse.$/for@:

Notice that EyeDrops-generated programs contain no trailing spaces, which complicates the above program.

Buffy looking in the mirror can now be created with:

sightly.pl -r -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 buffy2 shapes. What to do? Well, you could write a post processor program, pp.pl, to append the required number of spaces to each line:

chop,$==y===c,$=<$-or$-=$=for@a=<>;
print$_.($"x($--length)).$/for@a

With this program in place, we can write a briefer kk.pl:

open$%;chop,print+reverse.$/for<0>

and finally produce Buffy looking in the mirror with:

sightly.pl -r -f kk.pl -s buffy2 >b.pl
perl pp.pl b.pl >bb.pl

For this example, however, the Compact attribute provides a more direct solution, without requiring any trailing spaces:

sightly.pl -mr -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 buffy.pl:

                   ''=~('(?{'.(
                '`'|'%').('['^'-'
              ).('`'|'!').('`'|','
             ).+               ( '"'
            ).(                (  '`'
           )|+                 (   '/'
          )).                  (   '['
         ^((                  (     '+'
        )))              ).('`'      |((
        '%'          ))).      (     '`'
       |((       '.')           )     ).+
       (((     ((                (     (((
       (((    (                   (    (((
       (((   (                     '\\')))
      )))    )                      ) )  )
      )   )))) ))))))      .'$[;'     .  (
      (  (  ((                        (  (
      (  (      ( (( (     ( (( (     (   (
      (  (       '`')       ))))      )   )
      )   )                        )))    )
      )    )))                     )      )
      )|      (       (   (        (     ((
      '#'      )        )          )    )))
       ).(('`')|                   ('(')).(
       '`'|'/').    ('['^'+')     .',(\\$'
       .'=='.('['     ^'"')     . '==='.+(
       '`'|'#').')'            .  '>\\$-'
       .'&&(\\$-=\\'          .   '$=)'.(
       '`'|'&').('`' |      (     '/')).(
       '['^')').'\\'     .        '@:=<' .
       ('^'^(('`')|              "\.")).   (
       '>').(';').(              '!'^'+'     )
        .('['^'+').             ('['^')'     ).('`'|
        ')').("\`"|             "\.").(      (      ('['))^
  "\/").'\\$\\"'.(            ( "\[")^       (             (
 (    ( "\#"))))). (        (   '-'))        .              (
(     ( ('(')))).(   (   (     '['))         ^              (
(     '"'))).'--'       .     '-'.           (              (
(    '`'))|'#').        (                    (               (
(     '-')))).          (                    (               (
(     ( '\\'                                 )               )
)     )                                      )               .
(     (                                      (               (
(     (                                      (      (         (
(     (                                      (      (         (
(     (                                      (     (          (
(     (                                      (     (          (
(     '$'))))))))))))))))))))))))).'-).'.('['^    (           (
(    ')')))).('`'|'%').('['^'-').('`'|'%').(('[')^            (
(    ')'))).('['^'(').('`'|'%').'.\\$/'.('`'|'&').(           (
(   '`'))|'/').('['^')').'\\@:'.('!'^'+').'"})');$:=          (
(   '.'))^'~';$~='@'|'(';$^=')'^'[';$/='`'|'.';$_='('         ;

This is perhaps a cleaner solution, though some people find the plain sightly encoding more pleasing to the eye.

Interestingly, showing the face upside down, rather than reflected, is more easily solved with:

open$%;print+reverse<0>

and easier still for a self-printing shape:

open$%;print<0>

Twelve Thousand and Thirty Two Camels

Let's extend the Buffy example of the previous section to produce a camel-shaped program capable of emitting twelve thousand and thirty two different camels when run.

We start with a generator program, gencamel.pl:

my $src = <<'END_SRC_STR';
$~=uc shift;$:=pop||'#';open$%;chop(@~=<0>);$~=~R&&
(@~=map{$-=$_+$_;join'',map/.{$-}(.)/,@~}$%..33);
$|--&$~=~H&&next,$~!~Q&&eval"y, ,\Q$:\E,c",$~=~I&&
eval"y, \Q$:\E,\Q$:\E ,",$~=~M&&($_=reverse),
print$~=~V?/(.).?/g:$_,$/for$~=~U?reverse@~:@~
END_SRC_STR
$src =~ tr/\n//d;
my $prog = sightly( { Regex         => 1,
                      Compact       => 1,
                      Shape         => 'camel',
                      SourceString  => $src } );
my @a = split(/\n/, $prog);
my $max = 0; length > $max and $max = length for @a;
$_ .= ' ' x ($max - length) for @a; $\ = "\n";
print ' ' x ($max+2); print " $_ " for @a; print ' ' x ($max+2);

Note the use of the Compact attribute, necessary here to squeeze the above program into a single camel shape.

Running this program:

perl gencamel.pl >camel.pl

produces camel.pl:

                                      ''=~('(?{'.(                
           ('`')|                   '%').('['^'-').               
        ('`'|'!').                ('`'|',').'"\\$~='              
 .('['^'.')  .('`'|              '#').('{'^'[').('['^             
'(').('`'|'(').('`'|            ')').('`'|'&').(('[')^            
'/').';\\$:='.(('[')^          '+').('`'|'/').('['^'+'            
  ).'||'."'".'#'."'".        ';'.('`'|'/').('['^"\+").(           
       '`'|'%').('`'|      '.').'\\$%;'.('`'|'#').("\`"|          
      '(').('`'|'/')     .('['^'+').'(\\@~=<'.('^'^("\`"|         
     '.')).'>);\\$~'   .'=~'.('{'^')').'&&(\\@~='.('`'|'-'        
    ).('`'|('!')).(   '['^'+').'\\{\\$-=\\$_+\\$_;'.('`'|'*'      
    ).('`'|('/')).(  '`'|')').('`'|'.')."'"."'".','.('`'|'-')     
    .('`'|('!')).(  '['^'+').'/.\\{\\$-\\}(.)/,\\@~\\}\\$%..'     
    .('^'^('`'|'-'  )).('^'^('`'|'-')).');\\$|--&\\$~=~'.('`'^    
    '(').'&&'.('`'|'.').('`'|'%').('['^'#').('['^'/').',\\$~!'    
    .'~'.('{'^'*').'&&'.('`'|'%').('['^'-').('`'|'!').('`'|',')   
     .'\\"'.('['^'"').','.('{'^'[').',\\\\'.('{'^'*').'\\$:\\'.   
     '\\'.('`'^'%').','.('`'|'#').'\\",\\$~=~'.('`'^"\)").'&&'.(  
      '`'|'%').('['^'-').('`'|'!').('`'|',').'\\"'.('['^'"').','. 
       ('{'^'[').'\\\\'.('{'^'*').'\\$:\\\\'.('`'^"\%").',\\\\'.( 
        '{'^'*').'\\$:\\\\'.('`'^'%').('{'^'[').',\\",\\$~=~' .+( 
         '`'^'-').'&&(\\$_='.('['^')').('`'|'%').('['^'-').(  '`' 
          |'%').('['^')').('['^'(').('`'|'%').'),'. ('['^'+'  ).( 
            '['^')').('`'|')').('`'|'.').('['^'/')  .'\\$~'   .(( 
             '=')) .'~'.('{'^'-').'?/(.).?/'.('`'   |"\'").   ':' 
                   .'\\$_,\\$/'.('`'|'&').("\`"|    "\/").(   '[' 
                   ^(')')).    '\\$~=~'.( ('{')^     "\.").   ((  
                   '?')).(     '['^')')   .('`'|     '%').(  ((   
                   "\["))^     ('-')).(   "\`"|       '%').  (    
                   ('[')^      (')')).(   '['^         '(')       
                   .('`'|     '%').'\\'   .'@'         .'~'       
                    .':'.     '\\@~"}'    .')'         );$:       
                    ='.'^     '~';$~=     '@'|         '(';       
                    ($^)     ="\)"^       '[';         ($/)       
                    ='`'     |((          '.')         );$_       
                    ='('      ^((         '}'          ));        
                    $,=        '`'       |((           '!'        
                    ));         $\=     ')'            ^((        
                    '}'          ));   $:=              ((        
                    ((             '.')))               )^        
                    ((              '~'))               ;(        
                    $~             )=('@')|             ((        
                   '('            ));( ($^))            =(        
                  ')'           )^'[';  ($/)           =((        
                 '`')         )|'.';$_   =((          '(')        
               )^'}';                                $,='`'       
             |'!';$\=                               ')'^'}'       

Notice that the camel-shaped program above needs a leading and trailing line of spaces for best results with inverted shapes.

You can run camel.pl like this:

perl camel.pl           normal camel
perl camel.pl q         quine (program prints itself)
perl camel.pl m         mirror (camel looking in the mirror)
perl camel.pl i         inverted camel
perl camel.pl u         upside-down camel
perl camel.pl r         rotated camel
perl camel.pl h         horizontally-squashed camel
perl camel.pl v         vertically-squashed camel

And can further combine the above options, each combination producing a different camel, for example:

perl camel.pl uri

produces a large, bearded camel with a pony-tail, glasses, and a tie-dyed T-shirt. :)

camel.pl also accepts an optional second argument, specifying the character to fill the camel with (default '#'). For example:

perl camel.pl hv        small camel filled with #
perl camel.pl hv "$"    small camel filled with $

Why 12,032 camels? Combining the main options q, m, i, u, r, h, v can produce 128 different camels. And there are 94 printable characters available for the second argument, making a total of 128 * 94 = 12,032 camels.

Dueling Dingos

During the TPR02 Perl Golf tournament, `/anick composed a poem describing his experience, entitled Dueling Dingos.

You can produce a program that emits his superb poem like this:

print sightly( { Shape        => 'yanick3',
                 Regex        => 1,
                 Print        => 1,
                 SourceString => <<'END_DINGO' } );
#!/usr/bin/perl
# Dueling Dingos v1.1, by Yanick Champoux (9/4/2002)
#
# Inspired by the TPR(0,2) Perl Golf contest.
# Name haven't been changed, since the involved
# parties could hardly be labelled as 'innocent',
# and are way far too gone to protect anyway.

wait until localtime > @April[0];  # wait until the first of April

BEGIN{}

study and seek FOR, $some, $inspiration;

write $stuff;

$score = 145; # no good;

delete $stuff { I_can_do_without }
   and do $more_stuff;

delete $even{more_stuff};

reverse $engineer; study; eval $strategy and redo;

write, write, write;
delete $_{'!'}, delete $"{"@!"}, delete $@{'*'}; # must stop cursing

use less 'characters', $durnit;

read THE, $current, $solution;

not 2, $bad;

delete $white_spaces{''} until $program == glob;

for( $all, my @troubles )
{
    unlink 1, $character;
}

ARGH:

$must, not $despair;

$I->can(do{ $it });

study new Idea;

m/mmmm/m... do{able};

kill $chickens;

'ask', $Nanabozo, 2, bless $me, 'with more inspiration';

$so, close; warn $mailing_list and alarm $Andrew;

$toil until my $solution < /-\ndrew's
/;

GOT_IT:

send $solution, $to, ref;

$brain, shutdown  I,'m dead';

goto sleep;

wait; $till, $the, $day, $after;

readline last $scoreboard;

grep $all, stat;

read THE, $stats, $again until $it_sinks_in;

$Andrew,'s score' lt $mine;

$eyeball, pop @o
;
END_DINGO

The generated program, being 2577 lines long, is not reproduced here. To generate a shorter program summarising `/anick's TPR02 anguish:

print sightly( { Shape        => 'yanick,eye,mosquito,coffee',
                 Gap          => 3,
                 Regex        => 1,
                 Print        => 1,
                 SourceString => <<'END_SUFFERING' } );
My head is hurting, my right eye feels like it's going to pop
like a mosquito drinking from an expresso addict with high
blood pressure, I want to crawl somewhere damp and dark and
quiet and I consider never to touch a keyboard again.
END_SUFFERING

producing:

                            ''=~('('.'?'.'{'.(
                         '['^'+').('['^')').('`'|
                       ')').('`'|'.').('['^'/').'"'
                     .('`'^'-').('['^'"').('{'^'[').(
                    '`'|'(').('`'|'%').('`'|'!').("\`"|
                   '$').('{'^'[').('`'|')').('['^('(')).(
                  '{'^'[').('`'|'(').('['^'.').('['^"\)").(
                 '['^'/').('`'|')').('`'|'.').('`'|"'").','.
                ('{'^'[').('`'|'-').('['^'"').('{'^'[').('['^
                ')').('`'|')').('`'|"'").('`'|'(').('['^'/').(
               '{'^'[').('`'|'%').('['^'"').('`'|'%').('{'^'['
              ).('`'|'&').('`'|'%').('`'|'%').('`'|',').(('[')^
             '(').('{'^'[').('`'|',').('`'|')').('`'|'+').("\`"|
            '%').('{'^'[').('`'|')').           ('['^    ('/')).
           "'".('['^'(').('{'^'[').                       ("\`"|
           "'").('`'|'/').('`'|')'                         ).''.
          ('`'|'.').('`'|"'").('{'                         ^'[')
    .('[' ^'/').('`'|'/').(('{')^                          '[').
 ('['^'+'  ).('`'|'/').('['^'+').                          ('!'^
'+').('`'  |',')  .('`'|(')')).(                           "\`"|
'+').('`'  |'%'    ).('{'^'[').                            ('`'|
'!').('{'     ^      ('[')).(                              "\`"|
'-').('`'     |      "\/").(                               "\["^
'(').('['     ^       '*'                                   ).(
'['^'.'       )     .+(             (  ( (            ( (    (
'`')))        )   ))                         |      (        (
')'))         )                   .               (         (
'[')^         (                                            (
'/'))         )                      .('`'|        '/').  (
"\{"^          '['                   ).('`'        |'$') .
('['^           (                                (      (
')'))            )                               )     .
('`'|            (                  ')'))        .     (
"\`"|             (            '.'))              .   (
"\`"|              (                               ( (
'+')))              )           .(         (       (
"\`"))|              (           ((         (       (
')'))))))             .           +(         (     (
'`'))|'.').(           (           ((          ( (
'`')))))|"'").('{'^'[').(            ((         (
'`')))|'&').('['^')').('`'|            ((     (
'/')))).('`'|'-').('{'^'[').             ('`'
|'!').('`'|'.').('{'^'[').('`'             |
'%').('['^'#').('['^'+').("\["^          (
')')).('`'|'%').('['^('(')).(     '['^'('
).('`'|'/').('{'^'[').("\`"|
'!').('`'|'$').('`'|"\$").(



                         '`'|')').(('`')|
                   (  '#')).('['^'/').("\{"^  (
               (    '['))).('['^',').('`'|')')    .
            (     '['^'/').('`'|'(').('{'^'[').(     (
         (       '`'))|'(').('`'|')').('`'|"'").(       (
       (        '`'))|'(').('!'^'+').('`'|('"')).(        (
     (          '`'))|',').('`'|'/').('`'|('/')).(          (
   (           '`'))|'$').('{'^'[').('['^'+').('['^           (
 (             ')'))).('`'|'%').('['^'(').('['^'(')             .
(              '['^'.').('['^')').('`'|'%').(',').(              (
 (             '{'))^'[').('`'^')').('{'^'[').('['^             (
   (           ','))).('`'|'!').('`'|'.').('['^'/')           .
     (          '{'^'[').('['^'/').('`'|'/').('{'^          (
       (        '['))).('`'|'#').('['^')').(('`')|        (
         (       '!'))).('['^',').('`'|',').('{'^       (
            (     '['))).('['^'(').('`'|('/')).(     (
               (    '`'))|'-').('`'|'%').('['^    (
                   (  ','))).('`'|'(').('`'|  (
                         '%')).('['^')').



             +(                                                 ((
            '`'))                                             |  (
           "\%")).(                                         (   (
           '{'))^'['                 )  .                 (   (
           '`')|'$').(               (  (               (   (
           '`'))))|'!')              .  (            (   (
            '`'))|'-').(             (  (          (   (
             '['))))^'+')            .  (        (    (
              '{'))^'[').(           (  (     (    (
                '`'))))|'!'          ) .   (     (
   '`')|'.'       ).('`'|'$'         ) .  (  (
'{')^'[').('`'|      ('$')).(  '`'| '!' )  .
('['^')').('`'|'+')     .('{'^'[').('`'| (
 '!')).('`'|'.').('`'|'$').('!'^"\+").( (
  '[')^'*').('['^'.').('`'|')').('`'|'%'
   ).('['^'/').('{'^'[')   .('`'|'!').
     ('`'|('.')).(       '`'|('$')).(
                            '{'^'['
                           ).( '`'
                          ^+ ( ( (
                          (( ( ( (
                         (( ( (  (
                        (( (  (  (
                       ((  ( (   (
                    ')')  )  )   )
                     )) ) )  )   )
                        ) )  )   )
                        ) )  )  )
                        ) ) )   )
                       )  ) .   (
                       (  ( (  (
                       (  ( (  (
                       (  ( ( (
                       ( ( (  (
                       '{'))))
                       ))))))
                       )))))
                      )^'['
                     ).''.
                    ('`'|



'#').('`'|'/').('`'|'.').('['^'(').(('`')|   ')').(
'`'|'$').('`'|'%').('['^')').('{'^('[')).( '`'|'.').
('`'|'%').('['^'-').('`'|'%').('['^')').('{'^    '['
).('['^'/').('`'|'/').('{'^'[').('['^'/').(      '`'
|'/').('['^'.').('`'|'#').('`'|'(').("\{"^       '['
 ).('`'|'!').('{'^'[').('`'|'+').('`'|'%'       ).(
 '['^'"').('`'|'"').('`'|'/').('`'|'!').(     '['^
  ')').('`'|'$').('{'^'[').('`'|('!')).(    '`'|
   "'").('`'|'!').('`'|')').('`'|"\.").   '.'.
    ('!'^'+').'"'.'}'.')');$:='.'^('~');$~=
     '@'|'(';$^=')'^'[';$/='`'|'.';$_='('
       ^'}';$,='`'|'!';$\=')'^'}';$:=
         '.'^'~';$~='@'|('(');$^=
           ')'^'[';$/='`'|'.'

Encoding Binary Files

But wait, there's more. You can encode binary files too.

print sightly({Shape      => 'camel,mongers',
               SourceFile => 'some_binary_file',
               Binary     => 1,
               Print      => 1,
               Gap        => 3 } );

This is prettier than uuencode/uudecode. Here is how you encode/decode binary files with sightly.pl.

To encode:

sightly.pl -g3 -bps camel,mongers -f some_binary_file >eyesore

To decode:

perl eyesore >f.tmp

To verify it worked:

cmp f.tmp some_binary_file

A Slow Day

On a really slow day, you can sit at your Unix terminal and type things like:

sightly.pl -r -s camel -f helloworld.pl >t1.pl
cat t1.pl
perl t1.pl

Just one camel needed for this little program.

sightly.pl -r -s camel -f t1.pl >t2.pl
cat t2.pl
perl t2.pl

Hmm. 14 camels now.

sightly.pl -r -s camel -f t2.pl >t3.pl
ls -l t3.pl
cat t3.pl
perl t3.pl

195 camels. 563,745 bytes. Hmm. Getting slower. Is this the biggest, slowest hello world program ever written?

sightly.pl -r -s camel -f t3.pl >t4.pl
ls -l t4.pl
cat t4.pl
perl t4.pl

2046 camels. 5,172,288 bytes. Out of memory!

Buffy Goes to the Cricket

Buffy fans might like to rotate her letters:

print sightly( { Shape       => 'buffy',
                 Rotate      => 0,  # try 270, 90 and 180
                 RotateType  => 1,  # try 0, 1, 2
                 SourceFile  => 'helloworld.pl',
                 Regex       => 1 } );

or have her ride a pony:

print sightly( { Shape        => 'buffy3,buffy4,riding,a,pony',
                 SourceString => "This is how Catherine the ".
                                 "Great died.\n",
                 Gap          => 2,
                 Regex        => 1,
                 Print        => 1 } );

while cricket fans could compare:

print sightly( { Shape       => 'cricket',
                 SourceFile  => 'helloworld.pl',
                 Regex       => 1 } );

which produces:

                    '?'
                   =~+(
                  "\(".
                 "\?".
               "\{".(
              ('`')|
             '%').(
            ('[')^
           '-').(    "\`"|
          '!').(   '`'|',')
     .'"'.('['    ^'+').('['
     ^"\)").(     '`'|"\)").(
   '`'|'.')       .('['^'/')
   .(('{')^       '[').'\\'.
 '"'.(('`')|       '(').('`'
|'%').('`'|','      ).("\`"|
"\,").( '`'|'/')    .('{'^'[').
(('[')^  ',').('`'|'/').(('[')^
 "\)").(  '`'|',').('`'|'$').''.
  ('\\').  '\\'.('`'|"\.").'\\'.
    ('"').  ';'.('!'^'+').('"').
     '}'.')');$:='.'^'~';$~='@'|
     '(';$^=')'^'[';$/='`'|'.';$_
      ='('^'}';$,='`'|'!';$\=')'^
       '}';$:=   '.'^'~';$~="\@"|
        '(';      $^=')'^"\[";$/=
                  '`'|'.';$_='('^
                  '}';$,='`'|"\!";
                  $\=')'^('}');$:=
                  '.'^'~';$~="\@"|
                  '(';$^=')'^"\[";
                 $/='`'|'.';$_='('
                ^'}';$,='`'|'!';$\=
              ')'^'}';$:='.'^'~';$~=
             '@'|'(';$^=')'^('[');$/=
             '`'|'.';$_='('^'}';$,='`'
            |'!';$\=')'^'}';$:='.'^'~';
           $~='@'|'(';$^=')'^'[';$/='`'|
    (     '.');$_='('^'}'   ;$,='`'|"\!";
     $\   =')'^"\}";$:=      '.'^('~');$~=
      '@' |'(';$^=')'^        '[';$/=('`')|
      '.';$_=('(')^            '}';$,=('`')|
      '!';$\=(')')^             '}';$:=('.')^
      '~';$~='@'|'('              ;$^=')'^'[';
       $/='`'|('.');$_=            '('^"\}";$,=
        '`'|'!';$\=')'^'}'           ;$:='.'^'~'
           ;$~='@'|('(');$^=          ')'^"\[";$/=
              '`'|'.';$_='('           ^'}';$,='`'|
                    '!';$\=              ')'^'}';$:=
                     "\."^                 '~';$~='@'|
                    "\(";                    $^=')'^'['
                    ;$/=                      '`'|'.';
                    $_=                         "\(";

to:

print sightly( { Shape       => 'cricket',
                 Invert      => 1,
                 BorderWidth => 2,
                 SourceFile  => 'helloworld.pl',
                 Regex       => 1 } );

which produces:

''=~('('.'?'.'{'.('`'|'%').('['^'-').('`'|'!').('`'|(',')).
'"'.('['^'+').('['^')').('`'|')').('`'|'.').('['^'/').('{'^
'[').'\\'.'"'.('`'|'('   ).('`'|'%').('`'|',').('`'|"\,").(
'`'|'/').('{'^"\[").(    '['^',').('`'|'/').('['^')').('`'|
',').('`'|'$').'\\'.     '\\'.('`'|'.').'\\'.'"'.';'.("\!"^
'+').'"'.'}'."\)");     $:='.'^'~';$~='@'|'(';$^=')'^'[';$/
='`'|'.';$_="\("^      '}';$,='`'|'!';$\=')'^'}';$:='.'^'~'
;$~='@'|"\(";$^=      ')'^'[';$/='`'|'.';$_='('^'}';$,='`'|
'!';$\=')'^'}';      $:='.'^'~';$~='@'|'(';$^=')'^('[');$/=
'`'|'.';$_='('      ^'}';$,='`'|'!';$\=')'^'}';$:='.'^"\~";
$~='@'|'(';$^      =')'     ^'[';$/='`'|'.';$_='('^"\}";$,=
'`'|"\!";$\=      ')'        ^'}';$:='.'^'~';$~='@'|'(';$^=
')'^'['         ;$/=          '`'|'.';$_='('^'}';$,='`'|'!'
;$\=')'        ^'}';           $:='.'^'~';$~='@'|'(';$^=')'
^'[';        $/='`'|          '.';$_='('^'}';$,='`'|'!';$\=
"\)"^        '}';$:=          '.'^'~';$~='@'|'(';$^=')'^'['
;$/           =('`')|         '.';$_='('^'}';$,='`'|'!';$\=
((              ')'))^        '}';$:='.'^'~';$~='@'|'(';$^=
((       (        ')')           ))^'[';$/='`'|'.';$_="\("^
((       ((                      '}'))));$,='`'|'!';$\=')'^
'}'       ;(                      $:)='.'^'~';$~='@'|'(';$^
=')'       ^+                     '[';$/='`'|'.';$_='('^'}'
;($,)=      ((                    '`'))|'!';$\=')'^"\}";$:=
'.'^'~'                           ;$~='@'|'(';$^=')'^'[';$/
=('`')|                            '.';$_='('^'}';$,=('`')|
"\!";$\=                           ')'^'}';$:='.'^('~');$~=
'@'|"\(";       $^=                ')'^'[';$/='`'|('.');$_=
'('^'}';$,    ="\`"|               '!';$\=')'^'}';$:=('.')^
'~';$~='@'|('(');$^=               ')'^'[';$/='`'|('.');$_=
'('^'}';$,='`'|"\!";                $\=')'^'}';$:='.'^"\~";
$~='@'|'(';$^=(')')^                '[';$/='`'|'.';$_="\("^
'}';$,='`'|('!');$\=                ')'^'}';$:='.'^"\~";$~=
'@'|'(';$^=')'^"\[";                $/='`'|'.';$_='('^"\}";
$,='`'|'!';$\="\)"^                 '}';$:='.'^'~';$~="\@"|
'(';$^=')'^'[';$/=                   '`'|'.';$_='('^'}';$,=
'`'|'!';$\="\)"^                      '}';$:='.'^'~';$~='@'
|'(';$^=')'^'['                        ;$/='`'|'.';$_="\("^
'}';$,='`'|'!';                         $\=')'^'}';$:="\."^
'~';$~='@'|'('                           ;$^=')'^'[';$/='`'
|'.';$_="\("^                             '}';$,='`'|'!';$\
="\)"^ "\}";               $:=             '.'^'~';$~="\@"|
'(';$^=  ')'             ^"\[";             $/='`'|"\.";$_=
'('^'}';   (            $,)='`'|             '!';$\=')'^'}'
;$:='.'^             '~';$~="\@"|             '(';$^=(')')^
"\[";$/=             '`'|('.');$_=             '('^"\}";$,=
'`'|'!';              $\=')'^'}';$:=            '.'^'~';$~=
'@'|"\(";                $^=')'^"\[";            $/='`'|'.'
;$_=('(')^                  '}';$,='`'|           ('!');$\=
')'^('}');$:=                 '.'^'~';$~            =('@')|
'(';$^=')'^"\[";              $/='`'|'.';            $_='('
^'}';$,='`'|'!';$\=')'       ^'}';$:=('.')^           "\~";
$~='@'|'(';$^=')'^"\[";     $/='`'|'.';$_='('           ^((
'}'));$,='`'|('!');$\=     ')'^'}';$:='.'^"\~";          $~
='@'|'(';$^=')'^'[';$/    ='`'|'.';$_='('^'}';$,        =((
'`'))|'!';$\=')'^"\}";   $:='.'^'~';$~='@'|'(';$^=     ')'^
'[';$/='`'|'.';$_='('^'}';$,='`'|'!';$\=')'^'}';$:='.'^'~';
$~='@'|'(';$^=')'^'[';$/='`'|'.';$_='('^'}';$,='`'|"\!";#;#

to:

print sightly( { Shape       => 'cricket',
                 Invert      => 1,
                 BorderWidth => 1,
                 Reduce      => 1,
                 SourceFile  => 'helloworld.pl',
                 Regex       => 1 } );

which produces:

''=~('('.'?'.'{'.('`'|('%')).(
'['^"\-").(  '`'|'!').('`'|','
).'"'.('['   ^'+').('['^')').(
'`'|')').   ('`'|'.').('['^'/'
).("\{"^   '[').'\\'.'"'.('`'|
"\(").(   ((  '`'))|'%').('`'|
',')    .(     '`'|',').("\`"|
'/'    ).(     '{'^'[').("\["^
((     ',')    )).('`'|"\/").(
(        ((      '[')))^')').(
((   (           '`')))|',').(
'`'   |          '$').'\\'.''.
'\\'              .('`'|"\.").
'\\'.   ((        '"'))."\;".(
'!'^"\+").        '"'.'}'.')')
;$:=('.')^        '~';$~="\@"|
'(';$^=')'        ^'[';$/='`'|
('.');$_=          '('^'}';$,=
'`'|'!';            $\=')'^'}'
;$:='.'              ^"\~";$~=
'@' |+        (       '(');$^=
')'^        '[';       $/='`'|
'.';       $_='('       ^"\}";
($,)=        ('`')|      "\!";
$\=')'^        "\}";      ($:)
='.'^'~';$~    =('@')|     '('
;$^=')'^'['   ;$/=('`')|     (
'.');$_='('  ^'}';$,='`'|   ((
'!'));$\=')'^'}';$:='.'^'~';#;

REFERENCE

Sightly Encoding

There are 32 characters in the sightly character set:

! " # $ % & ' ( ) * + , - . /            (33-47)
: ; < = > ? @                            (58-64)
[ \ ] ^ _ `                              (91-96)
{ | } ~                                  (123-126)

A sightly string consists only of characters drawn from this set.

The ascii_to_sightly function converts an ASCII string (0-255) to a sightly string; the sightly_to_ascii function does the reverse.

Function Reference

ascii_to_sightly STRING

Given an ascii string STRING, returns a sightly string.

sightly_to_ascii STRING

Given a sightly string STRING, returns an ascii string.

regex_print_sightly STRING

Given an ascii string STRING, returns a sightly-encoded Perl program with a print statement embedded in a regular expression. When run, the program will print STRING.

regex_eval_sightly STRING

Given a Perl program in ascii string STRING, returns an equivalent sightly-encoded Perl program using an eval statement embedded in a regular expression.

clean_print_sightly STRING

Given an ascii string STRING, returns a sightly-encoded Perl program with a print statement executed via eval. When run, the program will print STRING.

clean_eval_sightly STRING

Given a Perl program in ascii string STRING, returns an equivalent sightly-encoded Perl program using an eval statement executed via eval.

regex_binmode_print_sightly STRING

Given an ascii string STRING, returns a sightly-encoded Perl program with a binmode(STDOUT) and a print statement embedded in a regular expression. When run, the program will print STRING. Note that STRING may contain any character in the range 0-255. This function is used to sightly-encode binary files. This function is dodgy because regexs don't seem to like binary zeros; use clean_binmode_print_sightly instead.

clean_binmode_print_sightly STRING

Given an ascii string STRING, returns a sightly-encoded Perl program with a binmode(STDOUT) and a print statement executed via eval. When run, the program will print STRING. Note that STRING may contain any character in the range 0-255. This function is used to sightly-encode binary files.

get_builtin_shapes

Returns a list of the built-in shape names.

get_eye_shapes

Returns a list of the eye shapes. An eye shape is just a file with a .eye extension residing in the same directory as EyeDrops.pm.

border_shape SHAPESTRING GAP_LEFT GAP_RIGHT GAP_TOP GAP_BOTTOM WIDTH_LEFT WIDTH_RIGHT WIDTH_TOP WIDTH_BOTTOM

Put a border around a shape.

invert_shape SHAPESTRING

Invert a shape.

reflect_shape SHAPESTRING

Reflect a shape.

reduce_shape SHAPESTRING FACT

Reduce the size of a shape by a factor of FACT.

expand_shape SHAPESTRING FACT

Expand the size of a shape by a factor of FACT.

rotate_shape SHAPESTRING DEGREES RTYPE FLIP

Rotate a shape clockwise thru 90, 180 or 270 degrees. RTYPE=0 big rotated shape, RTYPE=1 small rotated shape, RTYPE=2 squashed rotated shape. FLIP=1 to flip (reflect) shape in addition to rotating it. RTYPE and FLIP do not apply to 180 degrees.

pour_sightly SHAPESTRING PROGSTRING GAP RFILLVAR COMPACT

Given a shape string SHAPESTRING, a sightly-encoded program string PROGSTRING, and a GAP between successive shapes, returns a properly shaped program string. RFILLVAR is a reference to an array of filler variables. A filler variable is a valid Perl variable consisting of two characters: $ and a punctuation character. For example, RFILLVAR = [ '$:', '$^', '$~' ]. If COMPACT is 1, use compact sightly encoding, if 0 use plain sightly encoding.

sightly HASHREF

Given a hash reference, HASHREF, describing various attributes, returns a properly shaped program string.

The attributes that HASHREF may contain are:

Shape         Describes the shape you want.
              First, a built-in shape is looked for. Next, a
              'eye' shape (.eye file in the same directory
              as EyeDrops.pm) 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.

SourceString  Specify a string instead of a file name.

BannerString  String to use with built-in Shape 'banner'.

Regex         Boolean. If set, try to embed source program
              in a regular expression. 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.

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       Reflect the shape.

Reduce        Reduce the size of the shape.

Expand        Expand the size of the shape.

Invert        Invert the shape.

Indent        Indent the shape. The number of spaces to indent.

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,
              specifies the shape width in characters.

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 => [ '$:', '$^' ]

Shape Reference

When you specify a shape like this:

sightly( { Shape => 'camel' ...

EyeDrops looks for the file camel.eye in the same directory as EyeDrops.pm. You can also specify a shape with a file name:

sightly( { Shape => '/tmp/camel.eye' ...

or with a string, for example:

my $shapestr = <<'GROK';
         #####
#######################
GROK
sightly ( { ShapeString => $shapestr ...

The shapes (.eye files) distributed with this version of EyeDrops are:

a           Horizontal banner of "a"
bleach      Vertical banner of "use Acme::Bleach;"
buffy       Vertical banner of "Buffy"
buffy2      Buffy's angelic face
buffy3      Buffy riding a pony
buffy4      Horizontal banner of "Buffy"
camel       Dromedary (Camelus dromedarius, one hump)
camel2      Another dromedary (from use.perl.org)
camel3      London.pm's bactrian camel at London zoo
coffee      A cup of coffee
cricket     Australia are world champions in this game
damian      Damian Conway's face
dipsy       Teletubbies Dipsy (also london.pm infobot name)
eugene      Champion Perl golfer, Eugene van der Pijll
eye         An eye
golfer      A golfer hitting a one iron
japh        JAPHs were invented by Randal L Schwartz in 1988
kermit      Kermit the frog
larry       Larry Wall's face
larry2      Caricature of Larry contributed by Ryan King
london      Haiku "A Day in The Life of a London Perl Monger"
merlyn      Just another Perl hacker, aka Randal L Schwartz
mongers     Perl Mongers logo
mosquito    A mosquito
pgolf       Perl Golf logo (inspired by `/anick)
pony        Horizontal banner of "Pony"
pony2       Picture of a Pony
riding      Horizontal banner of "riding"
santa       Santa Claus playing golf
spoon       A wooden spoon
tpr         Vertical banner of "The Perl Review"
uml         A UML diagram
window      A window
yanick      Caricature of `/anick's noggin
yanick2     Uttered by `/anick during TPR02
yanick3     Pictorial version of yanick2

It is easy to create your own shapes. For some ideas on shapes, point your search engine at Ascii Art or Clip Art. If you generate some nice shapes, please send them in so they can be included in future versions of EyeDrops.

BUGS

A really diabolical shape with lots of single character lines will defeat the shape-pouring algorithm.

You can eliminate all alphanumerics (via Regex => 1) only if the program to be converted does not use regular expressions and is careful with use of $_. To convert complex programs, you must use Regex => 0, which emits a leading unsightly eval.

The code generated by Regex => 1 requires Perl 5.005 or higher in order to run; when run on earlier versions, you will likely see the error message: Sequence (?{...) not recognized.

The converted program runs inside an eval which may cause problems for non-trivial programs. A die statement or an INIT block, for instance, may cause trouble. If desperate, give the TrapEvalDie and TrapWarn attributes a go, and see if they fix the problem.

If the program to be converted uses the Perl format variables $:, $~ or $^ you may need to explicitly set the FillerVar attribute to a Perl variable/s not used by the program.

Linux /usr/games/banner does not support the following characters:

\ [ ] { } < > ^ _ | ~

When the CPAN Text::Banner module is enhanced, it will be used in place of the Linux banner command.

AUTHOR

Andrew Savige <asavige@cpan.org>

SEE ALSO

Perl Obfuscation Engines, for example, yaoe by Perl Monk mtve, at http://www.frox25.dhs.org/~mtve/code/eso/perl/yaoe/.

Acme::Bleach Acme::Smirch Acme::Buffy Acme::Pony

CREDITS

I blame Japhy and Ronald J Kimball and others on the fwp mailing list for exposing the ''=~ trick, Jas Nagra for explaining his Acme::Smirch module, and Rajah Ankur and Supremely Unorthodox Eric for provoking me.

I would also like to thank Ian Phillipps, Philip Newton, Ryan King, Michael G Schwern, Robert G Werner, Simon Cozens, and others on the fwp mailing list for their advice on ASCII Art, imaging programs, and on which picture of Larry to use.

Thanks also to Mtv Europe, Ronald J Kimball and Eugene van der Pijll for their help in golfing the program in the Twelve Thousand and Thirty Two Camels section. Keith Calvert Ivey also contributed some levity to this section.

COPYRIGHT

Copyright (c) 2001-2002 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.