How can I build a simple menu in Perl?

前端 未结 6 1104
野的像风
野的像风 2020-12-11 20:23

I\'m working on a Perl script that requires some basic menu functionality. Ultimately I would like each menu to have a few options and then the option to either return to th

6条回答
  •  情歌与酒
    2020-12-11 21:08

    If you don't want to go full OO with this, a simple way that you can make this a lot more flexible is to allow each menu choice to control how it is executed. Let's say each menu has an array of hashes that contain the menu text and a coderef that implements what the menu does.

    use strict;
    use warnings;
    
    sub menu {
        my @items = @_;
    
        my $count = 0;
        foreach my $item( @items ) {
            printf "%d: %s\n", ++$count, $item->{text};
        }
    
        print "\n?: ";
    
        while( my $line =  ) {
            chomp $line;
            if ( $line =~ m/\d+/ && $line <= @items ) {
                return $items[ $line - 1 ]{code}->();
            }
    
            print "\nInvalid input\n\n?: ";
        }
    }
    
    my @menu_choices;
    my @other_menu_choices;
    
    @menu_choices = (
        { text  => 'do something',
          code  => sub { print "I did something!\n" } },
        { text  => 'do something else',
          code  => sub { print "foobar!\n" } },
        { text  => 'go to other menu',
          code  => sub { menu( @other_menu_choices ) } }
    );
    
    @other_menu_choices = (
        { text  => 'go back',
          code  => sub { menu( @menu_choices ) } }
    );
    
    menu( @menu_choices );
    

    The menu subroutine takes an array of options, and each option "knows" how to perform its own action. If you want to switch between menus, the menu option just calls menu again with a different list of options, as in the "go back" example from @other_menu_choices. This make linking between menus very easy and it's also easy to add exit options and such.

    To keep this code clean and readable, for anything other than trivial menu actions, use a named reference to a subroutine instead of an anonymous subroutine reference. For example:

    @another_menu_options = (
        { text => 'complicated action'
          code => \&do_complicated_action
        }
    );
    
    sub do_complicated_action { 
        ...
    }
    

提交回复
热议问题