1up
1up

Reputation: 116

utilizing a menu in perl, cycle back to main menu after command

I would like to cycle back to the main menu after a command or menu command has been completed, something is giving out in my code, menu option 1 would cycle, but once I got the commands listing files and folders correctly, this stopped.

#!/usr/bin/perl -w

use strict;

my $menu1;
my $menu2;
my $menu3;
my $directory = '/home/jkiger';

my $quit_menu_item = [ "Quit", sub { exit; } ];

$menu1 = [
    "Chose a command for the home folder: ",
    [ "list home directory files and folders", \&ds1 ],
    [ "List file types in home directory",     \&ds2 ],
    [ "List file types in home directory",     \&ds3 ],
    [ "Quit", sub { exit; } ],
];

sub menu {
    my $m = shift;
    my $choice;
    while (1) {
        print "$m->[0]:\n";
        print map {"\t$_. $m->[$_][0]\n"} ( 1 .. $#$m );
        print "> ";
        chomp( $choice = <> );
        last if ( ( $choice > 0 ) && ( $choice <= $#$m ) );
        print "You chose '$choice'.  That is not a valid option.\n\n";
    }
    &{ $m->[$choice][1] };
}

sub ds1 {
    system("ls $directory") or die $!;
    &menu($menu1);
}

sub ds2 {
    system("ls -p $directory") or die $!;
    &menu($menu2);
}

sub ds3 {
    system("ls -s $directory") or die $!;
    &menu($menu3);
}

&menu($menu1);
&menu($menu2);
&menu($menu3);

Upvotes: 0

Views: 340

Answers (1)

Miller
Miller

Reputation: 35208

Instead of breaking out of your loop when you find a valid option, just execute the code and continue:

chomp( my $choice = <> );

if ( $choice > 0 && $choice <= $#$m ) {
    $m->[$choice][1]();
} else {
    print "You chose '$choice'.  That is not a valid option.\n\n";
}

For some additional tips I would point out the following

  1. Use a %hash for a dispatch table instead of an array. This helps you avoid having to check the datatype before verifying you're using a valid value.
  2. Read the spec for system for how to properly check for errors.

The following is a simplification of your script that accomplishes the same task:

#!/usr/bin/perl -w
use strict;
use warnings;

my $directory = '/home/jkiger';

my %dispatch = (
    1 => sub { system( 'ls', $directory ) == 0 or die $? },
    2 => sub { system( 'ls', '-p', $directory ) == 0 or die $? },
    3 => sub { system( 'ls', '-s', $directory ) == 0 or die $? },
    4 => sub {exit},
);

while (1) {
    print <<"END_PROMPT";
Chose a command for the home folder: 
1. List home directory files and folders
2. List file types in home directory
3. List file types in home directory
4. Quit
END_PROMPT

    chomp( my $choice = <> );

    if ( $dispatch{$choice} ) {
        $dispatch{$choice}();
    } else {
        print "You chose '$choice'.  That is not a valid option.\n\n";
    }
}

Upvotes: 1

Related Questions