perl - 有条件地从菜单中排除菜单选项

标签 perl user-interface menu conditional-statements submenu

我编写了一个 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/

相关文章:

mysql - 如何将 UTF-8 数据与保存在 Latin1 MySQL 数据库表中的相同数据进行比较

c++ - 我在播放 Mix_Chunk 时意外延迟

html - 如何使菜单居中? CSS

C# 和方向键

HTML/CSS : show submenu next to parent MENU, 不是父项

html - 鼠标悬停在 li 外时隐藏子菜单

mysql - 写入数据库时​​的编码问题 (Perl)

perl - 将 KeyForge API 与 Perl 结合使用

mysql - 有没有办法通过解析文本文件来填写Sharepoint条目?

java - 乒乓球不会从墙上弹起