[Top][All Lists]

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

Re: Generalizing find-definition

From: Jorgen Schaefer
Subject: Re: Generalizing find-definition
Date: Mon, 3 Nov 2014 19:28:53 +0100

On Mon, 03 Nov 2014 09:30:56 -0500
Stefan Monnier <address@hidden> wrote:

> >> And on the backend side we have:
> >> - identifier-at-point-function
> > Why do we need this?
> I thought we already agreed that we need a language-aware way to
> determine what is the identifier at point (taking into account the
> current namespace/package/etc..).

For Python, there is nothing suitable for "identifier at point" that I
can return that would help find the definition, except "the whole
contents of the buffer, the file name, and the position of point within
the buffer".

To get the definition of something, I pass that - the full text, the
file name, and the position - to a Python library and get back a list of

There is no intermediate "get the identifier at point" step, because
that concept does not make sense here.

> >> Etags.el currently offers some additional functionality:
> >> - jump to definition of any identifier, with TAB-completion.
> > C-u M-. could call a separate function when set, which would be
> > provided by the mode author to prompt for an identifier (with tab
> > completion if possible) and goes to the definition of that symbol.
> Right.  I guess the prompting can be part of the generic code, and the
> completion-table can be provided by an appropriate foo-function set by
> the backend providing find-definition-function.

For Python, I do provide a tab-completable list of identifiers
(currently only for pydoc, but the code should be reusable for this),
but it is not a simple list of identifiers, but a tree. The tab
completion starts with top-level modules (like "json"), but when you
add a ".", it will continue to complete attributes of the module or
class etc.. Providing the full list of possible completions right
away would take a very long time. This kind of completion is tricky to
generalize, so if we want the user to be able to type a symbol, we
should allow the backend to override this. We can provide a simple
default for the trivial case, though.

So as I see it, `find-definition' would usually call the value of
`find-definition-function' with no arguments. If that function returns
an empty list, or if `find-definition' was called with a prefix
argument, it would use a function from the backend that prompts for
a symbol and pass the result of that to `find-definition-function'.

Alternatively, the backend simply provides one function that prompts
the user for an identifier and returns the list of uses instead of the
dance above.

> [ Side note: I expect that identifier-at-point-function would pretty
>   much always be provided by the major mode, but I expect that
>   find-definition-function (as well as the TAB-completion function)
>   will sometimes be provided by the major mode, and sometimes by
>   a mode-agnostic package (like etags.el).  ]

Or even a minor mode that provide extra functionality for a major mode -
Elpy is a minor mode which is active in Python mode buffers.

> For the first distinction, at the UI level we could do:
> - Specify the kind of use by the key-binding (M-. to find
>   definitions, M-? to find uses).  This doesn't work too well if there
>   are many more refinements.
> - Specify the kind of use via a minibuffer prompt.
>   E.g. C-u M-. would first prompt for an identifier (defaulting to the
>   one at point), and then prompt for the kind of use to look for.
> - Specify the use by filtering in the "found matches" buffer.
>   For "definition", this kind of sucks since in many cases there'd be
>   only one definition, but you'd first have to go through the complete
>   list displayed in a buffer, and then use some key-binding to filter
>   the sole definition out of that.
> - A mix of the above.  E.g. M-. searches only for one particular
> subset of uses (e.g. definitions and refinements), while M-? search
> for the complementary subset (or for all possible uses, including the
> ones already provided under M-.), and after M-? you can filter the
> results in the buffer.

This is getting extremely complex and I do not see how this would
benefit the user much. There are definitions of an identifier, and uses
of an identifier.

Typical IDEs make a distinction between these, too. For example,
Eclipse provides "go to definition or declaration" on F3 or <C-left> on
a symbol.

The *uses* of an identifier are quite tricky. IDEs provide various
tools for that, including various searches, call graphs, highlighting
occurences, etc.

There are usually very few definitions, and M-. should just go there.
The "find uses of the identifier at point" functionality seems quite
distinct from a user's point of view, so should be distinct in the user
interface, too.


reply via email to

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