emacs-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Adding support for xref jumping to headers/interfaces


From: Dmitry Gutov
Subject: Re: Adding support for xref jumping to headers/interfaces
Date: Wed, 8 Nov 2023 01:17:59 +0200
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Thunderbird/102.13.0

On 07/11/2023 23:30, Eshel Yaron wrote:

Personally, I would prefer a `read-multiple-choice` alternative to
`completing-read` here, that would allow me to select the "kind" with a
single key press.  Since there are rarely more than a few kinds to
choose from, in many cases `completing-read` introduces unnecessary
friction.  Ideally, the backend should be able to choose whether to do a
`completing-read` or a "quick" `read-multiple-choice` on a case-by-case
basis.

People override completing-read using modes like
icomplete-vertical-mode, but there are no popular augmentations for
read-multiple-choice.

Sure, I also tweak and customize `completing-read`, and it's definitely
up for the task of selecting among a few candidates, but nevertheless I
think that `completing-read` is not the best tool for this job.  With
`read-multiple-choice` you make a selection with a single key, and you
don't need to press TAB to see which options are available--the prompt
tells you what each key does in case you don't know.  That's hard to
beat even with a highly optimized `completing-read` interface IME.

But for read-multiple-choice you have to move your eyes to the echo area, read the char->value mappings, choose one in your head, and type it. Typing the first 2-3 chars of the value you wanted without looking anywhere might take less time.

Also, sometimes the types will start with the same characters, and
sometimes not. Just using completing-read at least provides a stable
UI for all cases: if you remember the type, you can input the first
part of the name without thinking and press RET.

That's true, but to know which kinds are available you need to see the
list at least once, even if only to know how exactly the backend chose
to name these kinds (is it `defvar` or `variable`?).  Anyway, I don't
think this is such a crucial issue.  We can always add a
`read-multiple-choice` wrapper later, as long as the API permits it.

An advice binding completing-read to something using read-multiple-choice internally should do it. Or a user option, etc.

The backend can also associate stable `read-multiple-choice`
keys to the different kinds it support.  WDYT?

Perhaps you are instead thinking of a solution when there is a stable
keymap with known commands assigned to the same characters.

That could work too, perhaps, but what I meant is for the backend to
provide along with each kind the unique key that you press to select it.
So you always use the same key to the select the same kind with a given
backend, regardless of the set of kinds available for a specific identifier.

Imagine you are switching between different buffers using different languages. If the backends are different, your set of keys that could be used would have to be looked up every time, because the sets of values are different. That could even happen when using the same client, if e.g. Eglot should different kinds of different languages.

If, however, we managed to work out a fixed set of commands that cover 99% of the languages and assigned them to a map, old-style, that would make things more stable: at least the same char would always mean the same.

Just spitballing again, with a different take on the problem (a less flexible and extensible one).

To have something to test, I implemented this for Elisp. However, all
known kinds are already printed by the regular xref-find-definitions
output in that backend. So the result turned out interesting, but a
little impractical: with Elisp, we already make the choice between the
kinds in the Xref output buffer, when that buffer is shown at all (as
Eli pointed out, actually). So... we could proceed in that direction
and recommend that all kinds of definitions would be added there.
Yes, I've noticed that redundancy of sorts while testing this patch,
but I think that selecting the definition kind explicitly with this
new command still provides a distinct experience compared to the
`xref-find-definitions`.

Yes, but is it better? Does it bring much to the table? For Elisp, my
own answer is "probably not": all the kinds are available in
xref-find-definitions, and the selection UI is adequate already (isn't
it?)

I think that there's some benefit in being able to designate the kind of
definition you want in advance, especially if I already know which kind
I want.

It sometimes happens that the Elisp Xref backend guesses the "kind" automatically more correctly than I might (usually because of missing or extra parens), ultimately hinting at problems with code.

In the current state of affairs, I get all definitions and then
possibly skip one or two and get to select the one I wanted.  But I
don't know in advance if the one I want will come first, or last, so I
need to take a look at the results and respond accordingly.

Does that happen often? With which languages? Are there "kinds" that you more often would prefer not to see in the list?

That's indeed an added value IMO.  In that spirit, it might be better
for `xref-find-extra` to take the "kind" as an argument, so we can
define `xref-find-foo` as `(apply-partially #'xref-find-extra 'foo)`.
Interactively, `xref-find-extra` would still pick up the identifier
first and then prompt for the kind.

A helper for defining new commands is definitely doable. For that
route, though, I would like to ask whether we'll want to define any of
them inside core Xref. And if not, then where would those definitions
reside.


I would imagine that the backends should provide such commands in the
appropriate contexts, so maybe those definitions could reside alongside
the backend code?

Joao didn't want to have such definitions in Xref. I'm still on the fence, personally.

But these are two different/separate features:
- Add command that can ask you which kind you want, and show matches.
- Define different new commands, one for each "kind".

Also, for minor mode names, we currently suggest both "function" and
"variable" kinds, but they both point to the same `define-minor-mode`.
Ideally, we'd unify the two and simply suggest "minor-mode" as the
definition kind.

Also easy enough to do, e.g. by borrowing the solution from
elisp--xref-filter-definitions.

Still, though. It's not clear to me that improving this particular
feature for Elisp will bring a lot to the table.

Yes, the general API is probably more interesting to then the specifics
of the Elisp backend.

What I meant is, using it with the Elisp implementation didn't convince me of the usefulness of the feature. Perhaps you disagree?

Or it would be nice to hear from someone who have tried out Eglot's integration and found more upsides there.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]