我想寫一個函數,它會調用emacs中的函數列表(具體來說,是kill-buffer-query-functions
),但是如果它們中的任何一個需要用戶交互,我希望它們只是簡單地返回nil
,以便整個事物將運行非-interactively。我正在考慮使用defadvice
來修改每個通常會提示用戶輸入throw
的函數,該函數的值爲nil
。然後,我會用catch
表單包裝所有內容。唯一的問題是,我沒有列出所有emacs elisp函數的詳盡列表,這些列表可能會提示用戶提供某些東西。如何捕獲所有需要用戶交互的elisp函數調用?
有沒有人有這樣的清單,或者是否有更簡單的方法來解決這個問題?作爲示例,功能yes-or-no-p
和y-or-n-p
肯定會在此列表中,read-string
和completing-read
也是如此。
基本上,我想填省略號在此代碼:
(defun eval-but-return-if-requires-user (form &optional interactive-return)
"Evaluate FORM, but immediately stop and return INTERACTIVE-RETURN if any part of FORM would require user interaction."
;; Set up the safety net
(catch 'ui-required
(let ((ui-requiring-functions '( ... )) ; What goes in this list?
(ui-required-callback
;; A function that takes any number of args and throws an exception
'(lambda (&rest args)
(throw 'ui-required interactive-return)))
(flet-redefinitions
;; Use the above callback to create a list of redefinitions for `flet'
(mapcar (lambda (func)
(cons func (cdr ui-required-callback)))
ui-requiring-functions)))
`(flet
,flet-redefinitions ; Perform the function redefinitions,
,form)))) ; Then evaluate FORM
基本上,我在一個catch塊包裹的一切,然後我定義一個函數體,將簡單地採取任何參數並拋出一個適當的例外。我建立了一個重新定義清單,以便傳遞給flet
,它將暫時重新定義這些函數以使用上述異常拋出體。最後,我評估了form
的臨時函數重定義。
現在,該代碼中可能存在一些引用錯誤,但我認爲如果我只是具有要重新定義的函數的適當列表,它將起作用。
請注意,如果需要任何用戶交互,我希望整個表單返回,而不僅僅是需要用戶交互的表單中的特定函數調用。要明白爲什麼我需要這個,請考慮表單可能想要問以下任一問題:
- 是否要刪除這個非常重要的文件?是或否
- 你想保留這個非常重要的文件嗎? yes或no
顯然,如果我只是修改yes-or-no-p
總是返回nil
(意爲「無」),仍然不能保證被刪除保存我的重要文件。因此,由於我不知道可能會問什麼問題,因此如果想要詢問用戶的任何內容,我想讓整個表單簡單地中止並返回一個特定的值。基本上,我想說的是「評估這段代碼,但是如果你必須要問我什麼才能這樣做,那就把它忘掉吧,然後返回nil
」。
這似乎很好。任何人都可以想到任何合理的提示用戶的方式,不涉及minibuffer或對話框? – 2010-08-05 15:52:31