++ed by:
PJF SYP SSCAFFIDI DOLMEN KEEDI

5 PAUSE users
2 non-PAUSE users.

Andrew J. Savige

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.

Unlike Acme::Bleach and Acme::Buffy, the generated program runs without requiring that Acme::EyeDrops be installed on the target system.

EXAMPLES

Getting Started

Suppose you have a program, helloworld.pl, consisting of:

    print "hello world\n";

To convert this little program into an equivalent camel-shaped one, create 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, new.pl, to verify that it does indeed resemble a camel, run it:

   perl new.pl

to confirm it behaves identically to the original helloworld.pl.

Instead of using the API, as shown 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 EyeDrops sub-directory underneath where EyeDrops.pm is located, 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 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.

An Abbreviated History of Perl 6

Here is a summary of the Perl 6 development effort so far:

    print sightly( { Shape        => 'jon,larry,damian,simon,parrot,buffy3',
                     Gap          => 3,
                     Regex        => 1,
                     Print        => 1,
                     SourceString => <<'END_HAIKU' } );
    Coffee mug shatters
    Larry Apocalyptic
    Parrot not a hoax

    Design, debate, sift
    Prankster Piers pawky precis
    Weekly light relief

    Gallop Ponie bold!
    Beer to gulp, Buffy astride
    Orange sky surrounds
    END_HAIKU

producing:

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



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



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



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



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



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

Just another Perl hacker

Let's get more ambitious and create a big self-printing JAPH.

    my $src = <<'FLAMING_OSTRICHES';
    open 0;
    $/ = undef;
    $x = <0>;
    close 0;
    $x =~ tr/!-~/#/;
    print $x;
    FLAMING_OSTRICHES
    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 the program to be converted is careful with its use of regular expressions and $_.

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, by default, 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 use the TrailingSpaces attribute (-T switch to sightly.pl) to append the required number of trailing spaces to each line, allowing you to write a briefer kk.pl:

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

and finally produce Buffy looking in the mirror with:

    sightly.pl -Tr -f kk.pl -s buffy2 >bb.pl

Alternatively, the Compact attribute (-m switch to sightly.pl) could be used to produce a solution free of 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.

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>                    # self printing
    open$%;print+map{y;!-~;#;;$_}<0>   # replace sightly with '#'

A Somersaulting Camel

Let's extend the Buffy example of the previous section to produce a camel-shaped program capable of somersaulting across the screen when run.

We start with a generator program, gencamel.pl:

    print sightly( { Regex          => 1,
                     Compact        => 1,
                     RemoveNewlines => 1,
                     Indent         => 1,
                     BorderGapRight => 1,
                     Shape          => 'camel',
                     SourceString   => <<'END_SRC_STR' } );
    $~=pop||'';open$%;
    y,!-~,#,,s,(.).,$+,gs,$~&&($_=reverse)for@~=grep$|--,('')x18,<0>;
    @;=map~~reverse,reverse@~;
    map{system$^O=~Win?CLS:'clear';
    ($-=$_%3)||(--$|,map$_=reverse,@~,@;);
    print$"x($=/3*abs$|*2-$-),$_,$/for$-&1?@;:@~;
    sleep!$%}$%..11
    END_SRC_STR

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

Running this program:

    perl gencamel.pl >camel.pl

produces camel.pl:

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

Note: The use of a camel image in association with Perl is a trademark of O'Reilly & Associates, Inc. Used with permission.

You can run camel.pl like this:

    perl camel.pl           normal forward somersaulting camel
    perl camel.pl b         camel somersaults backwards
    perl camel.pl please do a backward somersault
                            same thing

You are free to add a leading #!/usr/bin/perl -w line to camel.pl, so long as you also add a blank line after this header line.

Twelve Thousand and Thirty Two Camels

In a similar way to the somersaulting camel described above, we create a camel-shaped program capable of emitting twelve thousand and thirty two different camels when run.

As usual, we start with a generator program, gencamel.pl:

    print sightly( { Regex          => 1,
                     Compact        => 1,
                     RemoveNewlines => 1,
                     BorderGap      => 1,
                     Shape          => 'camel',
                     SourceString   => <<'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

Running this program:

    perl gencamel.pl >camel.pl

produces camel.pl, which you can run 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.

Naked Arm Wrestling

The final auction at Y::E 2002 in Munich featured an epic athletic contest which you can remember with:

    use Acme::EyeDrops qw(sightly);
    my $s = sightly( { Regex         => 1,
                       Shape         => 'naw',
                       Indent        => 1,
                       SourceString  => <<'NAKED_ARM_WRESTLING' } );
    $/='';open$%;$x=<0>;$y=<0>;
    substr($y,428,$%)='     AAAAARRRGGGHHH!!!';
    map{system$^O=~Win?CLS:'clear';
    print$_&1?$y:$x;sleep!$%+($_&1)}$%..9
    NAKED_ARM_WRESTLING
    $s =~ s/ +$//m;
    print $s;

Baghdad Bob

Running this program:

    print sightly( { Shape             => 'baghdad',
                     Regex             => 1,
                     Compact           => 1,
                     RemoveNewlines    => 1,
                     BorderGap         => 1,
                     BorderWidthLeft   => 3,
                     BorderWidthRight  => 3,
                     BorderWidthTop    => 2,
                     BorderWidthBottom => 8,
                     SourceString      => <<'FAMOUS_COMICAL_ALI_QUOTES' } );
    warn+(
    "Britain is not worth an old shoe!",
    "There are no American infidels in Baghdad!",
    "We have them surrounded in their tanks!",
    "I speak better English than this villain Bush!")[rand(4)],$/
    FAMOUS_COMICAL_ALI_QUOTES

produces:

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

99 Bottles of Beer

The web site http://99-bottles-of-beer.ls-la.net/ features programs to display the lyrics of the famous 99 bottles of beer song in 515 different computer languages.

Over the years, many different Perl solutions have been proposed. On December 25 1998, for instance, Damian Conway suggested using his Lingua::EN::Inflect module:

    use Lingua::EN::Inflect 'inflect';
    $n=shift||99;
    print inflect<<BURP while $n;
    NO(bottle of beer,$n) on the wall, NO(bottle of beer,$n)!
    Take one down, pass it around,
    NO(bottle of beer,@{[--$n]}) on the wall.
    BURP

During May 2003, the two leading Perl golfers of that era, Ton Hospel and Mtv Europe, produced the shortest known Perl solution:

    sub
    b{[@b=(abs||No,bottle."s"x!!++$_,of,beer),on,the,wall]}print
    "@{+b},\n@b,\nTake one down, pass it around,\n@{+b}.\n"
    for-pop||-99..-1

Elegant though this solution is, they may have felt a little gobsmacked when the world's leading HQ9+ golfer, Casey West, uncorked a one stroke solution (9) in that surreal programming language.

To produce a solution shaped like a row of beer bottles, run this:

    use Acme::EyeDrops qw(sightly get_eye_string hjoin_shapes);
    my $ninety_nine = <<'BURP';
    $==pop||99;--$=;sub
    _{($;=($=||No)." bottle"."s"x!!--$=." of beer")." on the wall"}
    print+_,", $;!
    Take one down, pass it around,
    ",_,"!

    "while++$=
    BURP
    chop($ninety_nine); $ninety_nine =~ s/\nprint/print/;
    print sightly( { Regex         => 1,
                     Compact       => 1,
                     ShapeString   => hjoin_shapes(2,
                                      (get_eye_string('bottle2'))x6),
                     SourceString  => $ninety_nine } );

producing:

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

A larger single beer bottle shape can be produced with:

    print sightly( { Regex         => 1,
                     Compact       => 1,
                     Shape         => 'bottle',
                     SourceString  => $ninety_nine } );

while the canonical solution, shaped like 99 bottles of beer, can be generated with:

    print sightly( { Regex         => 1,
                     ShapeString   => join("\n", (hjoin_shapes(3,
                                      (get_eye_string('bottle2'))x3))x33),
                     SourceString  => $ninety_nine } );

Sierpinski Triangles

A simple and concise Sierpinski triangle generator, siertri.pl, is:

    #!perl -l
    $x=2**pop;print$"x--$x,map$x&$_?$"x2:"/\\",0..$y++while$x

which was posted by Mtv Europe to golf@perl.org on 14-sep-2002 as a one stroke improvement on Adam Antonik's original program. Running:

    perl siertri.pl 4

displays a Sierpinski triangle with 2**4 lines.

Proclaiming Mtv's program as the shortest (in Acme::EyeDrops 1.13) only served to provoke Adam Antonik and Eugene van der Pijll into shortening it by exploiting a hard $^F, as shown in some of the examples below:

    -l print$"x--$x,map$x&$_?$"x2:"/\\",0..$_-1for 1..($x=2**pop)
    -l $x=2**pop;print$"x--$x,map$x&$_?$"x2:"/\\",0..$y++while$x
    -l $^F**=pop;print$"x--$^F,map$^F&$_?$"x2:"/\\",0..$y++while$^F
    -lX061 print$"x--$/,map$/&$_?$"x2:"/\\",0..$y++while$/<<=pop
    -l print$"x--$^F,map$^F&$_?$"x2:"/\\",0..$y++while$^F*=2**pop
    -l $_=$"x2**pop;$_="$'/\\",print,s/(?<=\\)../$&^KI^D5/egwhile/^ /

An interesting obfuscated Sierpinski triangle generator is:

    #!/usr/bin/perl -l
    s--@{[(gE^Ge)=~/[^g^e]/g]}[g^e]x((!!+~~g^e^g^e)<<pop).!gE-ge,
    s-[^ge^ge]-s,,,,s,@{[(g^';').(e^'?')]},(G^'/').(E^'|')^Ge,ge,
    print,s,(?<=/[^g^e])[^g^e][^g^e],$&^(G^'/').(E^'|')^gE,ge-ge

As an alternative obfu, you can produce a Sierpinski triangle-shaped Sierpinski triangle generator based on Mtv's program like this:

    print sightly( { Regex           => 1,
                     Compact         => 1,
                     RemoveNewlines  => 1,
                     Indent          => 1,
                     BorderGap       => 1,
                     BorderWidth     => 2,
                     # For 'siertri' built-in shape, Width=>5 means:
                     #   height is 2**5 lines
                     #   width  is 2 * 2**5 characters
                     Width           => 5,
                     Shape           => 'siertri',
                     SourceString    => <<'END_SRC_STR' } );
    $-=!$%<<(pop||4);print$"x$-,map($-&$_?'  ':'/\\',$%..$.++),$/while$---
    END_SRC_STR

producing:

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

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 moving 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:

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



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



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



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

EyeDropping EyeDrops.pm

To illustrate EyeDropping a non-trivial module, we convert EyeDrops.pm itself into a bunch o' camels, via the following generator program, mkeye.pl:

    use Acme::EyeDrops qw(sightly);
    # Slurp EyeDrops.pm into $orig string.
    my $orig = Acme::EyeDrops::slurp_yerself();
    # Split $orig into the source ($src) and the pod ($doc).
    my ($src, $doc) = split(/\n1;\n/, $orig, 2);
    # Remove the line containing $this_dir = __FILE__ ...
    # because this line confuses eval.
    $src =~ s/^(my \$this_dir\b.*)$//m;
    # Generate the new sightly version of EyeDrops.pm.
    print $1, sightly( { Regex         => 0,
                         Compact       => 1,
                         TrapEvalDie   => 1,
                         FillerVar     => ';#',
                         Shape         => 'camel',
                         Gap           => 1,
                         SourceString  => $src } ),
    ";\n1;\n", $doc;

Running this program:

    perl mkeye.pl >m.tmp

produces m.tmp, which can be copied over the top of the original EyeDrops.pm in the Acme directory. Though the new bunch o' camels version passes the regression test suite, it's about 4 times slower than the original.

Notice that we used Regex => 0 (since EyeDrops.pm uses many regular expressions), TrapEvalDie => 1 (since EyeDrops.pm calls the die function) and FillerVar => ';#' (to avoid possible warnings due to unused variables). Notice too that the only known eval-hostile line in EyeDrops.pm:

    my $this_dir = __FILE__; ...

was extracted and inserted at the top of the new file.

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. 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 might create a reduced, inverted shape with:

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

producing:

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

Snowflakes

The Text and TextFiller attributes (-t/-u switches to sightly.pl) are handy when you simply want to pour some unsightly text into a shape.

To illustrate, consider an entry in the Cam.pm 2002 Christmas programming contest, 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 sightly.pl):

    print sightly( { Shape       => 'snow',
                     SourceFile  => 'snowing.pl',
                     Text        => 1,
                     TextFiller  => '#',
                     Indent      => 1 } );

producing a valid entry, 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 snowflake.pl produces a pretty 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
         @;,   -$_,  2,pop@,;@;=(""  ,@;)   ;;;
          ;sleep!                      $%}+2..
            18#                          /-\

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_dir

Returns the directory containing the .eye file shapes. This is the EyeDrops sub-directory underneath where EyeDrops.pm is located.

get_eye_shapes

Returns a list of the eye shapes. An eye shape is just a file with a .eye extension residing in the get_eye_dir directory.

get_eye_string SHAPENAME

Given a .eye SHAPENAME, returns the shape string.

make_triangle WIDTH

Returns a triangle shaped string of WIDTH characters.

make_siertri WIDTH

Returns a Sierpinski triangle shaped string containing 2**WIDTH lines.

make_banner WIDTH STRING

Linux only. Returns a banner of STRING, using the Linux command /usr/games/banner -w WIDTH.

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.

hjoin_shapes GAP SHAPESTRINGLIST

Join the shapes specified by SHAPESTRINGLIST horizontally with GAP spaces between each shape.

pour_text SHAPESTRING TEXTSTRING GAP FILLTEXT

Given a shape string SHAPESTRING, a string TEXTSTRING, and a GAP between successive shapes, returns a properly shaped string. That is, pour TEXTSTRING into SHAPESTRING. FILLTEXT (typically '#') is text to be used as a filler for any leftover part of the shape (if not set, don't fill in leftovers).

pour_sightly SHAPESTRING PROGSTRING GAP RFILLVAR COMPACT IH

Given a shape string SHAPESTRING, a sightly-encoded program string PROGSTRING, and a GAP between successive shapes, returns a properly shaped program string. That is, pour PROGSTRING into SHAPESTRING. RFILLVAR is either a reference to an array of filler variables or, alternatively, a string to fill the leftover of the last shape with. Common filler strings are '' for no filler at all, or '#' or ';' or ';#'. A filler variable is a valid Perl variable consisting of two characters: $ and a punctuation character. For example, RFILLVAR = [ '$:', '$^', '$~' ]. Do not use $; or $" or $_ as filler variables. If COMPACT is 1, use compact sightly encoding, if 0 use plain sightly encoding. If IH (inform handler) is undef, 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 IH to sub {}.

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
                   get_eye_dir() directory) 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.

    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.

    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.

Specifying a Shape

When you specify a shape like this:

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

first a built-in fred shape is looked for, then EyeDrops looks for the file fred.eye in the get_eye_dir directory. If you specify a '/' or '.' in the Shape attribute, a file with that name is looked for instead, for example:

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

Finally, you may specify a shape with a string, for example:

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

If you specify a shape without a source file:

    print sightly( { Shape => 'camel' } );

a no-op filler is used to fill the shape.

If you specify a source file without a shape:

    print sightly( { SourceFile => 'helloworld.pl' } );

a shapeless sightly string without any spaces or newlines is generated. You can break this string into fixed width lines via the Width attribute:

    print sightly( { SourceFile => 'helloworld.pl',
                     Width      => 40 } );

Generally, you should specify the Width attribute of built-in shapes. Notice that the Width attribute is ignored for .eye file shapes.

Shape Reference

The built-in shapes are:

    banner      Linux banner command (/usr/games/banner -w Width)
                of text in BannerString attribute
    srcbanner   Linux banner command (/usr/games/banner -w Width)
                of source text
    siertri     A Sierpinski triangle (2**Width lines)
    triangle    A triangle (width Width characters)
    all         A shape consisting of all .eye shapes joined together
                (Width blank lines between each shape)

The .eye file shapes distributed with this version of EyeDrops are:

    a             Horizontal banner of "a"
    acme          Perl/Parrot/Ponie Euro-hacker and modern artist who likes
                  the colour orange and enjoys having his bra-strap twanged
    alien         An alien (rumoured to be Ton Hospel, from the
                  Roswell archives circa 1974)
    alpaca        Lama pacos, from South America, with long shaggy hair
                  and related to the llama
    baghdad       Baghdad Bob aka Comical Ali
    beer          Beer glass designed by Matthew Byng-Maddick for the
                  cam.pm Beerfestival Perl Programming Contest 2002
    bighorn       Ovis canadensis (bighorn sheep) found in the Rocky Mountains
    bleach        Vertical banner of "use Acme::Bleach;"
    bottle        A bottle of beer
    bottle2       Abbreviated version of shape bottle
    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
    campm         Horizontal banner of "cam.pm"
    candle        A Christmas candle
    china1        Chinese characters, roughly translated as
                  "God is added a year of seniority; human is added a
                  year of age, Spring fills the universe; luck and
                  happiness fills the family"
    coffee        A cup of coffee
    cricket       Australia are world champions in this game
    damian        The Acme namespace is all his fault
    dipsy         Teletubbies Dipsy (also london.pm infobot name)
    eugene        Champion Perl golfer, Drs Eugene van der Pijll
                  of Utrecht, Holland
    eye           An eye
    flag_canada   Canada's flag, contributed by `/anick
    gelly         Featured speaker at every session of Y::E 2003, Paris
    golfer        A golfer hitting a one iron
    heart         A heart shape contributed by `/anick
    hipowls       A pair of hip owls
    japh          JAPHs were invented by Randal L Schwartz in 1988
    jon           Kick-started the Perl 6 development effort by smashing
                  a standard-issue white coffee mug against a hotel wall
    kansai_pm     Kansai.pm's mascot (Tiger with Perl characters)
                  contributed by Takanori KAWAI (Japanese)
    kermit        Kermit the frog
    larry         Wall, Larry (as opposed to Russell Wall who is
                  Wall, Russ)
    larry2        Caricature of Larry contributed by Ryan King
    llama         Llamas are so closely related to camels they can
                  breed with them (their progeny are called camas)
    london        Haiku "A Day in The Life of a London Perl Monger"
    map_australia Map of Australia
    map_italy     Map of Italy
    merlyn        Just another Perl hacker, aka Randal L Schwartz
    mongers       Perl Mongers logo
    mosquito      A mosquito
    naw           Naked Arm Wrestling (Y::E 2002, Munich)
    panda         A panda designed by Yanni Ellen Liu
    parrot        Originally an April fool's joke, the joke was that
                  it was not a joke
    pgolf         Perl Golf logo (inspired by `/anick)
    pony          Horizontal banner of "Pony"
    pony2         Picture of a Pony
    riding        Horizontal banner of "riding"
    rose          A rose
    santa         Santa Claus playing golf
    santa2        Santa Claus carrying presents
    schwern       is my bitch
    simon         The inventor of parrot
    smiley        A smiley face
    smiley2       Pulling a face
    smiley3       A sad face
    snow          Snowflake designed by Matthew Byng-Maddick for the
                  cam.pm Christmas Perl Programming Contest 2002
    spoon         A wooden spoon
    tonick        Pictorial representation of a golf contest between Ton
                  Hospel and `/anick; colourful but not very suspenseful
    tpr           Vertical banner of "The Perl Review"
    uml           A UML diagram
    undies        A pair of underpants
    window        A window
    writing_perl  Perl in camel-style by Takanori KAWAI (Japanese)
    yanick        Caricature of `/anick's noggin
    yanick2       Uttered by `/anick during TPR02
    yanick3       Pictorial version of yanick2
    yanick4       Abbreviated version of shape yanick

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 is careful with its use of regular expressions and $_. 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

Acme's Y::E 2002 naked arm wrestling movie at http://astray.com/tmp/yapcbits3.mov.

Japanese translations of selected CPAN modules (including Acme::EyeDrops) can be found at http://perldoc.jp/docs/modules/. (Japanized Perl Resources Project is at https://sourceforge.jp/projects/perldocjp/).

Perl Obfuscation Engines, for example, yaoe by Perl Monk mtve, at http://www.perlmonks.com/index.pl?node_id=161087 and http://212.16.6.108/~mtve/code/eso/perl/yaoe/.

More information on 99 bottles of beer can be found at http://99-bottles-of-beer.ls-la.net/ and http://archive.develooper.com/fwp@perl.org/msg03193.html.

To learn more about HQ9+ programming visit http://www.cliff.biffle.org/esoterica/hq9plus.html and http://search.cpan.org/search?dist=HQ9PLUS/.

Perl Monks Obfuscation section, especially: http://www.perlmonks.com/index.pl?node_id=45213 (Erudil's camel code) and http://www.perlmonks.com/index.pl?node_id=176043 (Len's Spiralling quine) and http://www.perlmonks.com/index.pl?node_id=188405 (Sierpinski Triangle).

The Y::E 2002 Dark Art of Obfuscation talk by Thomas Klausner at http://domm.zsi.at/talks/obfu_yapc2002/.

Les Perl Mongueurs de Paris $A++ page at http://paris.mongueurs.net/aplusplus.html.

Yanni Ellen Liu's excellent Ascii Art collection at http://www.cs.uwaterloo.ca/~y5liu/.

More information on Baghdad Bob can be found at http://www.welovetheiraqiinformationminister.com/.

The cam.pm Obfuscated Programming Contests at http://cam.pm.org/projects_home.shtml.

Some background on Y::E 2003 speakers can be found at http://london.pm.org/pipermail/london.pm/Week-of-Mon-20020923/013793.html.

The definitive Perl Golf reference is http://perlgolf.sourceforge.net/.

The $|-- idiom (exploited in the A Somersaulting Camel section) is "explained" in this thread: http://archive.develooper.com/fwp@perl.org/msg01360.html.

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.

Ideas from Adam Antonik, Mtv Europe, Eugene van der Pijll, Ton Hospel and Keith Calvert Ivey were used in the Sierpinski Triangles section.

The jon shape was derived from http://www.spidereyeballs.com/os5/set1/small_os5_r06_9705.html. Kudos to Elaine -HFB- Ashton for showing me this.

The merlyn shape was derived from this photo http://www.stonehenge.com/merlyn/my_real_proof.jpg of Randal singing a duet with Samantha Fox.

The simon shape was derived from a pencil sketch by the Japanese artist Eiko Yamashita.

The candle, china1, panda and santa2 shapes were derived from similar ones at Yanni Ellen Liu's Ascii Art collection at http://www.cs.uwaterloo.ca/~y5liu/.

COPYRIGHT

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