From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!.POSTED!not-for-mail From: Ryan Thompson Newsgroups: gmane.emacs.bugs Subject: bug#27158: 25.2; Eliminating old usage of completing-read from built-in files Date: Wed, 31 May 2017 11:45:33 +0000 Message-ID: References: <24f4a025-ad7b-06e5-10ee-f122bef32402@thompsonclan.org> <0276a0cd-874b-47ee-a2dc-fe8ca08ece9d@default> NNTP-Posting-Host: blaine.gmane.org Mime-Version: 1.0 Content-Type: multipart/alternative; boundary="001a113fe2dae2c06f0550d0758b" X-Trace: blaine.gmane.org 1496231175 18729 195.159.176.226 (31 May 2017 11:46:15 GMT) X-Complaints-To: usenet@blaine.gmane.org NNTP-Posting-Date: Wed, 31 May 2017 11:46:15 +0000 (UTC) To: Drew Adams , 27158@debbugs.gnu.org Original-X-From: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Wed May 31 13:46:10 2017 Return-path: Envelope-to: geb-bug-gnu-emacs@m.gmane.org Original-Received: from lists.gnu.org ([208.118.235.17]) by blaine.gmane.org with esmtp (Exim 4.84_2) (envelope-from ) id 1dG24n-0004YD-Io for geb-bug-gnu-emacs@m.gmane.org; Wed, 31 May 2017 13:46:10 +0200 Original-Received: from localhost ([::1]:58680 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dG24t-0003hs-2f for geb-bug-gnu-emacs@m.gmane.org; Wed, 31 May 2017 07:46:15 -0400 Original-Received: from eggs.gnu.org ([2001:4830:134:3::10]:41656) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dG24k-0003hb-VP for bug-gnu-emacs@gnu.org; Wed, 31 May 2017 07:46:08 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dG24g-0001UX-VY for bug-gnu-emacs@gnu.org; Wed, 31 May 2017 07:46:07 -0400 Original-Received: from debbugs.gnu.org ([208.118.235.43]:43573) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1dG24g-0001UP-CC for bug-gnu-emacs@gnu.org; Wed, 31 May 2017 07:46:02 -0400 Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1dG24g-0001Ku-6X for bug-gnu-emacs@gnu.org; Wed, 31 May 2017 07:46:02 -0400 X-Loop: help-debbugs@gnu.org Resent-From: Ryan Thompson Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Wed, 31 May 2017 11:46:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 27158 X-GNU-PR-Package: emacs X-GNU-PR-Keywords: Original-Received: via spool by 27158-submit@debbugs.gnu.org id=B27158.14962311535121 (code B ref 27158); Wed, 31 May 2017 11:46:02 +0000 Original-Received: (at 27158) by debbugs.gnu.org; 31 May 2017 11:45:53 +0000 Original-Received: from localhost ([127.0.0.1]:46250 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1dG24W-0001KW-Ef for submit@debbugs.gnu.org; Wed, 31 May 2017 07:45:52 -0400 Original-Received: from mail-io0-f174.google.com ([209.85.223.174]:32805) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1dG24U-0001KJ-B7 for 27158@debbugs.gnu.org; Wed, 31 May 2017 07:45:50 -0400 Original-Received: by mail-io0-f174.google.com with SMTP id p24so14369566ioi.0 for <27158@debbugs.gnu.org>; Wed, 31 May 2017 04:45:50 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=thompsonclan-org.20150623.gappssmtp.com; s=20150623; h=mime-version:references:in-reply-to:from:date:message-id:subject:to; bh=RK9Dwu3HKyggMhFU5kWWIlReW6Z4ostB0Yz9TN50Yqs=; b=maqYGaJN/dPb/ccrmkT4SJxMgkhaJunzr8E3n9pG1r6eu9sSFwiO3slgWYxi9DzgKD I53K2atczzx4pfzH8Cned5coP1Gm6mwTI+h3/3s3PkvQVX/OfhmY+LEn37IUFvZUUxG3 LHzP+7J+SX3V64RcW5JjtM7CiZfLYod3ZIgk+zGKEEvmORveu868qDd9fPXpeLOQbLhq 8beEvOwoY8b0O0bRXEmiBUuvGLWr+hDdmYForhW2NbC+A0nkwTuIE/kYJ2t54HYO/lwV bpVuhAoYJWbqskeHAVIMqCdB9Ov0bZ+quDVLZWT32T+gwuul3QQy7ar1Hlc+wNp1NKOI lR5g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to; bh=RK9Dwu3HKyggMhFU5kWWIlReW6Z4ostB0Yz9TN50Yqs=; b=apq4PdRcjRxx3O3ucEeXRPjyqbd9WojhCPyKTINrdhp1poNeo4eVPb/aaXK6qB+OYt DY6QWC+7Exzhi4jjcosPfe9WFm8Pz4S+XisuMKeup/0FHRBaeocLpWFWspV9djZS4fa2 VN3IWIR33vmqF6byPODkS7Lan9mkPA5Bfl7wRLRleOImu/uXykoRxdU0TqIQAWdOgkby yQZ6U7kDKh2Kkb7c77tVB458Zt1nemeoShFbx4geOlRs0b3h/GaJ6Nt2k4cs01uEL+J5 wGeGJtwoMvnVuCocTT4IPl9lsIif/gX7pURQ4tSvJBjfbyza1d1wQ8f4mFdF/2Qr3lQy AD6g== X-Gm-Message-State: AODbwcCRjp4Ra/sBczd+SpuLbcM/hITvtqhy6GiV8YOImGE7VJoMKjWN N6BzJD32Sg1KW77CI2xTxZA+ksM1ChQl X-Received: by 10.107.25.203 with SMTP id 194mr21188830ioz.182.1496231144761; Wed, 31 May 2017 04:45:44 -0700 (PDT) In-Reply-To: <0276a0cd-874b-47ee-a2dc-fe8ca08ece9d@default> X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 208.118.235.43 X-BeenThere: bug-gnu-emacs@gnu.org List-Id: "Bug reports for GNU Emacs, the Swiss army knife of text editors" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Original-Sender: "bug-gnu-emacs" Xref: news.gmane.org gmane.emacs.bugs:133082 Archived-At: --001a113fe2dae2c06f0550d0758b Content-Type: text/plain; charset="UTF-8" > > 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. --001a113fe2dae2c06f0550d0758b Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable
= 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.=C2=A0 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 intent= ionally in very few places (all fairly old code) and is triggered unintenti= onally in more places, i.e. more recently-written functions that set REQUIR= E-MATCH to t and then assume that completing-read will always return an ele= ment from the collection. The latter kind will typically produce an error o= r 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.=C2=A0 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 ab= out it.
=C2=A0
Would you make= a default arg be mandatory instead of optional?
Is that it?=C2=A0 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?

Thinki= ng 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 th= at the returned value is a valid completion. (Not sure what should happen i= n this case if DEF is provided and is not a valid completion.)
"" seems like a great choi= ce 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).=C2=A0 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.=C2=A0 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 c= ase of an empty input, RET causes these completion systems to return the fi= rst element of COLLECTION if no default was specified. Sometimes this is co= rrect, but sometimes this is wrong, as in the following usage pattern:
(defun pick-a-fruit ()
  (interactive)
  (let* ((default "banana")
         (prompt (format "Pic=
k a fruit (default %s): " default))
         (collection '("apple&q=
uot; "banana" "cherry"))
         (selection (completing-read prompt collection nil t)))
    (when (string=3D selection "")
      (setq selection default))
    (message "You selected %s"=
 selection)))
This pattern is used in e.g. In= fo-follow-reference. The problem is that there's no way for the complet= ion 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 t= o completing-read, it doesn't know whether it should return the empty s= tring or the first match. For an example where returning the first match se= ems 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 t= he desired convenience feature of "return the first match on RET"= with the documented completing-read behavior of "return the empty str= ing on empty input + RET" without breaking some functions. And it'= s not even possible to implement an automatic fallback to completing-read-d= efault, because there's no way for the completion function to know whet= her the caller is expecting that behavior (Info-follow-reference) or is exp= ecting it not to happen (read-char-by-name). Ultimately, that's the iss= ue: 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 expec= ting the empty string might represent a bug in the caller, the existence of= such functions makes it difficult to implement ido-style completion that d= oes the right thing in all cases.

Going back to yo= ur statement that "empty string is just the default default", it&= #39;s possible that one might get reasonable behavior for ido and ivy by ta= king this statement literally and prepending "" to the list of co= mpletions when DEF is nil. By "reasonable" I mean correct behavio= r 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 ret= urn "". I'll try that out and see how it works.
Thanks for the insights. I guess you can close this.
--001a113fe2dae2c06f0550d0758b--