From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: Jorgen Schaefer Newsgroups: gmane.emacs.devel Subject: Re: Generalizing find-definition Date: Mon, 3 Nov 2014 19:28:53 +0100 Message-ID: <20141103192853.2702fe7a@forcix> References: <20141102151524.0d9c665c@forcix> <20141102172944.0f7944e3@forcix> <20141103084433.12117c03@forcix> NNTP-Posting-Host: plane.gmane.org Mime-Version: 1.0 Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: 7bit X-Trace: ger.gmane.org 1415039358 657 80.91.229.3 (3 Nov 2014 18:29:18 GMT) X-Complaints-To: usenet@ger.gmane.org NNTP-Posting-Date: Mon, 3 Nov 2014 18:29:18 +0000 (UTC) Cc: emacs-devel@gnu.org To: Stefan Monnier Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Mon Nov 03 19:29:11 2014 Return-path: Envelope-to: ged-emacs-devel@m.gmane.org Original-Received: from lists.gnu.org ([208.118.235.17]) by plane.gmane.org with esmtp (Exim 4.69) (envelope-from ) id 1XlMNK-00018v-BB for ged-emacs-devel@m.gmane.org; Mon, 03 Nov 2014 19:29:10 +0100 Original-Received: from localhost ([::1]:36712 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1XlMNJ-0003SF-VI for ged-emacs-devel@m.gmane.org; Mon, 03 Nov 2014 13:29:09 -0500 Original-Received: from eggs.gnu.org ([2001:4830:134:3::10]:51674) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1XlMNC-0003Om-6r for emacs-devel@gnu.org; Mon, 03 Nov 2014 13:29:08 -0500 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1XlMN6-0002nM-9X for emacs-devel@gnu.org; Mon, 03 Nov 2014 13:29:02 -0500 Original-Received: from loki.jorgenschaefer.de ([87.230.15.51]:56444) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1XlMN6-0002n5-0L for emacs-devel@gnu.org; Mon, 03 Nov 2014 13:28:56 -0500 Original-Received: by loki.jorgenschaefer.de (Postfix, from userid 998) id B2A172045AD; Mon, 3 Nov 2014 19:28:54 +0100 (CET) Original-Received: from forcix (port-4853.pppoe.wtnet.de [84.46.19.8]) by loki.jorgenschaefer.de (Postfix) with ESMTPSA id D30822045A9; Mon, 3 Nov 2014 19:28:53 +0100 (CET) In-Reply-To: X-Mailer: Claws Mail 3.10.1 (GTK+ 2.24.25; i586-pc-linux-gnu) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x X-Received-From: 87.230.15.51 X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Original-Sender: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Xref: news.gmane.org gmane.emacs.devel:176294 Archived-At: On Mon, 03 Nov 2014 09:30:56 -0500 Stefan Monnier 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 locations. 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 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. Regards, Jorgen