Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
552 views
in Technique[技术] by (71.8m points)

user interface - How can I build a simple menu in Perl?

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 the previous menu or exit.

example:

This is a menu:

  1. Choice 1
  2. Choice 2
  3. Return to previous menu
  4. Exit

Select an option:

I currently have a menu subroutine making the menus, but there is no functionality allowing it to go back to the previous menu.

    sub menu
    {
        for (;;) {
            print "--------------------
";
            print "$_[0]
";
            print "--------------------
";
            for (my $i = 0; $i < scalar(@{ $_[1]}); $i++) {
                print $i + 1, ". ${ $_[1] }[$i]
";
            }
            print "
?: ";
            my $i = <STDIN>; chomp $i;
            if ($i && $i =~ m/[0-9]+/ && $i <= scalar(@{ $_[1]})) {
                return ${ $_[1] }[$i - 1];
            } else {
                print "
Invalid input.

";
            }
        }
    }

    # Using the menu
    my $choice1  = menu('Menu1 header', @list_of_choices1);

    # I would like this menu to give the option to go back to
    # the first menu to change $choice1
    my $choice2 = menu('Menu2 header', @list_of_choices2);

I don't want to hard code all of the menus and use if/elsif statements for all of the processing so I turned the menu into a function.

My menus currently look like this...

Menu Header:

  1. Choice1
  2. Choice2
  3. Choice3

?: (Enter input here)

This solution still doesn't allow the user to go back to the previous menu or exit though. I was considering making a menu class to handle the menus, but I am still not very good with object oriented Perl. This is a small program with only a few menus so using a complex menu building module may be overkill. I would like to keep my code as light as possible.

EDIT:

Thanks for the quick responses! However there is still an issue. When I select an option from "Menu1" and it progresses to "Menu2" I would like the save the choice from "Menu1" for later use:

Menu1:

  1. Choice1 <-- store value if selected and go to next menu
  2. Choice2 <-- ...
  3. Exit <-- quit

Menu2:

  1. Choice1 <-- store value if selected and go to next menu
  2. Choice2 <-- ...
  3. Back <-- go back to previous menu to reselect value
  4. Exit <-- quit

Selecting either Choice1 or Choice2 should store a value in a variable for later use and progress to the next menu. Then if you choose to go back to the first menu from Menu2, it will give you the option to reselect your choice and redefine the variable. I'm trying to avoid using global variables which makes this quite difficult.

After progressing through all of the menus and setting the values of all of these variables, I want to run a subroutine to process all of the choices and print a final output.

 sub main () {

   # DO MENU STUFF HERE

   # PROCESS RESULTS FROM MENU CHOICES
   my $output = process($menu1_choice, $menu2_choice, $menu3_choice, ... );
 }

Also if anyone has an object oriented approach to this using classes or some other data structure, although it may be overkill, I would still love to see it and try to wrap my head around the idea!

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

You could use a module such as Term::Choose:

use Term::Choose qw( choose );

my $submenus = {
    menu1 => [ qw( s_1 s_2 s_3 ) ],
    menu2 => [ qw( s_4 s_5 s_6 s_7) ],
    menu3 => [ qw( s_8 s_9 ) ],
};
my @menus = ( qw( menu1 menu2 menu3 ) );
my $mm = 0;
MAIN: while ( 1 ) {
    my $i = choose( 
        [ undef, @menus ],
        { layout => 3, undef => 'quit', index => 1, default => $mm }
    );
    last if ! $i;
    if ( $mm == $i ) {
        $mm = 0;
        next MAIN;
    }
    else {
        $mm = $i;
    }
    $i--;
    SUB: while ( 1 ) {
        my $choice = choose(
            [ undef, @{$submenus->{$menus[$i]}} ],
            { layout => 3, undef => 'back' }
        );
        last SUB if ! defined $choice;
        say "choice: $choice";
    }
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...