emacs-devel
[Top][All Lists]
Advanced

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

Re: Eglot, project.el, and python virtual environments


From: Eric Abrahamsen
Subject: Re: Eglot, project.el, and python virtual environments
Date: Sun, 20 Nov 2022 23:54:21 -0800
User-agent: Gnus/5.13 (Gnus v5.13)

João Távora <joaotavora@gmail.com> writes:

> Danny Freeman <danny@dfreeman.email> writes:
>
>> Dmitry Gutov <dgutov@yandex.ru> 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




reply via email to

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