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

From: Drew Adams <[email-masked]>
Date: Wed, 31 May 2017 07:51:47 -0700 (PDT)

"" 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.)

Today, `force' (or `abc', for that matter) does not exit IF at least some completion is performed. What you are requesting is, I guess, that it not exit even if no completion is performed - that it would be able to exit only if one of the candidates is chosen.

That would be backward-incompatible, since today the symbol `force' means the same as any other non-nil, non-t REQUIRE-MATCH value. Not the end of the world, but one consideration.

Today, you can just test the "" return value and re-issue the `completing-read'. Do that in a loop in and you have the behavior you want, no?

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. 

I think you are saying that those systems want/need to behave that way, but `completing-read' does not behave that way out of the box? But you can make calls to `completing-read' always behave that way, right (see above)?

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

I don't follow. What is the behavior that you want? The above seems to be fine, as would be to repeatedly calli `completing-read' until the user entered something (that completes). Which behavior do you want?

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. 

Do you want your completion system to obey the (outside) call to `completing-read' or to do its own thing of returning the first candidate on empty input?

It sounds like you have a system that wants to have an alternative completion behavior from what some of the possible behaviors `completing-read' provides, but you also want it to (sometimes?) respect the behavior that `completing-read' provides.

And you cannot tell when you want this and when you want that, that is, when the behavior specified by the (outside) code should be respected and when the usual behavior of your completion should be imposed instead.

Is that it? If so, that doesn't sound like a problem with `completing-read'. And I don't see how letting REQUIRE-MATCH = `force' would change anything. IIUC, you don't have control over (outside) calls to `completing-read', so you cannot change them to use `force' or whatever.

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. 

(So does `Info-follow-reference', BTW: "No reference was specified".)

Raising an error on empty input is not the same thing as forcing input to be non-empty. Today it is easy to test for empty input (and so throw an error), thanks to the default default behavior of returning "".

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. 

But your chosen convenience itself apparently gets in the way when you want to respect an (outside) call to `completing-read' that expects a different behavior, no?

This doesn't sound like a problem with `completing-read'. It sounds like a problem reconciling a one-size-fits-all convenient completion behavior (return the first candidate if no input) with (outside) code that might expect a different behavior for empty input.

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

Isn't that the real problem you're having: that there is no way to know when to respect the caller and when to impose a different completion behavior? How can changing `completing-read' help solve that problem?

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,

It's normal for different calling code to expect different such behavior, no? And you are trying to accommodate those different expectations (at least sometimes?), instead of overriding them, no?

and while not expecting the empty string might represent a bug in the caller, 

Why suppose that? Sure, it's possible, but it's more likely that that's the desired behavior. When trying to accommodate outside code, you might need to put on its rose-colored glasses, not only the rose-colored glasses of your completion system. ;-)

the existence of such functions makes it difficult to implement ido-style completion that does the right thing in all cases.

Can you give a concrete example, describing the intended behavior by the outside caller, your intended behavior, and the problem you have in achieving either one?

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. 

Does that do what you want?

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.

No reason to be hasty in closing it. Better for us all to understand just what the problem is. So far, I admit that I don't, so I can't say much that is helpful here.