Properly handle list and nil default in ivy-completing-read #1049
Thanks for the work, a large portion of it is definitely an improvement.
But this I don't like:
It means that even this common code will have
Probably the best way to go is to set
The problem it that it's not always unwanted. Some functions call
So if you don't allow it to work like this, you'll break some functions that work like this (same example from here) :
(defun pick-a-fruit () (interactive) (let* ((default "banana") (prompt (format "Pick a fruit (default %s): " default)) (collection '("apple" "banana" "cherry")) (selection (completing-read prompt collection nil t))) (when (string= selection "") (setq selection default)) (message "You selected %s" selection)))
Using ivy would effectively change the default to "apple" rather than "banana", despite the fact that the prompt clearly specifies that the default is banana. You'd have to use
Alternatively, you could default
This maintains compatibility with completing-read-default, which effectively treats a nil DEF as the empty string. Since this may not always be desired, there is also a variable to allow suppression of this behavior named ivy-completing-read-default-is-empty-string.
Now "ivy-completing-read" itself does nothing special when DEF is nil, but there is a new function "ivy-completing-read-with-empty-string-def" that treats a nil DEF as equivalent to the empty string for compatibility with "completing-read-default". This new function can be used in "ivy-completing-read-handlers-alist" to override ivy behavior for specific commands.
Previously, if a function in ivy-completing-read-handlers-alist called ivy-completing-read, this would result in infinite recursion. However, now if ivy-completing-read is called recursively without incrementing "(minibuffer-depth)", it ignores all handlers on the second call, breaking the recursion. The result of all this is that functions in ivy-completing-read-handlers-alist can now safely call ivy-completing-read.
These are based on the "enable-old" entries from the ido-ubiquitous 3.x overrides: https://github.com/DarwinAwardWinner/ido-ubiquitous/blob/3.x/ido-ubiquitous.el#L306-L371
Ok, instead of having a variable to control default handling, I just implemented a new function called
With these changes, ivy should now work with all of the functions that I know of that expect this special behavior from
In Emacs 24.4, "symbol-function" was changed to return nil when called on a symbol with no function. Previously, it threw a void-function error. This commit backports that fix so that cl-letf can work properly in ivy-test.el. The fix is only installed when running the tests.