Suite à une réponse à une autre question sur le nouveau système de conseil :
Dans l'ancien style advice.el
, il était possible de manipuler des membres individuels de la liste d'arguments d'une fonction conseillée, sans faire aucune affirmation concernant les membres non manipulés. Par exemple, les conseils suivants:
(defadvice ansi-term (around prompt-for-name last)
(let ((name (read-from-minibuffer "Tag: ")))
(and (not (string= name ""))
(ad-set-arg 1 (concat "Term: " name)))
ad-do-it))
permet la fourniture (facultative) d'un argument de nom de tampon à un ansi-term
appel, tandis ansi-term
qu'il obtiendra toujours son premier argument en l'invitant selon sa propre forme interactive.
(Pour référence ultérieure, ansi-term
la signature de est (PROGRAM &optional BUFFER-NAME)
, et sa forme interactive invite à PROGRAMME avec plusieurs valeurs par défaut possibles, mais ne fait rien en ce qui concerne BUFFER-NAME.)
Je ne sais pas si cela est possible ou non nadvice.el
. Si c'est le cas, je ne sais pas comment cela peut être fait. J'ai trouvé quelques façons de remplacer la liste d'arguments d'une fonction conseillée.
Par exemple, à partir de * info * (elisp) Combinateurs de conseils :
`:filter-args' Call FUNCTION first and use the result (which should be a list) as the new arguments to pass to the old function. More specifically, the composition of the two functions behaves like: (lambda (&rest r) (apply OLDFUN (funcall FUNCTION r)))
D'autres combinateurs offrent des capacités similaires, et le fil conducteur entre eux est que, bien que la liste d'arguments d'une fonction puisse être remplacée, tronquée, étendue, etc., il n'y a aucun moyen apparent pour que les conseils de fonction modifient l'argument à une position donnée de la liste sans affirmer quoi que ce soit sur le reste .
Dans le cas en discussion, il semble impossible pour l'auteur de conseils de ansi-term
ne transmettre qu'un nom de tampon, car il n'est pas possible de construire une liste qui a une valeur en position 1 mais rien, pas même nil
, en position 0. Dans le cas général, il semble impossible pour l'auteur du conseil de modifier arbitrairement les arguments au-delà de la position 0.
Cela semble regrettable dans la mesure où, pour produire un effet similaire, il est nécessaire de copier-coller du code: en particulier, soit je peux copier ansi-term
le formulaire interactif de et l'étendre à mon goût, soit je peux le copier ansi-term
et l'étendre de la même manière. Dans les deux cas, je dois maintenant redéfinir une partie de la distribution Emacs Lisp dans mon fichier init, ce qui me semble indésirable en termes de durabilité et d'esthétique.
Ma question est donc la suivante: peut-on éliminer ce type de liste d'arguments nadvice.el
? Si c'est le cas, comment?
Réponses:
Au contraire, je pense que ce serait une bonne idée de copier-coller la forme interactive de la fonction conseillée, même si vous n'êtes pas obligé de le faire ici.
Je vous lis la question de haut en bas. Quand je suis arrivé au bloc de code, j'ai deviné que votre conseil changeait probablement le nom du tampon. Mais je ne savais pas jusqu'à ce que vous fournissiez plus tard la signature en tant que commentaire.
En effet, rien n'est moins rien que rien. :-) Mais ce n'est guère pertinent ici.
Comme vous pouvez le voir dans la documentation que vous avez citée, la valeur retournée par le conseil est utilisée comme argument pour la fonction conseillée. La valeur de retour doit être une liste de tous les arguments, pas seulement ceux qui ont changé.
En restant le plus près possible de l'ancien conseil, voici ce que vous auriez à faire en utilisant
nadvice
:Mais je vous recommande plutôt de définir les conseils comme ceci:
Cette variante est en fait explicite.
la source
args
liste en cas d'appel comme(ansi-term "foo")
, sinon(setf (nth 1 args)...
cela déclencherait une erreur.buffer-name
c'est obligatoire.:filter-args
conseils reçoivent un seul argument qui est une liste d'arguments pour la fonction conseillée, donc la 1ère variante devrait être supprimée&rest
et la 2ème variante devrait utiliser une sorte de construction destructrice pour obtenir des noms sympas.Voici comment je le ferais:
alors que c'est moi qui l'
:filter-args
ai présenté, je trouve personnellement que cela est rarement pratique.la source