Controllare l'utilizzo del buffer sull'input è una questione
notevolmente dipendente dal sistema. Su molti sistemi, potete semplicemente
usare il comando stty come mostrato in perlfunc/getc, ma come potete
vedere, questo vi sta già portando in problematiche di
portabilità.
open(TTY, "+</dev/tty") or die "nessun tty: $!";
system "stty cbreak </dev/tty >/dev/tty 2>&1";
$chiave = getc(TTY); # forse questo funziona
# O ANCHE
sysread(TTY, $chiave, 1); # probabilmente questo va
system "stty -cbreak </dev/tty >/dev/tty 2>&1";
Il modulo Term::ReadKey da CPAN offre un'interfaccia semplice da usare che
dovrebbe essere più efficiente che non richiamare stty in una
shell esterna per ogni chiave. Include anche un limitato supporto a Windows.
use Term::ReadKey;
ReadMode('cbreak');
$chiave = ReadKey(0);
ReadMode('normal');
Ad ogni modo, usare il codice richiede l'avere un compilatore C
funzionante e la possibilità di usarlo per configurare e installare un modulo
CPAN. Ecco una soluzione che utilizza un modulo POSIX standard che
è già sui vostri sistemi (assumendo che il vostro
sistema supporti POSIX).
use HotKey;
$chiave = readkey();
Ed ecco il modulo HotKey che nasconde le, talvolta mistificatrici,
chiamate per manipolare le strutture termios di 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, non voglio nemmeno echo
$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 $chiave = '';
cbreak();
sysread(STDIN, $chiave, 1);
cooked();
return $chiave;
}
END { cooked() }
1;
|