I'm writing a generic user entry routine to capture strings from the user as well as an ending indicator. For example if they type a string and end with [Shift TAB] I will do one thing and if they end with [TAB] or [Enter] I will do something different. I am using the example "How do I read just one key without waiting for a return key?" from perlfaq8. So far so good. Well I quickly discovered that capturing certain keystrokes from a terminal isn't quite as easy as it is in a GUI environment. However I was able to figure out that [Shift TAB] gave me \e[Z. I also wanted to be able to trap for just [ESC] but I settled for [ESC q] instead. Now here's where the weirdness starts. I need to remove the ending character(s) from the string. With [Shift TAB] I was able to use:
$DataRead{'StringRead'} = substr($DataRead{'StringRead'}, -3);
but that didn't work with [ESC q]. Instead I ended up having to use:
$DataRead{'StringRead'} = substr($DataRead{'StringRead'}, 0, length($D +ataRead{'StringRead'}) - 2);
This works fine, but leaves me wondering why the first approach didn't work. BTW Term::HotKey is just the module given in perlfaq8. I'm using perl v5.6.1 in on a Sun OS box using putty as an xterm. My test script follows:
#!/usr/bin/perl use strict; use warnings; use constant true => 1; use constant TAB => 9; use constant LF => 10; use constant CR => 13; use constant ESC => 27; use constant BACKTAB => -1; $| = true; use Term::HotKey; # # ReadFromKeyboard # # Read a key at Time from the Keyboard # # Arguments: # # Returns: \%DataRead # 'StringRead' => Characters Read # 'ExitValue' => Character That Caused End of Read # # Thanks to Liverpole for the Original Version # sub ReadFromKeyboard { my %DataRead; $DataRead{'StringRead'} = ''; my $CharacterRead = ''; while(true) { $CharacterRead = readkey(); if($CharacterRead) { $DataRead{'StringRead'} .= $CharacterRead; print("\[$CharacterRead\]\[" . ord($CharacterRead) . "\]len\[ +" . length($CharacterRead) . "\] \[$DataRead{'StringRead'}\]\n"); if($DataRead{'StringRead'} =~ /.*\t|\n|\r|\e\[Z|\eq$/) { if($DataRead{'StringRead'} =~ /.*\e\[Z$/) { $DataRead{'ExitValue'} = -1; $DataRead{'StringRead'} = substr($DataRead{'StringRead' +}, -3); } elsif($DataRead{'StringRead'} =~ /.*\eq$/) { $DataRead{'ExitValue'} = 27; $DataRead{'StringRead'} = substr($DataRead{'StringRead' +}, 0, length($DataRead{'StringRead'}) - 2); } else { $DataRead{'ExitValue'} = ord(chop($DataRead{'StringRead +'})); } last(); } } } return(\%DataRead); } # Main program my $DataRead; $DataRead->{'StringRead'} = ''; while(uc($DataRead->{'StringRead'}) ne 'QUIT') { $DataRead = ReadFromKeyboard(); my $WhatIsIt; if($DataRead->{'ExitValue'} == TAB) { $WhatIsIt = 'TAB'; } elsif($DataRead->{'ExitValue'} == LF) { $WhatIsIt = 'LF'; } elsif($DataRead->{'ExitValue'} == CR) { $WhatIsIt = 'CR'; } elsif($DataRead->{'ExitValue'} == ESC) { $WhatIsIt = 'ESC'; } elsif($DataRead->{'ExitValue'} == BACKTAB) { $WhatIsIt = 'BACKTAB'; } else { $WhatIsIt = 'IDK'; } print("You Entered: \[$DataRead->{'StringRead'}\]\[" . length($Data +Read->{'StringRead'}) . "\]\nYou Ended with a \[$WhatIsIt\]\[$DataRea +d->{'ExitValue'}\]\n"); } __END__

In reply to Strange substr behavior by NateTut

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.