Ace128:
I had a little fun playing with your program. I don't know if I solved the problem you're having or not. (Mostly because I was having so much fun, I forgot what the problem was while playing around.) The original version had a few quirks, but this one works better on my machine. Please give it a try and let me know what you think...
#!/usr/bin/perl -w
use strict;
use warnings;
use Term::ReadKey;
startListening();
sub startListening {
ReadMode(4); # RAW mode (we'll do all the work!)
my $echofl=1; # 1=Normal, 0=Password mode
my $echoPwChar='#'; # Password mode char
my $word = ''; # Input accumulator
my $prompt = "> ";
print $prompt;
while (1) {
my $char = ReadKey(0);
my $ord = ord($char);
if ($ord == 3) {
# "\003" (^C) : STOP!
print "\n^C -- terminated!\n";
last;
}
elsif ($ord == 10 or $ord == 13) {
# "\n" (^J), "\r" (^M) : Finish line
enterPressed($word);
$word = "";
print $prompt;
}
elsif ($ord == 5) {
# "\005" (^E) : Toggle echo mode
$echofl = 1-$echofl;
}
elsif ($ord==127 or $ord==8) {
# "\177" (DEL), "\010" (^H) : Kill last char
print chr(8),' ',chr(8) if length($word)>0;
chop($word);
}
elsif ($ord == 27) {
# "\033" (Esc) : Clear line
print chr(8) x length($word)
. ' ' x length($word)
. "\r"
. $prompt;
$word="";
}
else { #if ($ord != 0) {
# Otherwise add to word & update display
$word .= $char;
$char = $echoPwChar if !$echofl;
print $char;
}
}
ReadMode(0);
}
sub enterPressed {
my $word = shift;
print "\n '" . $word . "'\n";
}
--roboticus
| [reply] [d/l] |
Hey, cool! Fun when code inspire ;)
Anyway, no, didn't solve my problem, but hey, that the ESC empties the line is quite a neat idea!
| [reply] |
Well, it sort of works for me on linux. That is: i can enter chars, see the "BACKSPACE!" output when i press backspace and see "WORD:" when i press enter. Ofcourse, since you're interpreting every keystroke yourself it fails to recognize EOF (^D) and a lot of other standard console shortcuts.
If you just want a lowlevel line-reading routine, you're probably better off with something like:
print "> ";
while (<STDIN>) {
chomp;
print "WORD: $_\n> ";
}
Have you tried re-insterting the $|=1 line?
updated: fixed some grammar and spelling mistakes
| [reply] [d/l] [select] |
Seems to be working fine in Linux, but not in Windows (as usuall). So typical! What to do now? This way I could do whatever on those special keys. So, yep, bug in windows. Enter key is eaten up in readmode 4.
| [reply] |
| [reply] |
Runing the example provided by the module:
use IO::Prompt;
use strict;
use warnings;
while( prompt "next: " ) {
print "You said '$_'\n";
}
gives:
Cannot write to terminal: No such file or directory at ioPromptTests.pl line 2
In windows XP... | [reply] [d/l] |
| [reply] |
Ok, after some work I solved most problems for the Win XP. However, now there is problems with the special keys like HOME/END/PGUP/LEFT ARROW ... and those... All I get back from ReadKey is 0. I've found some tricks that was supposed to solve it on the net (urls included in the code), but they didn't work! :(
#!/usr/bin/env perl
use Term::ReadKey;
use Time::HiRes qw( usleep );
use Data::Dumper;
#use IO::Handle;
use strict;
use warnings;
# http://www.perl.com/doc/FAQs/FAQ/oldfaq-html/Q4.31.html
# http://www.rocketaware.com/perl/perlfaq5/How_can_I_read_a_single_cha
+racte.htm
# Works only in linux:
# http://groups.google.com/group/linux.debian.user/browse_thread/threa
+d/eaaedcaae8bc3e9a/8109745493b41a58?lnk=st&q=pgup+perl+readkey&rnum=5
+&hl=sv#8109745493b41a58
# PC 2-byte keycodes = ^@ + the following:
# HEX KEYS
# --- ----
# 0F SHF TAB
# 10-19 ALT QWERTYUIOP
# 1E-26 ALT ASDFGHJKL
# 2C-32 ALT ZXCVBNM
# 3B-44 F1-F10
# 47-49 HOME,UP,PgUp
# 4B LEFT
# 4D RIGHT
# 4F-53 END,DOWN,PgDn,Ins,Del
# 54-5D SHF F1-F10
# 5E-67 CTR F1-F10
# 68-71 ALT F1-F10
# 73-77 CTR LEFT,RIGHT,END,PgDn,HOME
# 78-83 ALT 1234567890-=
# 84 CTR PgUp
$| = 1;
#$|++;
#select(STDOUT);
#$| = 1;
#my $io = new IO::Handle;
#if ($io->fdopen(fileno(STDOUT),"w")) {
# $io->print("Some text\n");
#}
#autoflush STDOUT 1;
#my $old_ioctl;
#BEGIN {
# $old_ioctl = ioctl(STDIN,0,0) || -1; # Gets device info
# $old_ioctl &= 0xff;
# ioctl(STDIN,1,$old_ioctl | 32); # Writes it back, setting bit
+5
#}
my %key_cmd_map = (
# escseq command
'[A' => sub { print "Up\n" }, # those escape sequences shoul
+d
'[B' => sub { print "Down\n" }, # work in the linux console
'[C' => sub { print "Right\n" },
'[D' => sub { print "Left\n" },
'[G' => sub { print "Center\n" },
'[5~' => sub { print "PgUp\n" },
'[6~' => sub { print "PgDn\n" },
'[1~' => sub { print "Home\n" },
'[4~' => sub { print "End\n" },
'[[A' => sub { print "F1\n" },
'[2~' => sub { print "Insert Key" }, # Insert key
'[3~' => sub { print "Delete Key" }, # Delete key
);
startListening();
sub startListening {
# Disable CTRL keys
ReadMode(4);
my $word = '';
my $prompt = "> ";
my $pos = 0;
print $prompt;
while(1){
my $char;
while (!defined ($char = ReadKey(-1))){
usleep 1_100;
}
#sysread(STDIN,$char,1); # Read a single charact
+er
my $ord = ord($char);
if ($ord == 0) {
#ioctl(STDIN,1,$old_ioctl); # Sets it back to cook
+ed mode.
#print Dumper($old_ioctl);
#sysread(STDIN,$char,1);
#while (!defined ($char = ReadKey(-1))){
# sleep 1;
# print "#\n";
#}
#print "NEW: " . hex(ord($char)) . "\n";
}
last if ($ord == 3);
last if ($ord == 4);
print $char;
#print $ord;
if ($ord == 10 or $ord == 13) { # "Enter"
print chr(8) x (length($word) + length($prompt))
. ' ' x (length($word) + length($prompt))
. "\r"
;
enterPressed($word);
$word = "";
print $prompt;
$pos = 0;
next;
}
elsif ($ord == 127) { # ie "Backspace"
#chop($word);
#print chr(8),' ',chr(8);
#print "BACKSPACE!\n";
next;
}
elsif ($ord == 27) { # "ESC"
print chr(8) x (length($word) + 1)
. ' ' x (length($word) + 1)
. "\r"
. $prompt;
$word="";
$pos = 0;
}
elsif ($ord == 8) {
if ($pos == 0) {
print " ";
next;
}
--$pos;
#print "BACKSPACE!\n";
#print chr(8) . ' ' . chr(8);
chop($word);
print " " . chr(8);
next;
}
if($ord >= 32 && $ord < 155) {
++$pos;
$word .= chr($ord);
#print '*';
}
}
ReadMode(0);
}
sub clearstream {
while(1) {
my $char;
if (defined ($char = ReadKey(-1)) ){}else{return}
}
return;
}
sub enterPressed {
my $word = shift;
print "WORD: " . $word . "\n";
}
ANY suggestion is warmly welcomed! Since all that is left now is to somehow make it possible for me to know what "special" key is pressed.
Thanks,
Ace
| [reply] [d/l] |