Comment détecter les frappes qui ne modifient pas le tampon?

8

Quelle est la meilleure façon de détecter les frappes (par exemple via un crochet) qui ne modifient pas le tampon? Je veux dire des choses comme les touches fléchées pour le mouvement de point, les appels à beginning-of-buffer, etc.

La raison en est que je travaille sur certaines ycmdliaisons pour emacs, et j'aimerais pouvoir détecter (au moins heuristiquement) lorsque l'utilisateur a arrêté de modifier et se déplace dans le tampon. C'est le bon moment pour expédier le contenu du tampon pour l'analyse. Le client vim fait cela lorsque l'utilisateur quitte le mode d'insertion, et j'essaie d'émuler ce comportement.

abingham
la source
8
Vous pouvez être intéressé par les temporisateurs inactifs pour ce genre de choses: gnu.org/software/emacs/manual/html_node/elisp/Idle-Timers.html
giordano
2
Une autre idée (ou un raffinement de l'idée avec des temporisateurs inactifs): conseiller self-insert-commandd'annuler et de replanifier un temporisateur au lieu d'utiliser un temporisateur inactif. De cette façon, même si l'utilisateur fait quelque chose, le minuteur n'est pas réinitialisé sauf si le "quelque chose" est une insertion de texte.
mbork
2
mbork: after-change-functionsest un mécanisme général pour réagir aux changements de texte.
phils
1
Utilisez a post-command-hook. Cela se déclenchera sur tout, vous devrez donc peut-être filtrer ce qui l'a déclenché avant de prendre l'action que vous souhaitez.
Malabarba
1
Je ne sais pas si c'est pertinent pour ce problème particulier, mais la buffer-chars-modified-tickfonction peut être utile.
Jon O.

Réponses:

2

Ajoutez les crochets suivants:

  • Pour pre-command-hook, définissez une variable sentinelle sur t- cela indique que la commande ne change pas.
  • Pour after-change-functions, définissez cette valeur sentinelle sur nil. (C'est un crochet, il ne ressemble tout simplement pas à un; merci à @phils de l'avoir signalé.)
  • Pour post-command-hook, vérifiez cette valeur sentinelle et exécutez votre fonction.

Cela peut ou peut ne pas fonctionner selon l'ordre d'exécution. Si ce n'est pas le cas, faites-le moi savoir dans les commentaires ci-dessous.


Lorsque je quitterai le travail, je publierai un exemple.

Sean Allred
la source
Je dois aller travailler maintenant…
Sean Allred
2
Ne conseille pas l'auto-insertion. Utiliser les fonctions après changement
Malabarba
Je vais essayer ça quand j'en aurai l'occasion.
abingham
4
@abingham En règle générale, les crochets sont préférables aux conseils. Les crochets sont spécialement conçus pour vous permettre d'attacher des fonctions, tandis que les conseils sont des moyens d'attacher quelque chose dans des endroits inattendus. Dans ce cas particulier, il est également déconseillé de conseiller certaines fonctions très fondamentales, car il interagit de manière non fiable avec la compilation d'octets.
Malabarba
2
Je pense que Sean voulait faire référence à post-self-insert-hook(ce morceau de la réponse semble confondre ce crochet avec le conseil self-insert-command). Dans tous les cas, je pense que vous préféreriez généralement after-change-functionscar il fait ce que vous voulez (car l'auto-insertion n'est pas le seul type de coup de clé qui modifie le tampon).
phils
0

Juste une pensée -

Cela ne devrait pas vraiment concerner les "frappes", mais les commandes - peu importe comment elles sont exécutées, non ? Si je comprends bien, vous cherchez vraiment un moyen de savoir si une commande donnée qui est invoquée modifie le tampon.

Si oui, alors peut-être faire quelque chose comme ceci:

  • Mettez une fonction sur pre-command-hook(1) enregistre la valeur actuelle de (buffer-modified-p)puis (2) utilise set-modified-ppour rendre le tampon non modifié.

  • Mettez une fonction sur post-command-hookcela (1) vérifie si la commande a modifié le tampon (en comparant la valeur enregistrée avec la nouvelle valeur actuelle de (buffer-modified-p)), puis agit en conséquence, et (2) si la nouvelle valeur est nilensuite réinitialisée à la valeur de pré-changement en utilisant set-modified-p.

Un peu lourd (il vérifie chaque commande invoquée), mais cela pourrait valoir la peine d'être essayé.

Si la partie " agit en conséquence " est juste un no-op pour toutes les commandes de modification du tampon, et si c'est aussi un no-op pour de nombreuses commandes non-modificatrices (par exemple parce que vous venez de le faire sur une précédente commande non-modificatrice), alors au moins vous ne ferez pas cette action " agit en conséquence " plus que nécessaire. Mais la vérification seule peut être chère / exagérée (ralentir trop les choses) - essayez-la pour voir.

A dessiné
la source