我编写了一个 Perl 模块,它可以构建简单的菜单并对其进行管理,但现在我需要弄清楚当我不希望它们可用时如何有条件地隐藏菜单选项。
例如我怎样才能让它隐藏"Choice2"
在 $menu1
如果满足特定条件?
这个问题在某种程度上是我的其他问题之一的延续:
How can I build a simple menu in Perl?
自从我开始这项工作以来,我已经取得了相当大的进步,但我似乎遇到了障碍。
菜单模块如下所示:
# Menu.pm
#!/usr/bin/perl
package Menu;
use strict;
use warnings;
# Menu constructor
sub new {
# Unpack input arguments
my $class = shift;
my (%args) = @_;
my $title = $args{title};
my $choices_ref = $args{choices};
my $noexit = $args{noexit};
# Bless the menu object
my $self = bless {
title => $title,
choices => $choices_ref,
noexit => $noexit,
}, $class;
return $self;
}
# Print the menu
sub print {
# Unpack input arguments
my $self = shift;
my $title = $self->{title };
my @choices = @{$self->{choices}};
my $noexit = $self->{noexit };
# Print menu
for (;;) {
# Clear the screen
system 'cls';
# Print menu title
print "========================================\n";
print " $title\n";
print "========================================\n";
# Print menu options
my $index = 0;
for my $choice(@choices) {
printf "%2d. %s\n", ++$index, $choice->{text};
}
printf "%2d. %s\n", '0', 'Exit' unless $noexit;
print "\n?: ";
# Get user input
chomp (my $input = <STDIN>);
print "\n";
# Process input
if ($input =~ m/\d+/ && $input >= 1 && $input <= $index) {
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;
以下是如何使用该模块的示例:
# test.pl
#!/usr/bin/perl
use strict;
use warnings;
use Menu;
my $menu1;
my $menu2;
# define menu1 choices
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(); }},
);
# define menu2 choices
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(); }},
);
# Build menu1
$menu1 = Menu->new(
title => 'Menu1',
choices => \@menu1_choices,
);
# Build menu2
$menu2 = Menu->new(
title => 'Menu2',
choices => \@menu2_choices,
);
# Print menu1
$menu1->print();
由于菜单选项被定义为散列数组,因此如果我不希望显示特定选项,我不确定如何有条件地排除特定选项。
是否有捷径可寻?
最佳答案
您可以创建一个 MenuItem 包,然后在选项中设置一个标志来决定是否应该包含它。下面是创建菜单选项时使用新包的完整代码集。为了演示它,在第一个菜单中为第二个选项设置了“禁用”标志。
请注意,在计算用户响应时,在“打印”子例程中添加了一些额外的代码来处理禁用的选择。
#!/usr/bin/perl
package MenuItem;
use strict;
use warnings;
sub new {
# Unpack input arguments
my $class = shift;
my (%args) = @_;
my $text = $args{text};
my $code = $args{code};
my $disabled = $args{disabled};
# Bless the menu object
my $self = bless {
text => $text,
code => $code,
disabled => $disabled,
}, $class;
return $self;
}
1;
package Menu;
use strict;
use warnings;
# Menu constructor
sub new {
# Unpack input arguments
my $class = shift;
my (%args) = @_;
my $title = $args{title};
my $choices_ref = $args{choices};
my $noexit = $args{noexit};
# Bless the menu object
my $self = bless {
title => $title,
choices => $choices_ref,
noexit => $noexit,
}, $class;
return $self;
}
# Print the menu
sub print {
# Unpack input arguments
my $self = shift;
my $title = $self->{title };
my @choices = @{$self->{choices}};
my $noexit = $self->{noexit };
# Print menu
for (;;) {
# Clear the screen
system 'cls';
# Print menu title
print "========================================\n";
print " $title\n";
print "========================================\n";
# Print menu options
my $index = 0;
my @items;
for my $choice(@choices) {
if ( ! $choice->{disabled} ) {
$items[$index]=$choice;
printf "%2d. %s\n", ++$index, $choice->{text};
}
}
printf "%2d. %s\n", '0', 'Exit' unless $noexit;
print "\n?: ";
# Get user input
chomp (my $input = <STDIN>);
print "\n";
# Process input
if ($input =~ m/\d+/ && $input >= 1 && $input <= $index) {
return $items[$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;
# define menu1 choices
my @menu1_choices = (
MenuItem->new(text => 'Choice1',
code => sub { print "I did something!\n"; }),
MenuItem->new(text => 'Choice2',
code => sub { print "I did something else!\n"; },
disabled => 1),
MenuItem->new(text => 'Go to Menu2',
code => sub { $menu2->print(); }),
);
# define menu2 choices
my @menu2_choices = (
MenuItem->new(text => 'Choice1',
code => sub { print "I did something in menu 2!\n"; }),
MenuItem->new(text => 'Choice2',
code => sub { print "I did something else in menu 2!\n"; }),
MenuItem->new(text => 'Go to Menu1',
code => sub { $menu1->print(); }),
);
# Build menu1
$menu1 = Menu->new(
title => 'Menu1',
choices => \@menu1_choices,
);
# Build menu2
$menu2 = Menu->new(
title => 'Menu2',
choices => \@menu2_choices,
);
# Print menu1
$menu1->print();
关于perl - 有条件地从菜单中排除菜单选项,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28564783/