Perl Term::ReadKey don't wait for newline
In a perl script, I'm trying to accept input without blocking and without echoing the characters entered (The script is producing output and I want to have 'hotkeys' to alter its behaviour).
I got a开发者_StackOverflows far as using
use Term::ReadKey;
ReadMode( "cbreak", STDIN );
if($input = ReadKey($pause_time, STDIN)){
#process input
}
But once the user types anything then the script stops until a newline is entered. I'd like the input to be processed per-character, without waiting for a newline.
Here is a small program that does what I think you desire:
#!/usr/bin/perl
use strict;
use warnings;
use Term::ReadKey;
ReadMode 4;
END { ReadMode 0 }
print <<EOS;
q to quit
b to print in binary
o to print in octal
d to print in decimal
x to print in hexadecimal
EOS
my $control = "d";
my $i = 0;
while (1) {
#use "if" if you want to have a buffer of commands
#that will be processed one per second
while (defined (my $key = ReadKey(-1))) {
exit 0 if $key eq 'q';
$control = $key if $key =~ /^[bodx]$/;
}
printf "%$control\n", $i++;
sleep 1;
}
I was going to leave this as a comment to your own 'answer' but decided I needed more room.
cbreak is equivalent to raw mode except in that cbreak doesn't intercept control sequences like ctrl-c, ctrl-z etc. They both collect characters one at a time. The difference in behavior between the two modes isn't the source of your problem. If Chas's solution does something like what you intended, then the problem more likely has to do with whatever you redacted in your #process input
line. I've commented already that your original script works fine if I fill it with something rudimentary so I can see that it's working. For example, a minor touch-up:
use strict;
use warnings;
use Term::ReadKey;
my ($char, $input, $pause_time);
ReadMode("cbreak");
# Collect all characters typed into $input
# and quit when '#' is typed.
$input = '';
while ($char = ReadKey($pause_time)) {
last if $char eq '#';
$input .= $char;
}
print "$input\n";
There's no need for me to hit 'enter' at the end of this, and doing so won't do anything (apart from throwing a carriage return into $input
and weirding up the string).
精彩评论