For Programmers: Free Programming Magazines  


Home > Archive > PerlTk > March 2007 > ExecuteCommand









You are viewing an archived Text-only version of the thread. To view this thread in it's original format and/or if you want to reply to this thread please [click here]

 

Author ExecuteCommand
akyv

2007-03-17, 4:04 am

Hello,
Please help. I can't get this code to work properly with the
ExecuteCommand procedure. I want the stdout and stderr to be in the
upper white screen. Not open another window. I would like to have them
merged. Anyway I can achieve that?

Below the code.

Thanks
akyv



use Tk;
use Tk::ExecuteCommand;
use strict;
use warnings;

my $Cmd = '';

my $mw = tkinit;

my $tx = $mw->Scrolled('ROText',
-background => 'white',
-scrollbars => 'osoe',
)->pack(
-fill => 'both',
-expand => 1,
);
$tx->tagConfigure('command', -foreground => '#0000A0');
$tx->tagConfigure('prompt', -foreground => '#006060');
prompt($tx);

my $en = $mw->Entry(
-textvariable => \$Cmd,
)->pack(-fill => 'x');
$en->focus;

my $f = $mw->Frame->pack;

my @pad = (-padx => 16, -pady => 8);
my $exc = $f->Button(
-text => 'Execute',
-command => \&execute,
)->pack(@pad, -side => 'left');
$mw->bind('<Return>', sub{$exc->invoke});

my $int = $f->Button(
-text => 'Interrupt',
-command => \&interrupt,
)->pack(@pad, -side => 'right');
$int->configure(-state => 'disabled');

MainLoop;

sub execute {
my $c = $Cmd;
$Cmd = '';
$tx->insert('end', "$c\n", 'command');
$exc->configure(-state => 'disabled');
$int->configure(-state => 'normal');

##### This is from where I am having problems

#my $ec = $exc -> ExecuteCommand(
$en -> ExecuteCommand(
-command => ' ',
-entryWidth => 50,
-height => 10,
-label => ' ',
-text => 'Execute', ) ->pack;

#$ec -> configure(-command => 'date; sleep 10; date; sleep 10;
date;');
# my $ec = $en;
$en -> configure(-command => 'date; sleep 10; date; sleep 10;
date;');
$f ->protocol('WM_DELETE_WINDOW' => sub {&interrupt ;} );

#$ec->execute_command;
$en->execute_command;

###Done inserting ExecuteCommand
$int->configure(-state => 'disabled');
$exc->configure(-state => 'normal');
prompt($tx);
}

sub interrupt {
$en->kill_command;
exit;
}

sub prompt {
my($t) = @_;
$t->insert('end', '> ', 'prompt');
}

__END__

zentara

2007-03-20, 7:04 pm

On 16 Mar 2007 23:44:45 -0700, "akyv" <yvntem@hotmail.com> wrote:

>Hello,
>Please help. I can't get this code to work properly with the
>ExecuteCommand procedure. I want the stdout and stderr to be in the
>upper white screen. Not open another window. I would like to have them
>merged. Anyway I can achieve that?
>Below the code.
>Thanks
>akyv


I waited to see if anyone knew an answer. Tk::ExecuteCommand
is supposed to open a new ROText widget when you run it, so maybe
you are better off doing it manually on your own, so you can direct
the output where you want. However, ExecuteCommand does have the
ROText widget set as an "advertised widget", meaning you can access
it externally. You may be able you get creative and work out a way to
tell all ExecuteCommand instances to use the same ROText, but I don't
have an example offhand.

To make your own, you can use piped opens to launch commands, save
their pids (to kill them later), and use fileevent to read the output.

It wasn't clear from your example script what you are trying to do.
Are you trying to run multiple commands simultaneously, and have all
output go to the same window? Or do you need to run just one command
at a time? Multiple simultaneous commands would be very tricky, to track
and interrupt early.

Here is a simple example showing how to use fileevent. It really is
simple, and needs much work to assure multiple commands
won't interfere with one another. I think I would use threads
if I was to do this personally.
See http://perlmonks.org?node_id=585533
for an example which should give you the idea.

But here is a non-threaded use of fileevent.

#!/usr/bin/perl
use warnings;
use strict;
use Tk;
use IPC::Open3;
require Tk::ROText;

$|=1;

my $mw = new MainWindow;

my $entry=$mw->Entry(-width => 80)->pack;

$mw->Button(-text => 'Execute',
-command => \&send_to_shell)->pack;

my $textwin =$mw->ROText(-width => 80,
-bg =>'white',
-height => 24,
)->pack;

$textwin->tagConfigure( 'err', -foreground => 'red' );

my $pid = open3( \*IN, \*OUT, \*ERR, '/bin/bash' ) or warn "$!\n";

$mw->fileevent( \*OUT, readable => \&read_stdout );
$mw->fileevent( \*ERR, readable => \&read_stderr );

MainLoop;

sub read_stdout {

if( sysread( OUT, my $buffer, 1024 ) > 0 ){
$textwin->insert( 'end', $buffer );
}
}

sub read_stderr {
if( sysread(ERR, my $buffer, 1024 ) > 0 ){
$textwin->insert( 'end', $buffer, 'err' );
}
}

sub send_to_shell {
my $cmd= $entry->get();
print IN "$cmd\n";
}
__END__











--
I'm not really a human, but I play one on earth.
http://zentara.net/japh.html
akyv

2007-03-22, 7:01 pm

This is Awsome!! I tried to implement your example into my code. It
took me a while to figure it out (novice). But it finally works.
I am still testing it. But this is great.
Thanks for your help!!!
Akyv


zentara wrote:
> On 16 Mar 2007 23:44:45 -0700, "akyv" <yvntem@hotmail.com> wrote:
>
>
> I waited to see if anyone knew an answer. Tk::ExecuteCommand
> is supposed to open a new ROText widget when you run it, so maybe
> you are better off doing it manually on your own, so you can direct
> the output where you want. However, ExecuteCommand does have the
> ROText widget set as an "advertised widget", meaning you can access
> it externally. You may be able you get creative and work out a way to
> tell all ExecuteCommand instances to use the same ROText, but I don't
> have an example offhand.
>
> To make your own, you can use piped opens to launch commands, save
> their pids (to kill them later), and use fileevent to read the output.
>
> It wasn't clear from your example script what you are trying to do.
> Are you trying to run multiple commands simultaneously, and have all
> output go to the same window? Or do you need to run just one command
> at a time? Multiple simultaneous commands would be very tricky, to track
> and interrupt early.
>
> Here is a simple example showing how to use fileevent. It really is
> simple, and needs much work to assure multiple commands
> won't interfere with one another. I think I would use threads
> if I was to do this personally.
> See http://perlmonks.org?node_id=585533
> for an example which should give you the idea.
>
> But here is a non-threaded use of fileevent.
>
> #!/usr/bin/perl
> use warnings;
> use strict;
> use Tk;
> use IPC::Open3;
> require Tk::ROText;
>
> $|=1;
>
> my $mw = new MainWindow;
>
> my $entry=$mw->Entry(-width => 80)->pack;
>
> $mw->Button(-text => 'Execute',
> -command => \&send_to_shell)->pack;
>
> my $textwin =$mw->ROText(-width => 80,
> -bg =>'white',
> -height => 24,
> )->pack;
>
> $textwin->tagConfigure( 'err', -foreground => 'red' );
>
> my $pid = open3( \*IN, \*OUT, \*ERR, '/bin/bash' ) or warn "$!\n";
>
> $mw->fileevent( \*OUT, readable => \&read_stdout );
> $mw->fileevent( \*ERR, readable => \&read_stderr );
>
> MainLoop;
>
> sub read_stdout {
>
> if( sysread( OUT, my $buffer, 1024 ) > 0 ){
> $textwin->insert( 'end', $buffer );
> }
> }
>
> sub read_stderr {
> if( sysread(ERR, my $buffer, 1024 ) > 0 ){
> $textwin->insert( 'end', $buffer, 'err' );
> }
> }
>
> sub send_to_shell {
> my $cmd= $entry->get();
> print IN "$cmd\n";
> }
> __END__
>
>
>
>
>
>
>
>
>
>
>
> --
> I'm not really a human, but I play one on earth.
> http://zentara.net/japh.html


Sponsored Links







Also available: Server administration forum archive | Web Design forum archive | Software forum archive | Hardware reviews archive

Copyright 2008 codecomments.com