Frage

Ich mag ein einzelnes Zeichen lesen at-a-time über die Befehlszeile in PHP, aber es scheint, als ob es irgendeine Art von Eingabe Pufferung von irgendwo diese zu verhindern.

Betrachten Sie diesen Code ein:

#!/usr/bin/php
<?php
echo "input# ";
while ($c = fread(STDIN, 1)) {
    echo "Read from STDIN: " . $c . "\ninput# ";
}
?>

Typing in "foo" als Eingang (und die Eingabetaste drücken), die Ausgabe erhalte ich ist:

input# foo
Read from STDIN: f
input# Read from STDIN: o
input# Read from STDIN: o
input# Read from STDIN: 

input# 

Der Ausgang Ich bin erwartet ist:

input# f
input# Read from STDIN: f

input# o
input# Read from STDIN: o

input# o
input# Read from STDIN: o

input# 
input# Read from STDIN: 

input# 

(Das heißt, mit Zeichen gelesen und verarbeitet werden, wie sie eingegeben werden).

Derzeit werden jedoch wird jedes Zeichen erst nach gelesen werden eingeben gedrückt wird. Ich habe den Verdacht, die TTY den Eingang Pufferung.

Schließlich mag ich in der Lage sein, Drücken von Tasten zu lesen wie Pfeil nach oben, Pfeil nach unten etc.

War es hilfreich?

Lösung

Die Lösung war für mich zu Satz -icanon-Modus auf dem TTY (mit stty). Zum Beispiel:.

stty -icanon

Also, die der Code, dass jetzt funktioniert, ist:

#!/usr/bin/php
<?php
system("stty -icanon");
echo "input# ";
while ($c = fread(STDIN, 1)) {
    echo "Read from STDIN: " . $c . "\ninput# ";
}
?>

Ausgabe:

input# fRead from STDIN: f
input# oRead from STDIN: o
input# oRead from STDIN: o
input# 
Read from STDIN: 

input# 

Requisiten auf die Antwort hier gegeben:
gibt es eine Möglichkeit, zu warten und einen Tastendruck von einer (remote) Terminalsitzung?

Weitere Informationen finden Sie unter:
http://www.faqs.org/docs/ Linux-HOWTO / Seriell-Programming-HOWTO.html # AEN92

Vergessen Sie nicht, die TTY wiederherzustellen, wenn Sie mit ihm fertig sind ...

Wiederherstellen der tty Konfiguration

Zurücksetzen des Terminal zurück auf die Art und Weise war es durch Speichern der tty Zustand durchgeführt werden, bevor Sie Änderungen daran vornehmen. Sie können dann in diesen Zustand wiederherzustellen, wenn Sie fertig sind.

Zum Beispiel:

<?php

// Save existing tty configuration
$term = `stty -g`;

// Make lots of drastic changes to the tty
system("stty raw opost -ocrnl onlcr -onocr -onlret icrnl -inlcr -echo isig intr undef");

// Reset the tty back to the original configuration
system("stty '" . $term . "'");

?>

Dies ist der einzige Weg, um die tty zu bewahren und ihn wieder einsetzen, wie der Benutzer es hatte, bevor Sie begann.

Beachten Sie, dass, wenn Sie nicht besorgt sind über den ursprünglichen Zustand zu bewahren, können Sie es zurück zu einem Standard „sane“ Konfiguration zurückgesetzt einfach, indem Sie:

<?php

// Make lots of drastic changes to the tty
system("stty raw opost -ocrnl onlcr -onocr -onlret icrnl -inlcr -echo isig intr undef");

// Reset the tty back to sane defaults
system("stty sane");

?>

Andere Tipps

Hier ist ein Weg, das funktioniert für mich mit readline- und Stromfunktionen, ohne mit tty Sachen herumschlagen müssten.

readline_callback_handler_install('', function() { });
while (true) {
  $r = array(STDIN);
  $w = NULL;
  $e = NULL;
  $n = stream_select($r, $w, $e, null);
  if ($n && in_array(STDIN, $r)) {
    $c = stream_get_contents(STDIN, 1);
    echo "Char read: $c\n";
    break;
  }
}

Getestet mit PHP 5.5.8 auf OSX.

Die Funktion ist eine vereinfachte Version von @ seb Antwort, die verwendet werden kann, um ein einzelnes Zeichen zu erfassen. Es erfordert keine stream_select und Verwendungen readline_callback_handler_install inhärente Sperr anstatt eine while-Schleife zu schaffen. Es beseitigt auch den Handler als normal weiteren Eingang (wie Readline-) zu ermöglichen.

function readchar($prompt)
{
    readline_callback_handler_install($prompt, function() {});
    $char = stream_get_contents(STDIN, 1);
    readline_callback_handler_remove();
    return $char;
}

// example:
if (!in_array(
    readchar('Continue? [Y/n] '), ["\n", 'y', 'Y']
    // enter/return key ("\n") for default 'Y'
)) die("Good Bye\n");
$name = readline("Name: ");
echo "Hello {$name}.\n";
<?php
`stty -icanon`;
// this will do it
stream_set_blocking(STDIN, 0);
echo "Press 'Q' to quit\n";
while(1){
   if (ord(fgetc(STDIN)) == 113) {
       echo "QUIT detected...";
       break;
   }
   echo "we are waiting for something...";
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top