Problèmes avec les raccourcis clavier lors de l'utilisation du terminal

30

J'ai la ligne suivante init.el:

(global-set-key [(control \;)] 'comment-region)

Cela fonctionne très bien dans la fenêtre GUI, mais si emacsest invoqué avec l' -nwoption alors C-;ne commente pas la région, insère seulement le ;caractère. M-x comment-region RETfonctionne bien cependant.

J'ai essayé de suivre cette réponse sur un problème similaire, mais C-q C-;revient juste ;et je ne veux évidemment pas me lier nu ;.

Comment obtenir l'effet souhaité?

WeSenseASoulInSearchOfAnswers
la source
4
Il est possible que votre terminal (qu'est-ce que vous utilisez, soit dit en passant?) Ne reconnaisse pas cette séquence de commandes. Essayez d'utiliser le C-;combo, puis utilisez M-x view-lossagepour voir s'il arrive même à Emacs.
Dan
J'utilise gnome-terminalet M-x view-lossagerenvoie:ESC [ > 1 ; 2 8 0 2 ; 0 c ; ESC x v i e w - l o s s a g e RET
WeSenseASoulInSearchOfAnswers
3
Cela ressemble à un problème de terminal: si cette combinaison de touches devait atteindre Emacs, elle ressemblerait C-;plutôt à c ;(ou, du moins, je reçois C-;).
Dan
@Dan: Pourriez-vous mettre cela en place comme réponse? Cela permettrait de répondre à la question et de voir plus facilement la solution, ce qui est bon pour d'autres personnes ayant le même problème. Merci!
Tikhon Jelvis
Résumée et publiée avec un lien supplémentaire pour plus de lecture. Modifier également le titre de la question pour le rendre un peu plus général.
Dan

Réponses:

17

Tout d'abord, le problème plus général: les émulateurs de terminaux sont souvent limités dans les séquences de contrôle et d'échappement qu'ils peuvent envoyer. Donc: il se peut que le terminal avale vos caractères spéciaux avant qu'ils n'atteignent Emacs. En tant que diagnostic général, vous pouvez appuyer sur C-h l(ou M-x view-lossage) pour voir si vos combinaisons de touches en font Emacs.

Pour plus de discussion sur ce problème, consultez ce fil de débordement de pile et les liens qui s'y trouvent.

Pour résumer le va-et-vient dans les commentaires, votre problème spécifique suggère que c'est le terminal plutôt que Emacs qui est le problème. Lorsque vous avez essayé C-;puis M-x view-lossage, vous avez obtenu blah blah blah c ; ESC v i e w - l o s s a g e RET. Cela ressemble à un problème de terminal: si la combinaison de touches atteignait Emacs, la c ;pièce ressemblerait C-;.

Dan
la source
33

Dans Shift + Up n'est pas reconnu par Emacs dans un terminal, j'explique comment les terminaux traduisent la plupart des touches de fonction en séquences d'échappement, car l'interface entre les applications et les terminaux transmet des caractères (ou plutôt des octets), pas des clés. Seules quelques combinaisons modificateur + personnage ont leur propre caractère:

  • Ctrlplus une lettre ou l'un des @[\]^_tours en octets 0–31 (caractères de contrôle ASCII ).
  • Souvent, Ctrl+ se ?transforme en octet 127 et Ctrl+ Spaceéquivaut à Ctrl+ @(octet 0).
  • Certaines touches de fonction sont équivalentes aux caractères de contrôle: Tab= Ctrl+ I, Return= Ctrl+ M, Esc= Ctrl+ [.
  • Et Backspace= Ctrl+ Hou Ctrl+ ?selon la configuration. Ctrl+ ?est plus pratique pour Emacs, car Ctrl+ Hest une aide.
  • Meta+ characterest envoyé Escsuivi du caractère .

Qu'en est-il des autres combinaisons telles que Ctrl+ ;ou Ctrl+ Shift+ letter? Puisqu'il n'y a pas de caractère correspondant, le terminal doit soit réutiliser un caractère, soit envoyer une séquence d'échappement. De nombreux terminaux ignorent les modificateurs lorsqu'il n'y a pas de caractère correspondant, vous vous retrouvez donc avec Ctrl+ ;envoi ;, Ctrl+ Shift+ letteréquivalent à Ctrl+ letter, etc.

Les vendeurs de terminaux ont continué à faire la chose simple pendant longtemps. Il n'y avait pas de norme pour les séquences d'échappement, qui se perpétuait - les fournisseurs de terminaux ne l'implémentent pas, les applications ne la prennent pas en charge, les utilisateurs ne s'y attendent pas. Certains émulateurs de terminaux peuvent être configurés pour envoyer des séquences d'échappement arbitraires, donc si le vôtre le peut, vous pouvez le configurer et déclarer les séquences d'échappement à Emacs (plus de détails plus loin).

Dernièrement, la situation évolue, car il y a eu deux propositions de standardisation des séquences d'échappement. L'un est libtermkey de LeoNerd avec la syntaxe . Un autre est le xterm de Thomas Dickey avec la syntaxe . Les versions actuelles de xterm (≥216) peuvent être configurées pour l'une ou l'autre syntaxe en définissant la ressource; la fonction doit être activée en définissant le sur une valeur différente de zéro.ESC [ codepoint ; modifier uESC [ 2 7 ; modifier ; codepoint ~formatOtherKeysmodifyOtherKeys

Si votre émulateur de terminal ne prend pas en charge ces syntaxes mais peut être configuré, choisissez l'un ou l'autre.

Depuis Emacs 24.4, Emacs active automatiquement la modifyOtherKeysfonction lorsqu'il détecte que le terminal est la version xterm ≥216. La détection des séquences d'échappement par Emacs pour encoder les clés fonctionne via la variable local-function-key-map. Depuis Emacs 24.4, toutes les séquences d'échappement ne sont pas prises en charge. Vous pouvez utiliser le code suivant dans votre fichier init pour terminer le travail.

;; xterm with the resource ?.VT100.modifyOtherKeys: 1
;; GNU Emacs >=24.4 sets xterm in this mode and define
;; some of the escape sequences but not all of them.
(defun character-apply-modifiers (c &rest modifiers)
  "Apply modifiers to the character C.
MODIFIERS must be a list of symbols amongst (meta control shift).
Return an event vector."
  (if (memq 'control modifiers) (setq c (if (or (and (<= ?@ c) (<= c ?_))
                                                (and (<= ?a c) (<= c ?z)))
                                            (logand c ?\x1f)
                                          (logior (lsh 1 26) c))))
  (if (memq 'meta modifiers) (setq c (logior (lsh 1 27) c)))
  (if (memq 'shift modifiers) (setq c (logior (lsh 1 25) c)))
  (vector c))
(defun my-eval-after-load-xterm ()
  (when (and (boundp 'xterm-extra-capabilities) (boundp 'xterm-function-map))
    (let ((c 32))
      (while (<= c 126)
        (mapc (lambda (x)
                (define-key xterm-function-map (format (car x) c)
                  (apply 'character-apply-modifiers c (cdr x))))
              '(;; with ?.VT100.formatOtherKeys: 0
                ("\e\[27;3;%d~" meta)
                ("\e\[27;5;%d~" control)
                ("\e\[27;6;%d~" control shift)
                ("\e\[27;7;%d~" control meta)
                ("\e\[27;8;%d~" control meta shift)
                ;; with ?.VT100.formatOtherKeys: 1
                ("\e\[%d;3u" meta)
                ("\e\[%d;5u" control)
                ("\e\[%d;6u" control shift)
                ("\e\[%d;7u" control meta)
                ("\e\[%d;8u" control meta shift)))
        (setq c (1+ c))))))
(eval-after-load "xterm" '(my-eval-after-load-xterm))

Si la TERMvariable d'environnement n'est pas définie sur xtermou une variante telle que xterm-256color, Emacs n'activera pas ces séquences. Si Emacs prend déjà en charge votre valeur de TERM, vous pouvez ajouter un support en définissant une fonction similaire à celle ci-dessus, à exécuter après le chargement du fichier Lisp dont le nom est la valeur deTERM . Si Emacs ne dispose pas d'un tel support, vous pouvez l'ajouter en créant un sous-répertoire appelé termquelque part dans votre load-path, et en créant un fichier Lisp appelé term/$TERM.el$TERMest la valeur de TERM, en définissant une fonction appelée terminal-init-$TERM.

Au moment où j'écris, il semble que peu d'émulateurs de terminaux autres que xterm aient adopté ces séquences d'échappement. Sous OSX, vous pouvez configurer iTerm2 en sélectionnant une séquence d'échappement pour chaque combinaison de touches, une par une.

Gilles 'SO- arrête d'être méchant'
la source
2
Vos réponses à ce sujet sont toujours superbes, Gilles. Très appréciée.
phils
Génial!. Bien que j'ai beaucoup de mal à trouver comment rendre urxvt l'envoi de ces séquences. Pourriez-vous me donner un coup de main :)
Amos
@Amos Je n'utilise pas rxvt. Vous devriez demander sur Unix et Linux comment faire pour que urxvt envoie les mêmes séquences d'échappement que xterm avec modifyOtherKeys.
Gilles 'SO- arrête d'être méchant'
ne fonctionne pas sur macOS xterm-256color. M-C-%être reconnu àESC 5
LoranceChen
@LoranceChen C'est le comportement attendu si la modifyOtherKeysfonction n'est pas active. Notez qu'il n'est pris en charge que dans les versions suffisamment récentes de xterm, et il n'est activé automatiquement que depuis Emacs 24.4. Je ne sais pas si OSX est livré avec des versions récentes. Si ce n'est pas le cas et que cela ne fonctionne pas pour vous, je vous suggère de poser une nouvelle question. Mentionnez les versions que vous utilisez.
Gilles 'SO- arrête d'être méchant'
2

La réponse de Gilles a déclaré: On OSX, you can configure iTerm2 by selecting an escape sequence for each key combination, one by one. J'ai eu un peu de mal à y arriver, alors voici une explication détaillée au cas où vous seriez comme moi, confus.

Si, lorsque vous exécutez Emacs dans un terminal (par exemple, Terminal.app par défaut de Mac), C-x C-;ne fonctionne pas comment-lineet que vous souhaitez cette fonctionnalité, vous devez basculer vers iTerm2 (Terminal.app n'a pas la capacité) et créer un mappage de clé sous Profils ... Clés comme suit:

^;     ^[[59;5u

Ceci est accompli en cliquant sur le +bouton, qui fait apparaître une petite fenêtre appelée "Raccourci clavier"; cette fenêtre comporte initialement deux champs; le haut a une valeur de «Cliquez pour définir» et le bas a une valeur de «Ignorer». Cliquez sur le bouton du haut et tapez C-;. Cela définit la combinaison de touches qui exécutera l'action et le code. Cliquez sur le champ du bas, "Action", et recherchez et cliquez sur "Send Escape Sequence", qui est un peu plus de la moitié du chemin. Après avoir cliqué sur cela, un troisième champ apparaîtra, appelé "Esc +". Dans ce champ, saisissez:

[59;5u

C'est 59le code ASCII décimal de la virgule et 5c'est le code de Ctrl. Appuyez ensuite sur "OK" pour terminer. Le combo de touches correct à la séquence de touches sera désormais inclus dans les préférences d'iTerm2. Lorsque vous démarrez Emacs dans iTerm, vous aurez désormais accès aux C-x C-;fonctionnalités.

Pomme de pin
la source