Como responder programaticamente "sim" aos comandos que solicitam uma decisão do usuário?

8

Eu fiz uma função personalizada que combina as duas funções do modo de twitter , twittering-favoritee twittering-native-retweet, no entanto estas duas necessidades de entrada de mim, respondendo a uma pergunta sim ou não.

Quero saber se existe uma maneira de envolver essas duas funções com algo que as faça receber uma resposta sem a minha intervenção direta.

shackra
fonte
8
Não uso twittering-mode(e não vou me incomodar em acessar o código), mas como um conselho geral: normalmente, em vez de fazer o que você sugere (crie um código que simule a resposta de um usuário yes), é melhor criar um código que usa diretamente o código que espera a resposta. IOW, tente aproveitar o caminho do código-fonte que uma yesresposta faria com que fosse invocada. (É só uma sugestão.)
de Drew
O título é enganoso, pois isso não pode ser feito corretamente de maneira genérica.
wasamasa

Respostas:

7

EDIT: Como @hatschipuh apontou nos comentários, uma fletconstrução de tipo é mais direta e não depende da minha macro de conselhos idiossincrásicos. Pelo menos no meu Emacs (24.5.1), cl-fletusa o escopo lexical, portanto, você precisará do nofletpacote para o seguinte snippet funcionar. Role para baixo para obter a resposta idiossincrática original.

(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: Esta é a resposta original, exceto que eu consertei my/bypass-confirmation-allpara trabalhar como anunciado e alterei um pouco as convenções de chamada.

Aqui está um invólucro geral que deve funcionar para qualquer função.

(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)))

Esse código depende dessa macro, que parece ser minha solução preferida para tudo no 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))))

Se esse código é a maneira mais inteligente de lidar com essa situação, eu não sei. Em geral, eu gosto de usar esse tipo de conselho temporário para fazer modificações nas funções existentes, em vez de duplicar o código das funções originais, em parte porque ajuda a tornar sua função modificada à prova do futuro contra alterações não relacionadas no original. Mas, nesse caso, talvez seja necessário tomar cuidado adicional, pois se twittering-modeatualizar e alterar os prompts ou adicionar outro, você não verá as alterações. Como um prompt de y ou n indica uma escolha controversa, isso pode ter consequências infelizes.


EDIT: Ocorreu-me que um exemplo de uso pode ser útil. Este exemplo funciona com qualquer uma das implementações.

(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
fonte
Isso não modificaria o comportamento das funções que eu gostaria que se comportasse de maneira diferente (apenas) dentro da minha função personalizada?
shackra
Sim, não é isso que você quer?
Aaron Harris
Bem, não exatamente, mudar o comportamento de ambos os comandos em todos os lugares é algo com o qual não me sinto confortável :(
shackra
1
Acho que entendi errado seu comentário anterior. Os únicos avisos ignorados são aqueles dentro da chamada de função agrupada. Para ajudar a esclarecer, adicionei um exemplo de uso à resposta.
Aaron Harris
1
O seguinte alcança basicamente o mesmo e é uma boa alternativa, eu acho:(flet ((yes-or-no-p (prompt) t) (y-or-n-p (prompt) t)) body...)
clemera