Subject: bug#65348: INITIAL-INPUT in completing-read repeats same entry twice consecutively

From: Christopher Dimech <[email-masked]>
Date: Mon, 21 Aug 2023 06:34:54 +0200

> Sent: Monday, August 21, 2023 at 12:23 PM
> From: "Drew Adams" <[email-masked]>
> To: "Juri Linkov" <[email-masked]>
> Cc: "Eli Zaretskii" <[email-masked]>, "[email-masked]" <[email-masked]>, "[email-masked]" <[email-masked]>
> Subject: bug#65348: INITIAL-INPUT in completing-read repeats same entry twice consecutively
>
> > > In case you're thinking, for your "obvious" use
> > > cases, of a case where you have few completion
> > > candidates, such as just "alpha", "beta", "gamma",
> > > then let's not forget that you can already cycle
> > > among those now, as completion candidates, without
> > > having them added to the future history.  That's
> > > available since Stefan added candidate cycling,
> > > AFAIK.
> >
> > Your answers are too short.  Please elaborate
> > what do you mean by "candidate cycling" and
> > what keys do you press to cycle candidates?
>
> Sorry.  First, I'm no expert on the cycling provided
> by vanilla Emacs.  I believe Stefan introduced it.
> He can probably tell you more, and better.
>
> There are two different completion metadata entries,
> `display-sort-function' and `cycle-sort-function'.
> See (elisp) `Programmed Completion':
>
> https://www.gnu.org/software/emacs/manual/html_node/elisp/Programmed-Completion.html
>
> (I don't see why anyone would ever want those two to
> have different values, but I don't think my ignorance
> about that is very relevant here.)
>
> Dunno whether there is some key that, by _default_,
> invokes one or the other of those functions.
>
> I use them in a two of my libraries, `sortie.el'
> and `keysee.el', to use vanilla Emacs cycling
> for cycling and display, together.
>
> With sortie.el, when you hit a key (`C-,' by
> default) the candidates in *Completions* are
> re-sorted, and so are the candidates you cycle
> through (same sort order).  So when you cycle to
> a candidate, that's also the current candidate
> in *Completions*.
>
> To turn on cycling you need to give
> `completion-cycle-threshold' a non-nil value.
> Then you can cycle among candidates using `TAB'.
>
> keysee.el uses key descriptions as candidates.
> sortie.el uses sort orders (functions) as
> candidates.  keysee.el uses sortie.el to let you
> change how its candidate key descriptions are
> sorted.
>
> In the Commentary of sortie there's a simple
> example of using the features it provides.
> Here's most of that example:
>
> (defun my-completion-with-sort-cycling ()
>   "Read and echo choice using completion with sort-order cycling."
>   (interactive)
>   (minibuffer-with-setup-hook #'sorti-bind-cycle-key
>     (let ((sorti-current-order          'order1)
>           (sorti-sort-function-chooser  'my-sort-fn-chooser)
>           (sorti-sort-orders-alist      '((order1 . "alphabetical")
>                                           (order2 . "by length")))
>           (sorti-sort-orders-ring       (let ((rng  (make-ring 4)))
>                                           (ring-insert rng 'order1)
>                                           (ring-insert rng 'order2)
>                                           rng)))
>       (message "RESULT: %S"
>                (completing-read "fff: "
>                                 (my-collection-fn
>                                  '("aa" "bb" "ab" "aaff" "c")))))))
>
> (defun my-collection-fn (candidates)
>   "Collection function that provides metadata for sorting.
> Sorting is per the current value of `my-sort-fn-chooser'."
>   (lambda (string pred action)
>     (if (eq action 'metadata)
>         (let ((order  (my-sort-fn-chooser)))
>           `(metadata ,@(and order
>                             `((display-sort-function . ,order)
>                               (cycle-sort-function   . ,order)))))
>       (complete-with-action action candidates string pred))))
>
> (defun my-sort-fn-chooser ()
>   "Return sort function for current value of `sorti-current-order'."
>   (if (eq 'order2 sorti-current-order)
>       'my-sort-by-length
>     'my-sort-alphabetically))
>
> So for example, with both sortie.el and keysee.el
> loaded, if you turn on mode `kc-mode' then
>
> * `S-TAB' shows currently available key bindings.
> * `C-,' re-sorts them in a few different ways
>   (for both *Completions* display and cycling).
>   You cycle among the available sort orders, to
>   choose one, with `completing-read'.
> * `TAB' cycles among the key bindings, to choose
>   one, with `completing-read'.
> ___
>
> As I say, I don't know how others make use of the
> vanilla cycling feature.  Maybe Emacs provides a
> key for such cycling by default, but I doubt it.
>
> I think you have to define the cycling yourself,
> by defining a function (such as `my-collection-fn'
> above) that dynamically sorts the candidates to
> produce a COLLECTION that's sorted as desired.
>
> But is it really needed - by default, i.e., in
> general - to be able to cycle among all candidates
> in COLLECTION?  Certainly some libraries, such as
> Icicles, offer that, but it's not as if it's so
> essential that vanilla Emacs should provide it by
> default, I think.  It makes sense to give coders
> ways to provide candidate cycling when they want
> it for `completing-read'.
>
> My main point was that IF any such cycling of
> COLLECTION entries is provided, it need not, and
> should NOT, be part of the history (future or not).
> Leave the history cycling to minibuffer input
> HISTORY and to DEFAULTS.  If you want cycling of
> all candidates in COLLECTION then provide that as
> a different kind of cycling (different key).

I would agree with such evaluation.  One should enter COLLECTION
and then instruct the function how to use it.

> > Then maybe this cycling could be used instead of 'M-n'.
>
> No, not in my opinion; not at all.
>
> `M-n' should be only for cycling forward in the
> history, just as `M-p' should be for cycling
> backward.  Users should know that that's what's
> being cycled, and that those things are NOT, in
> general, candidates from COLLECTION.  (Think lax
> completion.)
>
> The "feature" of unequivocally adding COLLECTION
> to the history mixes things that don't belong
> together.  It doesn't help users, IMO; and it can
> confuse them, by mixing carrots with car parts.
>
> My call is to first-and-foremost give control to
> (1) users interactively and (2) coders who call
> `completing-read'.
>
> We already have a way for any coder to add all of
> COLLECTION to the "future history": use it as, or
> include it in, the value of argument DEFAULTS.
> _End of story._
>
> That gives coders 100% control over such addition.
> It's not blindly imposed on them.  And it's easy
> to obtain when/if they want it.  Easy peasy.  They
> already have COLLECTION - just pass it also as arg
> DEFAULTS (or part of DEFAULTS).
>
> Arg DEFAULTS should, _alone_, determine/define the
> "future history".  You can do anything you want
> with it, including get the current behavior that
> gets imposed unilaterally.  But you need not live
> with that imposition.
>
> Do I want to argue this in emacs-devel?  Not really.
> I really don't have time for such things these days.
>
> But do I wish something were done to remove this
> imposition and give control back to coders & users?
> Absolutely.  If this makes sense to you, go for it.
>
> And I think it's simple to do: (1) Stop filling
> future history with COLLECTION, or at least provide
> a simple means to stop that.  (2) Point out to users
> that IF they want to for some reason (the "many" use
> cases Eli hinted at), they can simply include all of
> COLLECTION as, or in, the future history, by just
> passing it as (or as part of) the list arg DEFAULTS.
>
> What's more, they can sort it first, any way they
> like.  And they can filter it, if they don't want to
> include _all_ of COLLECTION.  The current "feature"
> is brutal - it's a one-size-fits-none, IMO.  It was
> never needed (DEFAULT suffices), and it can't be
> turned off.
>
> #2 is maybe not obvious, even though it has been
> available since Day One.  If it were really so
> useful in "many" situations then I think we would
> have seen "many" users pass COLLECTION also as
> DEFAULTS (e.g. before Emacs 23).  I seriously doubt
> we'v seen many - maybe not even any.
>
> Yet someone thought it was a great idea to impose
> that behavior always, on everyone - every call to
> `completing-read' that uses an explicit COLLECTION.
> Dunno who did that, and as Eli says, apparently it
> was done in Emacs 23.  I guess many of us just
> never noticed it.
>
> BTW, what about a COLLECTION that's not explicit,
> that's realized bit by bit with a function?  That
> doesn't work anyway for this "feature", I guess.
> You need to manifest an explicit COLLECTION, in
> order to add it to any history (history needs to
> be manifest for the call to `completing-read').
>
> (I guess if you know the candidate domain you can
> use `all-completions' with a function COLLECTION
> to get an explicit version, if you really need to
> add it to the future history.)
>
> HTH.  And BTW, thanks, Juri, for enhancing DEFAULT
> to be able to be a list (long ago).
> ___
>
> https://www.emacswiki.org/emacs/download/sortie.el
>
> https://www.emacswiki.org/emacs/download/keysee.el
>
>
>
>
>
>