Perl , - , friedo.
package Menu;
use strict;
use warnings;
sub new {
my $class = shift;
my (%args) = @_;
my $title = $args{title};
my $choices_ref = $args{choices};
my $noexit = $args{noexit};
my $self = bless {
title => $title,
choices => $choices_ref,
noexit => $noexit,
}, $class;
return $self;
}
sub print {
my $self = shift;
my $title = $self->{title };
my @choices = @{$self->{choices}};
my $noexit = $self->{noexit };
for (;;) {
system 'cls';
print "========================================\n";
print " $title\n";
print "========================================\n";
my $counter = 0;
for my $choice(@choices) {
printf "%2d. %s\n", ++$counter, $choice->{text};
}
printf "%2d. %s\n", '0', 'Exit' unless $noexit;
print "\n?: ";
chomp (my $input = <STDIN>);
print "\n";
if ($input =~ m/\d+/ && $input >= 1 && $input <= $counter) {
return $choices[$input - 1]{code}->();
} elsif ($input =~ m/\d+/ && !$input && !$noexit) {
print "Exiting . . .\n";
exit 0;
} else {
print "Invalid input.\n\n";
system 'pause';
}
}
}
1;
, . :
use strict;
use warnings;
use Menu;
my $menu1;
my $menu2;
my @menu1_choices = (
{ text => 'Choice1',
code => sub { print "I did something!\n"; }},
{ text => 'Choice2',
code => sub { print "I did something else!\n"; }},
{ text => 'Go to Menu2',
code => sub { $menu2->print(); }},
);
my @menu2_choices = (
{ text => 'Choice1',
code => sub { print "I did something in menu 2!\n"; }},
{ text => 'Choice2',
code => sub { print "I did something else in menu 2!\n"; }},
{ text => 'Go to Menu1',
code => sub { $menu1->print(); }},
);
$menu1 = Menu->new(
title => 'Menu1',
choices => \@menu1_choices,
);
$menu2 = Menu->new(
title => 'Menu2',
choices => \@menu2_choices,
noexit => 1,
);
$menu1->print();
. , .
! , , !
:
!
, Menu.pm Item.pm, , .
. :
script, .
use strict;
use warnings;
use Menu;
my $menu = Menu->new();
$menu->add(
'Test' => sub { print "This is a test\n"; system 'pause'; },
'Test2' => sub { print "This is a test2\n"; system 'pause'; },
'Test3' => sub { print "This is a test3\n"; system 'pause'; },
);
$menu->exit(1);
$menu->disable('Test2');
$menu->print();
$menu->exit(0);
$menu->enable('Test2');
$menu->print();
Menu.pm . Menu:: Item. , .
package Menu;
use strict;
use warnings;
use Carp;
use Menu::Item;
sub new {
my ($class, $title) = @_;
if (!defined $title) {
$title = 'MENU';
}
my $self = bless {
_title => $title,
_items => [],
_exit => 0,
}, $class;
return $self;
}
sub title {
my ($self, $title) = @_;
$self->{_title} = $title if defined $title;
return $self->{_title};
}
sub items {
my ($self, $items) = @_;
$self->{_items} = $items if defined $items;
return $self->{_items};
}
sub exit {
my ($self, $exit) = @_;
$self->{_exit} = $exit if defined $exit;
return $self->{_exit};
}
sub add {
my ($self, @add) = @_;
croak 'add() requires name-action pairs' unless @add % 2 == 0;
while (@add) {
my ($name, $action) = splice @add, 0, 2;
for my $index(0 .. $#{$self->{_items}}) {
if ($name eq $self->{_items}->[$index]->name()) {
splice @{$self->{_items}}, $index, 1;
}
}
my $item = Menu::Item->new($name, $action);
push @{$self->{_items}}, $item;
}
return 0;
}
sub remove {
my ($self, @remove) = @_;
for my $name(@remove) {
for my $index(0 .. $#{$self->{_items}}) {
if ($name eq $self->{_items}->[$index]->name()) {
splice @{$self->{_items}}, $index, 1;
}
}
}
return 0;
}
sub disable {
my ($self, @disable) = @_;
for my $name(@disable) {
for my $index(0 .. $#{$self->{_items}}) {
if ($name eq $self->{_items}->[$index]->name()) {
$self->{_items}->[$index]->active(0);
}
}
}
return 0;
}
sub enable {
my ($self, @enable) = @_;
for my $name(@enable) {
for my $index(0 .. $#{$self->{_items}}) {
if ($name eq $self->{_items}->[$index]->name()) {
$self->{_items}->[$index]->active(1);
}
}
}
}
sub print {
my ($self) = @_;
for (;;) {
system 'cls';
print "========================================\n";
print " $self->{_title}\n";
print "========================================\n";
for my $index(0 .. $#{$self->{_items}}) {
my $name = $self->{_items}->[$index]->name();
my $active = $self->{_items}->[$index]->active();
if ($active) {
printf "%2d. %s\n", $index + 1, $name;
} else {
print "\n";
}
}
printf "%2d. %s\n", 0, 'Exit' if $self->{_exit};
print "\n?: ";
chomp (my $input = <STDIN>);
if ($input =~ m/^\d+$/ && $input > 0 && $input <= scalar @{$self->{_items}}) {
my $action = $self->{_items}->[$input - 1]->action();
my $active = $self->{_items}->[$input - 1]->active();
if ($active) {
print "\n";
return $action->();
}
} elsif ($input =~ m/^\d+$/ && $input == 0 && $self->{_exit}) {
exit 0;
}
print "\nInvalid input.\n\n";
system 'pause';
}
}
1;
Item.pm "". . Menu:: Item, . .
package Menu::Item;
use strict;
use warnings;
sub new {
my ($class, $name, $action) = @_;
my $self = bless {
_name => $name,
_action => $action,
_active => 1,
}, $class;
return $self;
}
sub name {
my ($self, $name) = @_;
$self->{_name} = $name if defined $name;
return $self->{_name};
}
sub action {
my ($self, $action) = @_;
$self->{_action} = $action if defined $action;
return $self->{_action};
}
sub active {
my ($self, $active) = @_;
$self->{_active} = $active if defined $active;
return $self->{_active};
}
1;
.
, .
, ?