Massyn has asked for the wisdom of the Perl Monks concerning the following question:

Hi fellow monks.pl Pascal had a keypressed function, which worked something like this.
while(1) { ... do some stuff if(keypressed) { $key = key_user_pressed; print "The user pressed $key\n"; } }
Any idea on how this can be accomplished in perl? I can't make use of <STDIN>, as this will pause the loop. The loop needs to keep n running, as this is a service type of application. Thanks!

Replies are listed 'Best First'.
Re: How to code Pascal's keypressed function in Perl
by valdez (Monsignor) on Aug 03, 2002 at 17:04 UTC

    Try with Term::ReadKey, the man page says:

    Term::ReadKey is a compiled perl module dedicated to providing simple control over terminal driver modes (cbreak, raw, cooked, etc.,) support for non-blocking reads, if the architecture allows, and some generalized handy functions for working with terminals. One of the main goals is to have the functions as portable as possible, so you can just plug in "use Term::ReadKey" on any architecture and have a good likelyhood of it working.

    Here is a snippet of code that does what you need:

    use Term::ReadKey; ReadMode 4; # Turn off controls keys while (not defined ($key = ReadKey(-1)) { # No key yet } print "Get key $key\n"; ReadMode 0; # Reset tty mode before exiting

    Hope this helps. Ciao, Valerio

      If you have a while loop that is spinning and you don't want to prompt the user for any key to be pressed such as with <STDIN> and you don't want to use Term:ReadKey module but to silently break out when she hits ENTER key use the following 3 line function called "keystroke()" where $j variable will change from 0 to 1 when the ENTER key is pressed:

      while (true) {
         ...
         if (&keystroke == 1) {
           last;
         }
         ...
      }

      sub keystroke {
         $i = '';
         vec($i, fileno(STDIN), 1) = 1;
         $j = select ($i, undef, undef, 0);
      }
Re: How to code Pascal's keypressed function in Perl
by jlongino (Parson) on Aug 03, 2002 at 17:33 UTC
    For an example of how you can use Term::ReadKey in a manner similar to Pascal's keypressed function check out my module Term::TermKeys. The module works best with the predefined terminal emulations (vt52, vt100, vt102, and vt220) but is still somewhat functional in a Windows environment. I wouldn't necessarily recommend using my module directly, but it can be useful as example code.

    --Jim

Re: How to code Pascal's keypressed function in Perl
by YuckFoo (Abbot) on Aug 03, 2002 at 21:50 UTC
    You can use the select function like this for non-blocking input. This isn't exactly what you asked for because it won't respond to a simple keypress, you have to enter a string ending with a newline (Enter key).

    YuckFoo

    #!/usr/bin/perl use strict; my $timeout = 5; while (1) { my $str = getstr($timeout); if ($str ne '') { print "Got it! $str"; } else { print "I got nothing.\n"; } } #----------------------------------------------------------- sub getstr { my ($timeout) = @_; my ($rin, $rout); vec($rin,fileno(STDIN),1) = 1; print "You have $timeout seconds to enter a string:\n"; my $input = select($rout=$rin, undef, undef, $timeout); if ($input) { return <STDIN>; } else { return ''; } }

      Plus it would not work at all under Windows since there select() (the 4 parameter form) works only on sockets :-(((

        Jenda