Bagaimana secara terprogram menjawab "ya" untuk perintah-perintah yang meminta keputusan dari pengguna?


8

Saya membuat fungsi khusus yang menggabungkan dua fungsi mode-twitter , twittering-favoritedan twittering-native-retweet, namun kedua ini membutuhkan input dari saya dengan menjawab pertanyaan ya atau tidak.

Saya ingin tahu apakah ada cara untuk membungkus kedua fungsi itu dengan sesuatu yang akan membuat mereka menerima jawaban tanpa campur tangan langsung saya.


8
Saya tidak menggunakan twittering-mode(dan saya tidak akan repot-repot mengakses kode), tetapi sebagai saran umum: Biasanya, alih-alih melakukan apa yang Anda sarankan (membuat kode yang mensimulasikan jawaban pengguna yes) lebih baik membuat kode yang langsung menggunakan kode yang mengharapkan jawabannya. TKI, coba manfaatkan jalur kode sumber yang yesakan menyebabkan jawaban dipanggil. (Hanya saran.)
Drew

Judul ini menyesatkan karena ini tidak dapat dilakukan dengan benar dengan cara yang umum.
wasamasa

Jawaban:


7

EDIT: Seperti yang ditunjukkan oleh @hatschipuh dalam komentar, fletkonstruksi -type lebih mudah dan tidak bergantung pada saran makro istimewa saya. Paling tidak pada Emacs saya (24.5.1), cl-fletmenggunakan pelingkupan leksikal, jadi Anda akan membutuhkan nofletpaket untuk cuplikan berikut agar berfungsi. Gulir ke bawah untuk jawaban yang asli dan istimewa.

(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: Ini adalah jawaban asli, kecuali bahwa saya tetap my/bypass-confirmation-allbekerja seperti yang diiklankan dan sedikit mengubah kebiasaan panggilan.

Inilah pembungkus umum yang dapat digunakan untuk fungsi apa pun.

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

Kode ini tergantung pada makro ini, yang tampaknya menjadi solusi masuk saya untuk semuanya di 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))))

Apakah kode ini adalah cara paling cerdas untuk menangani situasi ini, saya tidak tahu. Secara umum, saya suka menggunakan saran sementara semacam ini untuk membuat modifikasi fungsi yang sudah ada alih-alih menduplikasi kode fungsi asli, sebagian karena ini membantu untuk membuktikan di masa depan fungsi modifikasi Anda terhadap perubahan yang tidak terkait dalam dokumen asli. Tetapi dalam hal ini Anda mungkin perlu berhati-hati, karena jika twittering-modememperbarui dan mengubah permintaan atau menambahkan yang lain, Anda tidak akan melihat perubahan. Karena prompt y-atau-n menunjukkan pilihan yang kontroversial, itu bisa memiliki konsekuensi yang tidak menguntungkan.


EDIT: Terpikir oleh saya bahwa contoh penggunaan mungkin bermanfaat. Contoh ini berfungsi dengan salah satu implementasi.

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

Tidakkah ini mengubah perilaku fungsi yang saya ingin berperilaku berbeda (hanya) di dalam fungsi kustom saya?
shackra

Ya, bukankah itu yang Anda inginkan?
Aaron Harris

Yah, tidak persis, mengubah perilaku kedua perintah di mana-mana adalah sesuatu yang saya tidak merasa nyaman dengan :(
shackra

1
Saya pikir saya mungkin salah membaca komentar Anda sebelumnya. Satu-satunya prompt yang dilewati adalah yang ada di dalam panggilan fungsi yang dibungkus. Untuk membantu memperjelas, saya menambahkan contoh penggunaan ke jawabannya.
Aaron Harris

1
Berikut ini pada dasarnya mencapai hal yang sama dan merupakan alternatif yang baik, saya kira:(flet ((yes-or-no-p (prompt) t) (y-or-n-p (prompt) t)) body...)
clemera
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.