From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail From: Eric Abrahamsen Newsgroups: gmane.emacs.devel Subject: Re: Eglot, project.el, and python virtual environments Date: Sun, 20 Nov 2022 23:54:21 -0800 Message-ID: <87bkp0vj2q.fsf@ericabrahamsen.net> References: <87zgcq68zp.fsf@ericabrahamsen.net> <878rkale3l.fsf@dfreeman.email> <4c5f4b07-3df6-d700-83f8-9a9d1b684afc@yandex.ru> <84781346-5b88-2be5-38bb-02696fcf1364@yandex.ru> <87o7t2vj19.fsf@dfreeman.email> <877czqtyfy.fsf@dfreeman.email> <87zgcml7g7.fsf@gmail.com> Mime-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable Injection-Info: ciao.gmane.io; posting-host="blaine.gmane.org:116.202.254.214"; logging-data="26897"; mail-complaints-to="usenet@ciao.gmane.io" User-Agent: Gnus/5.13 (Gnus v5.13) Cc: Danny Freeman , Dmitry Gutov , emacs-devel To: =?utf-8?B?Sm/Do28gVMOhdm9yYQ==?= Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane-mx.org@gnu.org Mon Nov 21 08:55:29 2022 Return-path: Envelope-to: ged-emacs-devel@m.gmane-mx.org Original-Received: from lists.gnu.org ([209.51.188.17]) by ciao.gmane.io with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1ox1eK-0006p4-NA for ged-emacs-devel@m.gmane-mx.org; Mon, 21 Nov 2022 08:55:28 +0100 Original-Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1ox1dZ-0001Gv-Pr; Mon, 21 Nov 2022 02:54:41 -0500 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1ox1dX-0001Gk-HM for emacs-devel@gnu.org; Mon, 21 Nov 2022 02:54:39 -0500 Original-Received: from mail.ericabrahamsen.net ([52.70.2.18]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1ox1dV-0006b2-Oh for emacs-devel@gnu.org; Mon, 21 Nov 2022 02:54:39 -0500 Original-Received: from localhost (c-71-197-232-41.hsd1.wa.comcast.net [71.197.232.41]) (Authenticated sender: eric@ericabrahamsen.net) by mail.ericabrahamsen.net (Postfix) with ESMTPSA id 326CFFA08F; Mon, 21 Nov 2022 07:54:28 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ericabrahamsen.net; s=mail; t=1669017269; bh=YWp+Apo+tRpni6gTc2J3hHlx1lhpHP149or6nb2dwFo=; h=From:To:Cc:Subject:In-Reply-To:References:Date:From; b=X8fZmtm1YdS6hslc8hcRrjLkm3ZztTsgs48EnIq2p5lGm20QmFsjB8ri5KAxXqKY4 5WGd0a9vMTHdUTsP0dwPusHB8zyn+YJGwBMIS+NemVSpbZNpLxgynNgczW9GmLyIJs eB7SWBg7hSpsy6vKcBCCYkBJoEcu7FYr5qUZdGks= In-Reply-To: <87zgcml7g7.fsf@gmail.com> (=?utf-8?Q?=22Jo=C3=A3o_T=C3=A1vor?= =?utf-8?Q?a=22's?= message of "Sun, 20 Nov 2022 01:51:04 +0000") Received-SPF: pass client-ip=52.70.2.18; envelope-from=eric@ericabrahamsen.net; helo=mail.ericabrahamsen.net X-Spam_score_int: -43 X-Spam_score: -4.4 X-Spam_bar: ---- X-Spam_report: (-4.4 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_MED=-2.3, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.29 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-mx.org@gnu.org Original-Sender: emacs-devel-bounces+ged-emacs-devel=m.gmane-mx.org@gnu.org Xref: news.gmane.io gmane.emacs.devel:300283 Archived-At: Jo=C3=A3o T=C3=A1vora writes: > Danny Freeman writes: > >> Dmitry Gutov writes: >> >>> Then your solution should work okay, but it also means it belongs >>> to the category of Eglot hacks (as >>> opposed to project.el hacks). >> >> It is absolutely an Eglot hack :) > > I don't consider this a hack at all. Not only does it work okay, it's > how supposed to work. [...] >> (defun eglot--find-lsp-root (dir) >> (when-let ((root (and eglot-root-marker >> eglot-lsp-context >> (locate-dominating-file dir eglot-root-marker)))) >> (cons 'transient root))) >> >> (add-hook 'project-find-functions #'eglot--find-lsp-root) > > > I think the code above is fine, but it belongs in the user's > configuration. In fact, it belongs in the manual, in a section similar > to what used to be section called "Handling Quirkly Servers" in the old > README. > > This code doesn't belong in Eglot. Eglot is designed as thin layer > making different Emacs facilities communicate with LSP servers. Eglot's > user interaction is mostly for LSP basics such as connect/disconnect and > Eglot's user preferences deal with LSP in its generality. Baking > project definition facilities into Eglot would bloat it and I don't want > that. > > Are we worried that users will find it hard to apply snippets such as > Danny's? My experience with libraries such as Yasnippet, SLY and Eglot > tells me otherwise: if robust simple Lisp snippets such as the one above > are easy to find, users have no trouble applying them. But if we really > must have a point-and-click interactive interface for programming-averse > programmers :-) , then we can also remember that Eglot is also an > Elisp-level API for major-modes to take advantage of. > > ... Which means that if the problem here is both LSP and Python-specific > a .venv specific version of the above snippet could well live in > python.el. >From the point of view of an end-consumer of all this, I agree that customization on my end is inevitable, and not a bad thing. I don't expect that an automatic solution to Python virtual envs, in particular, will ever be found: they are a mess, and there are several packages in ELPA/MELPA just for dealing with them. I spent some time looking at eglot.el and project.el, and was mostly surprised to find how little they need to know about each other. Really, Eglot only uses projects very lightly, to group managed buffers together under one `eglot-lsp-server' instance (I don't know if the actual external processes need to know which/how many buffers they're involved with). Other than that, it doesn't seem to matter at all that project.el and eglot.el might have different opinions about what project any given file buffer might belong to. So yes, Danny's "hack" seems quite sufficient. The only remaining question is finding the right LSP executable. In my Python venv case, that's done by using one of the aforementioned packages -- there's no guarantee that the virtual environment will be under "./.venv", it could be somewhere else entirely. The packages generally work by hacking exec-path, so that Eglot's `executable-find' call finds the right Python LSP executable. A little care needs to be taken that the environment is "activated" before the call to `eglot', but it's not that tricky. I don't think anything more should be done to help with this particular Python case (besides some documentation). But maybe something could be done for finding LSP executables in the more general case. I can imagine that for saner languages, simply customizing a different executable path (perhaps passing it different command-line arguments) would be sufficient. All I could think of was the possibility that the project structure returned by our custom project-finding function could contain information about the LSP executable. So instead of just (cons 'transient dir) We could return something like (cons 'transient dir 'eglot-lsp-program-overrides '((python-mode . ("~/proj/.venv/bin/python/pylsp")))) Where the provided sexp is used as a mask on `eglot-server-programs'. project.el is pretty vague about the structure of a project, so it's hard to know exactly how that value should be injected. But with this setup the user could either use 'transient directly, or first call some other project-finding function, and then figure out how to stick this information in there in a useful way. Then `eglot--guess-contact' could check for it there. Just a suggestion! Thanks to all for the discussion, Eric