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
    perl new.pl             (should print "hello world" as before)

Notice that the shape 'camel' is just the file camel.eye in the same directory as EyeDrops.pm, so you are free to add your own new shapes as required.

If your boss demands a UML diagram describing the program, you can give him this:

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

If it is a Windows program, you can indicate that too, by combining shapes:

    print sightly( { Shape       => 'uml,window',
                     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.

You can improve the quality of your programs simply by having them impersonate the Perl 6 maestros, Larry Wall and Damian Conway:

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

producing the following good karma:

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


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

If you sincerely idolize Larry, you should put a border around him like this:

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

For Linux-only, you can apply its /usr/games/banner command to the program's source text like this:

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

The generated program, shown below, is easier to understand than the original because its characters are bigger and easier to read:

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

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

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

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

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
















                                                     ')')^
                                                    '}';$:=
                                                   '.'^"\~";$~=
                                                   '@'|'('
                                                    ;($^)

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

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

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

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

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

















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

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

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

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

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

                                                     |'(';
                                                    $^=')'^
                                                   '[';$/="\`"|
                                                   '.';$_=
                                                    "\("^


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

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

    my $src = <<'PROG';
    open 0;
    $/ = undef;
    $x = <0>;
    close 0;
    $x =~ tr/!-~/#/;
    print $x;
    PROG
    print sightly( { Shape         => 'japh',
                     SourceString  => $src,
                     Regex         => 1 } );

This works. However, if we were to change:

    $x =~ tr/!-~/#/;

to:

    $x =~ s/\S/#/g;

the generated program would malfunction in strange ways because it is running inside a regular expression and Perl's regex engine is not reentrant. In this case, we must resort to:

    print sightly({Shape        => 'japh',
                   SourceString => $src,
                   Regex        => 0 } );

which runs the generated sightly program via eval instead.

EyeDrops can also convert plain text:

    print sightly({Shape        => 'spoon',
                   SourceString => "Ankur will get the wooden spoon!\n",
                   Regex        => 1,
                   Print        => 1 } );

In this example, the generated program will print the SourceString above. Or with a banner (Linux only):

    print sightly({Shape        => 'banner',
                   SourceString => "Eric is supremely unorthodox!\n",
                   BannerString => "Eric is supremely unorthodox!",
                   Width        => 70,
                   Regex        => 1,
                   Print        => 1 } );

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

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. 13 camels now.

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

163 camels. 412,064 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!

Here is the original one camel program, t1.pl:

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

Buffy fans might like to experiment with rotating her letters:

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

while cricket fans could compare:

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

which produces:

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

with:

    print sightly( { Shape       => 'cricket',
                     Invert      => 1,
                     BorderWidth => 2,
                     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 WIDTH

Put a border around a shape.

invert_shape SHAPESTRING

Invert a shape.

rotate_shape SHAPESTRING DEGREES

Rotate a shape thru 90, 180 or 270 degrees.

pour_sightly SHAPESTRING PROGSTRING GAP RFILLVAR

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

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.

    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 thru 90, 180 or 270 degrees.

    Invert        Invert the shape.

    BorderGap     Put a border around the shape. Gap between border
                  and the shape.

    BorderWidth   Put a border around the shape. Width of border.

    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.

Shapes

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 like this:

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

Finally, you can specify a shape with a string like this:

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

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

    bleach      banner of "use Acme::Bleach;"
    buffy       banner of "Buffy"
    camel       An animal
    cricket     Australia is world champions in this game
    damian      Damian Conway's face
    japh        First invented by Randal L Schwartz in 1988
    larry       Larry Wall's face
    mongers     Perl Mongers logo
    spoon       a wooden spoon
    uml         a UML diagram
    window      a window

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

To aid those migrating from Acme::Bleach and Acme::Buffy, the 'bleach' and 'buffy' shapes are provided.

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 for small programs with simple I/O and no regular expressions. 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.

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 <andrew.savige@ir.com>

SEE ALSO

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

CREDITS

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

COPYRIGHT

Copyright (c) 2001 Andrew Savige. All rights reserved. This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.