Perl Term::ReadKey со стрелками
Я использую Term::ReadKey в ReadMode('cbreak'), чтобы прочитать один символ и выполнить действие, основанное на вводе. Это прекрасно работает для всех других клавиш, кроме клавиш со стрелками. Когда нажимаются клавиши со стрелками, действие выполняется 3 раза, и я понимаю, что это потому, что клавиши со стрелками переводятся в "^[[A" и т. Д....
Как мне перевести клавиши со стрелками в какое-то произвольное единственное значение, которое может интерпретировать ReadKey?
Я попробовал следующий код, но он не работает:
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');
}
}
Вот мой код, основанный на предложении:
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
}
Теперь, что бы я ни нажимал, я не могу выйти из этого цикла
Вот вывод:
Enter key:
Enter key:
Enter key: You hit the normal 't' key
#Proceeds to function
4 ответа
Вот мое рабочее решение...
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) ) {}
}
}
}
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";
}
Если вы хотите прочитать высокоуровневые семантические идеи "нажатий клавиш", а не низкоуровневые идеи "байтов из терминала", вам понадобится что-то, что может проанализировать и собрать эти многобайтовые последовательности для вас.
Для такого рода задач я написал 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 );
На основе mob
ответ, используя Term:: RawInput, я сделал этот скрипт для эмуляции более сложного взаимодействия ввода. Самым важным отличием является использование rawInput: mob
предложил: rawInput("",1)
Я узнаю, что на самом деле с помощью rawInput("> ")
(без второго параметра) упрощает работу, а подсказка ">" более полезна.
Этот код принимает команды и специальные ключи. Кроме того, он прекрасно отображается для использования в качестве интерактивной оболочки для вашей системы.
DELETE
ключ удалит все символы и BACKSPACE
один персонаж. ESC
выйдет из оболочки. Вы можете добавить больше клавиш для включения стрелок или чего-либо еще для выполнения специальных функций. Этот код распечатывает любую специальную клавишу, которая не включена в 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);
Вы можете реализовать свои команды внутри "снаружи";