Someone on another list asked how to make a simple menu based program launcher for inexperienced people to do commandline tasks. Here is a simple example using Tk::ExecuteCommand, which launches asynchronously and non-blocking. I made a separate toplevel window and Execute object for each command, so that there is no memory gain when this is run for long periods and the commands are executed repeatedly.
#!/usr/bin/perl
use warnings;
use strict;
use Tk;
use Tk::Pane;
use Tk::ExecuteCommand;
my %commands = (
#buttontext => command
sleep => 'sleep 20',
dir => 'dir',
date => 'date',
date1 => 'date; sleep 5; date;',
ls => 'ls -la',
users => 'cat /etc/passwd',
who => 'who',
whomai => 'whoami',
ps => 'ps mauxww',
top => 'top',
cat_error => 'cat foobar'
);
my $width = 90;
my $height = 120;
my $mw = MainWindow->new();
$mw->geometry($width.'x'.$height.'+100+100');
$mw->configure(-background => 'black');
$mw->Button(-text => 'Quit',
-activebackground => 'red',
-highlightbackground => 'yellow',
-background => 'pink',
-command=> sub{Tk::exit} )->pack;
my $p = $mw->Scrolled('Pane', -scrollbars => 'oe',)->pack;
foreach my $key (keys %commands){
$commands{'tl'}{$key} = $mw->Toplevel(-background => 'lightsteelblu
+e');
$commands{'tl'}{$key}->title($key);
$commands{'ec'}{$key} = $commands{'tl'}{$key}->ExecuteCommand(
-background => 'lightsteelblue',
-command => $commands{$key},
-entryWidth => 50,
-height => 10,
-label => '',
-text => 'Execute',
)->pack;
my $t = $commands{'ec'}{$key}->Subwidget( 'text' ); # ROText widget
+
$t->configure(-background => 'lightyellow');
my $f1 = $commands{'tl'}{$key}->Frame(-background => 'black')
->pack(-expand => 1, -fill => 'x');
$f1->Button(-text => "Clear",
-activebackground => 'lightyellow',
-highlightbackground => 'white',
-background => 'yellow',
-command => sub {
$t->delete( '1.0' => 'end' );
})->pack(-side =>'left', -padx => 70);
$f1->Button(-text => "Get Status",
-activebackground => 'lightgrey',
-highlightbackground => 'white',
-background => 'grey',
-command => sub {
my @return = $commands{'ec'}{$key}->get_status;
#Returns a 2 element array of $? and $! from last command execut
+ion.
$t->insert( 'end' => "\nStatus->\t\$?=$return[0]\t\$!=$return[1]
+\n\n");
$t->see('end');
})->pack(-side =>'left', -padx => 70);
$f1->Button(-text => "Close",
-activebackground => 'hotpink',
-highlightbackground => 'white',
-background => 'pink',
-command => sub { $commands{'tl'}{$key}->withdraw;
$commands{'button'}{$key}->
configure(-state => 'normal');
})->pack(-side => 'right', -padx => 70);
$commands{'tl'}{$key}->withdraw;
$commands{'button'}{$key} = $p->Button(-text => $key,
-background => 'lightyellow',
-activebackground => 'yellow',
-command=>[\&execute, $key, ] )
->pack(-fill => 'x',-expand => 1,-pady => 1);
}
MainLoop;
sub execute {
my $key = shift;
$commands{'button'}{$key}->configure(-state => 'disabled');
$commands{'tl'}{$key}->deiconify;
$commands{'tl'}{$key}->raise;
$commands{'ec'}{$key}->bell;
$commands{'ec'}{$key}->update;
}