emacs-lsp / lsp-mode

Emacs client/library for the Language Server Protocol
https://emacs-lsp.github.io/lsp-mode
GNU General Public License v3.0
4.75k stars 872 forks source link

Emacs lsp client for python ruff language server #3876

Closed vikigenius closed 1 year ago

vikigenius commented 1 year ago

So ruff is an extremely fast linter for python.

There already is a language server for python-ruff https://github.com/charliermarsh/ruff-lsp. This is similar in functionality to the eslint language server and would probably be used in conjunction with pylsp for completions similar to how eslint lsp is used alongside the ts language server.

Here is the relevant issue on the repository https://github.com/charliermarsh/ruff-lsp/issues/19

It would be great if we could have a client for ruff-lsp so that we can leverage the extremely fast linting.

rassie commented 1 year ago

I would like to invoke Cunningham's law and post the configuration I'm using (which doesn't work too well, but it does nevertheless):

(defcustom lsp-ruff-executable "ruff-lsp"
  "Command to start the Ruff language server."
  :group 'lsp-python
  :risky t
  :type 'file)

(lsp-register-client
 (make-lsp-client
  :new-connection (lsp-stdio-connection (lambda () (list lsp-ruff-executable)))
  :activation-fn (lsp-activate-on "python")
  :add-on? t
  :server-id 'ruff
  :initialization-options (lambda ()
                              (append (list :interpreter (list (concat poetry-project-venv "/bin/python3")))))))

I've tried to accomodate poetry support with the :interpreter initialization options, it's fairly obvious that it needs a proper fallback for non-poetry projects and probably quite a bunch more (global binaries, venv binaries etc.) But maybe someone who is more fluent in Elisp can create a proper configuration.

rassie commented 1 year ago

Thanks to @yyoncho, current version looks like this:

(defcustom lsp-ruff-executable "ruff-lsp"
  "Command to start the Ruff language server."
  :group 'lsp-python
  :risky t
  :type 'file)

;; Register ruff-lsp with the LSP client.
(lsp-register-client
    (make-lsp-client
        :new-connection (lsp-stdio-connection (lambda () (list lsp-ruff-executable)))
        :activation-fn (lsp-activate-on "python")
        :add-on? t
        :server-id 'ruff
        :initialization-options (lambda ()
                                    (list :settings
                                        (cl-list*
                                          (when
                                            poetry-project-venv
                                                (list
                                                :interpreter (vector (f-join (f-long poetry-project-venv) "bin" "python3"))
                                                :workspace (f-long poetry-project-venv)
                                                :path (vector (f-join (f-long poetry-project-venv) "bin" "ruff")))
                                                )
                                            ))
                                    )))

It seems to be working for me. Poetry is still not optional (i.e. poetry.el is still required), but doesn't stand in the way for non-Poetry projects.

ahonnecke commented 1 year ago

Does not seem to quire work for me, while it will autocomplete from a type, it won't autocomplete from an object /of a type/

image

rassie commented 1 year ago

@ahonnecke I'm pretty sure ruff-lsp is not supposed to be auto-completing, it's just a linter. It's also marked as complementary, i.e. you'd have multiple servers running at once, of which the other one is the one auto-completing. You might be running python-lsp-server or pyright or mspyls in parallel.

ahonnecke commented 1 year ago

@rassie Oh, apologies. Upon restarting and re-evaluating it does not seem to have negatively affected auto-completion.

It seems that there are two types of integration offered, one through flycheck https://github.com/flycheck/flycheck/issues/1974 and this implementation. I'm not really clear on what the respective benefits and drawbacks are.

If I can help get this to work with pipenv, or test anything let me know. thanks!

ahonnecke commented 1 year ago

@rassie I have 1) installed ruff-lsp with pip 2) evaluated the most recent config from above 3) executed +lsp/switch-client I'm not presented with ruff-lsp as an option, is that expected?

rassie commented 1 year ago

@ahonnecke That's a good question, I don't I can answer it fully (maybe @yyoncho can give a hint what might be missing). I'm a doom-emacs user and the combination of LSP configuration for Python in doom-emacs with the configuration in this issue is sufficient to have both servers (pylsp and ruff) enabled automatically for all Python buffers.

In regards to Flycheck integration: I'm using the lsp checker for Flycheck, which basically leans onto diagnostics provided by the server(s). For me, it's somewhat more efficient, since I can combine pylsp's diagnostics (syntax, type checking via mypy etc.) with ruff's diagnostics, which is essentially flake8 with extras. I'm not sure whether Flycheck can currently use multiple checkers at the same time.

frejanordsiek commented 1 year ago

I managed to get it working and managed to make a working client file based loosely off clients/lsp-pylsp.el as well as the other clients, with all of ruff-lsp's settings except showNotification (not sure what values are allowed besides "off").

I still need to write the documentation to go with it, but once I have it, I will be submitting a pull request.

frejanordsiek commented 1 year ago

I actually have a question about writing the documentation for it. docs/page doesn't have any of the markdown files for any of the clients in mkdocs.yml. Is this autogenerated or am I looking in the wrong place?

frejanordsiek commented 1 year ago

I sorted out the documentation I think, so I made a pull request. Unfortunately, it does not currently support poetry like the implementation written earlier by @rassie .

rassie commented 1 year ago

The newest version of ruff-lsp includes a patch which prioritizes ruff binaries in environments. If it works as desired, my Poetry addition should become unnecessary.

doolio commented 9 months ago

@frejanordsiek I don't use lsp-mode but wish to submit a PR to the ruff-lsp repo with setup instructions for Emacs. Am I correct in assuming one simply has to M-x lsp in a python buffer for this to work (assuming one has already installed ruff-lsp? Thanks for your time.

Edit: @yyoncho perhaps you can advise?

frejanordsiek commented 6 months ago

@frejanordsiek I don't use lsp-mode but wish to submit a PR to the ruff-lsp repo with setup instructions for Emacs. Am I correct in assuming one simply has to M-x lsp in a python buffer for this to work (assuming one has already installed ruff-lsp? Thanks for your time.

Edit: @yyoncho perhaps you can advise?

I think it is actually M-x lsp-mode, but can't check at the moment (I don't have lsp-mode installed at the moment to test).