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. | [reply] [d/l] |
kewl, thanks alot for the help fellow monk.
| [reply] |
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.
| [reply] [d/l] |
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..
| [reply] [d/l] |