5

GitHub - zbelial/lspce: LSP Client for Emacs implemented as a module using rust.

 1 year ago
source link: https://github.com/zbelial/lspce
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

LSPCE

Introduction

LSPCE - LSP Client for Emacs, is a simple lsp client that is implemented as an Emacs module.

It does not want to be a full-featured lsp client. The features it supports are:

  • find definitions/references/implementatoins (as a xref backend)
  • completion (as a capf function) support snippet and auto import.
  • diagnostics (as a flymake backend) process diagnostics when idle.
  • hover (triggered by lspce-help-at-point)
  • signature/hover help (as an eldoc-documentation-functions function)
  • code action (triggered by lspce-code-actions)
  • rename (triggered by lspce-rename )

All features I need have been implemented now, and my next step is to make it more robust and more performant.

I have tested LSPCE with `pyright` and `rust-analyzer` in Emacs 28, and I’m using it to develop itself :).

Below are some images to illustrate what LSPCE looks like.

Complete using company-capf.

images/completion.png

Use xref to find references.

images/references.png

Display signature and hover at the same time.

images/eldoc.png

CAUTION

I think that lspce is a good shape now, but bugs are expected.

I develop, test and run lspce with Emacs 28.2 on Linux (manjaro), and since I don’t have any Windows and MacOS computer, lspce may not work as expected. But @fast-90 tested it with pylsp on MacOS and found that it worked almost (except could not recognize virual env).

Dependencies

Lspce depends on f.el, yasnippet and markdown-mode. You should install them first.

Installation

At the moment, you can only install LSPCE by cloning this repo and compile rust code manually.

Installing from the Git Repository

Before installing LSPCE, you should install rust and cargo first.

$ git clone https://github.com/zbelial/lspce.git ~/.emacs.d/site-lisp/lspce
$ cd ~/.emacs.d/site-lisp/lspce
$ cargo build
# or, to build a release version
$ cargo build --release
# then you should rename the .so file (and copy it to another directory )
$ mv target/debug/liblspce_module.so lspce-module.so 
# or alternatively, if .d and .dylib files are created for you: (thanks @fast-90 for this)
$ mv target/debug/liblspce_module.d lspce-module.d
$ mv target/debug/liblspce_module.dylib lspce-module.dylib

Get started

(use-package lspce
  :load-path "/path/to/lspce"
  :config (progn
            (setq lspce-send-changes-idle-time 1)

            ;; You should call this first if you want lspce to write logs
            (lspce-set-log-file "/tmp/lspce.log")

            ;; By default, lspce will not write log out to anywhere. 
            ;; To enable logging, you can add the following line
            ;; (lspce-enable-logging)
            ;; You can enable/disable logging on the fly by calling `lspce-enable-logging' or `lspce-disable-logging'.

            ;; enable lspce in particular buffers
            ;; (add-hook 'rust-mode-hook 'lspce-mode)

            ;; modify `lspce-server-programs' to add or change a lsp server, see document
            ;; of `lspce-lsp-type-function' to understand how to get buffer's lsp type.
            ;; Bellow is what I use
            (setq lspce-server-programs `(("rust"  "rust-analyzer" "" lspce-ra-initializationOptions)
                                          ("python" "pylsp" "" )
                                          ("C" "clangd" "--all-scopes-completion --clang-tidy --enable-config --header-insertion-decorators=0")
                                          ("java" "java" lspce-jdtls-cmd-args lspce-jdtls-initializationOptions)
                                          ))
            )
  )

Architecture

images/Architecture_of_LSPCE.png

Some notes about the architecture:

  1. Every project is represented by a Project struct in LSPCE (aka the largest Box in the above image).
  2. LSPCE sends requests/notifications to LSP server(rust-analyzer, pyright, etc.) processes via a Transport.
  3. Responses/notifications/requests issued by LSP servers are sent to Transport and then dispatched into three different queues by Message Dispatcher. Note that diagnositcs are disptched into a separate queue, from where LSPCE reads them and shows them using flymake.
  4. After sending a request, LSPCE will read the response from the response queue in an interruptable way, so it won’t block Emacs.

TODOs

There are some bugs/issues that should be fixed. Here is the list:

  • renaming class name in Java won’t rename the file name (LSPCE does not support file rename/create/delete now)
  • support server request `workspace/configuration` I’ve decided not to support it, unless this makes it impossible to implement some necessary features/functions.
  • support workspaceFolders (or not, not decided yet)
  • new created files cannot be recognized by lsp server (workaround: revert it or close and then open it)
  • diagnostics does not work well, sometimes they won’t disappear.
  • completion has a little bug, where it may complete foo.bar to foo.barb when current text is foo.b
  • after editing pom.xml, jdt.ls cannot automatically update configuration(e.g. cannot find class from the new added jar)

Lspce vs Eglot/lsp-mode/lsp-bridge

lspce vs eglot

  • lspce has less chance to block user input or freeze Emacs
  • lspce supports multiple servers in a single project For projects containing, for example python files and rust files, lspce can start a pylsp server and a rust-analyzer server respectively. IIRC, eglot does not support this. Corret me if I’m wrong.
  • lspce’s code is easier to understand for elisp newbies like me. Lspce does not use cl-loop, pcase-xxx etc, which I think is not easy to understand.
  • lspce supports a smaller set of LSP features
  • lspce has only been tested with several lsp servers Eglot supports much more lsp servers than lspce
  • lower code quality I’ve heard several times that eglot has high code quality.
  • lspce does not support tramp

lspce vs lsp-mode

  • lspce has less chance to block user input or freeze Emacs
  • lspce’s code is easier to understand for elisp newbies like me. I tried to understand lsp-mode’s code but I failed. I really think lsp-mode’s code is hard to understand, but I’m absolutely not an elisp export at all.
  • lspce supports a much smaller set of LSP features
  • lspce has only been tested with several lsp servers lsp-mode supports much more lsp servers than lspce
  • lspce does not support running multiple servers in a single buffer
  • lspce does not support dap

lspce vs lsp-bridge

  • lspce is compatible with xre/capf/imenu etc.
  • lspce support a smaller set of LSP features
  • In theory, lspce is slower than lsp-bridge
  • lspce does not support running multiple servers in a single buffer
  • lsp-bridge has built-in remote editing support
  • lsp-bridge provides other completing backends

License

GPLv3

Acknowledgements

Thanks to emacs-module-rs, which makes implementing LSPCE possible.

Thanks to eglot and lsp-mode, I learned a lot about LSP from both of them during developing this package.

Thanks to lsp-server from rust-analyzer, I used a lot of code from it (and modified them a little to make it suitable for a client).


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK