http://qs321.pair.com?node_id=578318
Category: GUI Programming
Author/Contact Info David Serrano
email: rot13 decode_base64 'ZHNlcnJhbm81IGF0IHlhaG9vLmVzCg=='
Description:

I'm very lazy. When I'm at the monastery, I hate to open an $EDITOR just for pasting that small snippet, saving it to a file ("Overwrite?" yes, of course) and then run it. So what I usually do is run perl at the shell prompt, and paste there. This has the drawback that, to modify it, I have to copy-paste part of it, change something and copy-paste the rest. And when the output of the program is so large that my terminal runs out of buffer space, it is lost. These problems notwithstanding, I'm very fond of this way of doing things since that's how I began using Perl. Just type, do a Ctrl-D and see the action!

This Gtk2 program has a text box in it, and a "Run" button. Just paste the code there, and click the button (or hit Alt-R). The output of the code goes to pexec.pl's STDOUT, so it has to be executed from a terminal. Snippets are run under -t to encourage good programming habits without standing in the way.

#!/usr/bin/perl

use warnings;
use strict;
use Gtk2;

## todo: change mnemonic into an accelerator (^D)
## todo: do another one for quitting (^Q)
## bug (fixed by forking): halts on infinite loops :^P

my ($window, $vbox, $ptext, $but, $label);
my $font = 'Monospace 10';
my $perl = '/usr/bin/perl';

sub do_run {
    my $pid;
    my $buf = $ptext->get_buffer;
    local $SIG{'CHLD'} = 'IGNORE';

    warn "fork: $!" and return unless defined ($pid = fork);
    if ($pid) { ## parent
        $ptext->grab_focus;
        return; 
    }

    ## child
    $pid = open my $fd, '|-', $perl, '-t' or die "fork: $!";
    print "\n$perl PID: $pid\n";  ## for easy killing
    print $fd $buf->get_text ($buf->get_bounds, 1);
    close $fd;
    exit;   
}

Gtk2->init;

$window = Gtk2::Window->new ('toplevel');
$vbox   = Gtk2::VBox->new (0, 0); 
$ptext  = Gtk2::TextView->new;
$but    = Gtk2::Button->new;
$label  = Gtk2::Label->new_with_mnemonic ('_Run!');

$but->signal_connect (clicked => \&do_run);
$but->add ($label);
$but->set_size_request (50, 30);

$ptext->set_size_request (50, 20);
$ptext->set_border_width (4);
$ptext->modify_font (Gtk2::Pango::FontDescription->from_string ($font)
+);
$ptext->get_buffer->set_text (<<_DEF_TEXT_);
use warnings;
use strict;
use Data::Dumper;

\$ENV{'PATH'} = \$ENV{'CDPATH'} = '/usr/bin:/bin';

_DEF_TEXT_

$vbox->add ($ptext);
$vbox->pack_end ($but, 0, 0, 0);

$window->signal_connect (destroy => sub { Gtk2->main_quit; });
$window->set_default_size (700, 400);
$window->add ($vbox);
$window->show_all;
Gtk2->main;