Subject: Re: bug#62621: 29.0.60; uniquify can't make buffers unique based on things other than filename

From: Dmitry Gutov <[email-masked]>
Date: Wed, 19 Jul 2023 05:47:45 +0300

On 18/07/2023 19:03, Spencer Baugh wrote:

>> Speaking of those, do you think it would be feasible to also offer
>> these tweaks (as options, or for particular buffers):
>>
>> - Make the presence of the buffer name mandatory. As shown in the
>>    examples in bug#59502, it could be useful to always see in buffers
>>    like *eshell* produced by project-eshell. Or project-vc-dir, for
>>   example.
> 
> (I assume you mean "make the presence of the project name mandatory")

Ah yes, sorry.

> I think there is a good solution to this which was not mentioned in
> bug#59502 only add the project name (or dirname or whatever) to the
> buffer when that's necessary to give the buffer a unique name.> That
> reduces overhead when working only with one project, and neatly fits in
> to how uniquify already works for file-visiting buffers.

We never talked about such an option. It's a little less obvious, but 
might indeed fit in more smoothly for both project and non-project use 
cases (and I also often work on just one project).

Something to consider, though: if I am in a project A, and a project B 
has an eshell buffer and project A does not, 'C-x b' won't tell me that 
that eshell is in project B. But ideally, it should, I suppose.

This might have been the original reasoning to simply include the 
project name in those buffers' names.

> To do this, I think we'd need to change commands to use a function other
> than get-buffer-create when accessing e.g. *xref* or *eshell*, which
> like create-file-buffer gets a chance to uniquify the buffer name.
> 
> It's a bit tricky though: we want commands to access and reuse existing
> a project-specific buffer if there is one, but commands doesn't know the
> name of that buffer so can't find it that way.  find-file has solved
> this same problem ages ago, of reusing an existing buffer if we
> find-file a buffer-file-name which is already open.  I think we may need
> something similar for non-file-visiting buffers.
> 
> Maybe some kind of mechanism to find a buffer with basename "*eshell*"
> whose default-directory contains our current default-directory?  Kind of
> a "locate-dominating-buffer"?

Well... a straightforward way would be to have some public function in 
uniquify which, given a set of name components, would construct the 
supposed buffer name and see whether one exists. And/or return the 
newest one that matches (if there are several, sequentially enumerated). 
But I suppose uniquify doesn't have to be enabled in every session. So a 
higher-level function could be added to the core. It's hard to decouple 
this idea from using uniquify, though, so I'm not sure what we'd call 
it. Alternatively, we'd just check every time whether uniquify is on, 
and have two different code paths for yes and no.

>> - Hide the parent directory from the uniquification logic (only
>>    keeping the project name). So that, for example, if I call 'M-x
>>    project-eshell' and then 'C-u M-x project-eshell', the generated
>>    buffer names would not try to use the parent segment to uniquify,
>>    and just stay as <project-name>/*eshell* and
>>    <project-name>/*eshell-2*. There is currently some bespoke logic for
>>    naming these particular buffers, but if we could move to uniquify
>>    (and obey its custom vars), that would probably be an improvement.
> 
> Hm, so if two *eshell* buffers are in the same project, they should
> first be uniquified from other *eshell* buffers by adding the project
> name, and then uniquified from each other by adding numbers to the end
> of the buffer name.

I wonder how that's going to play with existing user expectations. Like, 
if there are no projects, then a regular parent directory name will be 
used, right? And currently eshell buffer names don't include that at 
all. But maybe they should?..

Anyway, if the new behavior is opt-in, there won't be a cause for complaint.

> I think I can implement this pretty easily in uniquify.el: if a set of
> conflicting buffers all have the same dirname, then resolve the conflict
> by adding numbers to the end.

Yes, I suppose if directory names are equal, it doesn't make sense to 
prepend further name components -- a number makes more sense.

> (Actually I was a bit surprised to realize that uniquify wasn't doing
> this already, but I guess it's because it previously has only worked for
> file-visiting buffers, which as I mentioned above are kept unique by
> buffer-file-name, so there can't be conflicts between two buffer names
> if you include their entire buffer-file-name in the buffer name.)

True enough.

> Incidentally, another feature which I've been thinking about at the
> intersection of project.el and uniquify.el: We could rerun uniquify on
> project-buffers in a mode where it just outputs sufficiently unique
> names without actually renaming the buffers, and then use that in
> project-switch-to-buffer.  So then when picking the buffer, you are
> picking from buffer names which are unique *in that specific project*.
> It's otherwise kind of annoying to me that project-switch-to-buffer
> includes a bunch of long disambiguating paths in the buffer names even
> though the buffer names aren't actually ambiguous in that command.
> 
> Does that sound interesting?  I, like you, usually use C-x b.  But I
> think this feature would make C-x p b much nicer and competitive with
> C-x b.

That does sound interesting! And actually, when initially reading a 
message from this thread, I thought it was about something like that.

It could be implemented by altering the buffers' completion table, I 
suppose. But I'm not sure how much of uniquify's code could be reused 
there. Or the performance characteristics of re-running uniquification 
every time a buffer name is read.