Perl 有条件地从菜单中排除菜单选项
我编写了一个Perl模块,可以构建简单的菜单并对其进行管理,但现在我需要弄清楚,当我不希望菜单选项可用时,如何有条件地隐藏它们 例如,如果满足特定条件,如何使其在Perl 有条件地从菜单中排除菜单选项,perl,user-interface,menu,conditional-statements,submenu,Perl,User Interface,Menu,Conditional Statements,Submenu,我编写了一个Perl模块,可以构建简单的菜单并对其进行管理,但现在我需要弄清楚,当我不希望菜单选项可用时,如何有条件地隐藏它们 例如,如果满足特定条件,如何使其在$menu1中隐藏“Choice2” 这个问题是我的另一个问题的延续: 自从我开始这项工作以来,我已经取得了相当大的进步,但我似乎遇到了障碍 菜单模块如下所示: # Menu.pm #!/usr/bin/perl package Menu; use strict; use warnings; # Menu constructo
$menu1
中隐藏“Choice2”
这个问题是我的另一个问题的延续:
自从我开始这项工作以来,我已经取得了相当大的进步,但我似乎遇到了障碍
菜单模块如下所示:
# 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;
由于菜单选项被定义为一个散列数组,如果不希望显示特定选项,我不确定如何有条件地排除这些选项
有没有一种简单的方法可以做到这一点?您可以创建一个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();
#/usr/bin/perl
包装菜单项;
严格使用;
使用警告;
次新{
#解包输入参数
我的$class=shift;
我的(%args)=@;
my$text=$args{text};
my$code=$args{code};
my$disabled=$args{disabled};
#祝福菜单对象
我的$self=祝福{
text=>$text,
代码=>$code,
disabled=>$disabled,
},$class;
返回$self;
}
1.
套餐菜单;
严格使用;
使用警告;
#菜单构造函数
次新{
#解包输入参数
我的$class=shift;
我的(%args)=@;
my$title=$args{title};
my$choices\u ref=$args{choices};
my$noexit=$args{noexit};
#祝福菜单对象
我的$self=祝福{
title=>$title,
选项=>$choices\u ref,
noexit=>noexit美元,
},$class;
返回$self;
}
#打印菜单
子打印{
#解包输入参数
我的$self=shift;
my$title=$self->{title};
我的@choices=@{$self->{choices};
my$noexit=$self->{noexit};
#打印菜单
对于(;;){
#清除屏幕
系统“cls”;
#打印菜单标题
打印“=======================================================\n”;
打印“$title\n”;
打印“=======================================================\n”;
#打印菜单选项
我的$index=0;
我的@items;
对于我的$choice(@choices){
如果(!$choice->{disabled}){
$items[$index]=$choice;
printf“%2d.%s\n”,+$index,$choice->{text};
}
}
printf“%2d.%s\n”、“0”、“退出”,除非$noexit;
打印“\n?:”;
#获取用户输入
chomp(我的$input=);
打印“\n”;
#过程输入
如果($input=~m/\d+/&&&$input>=1&&&$input{code}->();
}elsif($input=~m/\d+/&&!$input&&!$noexit){
打印“正在退出…\n”;
出口0;
}否则{
打印“无效输入。\n\n”;
系统“暂停”;
}
}
}
1.
严格使用;
使用警告;
#使用菜单;
我的$menu1;
我的$menu2;
#定义菜单1选项
我的@menu1_选择=(
菜单项->新建(文本=>'Choice1',
code=>sub{print“我做了某事!\n”;}),
菜单项->新建(文本=>'Choice2',
code=>sub{print“我做了别的事!\n”;},
禁用=>1),
菜单项->新建(文本=>“转到菜单2”,
代码=>sub{$menu2->print();}),
);
#定义菜单2选项
我的@menu2\u选择=(
菜单项->新建(文本=>'Choice1',
code=>sub{print“我在菜单2中做了某事!\n”;}),
菜单项->新建(文本=>'Choice2',
code=>sub{print“我在菜单2中做了其他事情!\n”;}),
菜单项->新建(文本=>“转到菜单1”,
代码=>sub{$menu1->print();}),
);
#构建菜单1
$menu1=菜单->新建(
title=>“菜单1”,
选项=>\@menu1\u选项,
);
#构建菜单2
$menu2=菜单->新建(
title=>“菜单2”,
选项=>\@menu2\u选项,
);
#打印菜单1
$menu1->print();
我不完全清楚你在问什么。我想你是在问“既然我有一个散列数组,我怎么能忽略一些包含特定键的散列?”
在创建菜单对象时,您可以通过一条语句轻松完成这一任务:
my $menu2 = Menu->new(
title => 'Menu2',
choices => [grep { $_->{text} ne 'Choice2' } @menu2_choices],
);
让我们假设有一个黑名单作为参数。当然,你可以把它放在其他地方,例如作为对象的属性 只需检查黑名单中的每一个,或者直接从选择数组中删除它们
sub print {
my ($self, @blacklist) = @_;
for my $choice (@choices) {
printf "%2d. %s\n", ++$index, $choice->{text}
unless grep { $_ eq $choice->{text} } @blacklist;
}
}
感谢lovedatsnow提出的让这些项目成为自己的对象的想法!我基本上接受了你的答案,并对其进行了改进,使创建菜单的界面看起来比以前更干净 这是我的新代码:
# test.pl
#!/usr/bin/perl
# Always use these
use strict;
use warnings;
# Other use statements
use Menu;
# Create a menu object
my $menu = Menu->new();
# Add a menu item
$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'; },
);
# Disable a menu item
$menu->disable('Test2');
$menu->print();
# Enable a menu item
$menu->enable('Test2');
$menu->print();
我创建了一个菜单类,其中包含一些有用的函数,允许您直接操作菜单项。这使您可以轻松地启用/禁用它们
# Menu.pm
#!/usr/bin/perl
package Menu;
# Always use these
use strict;
use warnings;
# Other use statements
use Carp;
use Menu::Item;
# Menu constructor
sub new {
# Unpack input arguments
my ($class, $title) = @_;
# Define a default title
if (!defined $title) {
$title = 'MENU';
}
# Bless the Menu object
my $self = bless {
_title => $title,
_items => [],
}, $class;
return $self;
}
# Title accessor method
sub title {
my ($self, $title) = @_;
$self->{_title} = $title if defined $title;
return $self->{_title};
}
# Items accessor method
sub items {
my ($self, $items) = @_;
$self->{_items} = $items if defined $items;
return $self->{_items};
}
# Add item(s) to the menu
sub add {
# Unpack input arguments
my ($self, @add) = @_;
croak 'add() requires name-action pairs' unless @add % 2 == 0;
# Add new items
while (@add) {
my ($name, $action) = splice @add, 0, 2;
# If the item already exists, remove it
for my $index(0 .. $#{$self->{_items}}) {
if ($name eq $self->{_items}->[$index]->name()) {
splice @{$self->{_items}}, $index, 1;
}
}
# Add the item to the end of the menu
my $item = Menu::Item->new($name, $action);
push @{$self->{_items}}, $item;
}
return 0;
}
# Remove item(s) from the menu
sub remove {
# Unpack input arguments
my ($self, @remove) = @_;
# Remove items
for my $name(@remove) {
# If the item exists, remove it
for my $index(0 .. $#{$self->{_items}}) {
if ($name eq $self->{_items}->[$index]->name()) {
splice @{$self->{_items}}, $index, 1;
}
}
}
return 0;
}
# Disable item(s)
sub disable {
# Unpack input arguments
my ($self, @disable) = @_;
# Disable items
for my $name(@disable) {
# If the item exists, disable it
for my $index(0 .. $#{$self->{_items}}) {
if ($name eq $self->{_items}->[$index]->name()) {
$self->{_items}->[$index]->active(0);
}
}
}
return 0;
}
# Enable item(s)
sub enable {
# Unpack input arguments
my ($self, @enable) = @_;
# Disable items
for my $name(@enable) {
# If the item exists, enable it
for my $index(0 .. $#{$self->{_items}}) {
if ($name eq $self->{_items}->[$index]->name()) {
$self->{_items}->[$index]->active(1);
}
}
}
}
# Print the menu
sub print {
# Unpack input arguments
my ($self) = @_;
# Print the menu
for (;;) {
system 'cls';
# Print the title
print "========================================\n";
print " $self->{_title}\n";
print "========================================\n";
# Print menu items
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';
# Get user input
print "\n?: ";
chomp (my $input = <STDIN>);
# Process user input
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) {
return 0;
}
# Deal with invalid input
print "\nInvalid input.\n\n";
system 'pause';
}
}
1;
这为构建和使用菜单创建了一个非常优雅的界面
不再有丑陋的哈希数组。:)欢迎使用堆栈溢出!因为你是新来的,这里有一些建设性的反馈。这是一个很好的答案。你努力解决老年退休金问题。那太酷了,太棒了。但是,如果您只显示相关的代码段会更好,因为现在很难看到您更改了什么(我只是发现了它,因为您忘了缩进它)。它看起来杂乱无章。只需显示代码相关部分的摘录,并对您添加的内容发表评论。不要为别人做全部工作,而是帮助他们解决自己的问题,让他们学习。:)您还忘记了
packagemain代码>;)
# Menu.pm
#!/usr/bin/perl
package Menu;
# Always use these
use strict;
use warnings;
# Other use statements
use Carp;
use Menu::Item;
# Menu constructor
sub new {
# Unpack input arguments
my ($class, $title) = @_;
# Define a default title
if (!defined $title) {
$title = 'MENU';
}
# Bless the Menu object
my $self = bless {
_title => $title,
_items => [],
}, $class;
return $self;
}
# Title accessor method
sub title {
my ($self, $title) = @_;
$self->{_title} = $title if defined $title;
return $self->{_title};
}
# Items accessor method
sub items {
my ($self, $items) = @_;
$self->{_items} = $items if defined $items;
return $self->{_items};
}
# Add item(s) to the menu
sub add {
# Unpack input arguments
my ($self, @add) = @_;
croak 'add() requires name-action pairs' unless @add % 2 == 0;
# Add new items
while (@add) {
my ($name, $action) = splice @add, 0, 2;
# If the item already exists, remove it
for my $index(0 .. $#{$self->{_items}}) {
if ($name eq $self->{_items}->[$index]->name()) {
splice @{$self->{_items}}, $index, 1;
}
}
# Add the item to the end of the menu
my $item = Menu::Item->new($name, $action);
push @{$self->{_items}}, $item;
}
return 0;
}
# Remove item(s) from the menu
sub remove {
# Unpack input arguments
my ($self, @remove) = @_;
# Remove items
for my $name(@remove) {
# If the item exists, remove it
for my $index(0 .. $#{$self->{_items}}) {
if ($name eq $self->{_items}->[$index]->name()) {
splice @{$self->{_items}}, $index, 1;
}
}
}
return 0;
}
# Disable item(s)
sub disable {
# Unpack input arguments
my ($self, @disable) = @_;
# Disable items
for my $name(@disable) {
# If the item exists, disable it
for my $index(0 .. $#{$self->{_items}}) {
if ($name eq $self->{_items}->[$index]->name()) {
$self->{_items}->[$index]->active(0);
}
}
}
return 0;
}
# Enable item(s)
sub enable {
# Unpack input arguments
my ($self, @enable) = @_;
# Disable items
for my $name(@enable) {
# If the item exists, enable it
for my $index(0 .. $#{$self->{_items}}) {
if ($name eq $self->{_items}->[$index]->name()) {
$self->{_items}->[$index]->active(1);
}
}
}
}
# Print the menu
sub print {
# Unpack input arguments
my ($self) = @_;
# Print the menu
for (;;) {
system 'cls';
# Print the title
print "========================================\n";
print " $self->{_title}\n";
print "========================================\n";
# Print menu items
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';
# Get user input
print "\n?: ";
chomp (my $input = <STDIN>);
# Process user input
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) {
return 0;
}
# Deal with invalid input
print "\nInvalid input.\n\n";
system 'pause';
}
}
1;
# Item.pm
#!/usr/bin/perl
package Menu::Item;
# Always use these
use strict;
use warnings;
# Menu::Item constructor
sub new {
# Unpack input arguments
my ($class, $name, $action) = @_;
# Bless the Menu::Item object
my $self = bless {
_name => $name,
_action => $action,
_active => 1,
}, $class;
return $self;
}
# Name accessor method
sub name {
my ($self, $name) = @_;
$self->{_name} = $name if defined $name;
return $self->{_name};
}
# Action accessor method
sub action {
my ($self, $action) = @_;
$self->{_action} = $action if defined $action;
return $self->{_action};
}
# Active accessor method
sub active {
my ($self, $active) = @_;
$self->{_active} = $active if defined $active;
return $self->{_active};
}
1;