package main;
use 5.008;
use strict;
use warnings;
# use Demo::App;
my $app = Demo::App->new;
$app->run;
package Shell::App;
use strict;
use warnings;
use base 'Wx::App';
$| = 1;
our $frame;
sub OnInit {
my ($self) = @_;
$frame = Shell::App::Frame->new($self);
$frame->Show( 1 );
}
sub new {
my $class = shift;
my $self = $class->SUPER::new(@_);
return $self;
}
sub run {
my ($self) = @_;
$self->setup;
$self->MainLoop;
}
sub setup {
}
sub commands {
my ($self, @commands) = @_;
$self->{commands}->{$_}++ for @commands;
return;
}
sub args {
my ($self) = @_;
# wantarray?
return $self->{args};
}
package Shell::App::Frame;
use strict;
use warnings;
use Wx qw(:everything);
use base 'Wx::Frame';
my ($out, $in);
sub new {
my ($class, $app, $windows) = @_;
$windows = 1 if not defined $windows;
die if $windows !~ /^[123]$/;
my $self = $class->SUPER::new( undef, -1,
'Shell::App',
wxDefaultPosition, [600, 600],
);
$self->{_app} = $app;
$self->{prompt} = '>';
$self->{windows} = $windows;
my $main = Wx::SplitterWindow->new(
$self, -1, wxDefaultPosition, wxDefaultSize,
wxNO_FULL_REPAINT_ON_RESIZE|wxCLIP_CHILDREN );
if ($windows == 1) {
$out = Wx::TextCtrl->new( $main, -1, '', wxDefaultPosition, wxDefaultSize,
wxTE_MULTILINE|wxNO_FULL_REPAINT_ON_RESIZE
);
$in = $out;
} elsif ($windows == 2) {
$out = Wx::TextCtrl->new( $main, -1, '', wxDefaultPosition, wxDefaultSize,
wxTE_READONLY|wxTE_MULTILINE|wxNO_FULL_REPAINT_ON_RESIZE
);
$in = Wx::TextCtrl->new( $main, -1, '', wxDefaultPosition, wxDefaultSize,
wxTE_PROCESS_ENTER|wxNO_FULL_REPAINT_ON_RESIZE
);
Wx::Event::EVT_TEXT_ENTER($self, $in, \&enter);
$main->SplitHorizontally( $out, $in, -50 );
} else {
die "windows=3 Not implemented yet\n";
}
#Wx::Event::EVT_TEXT($in, \&text_changed ); #here is where we can implement command line cleverness?
$in->SetFocus;
$out->AppendText($self->{prompt});
Wx::Event::EVT_CLOSE( $self, sub {
my ( $self, $event ) = @_;
$event->Skip;
});
return $self;
}
sub enter {
my ($self, $event) = @_;
my $output;
if ($self->{windows} eq 1) {
$output = $self->enter_1($event);
} elsif ($self->{windows} eq 2) {
$output = $self->enter_2($event);
} else {
$output = $self->enter_2($event);
}
return $output;
}
sub enter_1 {
my ($self, $event) = @_;
my $cmd_line = $in->GetValue;
print $cmd_line;
}
sub enter_2 {
my ($self, $event) = @_;
my $cmd_line = $in->GetValue;
#process
$out->AppendText("$cmd_line\n");
my ($cmd, $args) = split /\s+/, $cmd_line, 2;
$self->{_app}->{args} = $args;
if ($self->{_app}->{commands}->{$cmd}) {
my $output = $self->{_app}->$cmd();
$out->AppendText($output);
} else {
$out->AppendText("No such command '$cmd'\n");
}
$out->AppendText($self->{prompt});
$in->SetValue('');
#$out
return;
}
package Demo::App;
use strict;
use warnings;
use base 'Shell::App';
sub setup {
my ($self) = @_;
$self->commands(qw(
ls
));
return;
}
sub ls {
my ($self) = @_;
my $dir = $self->args;
$dir = '.' if not defined $dir;
#return "running ls\n";
my $res = '';
if (opendir my $dh, $dir) {
my @items = readdir $dh;
foreach my $thing (@items) {
$res .= "$thing\n";
}
} else {
$res = "Could not open '$dir': $!";
}
return $res;
}