Ответ 1
От perlfaq8 ответ на Как читать только один ключ не дожидаясь возврата ключа?:
Управление буферизацией ввода - это замечательно зависящее от системы значение. На многих системах вы можете просто использовать команду stty, как показано в getc в perlfunc, но, как вы видите, это уже привело вас к переносимости переносимости.
open(TTY, "+</dev/tty") or die "no tty: $!";
system "stty cbreak </dev/tty >/dev/tty 2>&1";
$key = getc(TTY); # perhaps this works
# OR ELSE
sysread(TTY, $key, 1); # probably this does
system "stty -cbreak </dev/tty >/dev/tty 2>&1";
Модуль Term:: ReadKey от CPAN предлагает простой в использовании интерфейс, который должен быть более эффективным, чем обход для stty для каждого ключа. Он даже включает ограниченную поддержку Windows.
use Term::ReadKey;
ReadMode('cbreak');
$key = ReadKey(0);
ReadMode('normal');
Однако, используя код, требуется, чтобы у вас был рабочий компилятор C и он может использовать его для сборки и установки модуля CPAN. Вот решение, использующее стандартный POSIX-модуль, который уже находится в вашей системе (при условии, что ваша система поддерживает POSIX).
use HotKey;
$key = readkey();
И здесь модуль HotKey, который скрывает несколько загадочные призывы манипулировать структурами терминалов POSIX.
# HotKey.pm
package HotKey;
@ISA = qw(Exporter);
@EXPORT = qw(cbreak cooked readkey);
use strict;
use POSIX qw(:termios_h);
my ($term, $oterm, $echo, $noecho, $fd_stdin);
$fd_stdin = fileno(STDIN);
$term = POSIX::Termios->new();
$term->getattr($fd_stdin);
$oterm = $term->getlflag();
$echo = ECHO | ECHOK | ICANON;
$noecho = $oterm & ~$echo;
sub cbreak {
$term->setlflag($noecho); # ok, so i don't want echo either
$term->setcc(VTIME, 1);
$term->setattr($fd_stdin, TCSANOW);
}
sub cooked {
$term->setlflag($oterm);
$term->setcc(VTIME, 0);
$term->setattr($fd_stdin, TCSANOW);
}
sub readkey {
my $key = '';
cbreak();
sysread(STDIN, $key, 1);
cooked();
return $key;
}
END { cooked() }
1;