primus has asked for the wisdom of the Perl Monks concerning the following question:

hail monks!

OK, i am just trying to write a simple command line based program that accepts input from the user (win32 based).

i was looking for the best way to implement this terminal based program, should i use getc ? or POSIX module off of CPAN... i have never really written one of these before, so i am not sure how to go about it.

the basics i need it to do:

thus far i just have (very basic):
my ($getch); while (1) { print "Enter a something: "; $getch = getc; print "\n\n$getch\n\n"; exit if ($getch =~ /^q/); }
is this all i need to do? any suave way of implementing this? thanks for the help!

Replies are listed 'Best First'.
Re: ~ simple command line program ~
by JamesNC (Chaplain) on Jan 04, 2003 at 06:27 UTC
    Try using Term::ReadKey you can make the shell behave anyway you want by setting the ReadMode. Here is some code I wrote to capture a key, and echo back a * on a Win32 machine. It did not behave properly until (tye) got me to try putting STDIN in binmode. This may be over-board for you... play with it :)
    #!/perl/bin/perl use Term::ReadKey; while(1){ ReadMode 3; #cbreak mode &menu; print "\tChoice: "; my $key = ReadKey(); print "$key"; &hello_world if $key == 1; &get_password if $key == 2; if( $key eq 'q' || $key eq 'Q'){ print "\nExiting"; exit(0); } } sub get_password{ binmode STDIN, ":raw"; ReadMode 3; my ($key, $val, $pass, $backstop); my @password; my $prompt = "\n\n\tPassword: "; system("cls"); # NOTE if you make a call to the system you have to +reset the ReadMode :) #After we make the system call... ReadMode is set back to normal or 0! +! ReadMode 3; print "$prompt"; while($key = ReadKey()){ $val = ord $key; push @password, $key unless $val == 8 || $val == 13; $backstop = @password; last if $val == 13; if($val == 8){ pop @password; if($backstop) {print "\b \b"; } } print "*" unless $val == 8; } ReadMode 0; binmode STDIN, ":crlf"; foreach(@password) { $pass .= $_; } print "\n\n\tYou entered: $pass\n\t(will return to main menu in 3 tick +s)"; sleep 3; system("cls"); } sub menu{ print <<MENU; [1] Hello World [2] Password Sub [Q] Exit MENU } sub hello_world{ system ("cls"); for(1..10){ print "\n\t\tHELLO WORLD \n"; } print "\n\t(will return to main menu in 3 ticks)"; sleep 3; system ("cls"); }
    Update: 13 is the ord value of the enter key and 8 is the backspace, you will need to use 10 for your enter key on a unix OS. Windows consoles "steal" the delete and arrow keys so I can't catch them. You may be able to add them to handle rubouts, it just wouldn't do it on Win32, most folks use backspace to rubout so I didn't try too hard to find a way to bind to the delete key.
Re: simple command line program
by rbc (Curate) on Jan 04, 2003 at 04:31 UTC
        kewl, thanks alot for the help fellow monk.
    Re: simple command line program
    by pg (Canon) on Jan 04, 2003 at 08:14 UTC
      There is one thing you can do to make your program structure really neat, and that is to use a HoH (also could be AoA, AoH or whatever two-level sturcture that fits) to store your call back functions.

      Give each of your question a unique identifier, could be a number or a string. Also give each of your choices an identifier, which is unique within the related question.

      To demo, I just use string as identifier, and pick HoH as the structure. I can store all the callback functions in this way:

      my $callback_functions = { #I am not suggesting this kind of 1,2,3,4 naming convention in you +r actual code, this is just for demo, it is never a good idea to hard + code the index as part of your identifier. "question1" => { "answer1" => \&func1, "answer2" => \&func2, "answer3" => \&func3, }, "question2" => { "answer1" => \&func4, "answer2" => \&func5, "answer3" => \&func6, }, "question3" => { "answer1" => \&func7, "answer2" => \&func8, "answer3" => \&func9, } };
      But you better use some meaningful identifiers.

      By doing this, you can actually avoid those tedious nested if-else, and make your logic much more straight and clear. Now the differences among questions and answers is detached from your logic, and is largely contained in that callback structure.
    Re: simple command line program
    by eoin (Monk) on Jan 04, 2003 at 13:10 UTC
      This is a rather lenghty way of doing it but it helps you understand how the code works. Hope it helps..
      print ".Main menu.\n\n"; print "1. Whatever1\n"; print "2. Whatever2\n"; print "3. Whatever3\n"; print "4. Whatever4\n"; print "5. Whatever5\n"; print "6. Whatever6\n\n"; print "Please choose an option or (q) quit\n"; while (1) { $opt = <>; chomp($opt); if ($opt eq 'q') { print "Bye now"; exit; } elsif ($opt eq '1') { print "do whatever 1\n"; print "Thank You, what do you want to do now, choose option(1...6) or +quit(q)\n"; } elsif ($opt eq '2') { print "do whatever 2\n"; print "Thank You, what do you want to do now, choose option(1...6) or +quit(q)\n"; } #And on like this until all options are accounted for the to finish... +. else { print "You must either enter an option number(1...6) or (q) to quit\n" +; print "Please enter a value:\n"; } }
      All the best, Eoin..