http://www.perlmonks.org?node_id=48497

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

I am trying to have my program wait for user input.
<> is not good enough for me, since I don't want the user to press Enter.

select seems a very good choice: with a well chosen timeout, I can even spare a few cycles for all the other processes... ;-)

Alas, I don't know how to use it properly. Can anybody help me? (and explain how all of this works?)

PS: No, I don't want to use a module for this: only stuff in perlfunc...

Replies are listed 'Best First'.
Re: select?
by chipmunk (Parson) on Dec 27, 2000 at 23:05 UTC

      The O word...

      I thought select would be a good choice, since I can set a timeout. But, when I use it with STDIN, I always get a "Bad filehandle" error (in $!). That's why I asked for help specifically about select... (I knew I shouldn't have mentionned the user behind the keyboard)

        That is the first truly great reason I have heard for insisting that a solution not use modules. One more absolute that now has to be moderated with an except... =)

        In the future, you should mention that up front when you insist on core features only, that way if someone is really ornery, they might just find a vile way to load the module they want as a bonus...

        --
        $you = new YOU;
        honk() if $you->love(perl)

Re: select?
by Fastolfe (Vicar) on Dec 27, 2000 at 23:06 UTC
    For those that don't have any silly "no modules" restrictions, this problem could be solved by using the Term::ReadKey module. For those that insist on re-inventing the wheel, reading the code in this module will probably help you along your way. Remember that even though you may (for whatever reason) not be able to use a module with your project, that doesn't prevent you from downloading it and reading through the code to see how they do it.

    The short answer: check out the documentation for getc, which is Perl's implementation of the standard C function by the same name. Update: I highly recommend going with the FAQ links mentioned above, as there are some caveats with using getc on terminals.

    If you need to be monitoring several input streams at once for data, and thus need to use select, that is a very weighty topic. See the documentation for IO::Select.. There are probably other tutorials floating around, but I doubt you're going to get a thorough lesson on select here. Good luck.

(tye)Re: select?
by tye (Sage) on Dec 27, 2000 at 23:20 UTC

    Being asked by BooK, I assumed this was for obfuscation.

    select("\01","","",10);
    should wait for any character on STDIN [but this won't work under Win32, for example, because select() there only works on sockets]. However, this only works for a Unix TTY if the TTY is not in "line mode". So I don't think this will help you much, BooK.

            - tye (but my friends call me "Tye")

      Thanks, at least I know why it doesn't work on my Win32 box at work... :-)

      As for line mode, wouldn't $| help? (mmm, doesn't look like it) Well, if this doesn't work, it seems there are still other options...

      PS: Tye, there are two me, really: I do actually write readable, useful code. It's just not as fun...

        No, $| controls auto-flushing of output which is often confused with buffering (which can be "none", "line", or "block" in Unix) but doesn't have much to do with input.

        To see characters from a Unix TTY before a newline, you need to get into "raw" or "semi cooked" mode instead of the usually "cooked" mode. "raw" means no processing is done and "semi cooked" means much (but not all of the usual) processing is done but you get characters as they are typed (though I still think there is a timer involved here so you usually don't even get them immediately, just almost immediately -- it has been too long since I had the misfortune to care about this stuff).

        I have yet to find a good way to read one character at a time in Win32, much less a module that portably handles this.

                - tye (but my friends call me "Tye")