How can I get user input without waiting for enter in Perl

De openkb
Aller à : Navigation, rechercher

Sommaire

Questions

I am trying to make an interactive shell script in Perl.

The only user input I can find is the following:

 $name = <STDIN>;
 print STDOUT "Hello $name
";

But in this the user must always press enter for the changes to take effect. How can I get the program to proceed immediately after a button has been pressed?

Answers

http://faq.perl.org/perlfaq8.html#How_do_I_read_just_o http://faq.perl.org/perlfaq8.html#How_do_I_read_just_o </a>:


Controlling input buffering is a remarkably system-dependent matter. On many systems, you can just use the stty command as shown in getc in perlfunc, but as you see, that s already getting you into portability snags.

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

The Term::ReadKey module from CPAN offers an easy-to-use interface that should be more efficient than shelling out to stty for each key. It even includes limited support for Windows.

use Term::ReadKey;
ReadMode( cbreak );
$key = ReadKey(0);
ReadMode( normal );

However, using the code requires that you have a working C compiler and can use it to build and install a CPAN module. Here s a solution using the standard POSIX module, which is already on your system (assuming your system supports POSIX).

use HotKey;
$key = readkey();

And here s the HotKey module, which hides the somewhat mystifying calls to manipulate the POSIX termios structures.

# 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;

Source

License : cc by-sa 3.0

http://stackoverflow.com/questions/2685148/how-can-i-get-user-input-without-waiting-for-enter-in-perl

Related

Outils personnels
Espaces de noms

Variantes
Actions
Navigation
Outils