Comment répondre par programme «oui» à ces commandes qui demandent une décision de l'utilisateur?

8

J'ai fait une fonction personnalisée qui combine deux fonctions du mode Twitter , twittering-favoriteet twittering-native-retweetcependant ces deux ont besoin de ma part en répondant à une question oui ou non.

Je veux savoir s'il existe un moyen d'envelopper ces deux fonctions avec quelque chose qui leur fera recevoir une réponse sans mon intervention directe.

shackra
la source
8
Je n'utilise pas twittering-mode(et je ne prendrai pas la peine d'accéder au code), mais comme un conseil général: généralement, au lieu de faire ce que vous suggérez (faire du code qui simule la réponse d'un utilisateur yes), il est préférable de faire du code qui utilise directement le code qui attend la réponse. IOW, essayez de tirer parti du chemin du code source qu'une yesréponse provoquerait à invoquer. (Juste une suggestion.)
Drew
Le titre est trompeur car cela ne peut pas être fait correctement de manière générique.
wasamasa

Réponses:

7

EDIT: Comme @hatschipuh l'a souligné dans les commentaires, une fletconstruction de type est plus simple et ne repose pas sur ma macro de conseil idiosyncrasique. Au moins sur mon Emacs (24.5.1), cl-fletutilise la portée lexicale, vous aurez donc besoin du nofletpackage pour que l'extrait de code suivant fonctionne. Faites défiler vers le bas pour la réponse originale et idiosyncrasique.

(defun my/bypass-confirmation (function &rest args)
  "Call FUNCTION with ARGS, bypassing all `y-or-n-p' prompts."
  (require 'noflet)
  (noflet
      ((y-or-n-p (prompt) t))
    (apply function args)))

(defun my/bypass-confirmation-all (function &rest args)
  "Call FUNCTION with ARGS, bypassing all prompts.
This includes both `y-or-n-p' and `yes-or-no-p'."
  (require 'noflet)
  (noflet
      ((y-or-n-p    (prompt) t)
       (yes-or-no-p (prompt) t))
    (apply function args)))

EDIT: Ceci est la réponse d'origine, sauf que j'ai corrigé my/bypass-confirmation-allde travailler comme annoncé et changé un peu les conventions d'appel.

Voici un wrapper général qui devrait fonctionner pour n'importe quelle fonction.

(defun my/bypass-confirmation (function &rest args)
  "Call FUNCTION with ARGS, bypassing all `y-or-n-p' prompts."
  (my/with-advice
      ((#'y-or-n-p :override (lambda (prompt) t)))
    (apply function args)))

(defun my/bypass-confirmation-all (function &rest args)
  "Call FUNCTION with ARGS, bypassing all prompts.
This includes both `y-or-n-p' and `yes-or-no-p'."
  (my/with-advice
      ((#'y-or-n-p    :override (lambda (prompt) t))
       (#'yes-or-no-p :override (lambda (prompt) t)))
    (apply function args)))

Ce code dépend de cette macro, qui semble être ma solution de choix pour tout sur Stackexchange.

(defmacro my/with-advice (adlist &rest body)
  "Execute BODY with temporary advice in ADLIST.

Each element of ADLIST should be a list of the form
  (SYMBOL WHERE FUNCTION [PROPS])
suitable for passing to `advice-add'.  The BODY is wrapped in an
`unwind-protect' form, so the advice will be removed even in the
event of an error or nonlocal exit."
  (declare (debug ((&rest (&rest form)) body))
           (indent 1))
  `(progn
     ,@(mapcar (lambda (adform)
                 (cons 'advice-add adform))
               adlist)
     (unwind-protect (progn ,@body)
       ,@(mapcar (lambda (adform)
                   `(advice-remove ,(car adform) ,(nth 2 adform)))
                 adlist))))

Je ne sais pas si ce code est le moyen le plus intelligent de gérer cette situation. En général, j'aime utiliser ce genre de conseils temporaires pour apporter des modifications aux fonctions existantes au lieu de dupliquer le code des fonctions d'origine, en partie parce que cela aide à pérenniser votre fonction modifiée contre les changements indépendants de l'original. Mais dans ce cas, vous devrez peut-être prendre des précautions supplémentaires, car si les twittering-modemises à jour et les modifications des invites ou en ajoute une supplémentaire, vous ne verrez pas les modifications. Puisqu'une invite y ou n indique un choix controversé, cela pourrait avoir des conséquences malheureuses.


EDIT: Il m'est venu à l'esprit qu'un exemple d'utilisation pourrait être utile. Cet exemple fonctionne avec l'une ou l'autre implémentation.

(defun my/twittering-function ()
  ;; This will bypass `y-or-n-p' in both commands.
  (my/bypass-confirmation #'twittering-favorite arg)
  (my/bypass-confirmation #'twittering-native-retweet)
  ;; This will bypass both `y-or-n-p' and `yes-or-no-p' in this command.
  (my/bypass-confirmation-all #'twittering-favorite arg)
  ;; Prompts in this call are not bypassed.
  (twittering-native-retweet)
Aaron Harris
la source
Cela ne modifierait-il pas le comportement des fonctions que j'aimerais avoir un comportement différent (uniquement) à l'intérieur de ma fonction personnalisée?
shackra
Oui, n'est-ce pas ce que tu veux?
Aaron Harris
Eh bien, pas exactement, changer le comportement des deux commandes partout est quelque chose avec
lequel
1
Je pense que j'ai peut-être mal lu votre commentaire précédent. Les seules invites ignorées sont celles contenues dans l'appel de fonction encapsulé. Pour aider à clarifier, j'ai ajouté un exemple d'utilisation à la réponse.
Aaron Harris
1
Ce qui suit réalise essentiellement le même et est une bonne alternative je pense:(flet ((yes-or-no-p (prompt) t) (y-or-n-p (prompt) t)) body...)
clemera