Perl Term :: ReadKey with Arrows

I use Term :: ReadKey in ReadMode ('cbreak') to read a single character and perform an action based on input. This works great for all other keys except the arrow keys. When the arrow keys are pressed, the action is performed 3 times, and I understand that this is because the arrow keys translate to "^ [[A], etc.

How to translate arrow keys into some arbitrary single value that ReadKey can interpret?

I tried the following code, but it does not 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 my code is based on the assumption:

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 click, I cannot exit this loop

Here's the conclusion:

Enter key: 
Enter key:
Enter key: You hit the normal 't' key

#Proceeds to function
+4
source share
4 answers

...

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) ) {}
        }
     }
}
+2

Term::RawInput , :

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";
}
+2

"keypresses", " ", -, .

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 );
+1

mob, Term:: RawInput, script . "rawInput": mob : rawInput("",1), , rawInput("> ") ( ) " > ", .

This code accepts commands and special keys. In addition, it is well displayed for use as an interactive shell for your system.

Key

DELETEwill delete all characters and BACKSPACEone character. ESCwill come out of the shell. You can add more keys to turn on arrows or something else to perform special functions. This code will print any special key that is not included inside if..elsif(so you know what you need to add).

use warnings;
use strict;
use Term::RawInput;

sub out {
    my $out = shift;
    print "[ $out ]\n";
}

do {
    my ($keystroke,$special) = rawInput("> ");
    if($special eq 'ESC') {
        print "\n";
        exit;
    } elsif($special eq 'ENTER') {
        out($keystroke);
    } elsif($special ne 'DELETE') {
        if ($keystroke ne '') {
            out($keystroke);
        } else {
            print "'$special' key is not associated\n";
        }
    }
} while(1);

You can implement your commands inside "out";

+1
source

Source: https://habr.com/ru/post/1606662/


All Articles