Beefy Boxes and Bandwidth Generously Provided by pair Networks
We don't bite newbies here... much
 
PerlMonks  

Capture a non-printable char and test what it is

by almsdealer (Acolyte)
on May 21, 2022 at 14:03 UTC ( [id://11144044]=perlquestion: print w/replies, xml ) Need Help??

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

Good morning,

Can anyone tell me how I would capture a non-printable character from STDIN and test what the character is?

Specifically, I want to test if the escape key has been pressed.

Trying to build a console based text editor.

Replies are listed 'Best First'.
Re: Capture a non-printable char and test what it is
by haukex (Archbishop) on May 21, 2022 at 15:27 UTC
    Can anyone tell me how I would capture a non-printable character from STDIN and test what the character is? Specifically, I want to test if the escape key has been pressed.

    See Term::ReadKey:

    use warnings; use strict; use Term::ReadKey qw/ReadMode ReadKey/; use Data::Dumper; $Data::Dumper::Useqq=1; print "Press a key\n"; ReadMode 'cbreak'; my $key = ReadKey(0); ReadMode 'restore'; print Dumper($key); if ( $key eq "\e" ) { print "Escape pressed\n"; }
    Trying to build a console based text editor.

    Beware of reinventing the wheel, but anyway, see Curses and perhaps Curses::UI (though the latter is pretty old by now).

      How does \e represent the escape key? Where do you find that?

      If I look at the ascii table I see that the escape key can be represented as: 27 (decimal), 1B (hexadecimal), 033 (octal). But I am not sure how to test whether the value returned from ReadKey is one of those.

        Where do you find that?

        kcott is right that I simply looked at the code's output, but it's also documented in Quote and Quote like Operators.

        If I look at the ascii table I see that the escape key can be represented as: 27 (decimal), 1B (hexadecimal), 033 (octal).

        Those work too: the string "\e" is the same as "\x1B" and "\033" - you can try this out yourself with eq.

        "How does \e represent the escape key? Where do you find that?"

        If you'd bothered to run the short piece of code ++haukex provided, and pressed the escape key, you would have seen:

        Press a key $VAR1 = "\e"; Escape pressed

        Had you pressed the enter key:

        Press a key $VAR1 = "\n";

        I suggest you also read ++haj's post for additional information and alternative methods to use.

        — Ken

        If I look at the ascii table

        then you only see a part of the non-printable characters available on modern computer systems. Unicode has more control characters, emoji skin tone modifiers, right-to-left mark and a host of other stuff that is unprintable on it's own.

        As an additional bonus, the same character on screen can sometimes be encoded in Unicode in multiple ways, see Unicode equivalence.

        Unfortunately, input processing has gotten a tad more complex since the world gave up on ye olde ASCII table. On the bright side, these days more than the 20% of world population of the old ASCII days can now type their name into a computer with a reasonable expectation that it will be processed correctly.

        perl -e 'use Crypt::Digest::SHA256 qw[sha256_hex]; print substr(sha256_hex("the Answer To Life, The Universe And Everything"), 6, 2), "\n";'
Re: Capture a non-printable char and test what it is
by haj (Vicar) on May 21, 2022 at 15:35 UTC

    Capturing non-printable characters isn't that different from capturing any other character. One gotcha is that on a terminal your program usually does not receive any characters until the user hits the <ENTER> key.

    If you want to capture individual characters, you need to check which characters have a meaning to your console - and thus never reach your program. The following small example uses Term::ReadKey in "raw" mode to capture one byte and then prints its hex value plus its interpretation. This works for the escape key and also for combinations with the <CTRL> key.

    A warning, though: This example reads one byte, not one character. If your terminal uses UTF-8 encoding and you enter a key outside the ASCII range, then you'll receive only part of one character (Dealing with UTF-8 is left as an exercise to the reader). Also, cursor keys, function keys and the like are usually sequences which start with an escape character, my short example drops the rest of the sequence.

    use Term::ReadKey; use charnames ':full'; ReadMode 4; print "Enter a key: "; my $key = ReadKey(0); printf "%v02x",$key; print " = ",charnames::viacode(ord $key),"\n"; END { ReadMode 0; }
      Thank you. knowing about the ord function is useful.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://11144044]
Approved by LanX
Front-paged by Corion
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others meditating upon the Monastery: (4)
As of 2024-03-28 13:21 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found