Subject: bug#27158: 25.2; Eliminating old usage of completing-read from built-in files

From: Ryan Thompson <[email-masked]>
Date: Wed, 31 May 2017 11:45:33 +0000

>
> The default arg has been available since the beginning, AFAIK.
> The behavior you describe is no more legacy than is providing a
> default-value arg.  Nothing to do with backward compatibility,
> I think.

I suppose I inferred that it was a backward-compatibility issue from the
fact that the feature is used intentionally in very few places (all fairly
old code) and is triggered unintentionally in more places, i.e. more
recently-written functions that set REQUIRE-MATCH to t and then assume that
completing-read will always return an element from the collection. The
latter kind will typically produce an error or do something nonsensical for
the empty string.

And it returns the default, even if REQUIRE-MATCH is non-nil
> and the default is not in the collection.  Do you dislike
> that behavior too?
>
> "" is just the default default, if you like (or not).
>

Thanks, that's actually a good way to think about it.

> Would you make a default arg be mandatory instead of optional?
> Is that it?  If not, what default default would you propose?
> What should be returned if no explicit default is provided and
> the user hits RET with no input?
>

Thinking some more about it, I guess one solution would be to give
REQUIRE-MATCH could gain a special 3rd value, such as `force', which would
mandate that the returned value is a valid completion. (Not sure what
should happen in this case if DEF is provided and is not a valid
completion.)

"" seems like a great choice for the default default, to me.
> It's pretty much guaranteed never to coincide with any usable
> completion candidate (which is not the case for a non-empty
> default value).  For one thing, that lets you easily check
> whether the user chose one of the candidates, even in the
> case where the collection is complex (e.g. a function).
>
> > This quirk
>
> Why is it a quirk?
>
> IN any case, nothing stops someone from defining their own
> `my-completing-read', which does not have this feature, er,
> quirk.  I don't see the problem.
>

The problem comes when implementing a completion system that returns the
first available completion when pressiong RET (e.g. ido and ivy). In the
case of an empty input, RET causes these completion systems to return the
first element of COLLECTION if no default was specified. Sometimes this is
correct, but sometimes this is wrong, as in the following usage pattern:

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

This pattern is used in e.g. Info-follow-reference. The problem is that
there's no way for the completion function to know whether it's being used
in this way or not, so if the user presses RET on an empty input and the
default wasn't provied to completing-read, it doesn't know whether it
should return the empty string or the first match. For an example where
returning the first match seems like the more correct behavior, see
read-char-by-name, which throws an error on the empty string. This
ambiguity makes it difficult to reconcile the desired convenience feature
of "return the first match on RET" with the documented completing-read
behavior of "return the empty string on empty input + RET" without breaking
some functions. And it's not even possible to implement an automatic
fallback to completing-read-default, because there's no way for the
completion function to know whether the caller is expecting that behavior
(Info-follow-reference) or is expecting it not to happen
(read-char-by-name). Ultimately, that's the issue: if completing-read is
called with a DEF being nil, the calling code may or may not be expecting
it to return the empty string, and while not expecting the empty string
might represent a bug in the caller, the existence of such functions makes
it difficult to implement ido-style completion that does the right thing in
all cases.

Going back to your statement that "empty string is just the default
default", it's possible that one might get reasonable behavior for ido and
ivy by taking this statement literally and prepending "" to the list of
completions when DEF is nil. By "reasonable" I mean correct behavior in all
of the cases that completing-read-default is correct, and bug-for-bug
compatibility in functions that don't expect completing-read to return "".
I'll try that out and see how it works.

Thanks for the insights. I guess you can close this.