Subject: Re: bug#77312: [PATCH] Add uniquify-get-unique-names

From: Spencer Baugh <[email-masked]>
Date: Tue, 10 Jun 2025 11:05:06 -0400

Daniel Mendler <[email-masked]> writes:

> Dmitry Gutov <[email-masked]> writes:
>
>> Hey Daniel!
>>
>> On 07/06/2025 11:11, Daniel Mendler wrote:
>>> Would it be possible to attach the buffer object or the original buffer
>>> name to the completion candidate string as text property? This would
>>> make it possible to attach annotations via Marginalia or to execute
>>> buffer actions via Embark. Otherwise I don't see a possibility to access
>>> the original buffer, since they are only present in the `unique-names`
>>> alist local variable.
>>
>> That makes sense. Just call the property 'buffer'?
>
> That would work. I prefer a more specific property name to ease
> grepping/debugging. Also see below regarding the consing.
>
>> I wonder if it would make sense to alter the calling convention for
>> uniquify-get-unique-names itself to return a list of propertized strings
>> instead. project--read-project-buffer can do the conversion (copy each string
>> and attach the property), but it's just extra consing.
>
> I haven't checked if the current function is already working hard to
> avoid unnecessary allocations. If yes, it would be wasteful to add extra
> string allocations.
>
> In order to avoid them, we could only attach the property if the buffer
> name has really changed, such that no strings have to be copied. The
> property could be called `uniquify-orig-buffer-name`. If the property is
> present, it holds the original buffer name, if it is not present the
> string itself is the original buffer name.

All else being equal, I think changing uniquify-get-unique-names to
return a list of strings which have the original buffer names as a
property is a reasonable and easy thing to do.  uniquify.el is generally
pretty allocation heavy, so I wouldn't worry about the excess
allocations, just stick the property on all the returned strings.

Also, some future work I was considering, which I hope we can
accomodate: making this be internal functionality of read-buffer.  That
is, when read-buffer is passed a predicate, it could:
- use the predicate to filter the buffers
- then use uniquify-get-unique-names to get less-verbose buffer names
- then call completing-read with those buffer names
I think the text property approach would indeed work with this, but just
mentioning it.

Some unnecessary speculation about alternatives to the text property
approach follows:

One alternative to the text property approach is to have the alist
returned by uniquify-get-unique-names be let-bound in some special
variable around the call to completing-read.  Then Embark/Marginalia
could look up strings in that alist to figure out the underlying buffer
that a string is referring to.

Or, we could have a completion table action (ACTION='get-buffer or
something) which ignores PRED and returns the buffer corresponding to
the passed in STRING.  No new special variables at all.

I am reminded of the perennial discussions about how completing-read is
an API for "read string with completion", not "select a value by its
string name from a set of possible values", maybe this would be useful
for that...)

>> Unless some more new callers are going to prefer the current convention.
>
> Both would be fine for me. Generally I think it is nice to push
> functionality to the lower level API, as long as the functionality is
> generic enough.
>
> Btw, would you be interested in having `uniquify-get-unique-names' in
> Compat, such that you avoid the fboundp check? project.el would have to
> depend on Compat for that, but that's essentially free on Emacs 30 and
> newer.

I think adding uniquify-get-unique-names to compat might be difficult
because it depends on non-trivial changes to the rest of the code in
uniquify.el.