I'm using Term::ReadKey in ReadMode('cbreak') to read a single character and perform an action based on the input. This works fine for all other keys except the arrow keys. When the arrow keys are pressed, the action is performed 3 times and I understand this is because the arrow keys translate to '^[[A', etc...
How do I translate the arrow keys into some arbitrary single value that the ReadKey can interpret?
I tried the following code but it doesn't work:
use Term::ReadKey;
ReadMode('cbreak');
my $keystroke = '';
while ($keystroke ne 'h') {
print "Enter key: ";
#Read user keystroke
$keystroke = ReadKey(0);
chomp($keystroke);
if(ord($keystroke) == 27) {
$keystroke = ('0');
}
}
Here's my code based on the suggestion:
use Term::RawInput;
use strict;
use warnings;
my $keystroke = '';
my $special = '';
while(lc($keystroke) ne 'i' && lc($keystroke) ne 't'){
my $promptp = "Enter key: ";
($keystroke,$special) = rawInput($promptp, 1);
if ($keystroke ne '') {
print "You hit the normal '$keystroke' key\n";
} else {
print "You hit the special '$special' key\n";
}
chomp($keystroke);
$keystroke = lc($keystroke);
}
if($keystroke eq 'i') {
#Do something
}
if($keystroke eq 't') {
#Do something
}
Now, no matter what I press, I can't exit this loop
Here's the output:
Enter key:
Enter key:
Enter key: You hit the normal 't' key
#Proceeds to function
Here's my working solution...
use Term::ReadKey;
ReadMode('cbreak');
{
#Temporarily turn off warnings so no messages appear for uninitialized $keystroke
#that for some reason appears for the if statement
no warnings;
my $keystroke = '';
while ($keystroke ne 'h') {
print "\nEnter key: ";
#Read user keystroke
$keystroke = ReadKey(0);
#The first character for the arrow keys (ex. '^[[A') evaluates to 27 so I check for
#that
if(ord($keystroke) == 27) {
#Flush the rest of the characters from input buffer
#This produces an 'Use of uninitialized value...' error
#for the other two characters, hence 'no warnings' at the beginning.
#This will ignore the other 2 characters and only cause a single iteration
while( defined ReadKey(-1) ) {}
}
ReadMode 0;
}
}
Term::RawInput
doesn't cover everything, but it's a pretty good start for this task:
use Term::RawInput;
my ($keystroke,$special) = rawInput("", 1);
if ($keystroke ne '') {
print "You hit the normal '$keystroke' key\n";
} else {
print "You hit the special '$special' key\n";
}
If you're wanting to read high-level semantic ideas of "keypresses", rather than lower-level ideas of "bytes from the terminal" you'll need something that can parse and collect up those multi-byte sequences for you.
For this sort of task, I wrote Term::TermKey:
use Term::TermKey;
my $tk = Term::TermKey->new( \*STDIN );
print "Press any key\n";
$tk->waitkey( my $key );
print "You pressed: " . $tk->format_key( $key, 0 );
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With