Pourquoi la touche FIN n'a pas d'entrée terminfo?

8

Sur un système Debian, une pression sur la ENDtouche génère ^[[F:

$ showkey -a

Press any keys - Ctrl-D will terminate this program

^[[F     27 0033 0x1b
         91 0133 0x5b
         70 0106 0x46

Mais pourquoi ce clavier n'est-il pas en terminfo ?

$ infocmp -1 | grep end
kend=\EOF,

Néanmoins, ncurses parvient à le reconnaître correctement comme KEY_END. Comment?

TERM est xterm-256color

BTW, quelle est la motivation derrière avoir kendet endau lieu de juste end? (pareil pour khomeet home)

ÉDITER

Comme dit dans le commentaire de Johan Myréen, la khomechaîne est la séquence produite par la touche Home. Mais sur Debian, appuyer sur la touche Accueil produit home. Pourquoi?

$ showkey -a

Press any keys - Ctrl-D will terminate this program

^[[H     27 0033 0x1b
         91 0133 0x5b
         72 0110 0x48
$ infocmp -1 | grep home
    home=\E[H,
    khome=\EOH,
Igor Liferenko
la source
1
La différence entre homeet khomeest que la khomechaîne est la séquence qui produit la touche Home, tandis que la homechaîne est la séquence qui doit être envoyée au terminal pour déplacer le curseur à la position d'origine. À ma connaissance, terminfo ne définit pas une endcapacité, juste kend.
Johan Myréen
@ JohanMyréen Pourriez-vous s'il vous plaît expliquer ce qu'est la "position d'origine" d'un curseur avec un exemple? Et pourquoi kendest défini comme \EOFdans terminfo , alors que le terminal génère \E[F? Est-ce un bogue dans le terminfo de Debian ? Et comment ncurses parvient-il à le détecter KEY_ENDquand même?
Igor Liferenko du
La position d'origine est le coin supérieur gauche de l'écran.
Johan Myréen

Réponses:

10

La réponse de Johan Myréen était proche, mais pas exactement le problème: la plupart des émulateurs de terminaux que vous utiliserez ont des modes normal et d' application pour les touches spéciales. Les descriptions des terminaux sont écrites pour un mode, ce qui correspond à ce qu'une application plein écran utilise. D'autres applications (comme un shell interactif ) n'initialisent généralement pas l'écran pour utiliser le mode d' application . Bash en est un exemple.

En mode normal , les terminaux xterm et similaires envoient escape[(CSI) tandis qu'en mode application , leurs claviers envoient escapeO(SS3). Dans la syntaxe terminfo, cet échappement est \E. Donc , infocmpvous montre que la description utilise le mode d'application. La homecapacité est envoyée au terminal, lui indiquant comment déplacer le curseur vers la position d' origine (en haut à gauche), et n'est pas la même que khome(envoyée depuis le terminal à l'aide du clavier).

Les applications plein écran (telles que celles utilisant ncurses) peuvent envoyer les chaînes de capacité de terminal pour initialiser le clavier. Certaines descriptions de terminaux mettent le terminal en mode application, d'autres non.

L'utilisation de kendversus endest une convention de dénomination: dans terminfo par convention, tout nom commençant par k fait référence à une touche spéciale (touche de fonction, touche de curseur, touche de clavier) pour indiquer clairement qu'il s'agit de chaînes à lire par une application. Par exemple, kcub1( touche curseur vers l'arrière ) est différent de cub1(déplacer le curseur d'une colonne vers l'arrière).

ncurses reconnaît la clé KEY_ENDcar l'application que vous utilisez appellera la keypadfonction pour initialiser le terminal en utilisant le smkx(le mnémonique signifie "démarrer le mode de transmission clavier"). Cela peut / peut ne pas réellement activer le mode d'application. La description du terminal de la console Linux ne le fait pas, celle de xterm le fait.

En principe, vous pouvez utiliser tputpour changer de mode (et obtenir des résultats différents showkey):

$ showkey -a

Press any keys - Ctrl-D will terminate this program

^[[H     27 0033 0x1b
         91 0133 0x5b
         72 0110 0x48
^C        3 0003 0x03
^D        4 0004 0x04
$ tput smkx
$ showkey -a

Press any keys - Ctrl-D will terminate this program

^[OH     27 0033 0x1b
         79 0117 0x4f
         72 0110 0x48

Comme complication, les curses ne reconnaîtront qu'un seul nom pour une chaîne. Certains terminaux (tels que xterm) émulent des terminaux matériels plus anciens en utilisant des noms différents pour les touches du clavier d'édition. Dans la FAQ xterm listée ci-dessous, il est possible de nommer la touche "Accueil" "Insérer" ...

Lectures complémentaires:

Thomas Dickey
la source
Oui, j'utilise la keypadfonction. Mais la question « comment ncurses parvient à détecter comme KEY_END» je voulais dire « comment keypaddécodages ^[[Fdans kend» (considérant que les keypadutilisations terminfo base de données pour interpréter les keychords). Si j'ai bien compris, cela se produit car showkey -aest en mode curseur, tandis que l'application ncurses est en mode application.
Igor Liferenko
showkeyne bascule pas entre les modes normal / d'application. C'est un programme spécifique à Linux, faisant des hypothèses sur la console Linux, plutôt que d'utiliser la base de données du terminal
Thomas Dickey
Si showkeyne passe pas d'un mode à l'autre, il utilise un état par défaut, quel qu'il soit. Le fait est que les showkeyimpressions ^[[F, non ^[OF, ce qui conduit à ma confusion. (Je viens showkeyde représenter visuellement le véritable clavier qui est envoyé par le terminal en appuyant sur un bouton du clavier, sans soupçonner qu'il puisse y avoir des subtilités.)
Igor Liferenko
Oui, c'est le mode "normal" (la façon habituelle de s'y référer). Vous pouvez bien sûr initialiser votre terminal en utilisant tput smkxet obtenir des résultats différents.
Thomas Dickey
Je pense qu'il y a un bug dans l' lessutilitaire: il se met en mode application, mais ne parvient pas à interpréter la touche d'entrée du clavier. Dois-je soumettre un rapport de bug? (Vous pouvez vérifier cela en démarrant lesset en appuyant sur la touche Entrée du clavier après avoir tapé /- cela produira ESCOM, au lieu de faire ce que la touche Entrée doit faire.)
Igor Liferenko
5

Le problème avec la touche Accueil est que les terminaux physiques et plus tard les émulateurs de terminaux qui les émulent ont deux modes: le mode normal et le mode d'application, et les séquences d'échappement sont différentes selon le mode dans lequel se trouve le terminal. Terminfo ne gère pas bien cela. En mode normal (aka "Mode curseur"), la séquence d'échappement de la touche Fin est ESC [ F, en mode Application ESC O F. Googler pour ce problème révèle tout le gâchis.

Modifier à partir de la source terminfo:

les touches de curseur sont alors supposées être en "mode curseur" et les définitions des touches de curseur doivent correspondre à cette hypothèse, sinon l'application peut échouer. Il est également prévu que les applications transmettent toujours la chaîne au terminal avant de quitter. "

Johan Myréen
la source
Quelle est la procédure de passage en "mode application"? Est-ce fait par ncurses ?
Igor Liferenko