2016-03-21 1 views
3

J'ai une application de console Rebol2 (Rebol Core) dont je voudrais désactiver l'écho du clavier sur la console. L'application est exécutée à partir d'un noyau Linux minimal/initramfs, et est lancée par busybox inittab (pas depuis le terminal). Il dispose d'une interface utilisateur console minimale utilisant des codes ansi pour la couleur, etc., et répond aux sélections de menu via des touches uniques. Pour "calmer" la console, j'ai le curseur éteint, et ne vois pas la sortie de la touche appuie (jusqu'à récemment). Je pensais auparavant avoir résolu le problème en appelant 'stty -echo' dans Rebol, mais cela ne fonctionne pas comme je viens de le découvrir - il y a une fonction qui prend 5-10 secondes et peut voir les touches enfoncées en attendant que la fonction se termine. Je ne suis pas tout à fait sûr pourquoi je ne vois que les caractères renvoyés pendant que cette fonction est en cours d'exécution, mais c'est la seule fonction qui prend un certain temps. Le clavier est interrogé en ouvrant la console: // en mode binaire, en attendant une pression sur une touche, puis une instruction switch pour choisir la fonction. La lecture des touches en binaire/console semblent « consommer » la clé écho-Rebol 2 désactiver l'écho de la console

minimal example, pressing 'a'- 

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

(la valeur est renvoyée comme je veux, et le charbon ne sont pas repris, ce qui est bon enfant, je pense que dans la plupart des fonctions mes clés sont «consommées» dans la boucle get-key, mais la fonction la plus longue n'a pas la chance de les «consommer» et finit par se répercuter sur la console)

Y at-il un moyen de désactiver l'écho des caractères de la console? à l'intérieur de Rebol2? J'ai regardé dans le système/console et le système/ports/entrée, sortie, mais ne vois rien d'évident. Ma solution de contournement actuelle consiste à simplement modifier la couleur du texte pour qu'elle corresponde à l'arrière-plan afin que les pressions sur les touches ne soient pas visibles pendant l'exécution de la fonction spécifique.

ici est un exemple minimal de ce que je suis 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 ] 
    ] 
] 

La boucle semble toujours à « consommer » l'entrée du clavier (rien écho), mais si l'une des fonctions prend une quantité de temps , toute entrée au clavier sera renvoyée à l'écran à l'endroit où se trouve le curseur. Dans la plupart des cas, je ne vois jamais de caractères en écho car le temps entre l'appel de la touche get est minimal. Je note également que les caractères renvoyés n'apparaissent pas aussi dans l'appel suivant à get-key.

update-

ici est un meilleur exemple de code pour voir le de problèmes

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 ] 
    ] 
] 

je me suis dit que ce qui utilise son appel ma fonction « long » peut prendre quelques secondes, de sorte que le problème se pose lorsqu'un appel est utilisé. Le code ci-dessus, lorsqu'il est exécuté, indique que les touches sont renvoyées uniquement parce qu'elles sont imprimées dans la fonction get-key (parenthèses), lorsque la fonction long est activée, les touches sont renvoyées en dehors de la touche get (non parenthèses), et une fois terminé, la clé get traitera également ces clés. Ou lancez simplement 'call/wait {sleep 10}' et vous obtiendrez des touches en écho pendant l'attente, et obtenez également les touches sames en écho avec Rebol lorsque l'appel revient. Les clés ne sont pas répercutées lorsque la fonction reb-func est exécutée, et la commande get-key traitera toutes les clés mises en mémoire quand la fonction reb-func est terminée. L'entrée au clavier est traitée deux fois lorsque l'appel est utilisé.

J'ai essayé de rediriger stdin/stdout dans la commande call (dans la commande call string, comme à l'invite bash), mais je n'ai pas trouvé de combo qui fonctionne. (Mon code actuel exécute l'appel avec/output/error pour capturer toutes les sorties).

+0

Pouvez-vous montrer la fonction la plus longue? Utiliser la console: // est la bonne façon. – sqlab

Répondre

1

Les contre réarrangés Le code d'erreur n'est pas nécessaire (et toutes les clés sont mises en cache quel que soit l'arrangement utilisé), bien que la possibilité d'ajouter une fonction d'éveil soit bonne à savoir. Dans mon code réel, la clé get-key a une option '/ timeout t' où je peux faire 'wait [cons t]' et retourner une chaîne (pour les codes clés étendus comme la flèche vers le haut) ou none, ce qui signifie que je peux aussi vider l'entrée de la console avant l'activation de la touche get (donc toutes les touches enfoncées lors de l'exécution des fonctions sont vidées).

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

Le « stty -echo » fonctionne bien dans l'exemple donné, et semble résoudre mon problème, mais je vois encore quelques personnages résonnaient si je presse un trousseau de clés, tandis que les fonctions longues sont en cours d'exécution (J'ai inséré {stty -echo;} dans toutes les commandes). D'une manière ou d'une autre, dans l'appel à la création de processus Rebol (fork/exec je suppose), les entrées/sorties tty peuvent encore 'fuir' les caractères d'entrée/sortie. Ou peut-être l'un des programmes appelés ouvre un tty même s'il hérite des descripteurs de fichiers du parent.

Voici ce que j'ai fini par faire - changer la façon dont j'appelle les commandes afin qu'elles s'exécutent en arrière-plan, mais attendent toujours qu'elles se terminent.

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

Cela fonctionne, comme je ne peux pas obtenir des caractères (indésirables) pour montrer à l'écran comme avant (et je suppose que cela prouve ces personnages provenaient des processus dits).

2

Sans l'optimisation de votre code avec attente sur le port et une fonction éveillé, je suppose que votre problème peut être résolu en plaçant l'ouverture et la fermeture du port de console en dehors de votre rendez-vous touche de fonction comme dans

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, ici est une version optimisée, y compris votre deuxième exemple

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] 
] 

vous pouvez voir, que toutes les clés sont attrapés sans écho supplémentaire

+0

Cela ne fait aucune différence. Je pense que je commence à comprendre ce qui se passe. Je vais ajouter quelques informations supplémentaires. – cv007

+0

Vous pouvez essayer d'utiliser l'implémentation de l'appel asynchrone depuis http://softinnov.org/rebol/acall.shtml – sqlab

+0

Cela nécessite un composant Library, donc je ne peux même pas l'essayer. J'utilise Core car c'est une configuration Linux minimale avec une ligne de commande seulement (le noyau entier/rootfs est <6MB). – cv007