catch arrow keys

Discussion in 'Perl Misc' started by Michael Goerz, Apr 10, 2006.

  1. Hi, how can I catch if someone presses the Arrow-Keys (Up, Down, Left,
    Right) on the keyboard? I tried

    use Term::ReadKey;
    while (not defined ($pressedkey = ReadKey(-1))) {
    # No key yet
    }
    printf(" Decimal: %d\tHex: %x\n", ord($pressedkey),
    ord($pressedkey));

    but that only return the escape-symbol (27) for each of the arrow-keys.
    I need to react on which key was pressed.

    Thanks,
    Michael Goerz
     
    Michael Goerz, Apr 10, 2006
    #1
    1. Advertising

  2. Michael Goerz

    Guest

    Michael Goerz <4ward.com> wrote:
    > Hi, how can I catch if someone presses the Arrow-Keys (Up, Down, Left,
    > Right) on the keyboard? I tried
    >
    > use Term::ReadKey;
    > while (not defined ($pressedkey = ReadKey(-1))) {
    > # No key yet
    > }


    Isn't that pretty silly? You go out of your way to do a nonblocking
    read, only to put it into a busy-wait loop which emulates blocking in
    a very inefficient way.

    $pressedkey = ReadKey();


    > printf(" Decimal: %d\tHex: %x\n", ord($pressedkey),
    > ord($pressedkey));
    >
    > but that only return the escape-symbol (27) for each of the arrow-keys.
    > I need to react on which key was pressed.


    Control keys return multiple bytes per key-press. Once you see the 27, you
    need to call ReadKey some more to get the rest of them.

    Xho

    --
    -------------------- http://NewsReader.Com/ --------------------
    Usenet Newsgroup Service $9.95/Month 30GB
     
    , Apr 10, 2006
    #2
    1. Advertising

  3. Michael Goerz

    Guest

    Michael Goerz wrote:
    > Hi, how can I catch if someone presses the Arrow-Keys (Up, Down, Left,
    > Right) on the keyboard? I tried
    >
    > use Term::ReadKey;
    > while (not defined ($pressedkey = ReadKey(-1))) {
    > # No key yet
    > }
    > printf(" Decimal: %d\tHex: %x\n", ord($pressedkey),
    > ord($pressedkey));
    >
    > but that only return the escape-symbol (27) for each of the arrow-keys.
    > I need to react on which key was pressed.



    Dear Michael,

    You might want to try reading the next two keys to see which
    direction was pressed. If you get "[A", then that means UP was
    pressed. "[B" means DOWN was pressed, "[C" means RIGHT was pressed,
    and "[D" means LEFT was pressed.

    Therefore, try this modification to your script:


    use Term::ReadKey;
    ReadMode 4; # Turn off controls keys
    while (not defined ($key = ReadKey(-1))) {
    # No key yet
    }
    if (ord($key) != 27) {
    print "Got key $key\n";
    } elsif ($key = ReadKey(-1) and $key ne '[') {
    print "Not sure what I have...\n"
    } else {
    $key = ReadKey(-1);
    if ($key eq 'A') { print "UP pressed.\n" }
    elsif ($key eq 'B') { print "DOWN pressed.\n" }
    elsif ($key eq 'C') { print "RIGHT pressed.\n" }
    elsif ($key eq 'D') { print "LEFT pressed.\n" }
    else { print "Not sure what I have...\n" }
    }
    ReadMode 0; # Reset tty mode before exiting


    Just a warning: I don't know how portable this solution is, so
    don't expect it to work on all platforms (like Win32).

    I hope this helps, Michael.

    -- Jean-Luc
     
    , Apr 10, 2006
    #3
  4. Michael Goerz

    Guest

    > Michael Goerz <4ward.com> wrote:
    > >
    > > use Term::ReadKey;
    > > while (not defined ($pressedkey = ReadKey(-1))) {
    > > # No key yet
    > > }



    replied:
    >
    > Isn't that pretty silly? You go out of your way to do a nonblocking
    > read, only to put it into a busy-wait loop which emulates blocking in
    > a very inefficient way.



    Actually, he got that code straight from "perldoc Term::ReadKey".
    (But I don't disagree with you that that code could be written better.)

    -- Jean-Luc
     
    , Apr 10, 2006
    #4
  5. wrote:
    >> Hi, how can I catch if someone presses the Arrow-Keys (Up, Down, Left,
    >> use Term::ReadKey;
    >> while (not defined ($pressedkey = ReadKey(-1))) {
    >> # No key yet
    >> }

    >
    > Isn't that pretty silly? You go out of your way to do a nonblocking
    > read, only to put it into a busy-wait loop which emulates blocking in
    > a very inefficient way.
    >
    > $pressedkey = ReadKey();

    Then I have to press Enter after each "keystroke". The code I used
    before was actually taken from
    http://search.cpan.org/~jstowe/TermReadKey-2.30/ReadKey.pm

    > Control keys return multiple bytes per key-press. Once you see the 27, you
    > need to call ReadKey some more to get the rest of them.

    Yes, that appears to work. Thanks a lot!

    Michael
     
    Michael Goerz, Apr 10, 2006
    #5
  6. wrote:
    > use Term::ReadKey;
    > ReadMode 4; # Turn off controls keys
    > while (not defined ($key = ReadKey(-1))) {
    > # No key yet
    > }
    > if (ord($key) != 27) {
    > print "Got key $key\n";
    > } elsif ($key = ReadKey(-1) and $key ne '[') {
    > print "Not sure what I have...\n"
    > } else {
    > $key = ReadKey(-1);
    > if ($key eq 'A') { print "UP pressed.\n" }
    > elsif ($key eq 'B') { print "DOWN pressed.\n" }
    > elsif ($key eq 'C') { print "RIGHT pressed.\n" }
    > elsif ($key eq 'D') { print "LEFT pressed.\n" }
    > else { print "Not sure what I have...\n" }
    > }
    > ReadMode 0; # Reset tty mode before exiting
    >
    >
    > Just a warning: I don't know how portable this solution is, so
    > don't expect it to work on all platforms (like Win32).
    >
    > I hope this helps, Michael.
    >
    > -- Jean-Luc

    That's perfect! Thank you!

    Michael
     
    Michael Goerz, Apr 10, 2006
    #6
  7. wrote:
    >> Michael Goerz <4ward.com> wrote:
    >>> use Term::ReadKey;
    >>> while (not defined ($pressedkey = ReadKey(-1))) {
    >>> # No key yet
    >>> }

    >
    >
    > replied:
    >> Isn't that pretty silly? You go out of your way to do a nonblocking
    >> read, only to put it into a busy-wait loop which emulates blocking in
    >> a very inefficient way.

    >
    >
    > Actually, he got that code straight from "perldoc Term::ReadKey".
    > (But I don't disagree with you that that code could be written better.)
    >
    > -- Jean-Luc
    >


    What would be more efficient code, if I don't want to have to press
    Enter after each keystroke? In fact, the tight loop bothers me somewhat.

    Michael
     
    Michael Goerz, Apr 10, 2006
    #7
  8. Michael Goerz

    Guest

    Michael Goerz wrote:
    > >>> use Term::ReadKey;
    > >>> while (not defined ($pressedkey = ReadKey(-1))) {
    > >>> # No key yet
    > >>> }

    >
    > What would be more efficient code, if I don't want to have to press
    > Enter after each keystroke? In fact, the tight loop bothers me somewhat.



    Basically, the purpose of the while-loop is to wait until a key has
    been read in. If no key was read in, the while-block gets executed.
    In the above example, the block does absolutely nothing. (Sometimes
    you may want something to happen if no was pressed, which is why I
    think the example was written like this.)

    However, if all you want to do is wait until the first key is
    pressed, you basically want to perform a "blocking" read (as opposed to
    a "non-blocking" read). The "ReadKey(-1)" performs a "non-blocking"
    read; to do a "blocking" read, you want to pass in a zero for
    ReadKey()'s argument.

    Therefore, I would recommend changing the above while-loop to the
    following one line of code:

    $pressedkey = ReadKey(0); # Note: no loop!

    This will prevent the program from advancing any further until a key is
    pressed.

    By the way, did you know that you can get comprehensive
    documentation for a module by using the perldocs? That is, you can
    read the documentation for Term::ReadKey by typing the following at any
    Unix prompt:

    perldoc Term::ReadKey

    The reason I ask this is because, in a previous post, you mentioned
    that you found the Term::ReadKey documentation online. (I once knew a
    programmer who'd been programming Perl for several years who wasn't
    aware that he could look up the documentation for any module just by
    typing "perldoc ModuleName" at a Unix prompt. Instead of using
    documentation he already had, he had to scour the web to find it!)

    (And sometimes the programmers who already know about the perldocs
    don't realize that there are a lot of other programmers who don't know
    about them, so the ones who don't know about the usefulness of the
    perldocs continue to be left in the dark about them.)

    Anyway, I hope this helps you, Michael.

    -- Jean-Luc
     
    , Apr 10, 2006
    #8
  9. wrote:
    > Therefore, I would recommend changing the above while-loop to the
    > following one line of code:
    >
    > $pressedkey = ReadKey(0); # Note: no loop!
    >
    > This will prevent the program from advancing any further until a key is
    > pressed.

    Wow, yes... that's exactly what I was looking for. Should have read the
    docs more carefully.

    > By the way, did you know that you can get comprehensive
    > documentation for a module by using the perldocs? That is, you can
    > read the documentation for Term::ReadKey by typing the following at any
    > Unix prompt:
    >
    > perldoc Term::ReadKey

    Yes, I know, but usually I prefer the online documentation, because of
    its very readable formatting (syntax highlighting) and because it's
    easier to browse around

    > Anyway, I hope this helps you, Michael.

    That did help a lot! Thanks again.

    Michael
     
    Michael Goerz, Apr 11, 2006
    #9
  10. Michael Goerz

    Guest

    Michael Goerz <4ward.com> wrote:
    > wrote:
    > >> Hi, how can I catch if someone presses the Arrow-Keys (Up, Down, Left,
    > >> use Term::ReadKey;
    > >> while (not defined ($pressedkey = ReadKey(-1))) {
    > >> # No key yet
    > >> }

    > >
    > > Isn't that pretty silly? You go out of your way to do a nonblocking
    > > read, only to put it into a busy-wait loop which emulates blocking in
    > > a very inefficient way.
    > >
    > > $pressedkey = ReadKey();


    > Then I have to press Enter after each "keystroke".


    In your original code, exactly as you posted it, you need to press Enter,
    too. I suspect this is because the code you posted is not the real code
    you are running, but rather your real code has "ReadMode 4;" in it.

    If you don't include the "ReadMode 4;", then you have to press Enter
    either way. If you do include the "ReadMode 4;", then you don't need
    to press Enter, either way. It isn't about the ReadKey, it is about the
    ReadMode


    > The code I used before was actually taken from
    > http://search.cpan.org/~jstowe/TermReadKey-2.30/ReadKey.pm


    Yep, but that example is expecting you to replace the "# No key yet" line
    with something meaningful. If you leave it as is, then you are better
    off using the blocking ReadKey.

    Cheers,

    Xho

    --
    -------------------- http://NewsReader.Com/ --------------------
    Usenet Newsgroup Service $9.95/Month 30GB
     
    , Apr 11, 2006
    #10
  11. On 10 Apr 2006 15:21:27 -0700, ""
    <> wrote:

    >programmer who'd been programming Perl for several years who wasn't
    >aware that he could look up the documentation for any module just by
    >typing "perldoc ModuleName" at a Unix prompt. Instead of using


    s/Unix//; # Works on all DOS/Win* cli's I know of too.


    Michele
    --
    {$_=pack'B8'x25,unpack'A8'x32,$a^=sub{pop^pop}->(map substr
    (($a||=join'',map--$|x$_,(unpack'w',unpack'u','G^<R<Y]*YB='
    ..'KYU;*EVH[.FHF2W+#"\Z*5TI/ER<Z`S(G.DZZ9OX0Z')=~/./g)x2,$_,
    256),7,249);s/[^\w,]/ /g;$ \=/^J/?$/:"\r";print,redo}#JAPH,
     
    Michele Dondi, Apr 13, 2006
    #11
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Rob R. Ainscough
    Replies:
    0
    Views:
    719
    Rob R. Ainscough
    Jul 20, 2005
  2. (Pete Cresswell)
    Replies:
    2
    Views:
    598
    (Pete Cresswell)
    Oct 12, 2004
  3. Daniel Alexandre

    Arrow-keys bug.

    Daniel Alexandre, Feb 23, 2005, in forum: Python
    Replies:
    0
    Views:
    410
    Daniel Alexandre
    Feb 23, 2005
  4. Vidar Gundersen
    Replies:
    1
    Views:
    799
  5. tac-tics

    arrow keys don't work

    tac-tics, Jan 22, 2007, in forum: Python
    Replies:
    6
    Views:
    367
    Terry Reedy
    Jan 23, 2007
Loading...

Share This Page