After delving into the innards of the minibuffer, I've developed a solution that should work for all prompting functions. It's pretty hacky though.
This method intercepts the prompt function itself (read-from-minibuffer
) and returns the default value - iff the prompt matches one of a list of regular expressions. This could be extended to return a specific value (other than the default), based on the prompt.
This is the code:
;; First, we set up a global list of regular expressions. This
;; variable should only be modified by auto-pick-default-prompt. A
;; prompt that matches any of these regular expressions will be
;; accepted automatically.
(setq auto-pick-default-prompts '())
(defun auto-pick-default-internal (original-function
prompt
&optional initial-contents key-map
read history default-value
inherit-input-method)
"Function to be run around prompts to auto-pick default value.
Uses the global variable auto-pick-default-prompts to
determine whether the particular prompt it is enclosing should be
automatically confirmed.
If no regular expressions for prompts are specified, auto
confirms all prompts."
;; If no prompt filters have been set, just return the default value
;; for the prompt
(if (not auto-pick-default-prompts)
default-value
;; Else check if the prompt matches one of the filters.
;; If so, return the default value for the prompt.
(let ((matches nil))
(mapc #'(lambda (regexp)
(if (string-match regexp prompt)
(setq matches t)))
auto-pick-default-prompts)
(if matches
default-value
(funcall original-function
prompt initial-contents key-map read history
default-value inherit-input-method)))))
(defun auto-pick-default-prompt (function is-interactive prompt-regexps &optional args)
"Runs a function, auto selecting the default option in prompts.
Takes a list of regular expressions for prompts that should be
auto-confirmed. Prompts which do not match any of these
expressions will not be auto confirmed."
(condition-case nil
(progn
;; Set the prompts that should be auto-accepted
(setq auto-pick-default-prompts prompt-regexps)
;; Add the intercepting command
(advice-add 'read-from-minibuffer :around #'auto-pick-default-internal)
;; Call the function in the appropriate manner (interactive,
;; with arguments, without arguments)
(if is-interactive
(if (> (length args) 0)
(call-interactively function nil args)
(call-interactively function))
(apply function args))
;; Now remove the intercepting command and reset the prompts
;; that should be auto-accepted.
(advice-remove 'read-from-minibuffer #'auto-pick-default-internal)
(setq auto-pick-default-prompts nil))
((debug error) (progn
;; This function wraps a child function with some
;; advice. If the child throws an error, the
;; advice will not be removed. Explicitly remove
;; advice after an error has been thrown.
(advice-remove 'read-from-minibuffer #'auto-pick-default-internal)
(setq auto-pick-default-prompts nil)
(signal err)))))
(defun noprompt-rope-rename (&rest args)
"Call rope-rename, skipping the confirmation prompt."
(interactive "P")
(let ((prompts-to-skip'("Choose what to do")))
(auto-pick-default-prompt 'rope-rename t prompts-to-skip)))
A limitation of this approach is that it can't be called recursively. A command wrapped by auto-pick-default-prompt
cannot itself call auto-pick-default-prompt
. That should be fine though, and I imagine it's possible to get around this limitation by extending the advice system.