2016-03-21 30 views
3

Ich habe eine Rebol2-Konsole App (Rebol Core), die ich möchte die Tastatur Zeichen Echo auf der Konsole deaktivieren. Die App wird von einem minimalen Linux-Kernel/initramfs gestartet und von busybox inittab gestartet (nicht vom Terminal). Es hat eine minimale Konsolenbenutzerschnittstelle, die Ansi-Codes für Farbe usw. verwendet und reagiert auf Menüauswahlen durch Drücken einzelner Tasten. Um die Konsole zu "beruhigen", habe ich den Cursor ausgeschaltet und sehe die Ausgabe der Taste nicht (bis vor kurzem).Rebol 2 deaktivieren Konsole Echo

Ich dachte vorher, ich hätte das Problem gelöst, indem ich "stty -echo" innerhalb Rebol, aber es funktioniert tatsächlich nicht, wie ich gerade entdeckt habe- es gibt eine Funktion, die 5-10 Sekunden dauert und die gedrückten Tasten drücken kann während Sie auf die Fertigstellung der Funktion warten.

Ich bin nicht ganz sicher, warum ich nur die Echo-Zeichen sehen, während diese eine Funktion ausgeführt wird, aber es ist die einzige Funktion, die jede Menge Zeit benötigt. Die Tastatur wird durch Öffnen der Konsole abgefragt: // im Binärmodus, Warten auf einen Tastendruck, dann eine switch-Anweisung, um die Funktion auszuwählen. Das Lesen der Schlüssel in Binär/Konsole scheinen zu ‚verbrauchen‘ der Schlüssel Echo-

minimal example, pressing 'a'- 

    cons: open/binary console:// 
    first cons 
    == 97 

(der Wert zurückgegeben wird, wie ich will, und die Zeichen nicht wiederholte, was gut- ist ich in den meisten Funktionen denken Meine Schlüssel werden in der Get-Key-Schleife "konsumiert", aber die längere Funktion hat keine Chance, sie zu "konsumieren" und am Computer zu senden.

Gibt es eine Möglichkeit, das Konsolenzeichen-Echo zu deaktivieren? in Rebol2? Ich habe in system/console und system/ports/input, output gesucht, aber sehe nichts offensichtliches. Meine aktuelle Problemumgehung besteht darin, die Textfarbe einfach so zu ändern, dass sie mit dem Hintergrund übereinstimmt, so dass während der Ausführung der jeweiligen Funktion keine Tastenbetätigungen sichtbar sind.

hier ist ein minimales Beispiel dafür, was ich bin doing-

get-key: func [ /local cons ch ][ 
    cons: open/binary console:// 
    ch: lowercase to-string to-char first cons 
    all [ equal? ch "^[" append ch copy/part cons 2 ] 
    close cons 
    ch 
] 

forever [ 
    switch get-key [ 
     ;up arrow 
     "^[[A" [ some-function1 ] 
     ;down arrow 
     "^[[B" [ some-function2 ] 
     ;enter 
     "^M" [ some-function3 ] 
     ;quit 
     "q" [ break ] 
    ] 
] 

Die für immer Schleife der Tastatureingabe zu ‚verbrauchen‘ scheint (nichts Echo), aber wenn eine der Funktionen nimmt jede Menge Zeit Jede Tastatureingabe wird auf dem Bildschirm angezeigt, wo auch immer sich der Cursor gerade befindet. In den meisten Fällen sehe ich keine wiederholten Zeichen, da die Zeit zwischen dem Aufrufen des get-keys minimal ist. Ich würde auch bemerken, dass die Echo-Zeichen nicht auch im nachfolgenden Aufruf von get-key angezeigt werden.

Update-

hier ist eine bessere Probe des Codes der Problem-

get-key: has [ cons ch ][ 
    cons: open/binary console:// 
    ch: lowercase to-string to-char first cons 
    prin rejoin [ "<" ch ">" ] ;show get-key chars 
    ch 
] 
long-func: does [ call/wait {sleep 10} ] 
reb-func: does [ wait 10 ] 

forever [ 
    switch get-key [ 
    "f" [ long-func ] 
    "r" [ reb-func ] 
    "q" [ break ] 
    ] 
] 

ich, dass mein ‚long‘ herausgefunden, um zu sehen Funktionsaufruf des verwendet, die einige Sekunden dauern kann, so dass die Problem tritt auf, wenn ein Anruf verwendet wird.

Der obige Code, wenn zeigen lief, dass die Schlüssel nur Echo, weil sie in der get-Tastenfunktion gedruckt werden (Klammern), wenn die Lang func läuft, dann Tasten hallen außerhalb von get-Taste (Nein Klammern), und wenn Sie fertig sind, wird der get-key auch diese Schlüssel verarbeiten. Oder rufen Sie einfach "call/wait {sleep 10}" auf, und Sie erhalten während des Wartens die gechlossenen Schlüssel und erhalten auch die gleichen Schlüssel, die von Rebol wiederholt werden, wenn der Anruf zurückkehrt. Schlüssel werden nicht ausgegeben, wenn reb-func ausgeführt wird, und get-key verarbeitet alle gepufferten Schlüssel, wenn reb-func ausgeführt wird. Die Tastatureingabe wird zweimal behandelt, wenn ein Anruf verwendet wird.

Ich habe versucht, stdin/stdout in den Aufruf-Befehl umleiten (in der Aufrufzeichenfolge Befehl, wie bei Bash-Eingabeaufforderung), aber habe keine Combo gefunden, die funktioniert. (Mein tatsächlicher Code führt einen Aufruf mit/output/error aus, um alle Ausgaben zu erfassen).

+0

Können Sie die längere Funktion zeigen ?. Verwenden von console: // ist der richtige Weg. – sqlab

Antwort

1

Die umgeordneten Nachteile gefangen werden Ole-Code ist nicht notwendig (und alle Schlüssel werden zwischengespeichert, egal welche Anordnung verwendet wird), obwohl die Fähigkeit, eine Wach-Funktion hinzuzufügen, gut zu wissen ist. In meinem echten Code hat die get-Taste eine '/ timeout t'-Option, wo ich' wait [cons t] 'und eine Zeichenfolge (für erweiterte Schlüsselcodes wie Pfeil nach oben) oder keine zurückgeben kann, was bedeutet, dass ich auch kann Flush den Konsoleneingang vor meinem Schalter get-Taste (so alle Tasten gedrückt, während die Funktionen ausgeführt werden).

forever [ 
    while [ get-key/timeout 0.1 ][] ;flush 
    switch get-key [ ;wait for key 
... 

Die ‚stty -echo‘ funktioniert gut in dem gegebenen Beispiel, und scheint mein Problem zu lösen, aber ich sehe noch ein paar Zeichen hallten, wenn ich ein paar Tasten drücken, während die langen Funktionen ausgeführt werden (Ich habe {stty -echo;} in alle Befehle eingefügt. Irgendwie, in der Rebol-Aufruf-Erstellung von Prozessen (fork/exec nehme ich an), tty Eingabe/Ausgabe kann immer noch "leak" i/o Zeichen. Oder vielleicht öffnet eines der aufgerufenen Programme ein tty, obwohl es die Dateideskriptoren des Elternteils erbt.

Hier ist, was ich getan habe - Ändern der Art, wie ich Befehle aufrufen, so dass sie im Hintergrund laufen, aber immer noch warten, bis sie abgeschlossen sind.

;used by other funcs to parse output of commands 
set 'cmd-output "" ;output from 'call' commands 
set 'cmd-error "" ;error from 'call commands 

set 'cmd func [ str [string!] /local ret ][ 
    --old-- 
    ;clear previous 
    cmd-output: copy "" 
    cmd-error: copy "" 

    ;--new-- 
    write %out "" 
    write %err "" 
    attempt [ delete %ret ] 

    ;--old-- 
    ;ret: call/wait/output/error str cmd-output cmd-error 

    ;--new-- stdout->out stderr->err exitcode->ret 
    call rejoin [ str { >out 2>err; echo -n $? > ret} ] 
    ;wait for return code, (up to 20 seconds, should be plenty) 
    loop 200 [ all [ exists? %ret break ] wait 0.1 ] 
    cmd-output: read %out 
    cmd-error: read %err 
    ret: to-integer read %ret 

    --old-- 
    ;debug-cmd writes info to a logfile 
    debug-cmd str ret 
    ret 
] 

Dies funktioniert, da ich keine (unerwünschten) Zeichen auf dem Bildschirm nach wie vor zeigen, bekommen (und ich denke, es ist dieses Zeichen beweist aus den genannten Prozessen kam).

2

Ohne Ihren Code mit warten auf den Hafen zu optimieren und eine wach Funktion ich Ihr Problem erraten kann, indem das Öffnen und Schließen der Konsolen-Port außerhalb Ihres get-Schlüsselfunktion wie in

get-key: func [ /local ch ][ 
    ch: lowercase to-string to-char first cons 
    all [ equal? ch "^[" append ch copy/part cons 2 ] 
    ch 
] 
cons: open/binary [scheme: 'console] 
forever [ 
    switch get-key [ 
     ;up arrow 
     "^[[A" [ some-function1 ] 
     ;down arrow 
     "^[[B" [ some-function2 ] 
     ;enter 
     "^M" [ some-function3 ] 
     ;quit 
     "q" [ break ] 
    ] 
] 
close cons 

ok gelöst werden, hier ist eine optimierte Version Ihres zweites Beispiel

long-func: does [ call/wait {stty -echo ; sleep 10} ] 
reb-func: does [ wait 10 ] 

cons: open/binary [scheme: 'console] 
cons/awake: func [port] [ 
    key: to-char first port 
    print ["<" key ">"] 
    switch key [ 
     #"f" [long-func] 
     #"r" [reb-func] 
     #"q" [break] 
    ] 
] 
forever [ 
    wait [cons] 
] 

Sie sehen können, einschließlich, dass alle Schlüssel ohne zusätzliches Echo

+0

Es macht keinen Unterschied. Ich glaube, ich beginne zu verstehen, was passiert. Ich werde noch ein paar Infos hinzufügen. – cv007

+0

Sie können versuchen, die asynchrone Call-Implementierung von http://softinnov.org/rebol/acall.shtml zu verwenden – sqlab

+0

Das erfordert Bibliothekskomponente, so dass ich es nicht einmal versuchen kann. Ich verwende Core, da dies ein minimales Linux-Setup mit nur Kommandozeile ist (der gesamte Kernel/rootfs ist <6MB). – cv007