Subject: RE: bug#1085: 23.0.60; all-completions, try-completion inconsistent: Info-read-node-name-1

From: "Drew Adams" <[email-masked]>
Date: Mon, 6 Oct 2008 09:47:03 -0700

> From: Stefan Monnier Sent: Monday, October 06, 2008 7:37 AM
> > It has been true in general. It has just been false for a 
> > few exceptions.
> 
> Different uses of "in general".

Yes. It is true almost all of the time, but not all of the time.

I think it is false for some cases where it could be made true.

> > I think it should be true always.
> 
> There are 2 different needs.  For the user's convenience, the
> *Completions* buffer should only list "foo for fot" rather than
> "/toto/foo /toto/for /toto/fot" and similarly for various other
> completion cases.

Agreed.

> Currently all-completions returns the first list and
> the `boundary' thingy can indicate that the missing prefix is 
> "/toto/".

In passing: The `boundary' thingy needs to be documented. It is not obvious how
to use it or how it works.

> You want to change that so that all-completions returns the 
> second list,

No, not necessarily. I only want `try-completion', `all-completions' and
`test-completion' to be on the same page, in the sense of the invariants I
mentioned.

I believe it should be possible for the functions that perform completion to
DTRT even for cases like file-name completion, so that the user's input
corresponds to the candidates in *Completions* and to `all-completions' and
`try-completion'.

I'm not sure how that should best be done, but I think it should be possible to
take care of the directory part without it becoming part of each completion
candidate. That's kind of what we do now anyway. Perhaps you have an idea about
how to do it?

> which still requires some way to figure out that the part that should be
> stripped from display is "/toto/". Efficiency and history are on the side
> of the current behavior.
> 
> > It should be possible to bring those exceptions into the fold.
> 
> For what benefit?

Consistency. Ability to manipulate or reason about completion code and treat it
in a general manner. See next. 

> >  One should be able to use `all-completions' to construct a cons
> >  completion table that is equivalent to the original TABLE argument,
> >  regardless of how TABLE is defined (e.g. function, obarray).
> 
> Use the `boundary' thingy.  And note that this is new in Emacs-23.
> In previous versions of Emacs there simply was no 
> standardized way to do that reliably.

Can you explain a bit how to do that?
Will that enable respect of the invariants I mentioned?

> >> In practice the main case where this "invariant" does not 
> >> hold is when the completion table is the one for file names,
> >> where all-completions returns names that do not "full" (i.e.
> >> do not include the directory name).
> 
> > Why shouldn't it be true in that case also? It isn't now, 
> > but it could be, could it not? File name completion could be made
> > to keep the same user behavior it has now and still respect the
> > invariants I mentioned.
> 
> Because the output of all-completions has historically been 
> used for the *Completions* output,

That's OK. What I'm thinking of is having both `all-completions' and
*Completions* display, say, relative file names, as now, and having
`try-completion' also use and return a relative file name, but have them all
somehow deal with the directory. The directory can be passed separately, no?

> so aesthetic and convenience may impose other constraints.

I'm not claiming a simple, immediate solution. I'm asking you to think about it.

> >> For code that needs to live with this problem (e.g. minibuffer.el),
> >> Emacs-23 introduces a new way to call the completion table 
> >> function with a `boundary' argument.
> 
> > Why should `Info-read-node-name-1' in particular "need to live with
> > this problem"?
> 
> Info-read-node-name-1 does not "live with this problem".  On the
> contrary it makes good use of this freedom.

I don't see it as such good use. To me it is a bug. I sent a fix.

> > Why shouldn't it return, for a CODE of t, a valid list
> > of completions satisfying the invariants I mentioned? Why not do
> > it right?
> 
> I don't know what you mean by "a CODE of t".

Argument `code' = t in the source code (and in the fix I sent).

> > Ideally (this part is for the wish list), we would provide 
> > completion not only for input such as `(ema', giving
> > all-completions `("(emacs)" "(emacs-mime)")', but also for
> > input such as `(emacs)Mac', giving all-completions
> > `("(emacs)Mac Directories" "(emacs)Mac Environment"...)'.
> 
> It's indeed on the wishlist.  I'm pretty sure there's a TODO 
> about it in the code.  But it has noting to do with the
> dicsussion at hand.

No, admittedly it is not directly related.

The question at hand is how to handle completion of just the Info file-name
part, e.g. `(emacs-mime)'. To me, the user's input should match what s?he sees
in *Completions* (with parens), and they should both reflect both
`all-completions' and `try-completion'.

> >                   (mapcar (lambda (file) (concat "(" file ")")) ctwc))
> 
> That's not correct when completing "(/usr/shar".

Is that possible? Could you elaborate? What should the code do here?

I don't claim that the fix I sent is 100%. It seems to DTRT, but it might
require some tweaking.

In any case, the `all-completions' part of the current code is currently broken
and requires some fix. It doesn't make sense for input of `(emacs)' with CODE =
t to return nil (no completions). `all-completions' should be able to return the
complete set of file-name completions in that case. IOW, (Info-read-node-name-1
"(emacs)" nil t) should not return nil, meaning no completions - it should
return the list of all completions, ("(emacs)"), just as (Info-read-node-name-1
"(emacs)" nil nil) returns "(emacs)".

> > I hope you'll reconsider the policy wrt support for the invariants
> > I suggested, instead of encouraging (yes) n'importe quoi.
> 
> I have banged my head against this problem for a long time, while
> working on the minibuffer.el code (and its predecessors), so I don't
> expect to change my mind any time soon.  The only thing you'd 
> accomplish with your proposal is "change", but it would just shift
> the problems from one place to another without any actual benefit.

Could you maybe explain some of your thoughts on it? Share some of your internal
head-banging behind the design and implementation? I don't doubt that you've
thought it over - how about sharing some of the thoughts and considerations?