7 Stimmen

Perl Term::ReadKey wartet nicht auf Newline

In einem Perl-Skript versuche ich, Eingaben zu akzeptieren, ohne sie zu blockieren und ohne die eingegebenen Zeichen als Echo auszugeben (das Skript erzeugt Ausgaben, und ich möchte "Hotkeys" haben, um sein Verhalten zu ändern).

Ich bin so weit gekommen, dass ich

use Term::ReadKey;
ReadMode( "cbreak", STDIN );
if($input = ReadKey($pause_time, STDIN)){
    #process input
}

Aber sobald der Benutzer etwas eingibt, hält das Skript an, bis ein Zeilenumbruch eingegeben wird. Ich möchte, dass die Eingabe pro Zeichen verarbeitet wird, ohne auf einen Zeilenumbruch zu warten.

7voto

Chas. Owens Punkte 62716

Hier ist ein kleines Programm, das genau das tut, was ich glaube, dass Sie wünschen:

#!/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;
}

2voto

cikkle Punkte 448

Ich wollte dies eigentlich als Kommentar zu Ihrer eigenen "Antwort" hinterlassen, aber ich habe beschlossen, dass ich mehr Platz brauche.

cbreak entspricht dem Rohmodus, außer dass cbreak keine Steuersequenzen wie ctrl-c, ctrl-z usw. abfängt. Sie sammeln beide ein Zeichen nach dem anderen. Der Unterschied im Verhalten zwischen den beiden Modi ist nicht die Ursache für Ihr Problem. Wenn die Lösung von Chas in etwa das tut, was Sie beabsichtigt haben, dann hat das Problem wahrscheinlich eher mit dem zu tun, was Sie in Ihrem #process input Linie. Ich habe bereits darauf hingewiesen, dass Ihr ursprüngliches Skript gut funktioniert, wenn ich es mit etwas Rudimentärem fülle, damit ich sehen kann, dass es funktioniert. Zum Beispiel, eine kleine Nachbesserung:

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";

Es besteht keine Notwendigkeit, am Ende die Eingabetaste zu drücken, und dies wird auch nichts bewirken (abgesehen davon, dass ein Zeilenumbruch in $input und die Zeichenkette durcheinander bringen).

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X