Beefy Boxes and Bandwidth Generously Provided by pair Networks
Do you know where your variables are?
 
PerlMonks  

Re: Printing a subset of a data structure

by jdporter (Paladin)
on May 01, 2006 at 16:15 UTC ( [id://546683]=note: print w/replies, xml ) Need Help??


in reply to Printing a subset of a data structure

I think what you're trying to achieve here (correct me if I'm wrong) is to display a submenu only when it's needed, i.e. if the user has selected an item from the main menu which has a submenu. To do this, you're wanting to defer the printing of a submenu. Your code, as shown, does not acheive this; even though you're taking a reference to the print_sub_menu function, you're still calling it right away, and putting the result in the data structure. Instead, you should put a code reference in the data structure. E.g.:

my %menus = ( '1' => { 'ITEM' => 'List and Kill UDT* processes by user', 'ACTION' => sub { $RunCMD->('ListKillProc') }, }, '2' => { 'ITEM' => 'List and Kill Print Jobs', 'ACTION' => sub { $PrintSubmenu->('2') }, . . .

Then, when the user selects an item, you can execute the action; something like this:

$menu->{$MenuItem}->{'ACTION'}->();

Other than that, there's a lot you could do to this to make it more generic and robust.

Might I also suggest that you're suffering from (or inflicting) Indentation Hell. Try it this way:

my %menus = ( '1' => { 'ITEM' => 'List and Kill UDT* processes by user', 'ACTION' => $RunCMD->('ListKillProc'), }, '2' => { 'ITEM' => 'List and Kill Print Jobs', 'ACTION' => $PrintSubmenu->('2'), 'SUBMENU' => { '1' => { 'ITEM' => 'Show all Printers', 'ACTION' => $RunCMD->('showprintersall'), }, '2' => { 'ITEM' => 'Show user print jobs', 'ACTION' => $RunCMD->('showprintersuser'), }, '3' => { 'ITEM' => 'Show single printer', 'ACTION' => $RunCMD->('showprinter'), }, '4' => { 'ITEM' => 'Kill a print job', 'ACTION' => $RunCMD->('killprint'), }, } }, '3' => { 'ITEM' => 'Manage user accounts', 'ACTION' => $PrintSubmenu->('3'), 'SUBMENU' => { '1' => { 'ITEM' => 'Unlock user account', 'ACTION' => $RunCMD->('unlockuser'), }, '2' => { 'ITEM' => 'Change account password', 'ACTION' => $RunCMD->('changepass'), }, }, }, '4' => { 'ITEM' => 'Run App', 'ACTION' => $RunCMD->('APP'), }, '5' => { 'ITEM' => 'quit', 'ACTION' => $RunCMD->('quit'), }, );
We're building the house of the future together.

Replies are listed 'Best First'.
Simple Console Menuing System
by jdporter (Paladin) on May 01, 2006 at 17:49 UTC

    Inspired by the OP, I wrote the following. It's a system for simple console-based menus. It's easily extensible.

    use strict; use warnings; sub do_menu { my( $menu ) = @_; while(1) { my( $menu ) = @_; # display the menu print "\n"; print $_+1, '. ', $menu->[$_]{'label'}, "\n" for 0 .. $#{$menu}; print '0. ', ( @_ > 1 ? 'Return' : 'Exit' ), "\n"; # get the user's input local @ARGV; print STDERR '> '; local $_ = <>; chomp; /\d/ && !/\D/ or next; $_ == 0 and last; # item 0 is special defined $menu->[$_-1] or warn("Invalid choice\n"), next; my $op = $menu->[$_-1]{'op'}; my $arg = $menu->[$_-1]{'arg'}; if ( $op eq 'submenu' ) { do_menu( $arg, @_ ); # maintain the stack! } elsif ( $op eq 'exec_cmd' ) { execute_command( $arg ); } else { warn "Unrecognized op '$op'\n"; } } } my @printers_menu = ( { label => 'Show all Printers', op => 'exec_cmd', arg => 'showprintersall', }, { label => 'Show user print jobs', op => 'exec_cmd', arg => 'showprintersuser', }, { label => 'Show single printer', op => 'exec_cmd', arg => 'showprinter', }, { label => 'Kill a print job', op => 'exec_cmd', arg => 'killprint', }, ); my @accounts_menu = ( { label => 'Unlock user account', op => 'exec_cmd', arg => 'unlockuser', }, { label => 'Change account password', op => 'exec_cmd', arg => 'changepass', }, ); my @main_menu = ( { label => 'List and Kill UDT* processes by user', op => 'exec_cmd', arg => 'ListKillProc', }, { label => 'List and Kill Print Jobs...', op => 'submenu', arg => \@printers_menu, }, { label => 'Manage user accounts...', op => 'submenu', arg => \@accounts_menu, }, { label => 'Run App', op => 'exec_cmd', arg => 'APP', }, ); sub execute_command { warn "Executing command '@_'\n"; } do_menu( \@main_menu );

    Of course, with objects, this might have been even more elegant.

    We're building the house of the future together.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://546683]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others perusing the Monastery: (4)
As of 2024-04-19 14:40 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found