简体   繁体   English

Perl Term::ReadKey 带箭头键

[英]Perl Term::ReadKey with Arrow Keys

I'm using Term::ReadKey in ReadMode('cbreak') to read a single character and perform an action based on the input.我在 ReadMode('cbreak') 中使用 Term::ReadKey 读取单个字符并根据输入执行操作。 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...当按下箭头键时,该操作执行 3 次,我理解这是因为箭头键转换为 '^[[A' 等...

How do I translate the arrow keys into some arbitrary single value that the ReadKey can interpret?如何将箭头键转换为 ReadKey 可以解释的任意单个值?

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: 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";
}

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 :对于此类任务,我编写了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 );

Based on mob answer, using Term::RawInput , I did this script to emulate a more complex input interaction.基于mob answer,使用Term::RawInput ,我做了这个脚本来模拟更复杂的输入交互。 The most important difference is the use of 'rawInput': mob suggested: rawInput("",1) , I find out that actually using rawInput("> ") (without the second parameter) makes things easier to work with, and having a prompt ">" is more useful.最重要的区别是使用 'rawInput': mob rawInput("",1) : rawInput("",1) ,我发现实际上使用rawInput("> ") (没有第二个参数)使事情更容易使用,并且有提示“>”更有用。

This code accepts commands and special keys.此代码接受命令和特殊键。 Also, it displays nicely to be used as an interactive shell for your system.此外,它可以很好地用作系统的交互式 shell。

DELETE key will remove all chars and BACKSPACE a single character. DELETE键将删除所有字符并BACKSPACE单个字符。 ESC will exit the shell. ESC将退出外壳。 You can add more keys to include arrows or anything else to perform special functions.您可以添加更多键以包含箭头或其他任何执行特殊功能的键。 This code will print-out any special key pressed which is not included inside the if..elsif (so you know what you need to add).此代码将打印出任何未包含在if..elsif特殊按键(因此您知道需要添加什么)。

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";您可以在“out”内执行您的命令;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM