Giter Site home page Giter Site logo

lsp-bridge's Introduction


InstallationSupport languagesKeymapsCustomize optionsJoin development

lsp-bridge

The goal of lsp-bridge is use multi-thread technology to implement the fastest LSP client in the Emacs ecosystem.

Advantages of lsp-bridge:

  1. Blazingly fast: Offload LSP request and data analysis to an external process, preventing Emacs from getting stuck due to delays or large data triggering garbage collection
  2. Remote Completion: Built-in support for remote server code completion, with various login methods such as passwords and public keys, supports tramp protocol and jump server
  3. Out of the box: Ready to use immediately after installation, no additional configuration required, no need to tweak with completion frontend, completion backend and multi-backend mix
  4. Multi-server fusion: A simple JSON is all you need to combine multiple LSP Servers into one file that provides services for example Python which offers code completion with Pyright and diagnostic and formatting capabilities with Ruff
  5. Flexible Customization: Customizing LSP server options is as simple as using a JSON file, allowing different projects to have different JSON configurations with just a few lines of rules

The video explains the principle of lsp-bridge

EmacsConf 2022 talk page

Installation

  1. Install Emacs 28 or higher version

  2. Install Python dependencies: pip3 install epc orjson sexpdata six setuptools paramiko rapidfuzz (orjson is optional, orjson is based on Rust, providing faster JSON parsing performance)

  3. Install Elisp dependencies: markdown-mode, yasnippet

  4. Download this repository using git clone, and replace the load-path path in the configuration below.

  5. Add the following code to your configuration file ~/.emacs:

(add-to-list 'load-path "<path-to-lsp-bridge>")

(require 'yasnippet)
(yas-global-mode 1)

(require 'lsp-bridge)
(global-lsp-bridge-mode)

To use terminal mode, please install acm-terminal. However, it's essential to note that acm-terminal may potentially cause compatibility issues due to modifications made to the acm.el code by me. Should such an occurrence arise, you can report any problems as an issue in the repository of acm-terminal, as its creator is a highly skilled developer who will swiftly address any compatibility issues.

  • If you are using straight to install, you should use the following configuration to install:
(use-package lsp-bridge
  :straight '(lsp-bridge :type git :host github :repo "manateelazycat/lsp-bridge"
            :files (:defaults "*.el" "*.py" "acm" "core" "langserver" "multiserver" "resources")
            :build (:not compile))
  :init
  (global-lsp-bridge-mode))
  • If you are using doom-emacs

add this to your packages.el

(when (package! lsp-bridge
        :recipe (:host github
                 :repo "manateelazycat/lsp-bridge"
                 :branch "master"
                 :files ("*.el" "*.py" "acm" "core" "langserver" "multiserver" "resources")
                 ;; do not perform byte compilation or native compilation for lsp-bridge
                 :build (:not compile)))
  (package! markdown-mode)
  (package! yasnippet))

and add this to your config.el

(use-package! lsp-bridge
  :config
  (setq lsp-bridge-enable-log nil)
  (global-lsp-bridge-mode))

and run doom sync to install it.

If you are unable to use normally after installing it, please read Report bug first

Please note:

  1. When using lsp-bridge, please first disable other completion plugins, such as lsp-mode, eglot, company, corfu, etc. lsp-bridge provides a complete solution from the completion backend, completion frontend to multi-backend integration
  2. In addition to providing LSP completion, lsp-bridge also provides many non-LSP completion backends, including file words, paths, Yas/Tempel, TabNine, Codeium, Copilot, Citre, Tailwind, Ctags, Org roam and other completion backends. If you expect to provide these completions in a certain mode, please add the corresponding mode to lsp-bridge-default-mode-hooks
  3. Please do not perform byte compilation or native compilation for lsp-bridge as it will result in a difference in API and the latest version after upgrading compiling afterwards, Lsp-bridge is designed with multi-threading that does not require compilation to speed it up

Local Usage

Lsp-bridge works out of the box. After installing the corresponding LSP server and mode plugin for the language, you can start coding directly without any additional settings.

It should be noted that lsp-bridge has three scanning modes:

  1. Determine the project's root directory by searching upward for a .git or .dir-locals.el file, thereby providing completion for the entire project directory.
  2. If a .git or .dir-locals.el file is not found, lsp-bridge will only provide single file completion for the opened file.
  3. You can also tell lsp-bridge the root directory of the project by customizing the lsp-bridge-get-project-path-by-filepath function. This function takes the path string of the opened file as the input parameter and outputs the project directory path.

Remote Usage

lsp-bridge can perform code syntax completion on files on a remote server, similar to VSCode. The configuration steps are as follows:

  1. Install lsp-bridge and the corresponding LSP Server on the remote server.
  2. Start lsp-bridge: python3 lsp-bridge/lsp_bridge.py.
  3. Use the lsp-bridge-open-remote-file command to open files, entering the username, IP, SSH port (default 22), and path, such as user@ip:[ssh_port]:/path/file
  4. Enabling the lsp-bridge-enable-with-tramp option allows direct opening of tramp files, using the efficient algorithm of lsp-bridge instead of tramp, achieving smooth completion. If the host in tramp is defined in ~/.ssh/config, lsp-bridge can synchronize the following options for remote connection:
    • HostName (must be in IP format, domain format may cause issues)
    • User
    • Port
    • GSSAPIAuthentication
    • ProxyCommand (currently only supports ProxyCommand option, does not support ProxyJump option)
  5. (setq lsp-bridge-remote-start-automatically t) can automatically start the lsp_bridge.py process on the remote host (which needs to support bash) when opening a tramp file, and it will also automatically close the process when quitting emacs. When using this feature, the following options need to be correctly set:
    • lsp-bridge-remote-python-command: the name of the python command on the remote host
    • lsp-bridge-remote-python-file: the full path of lsp_bridge.py on the remote host
    • lsp-bridge-remote-log: the full path for log output of lsp_bridge.py on the remote host

Principle of remote completion:

  1. Log in to the server with SSH authentication, access and edit files.
  2. When editing a replica of a remote file, real-time diff sequences will be sent to lsp-bridge, and the server side will use these sequences to rebuild the file and calculate the completion data by the remote LSP Server.
  3. The remote LSP Server will send back the completion data to the local side, and Emacs will display the completion menu.

Note:

  1. If the completion menu is not displayed, check the output of lsp_bridge.py on the remote server, it may be that the LSP Server is not fully installed.
  2. lsp-bridge will use the first *.pub file in ~/.ssh as a login credential. If public key login fails, you will be asked to enter a password. lsp-bridge will not store the password, it is recommended to use public key login to avoid repeated password entry.
  3. To run lsp_bridge.py successfully you need to completely download the entire git repository of lsp-bridge on a remote server, and switch into its directory, lsp_bridge.py requires other files to function properly, so copying only the lsp_bridge.py file can't work
  4. If a tramp file encounters an lsp-bridge connection error, you can execute the lsp-bridge-tramp-show-hostnames function and then check if the output of the host configuration options meets expectations

Keymap

Key Command Description
Alt + n acm-select-next Select next candidate
Down acm-select-next Select next candidate
Alt + p acm-select-prev Select previous candidate
Up acm-select-prev Select previous candidate
Alt + , acm-select-last Select last candidate
Alt + . acm-select-first Select first candidate
Ctrl + v acm-select-next-page Select next page candidate
Alt + v acm-select-prev-page Select previous page candidate
Ctrl + m acm-complete Complete completion
Return acm-complete Complete completion
Tab acm-complete Complete completion
Alt + h acm-complete Complete completion
Alt + H acm-insert-common Insert common part of candidates
Alt + u acm-filter Performing second-level filtering on candidate words, similar to the fuzzy search feature in other auto-complete frontends
Alt + d acm-doc-toggle Enable or disable candidate documentation
Alt + j acm-doc-scroll-up Scroll up candidate documentation
Alt + k acm-doc-scroll-down Scroll down candidate documentation
Alt + l acm-hide Hide completion menu
Ctrl + g acm-hide Hide completion menu
Alt + Number acm-complete-quick-access Selecting candidate quickly, need to enable acm-enable-quick-access first
Number acm-complete-quick-access Selecting candidate (even more) quickly, need both acm-enable-quick-access and acm-quick-access-use-number-select enabled

Commands

  • lsp-bridge-find-def: jump to the definition
  • lsp-bridge-find-def-other-window: jump to the definition in other-window
  • lsp-bridge-find-def-return: return to the location before calling lsp-bridge-find-def
  • lsp-bridge-find-type-def: Jump to the position of type definition.
  • lsp-bridge-find-type-def-other-window: Jump to the position of type definition in another window.
  • lsp-bridge-find-impl: jump to the implementation
  • lsp-bridge-find-impl-other-window: jump to the implementation in other-window
  • lsp-bridge-find-references: traverse across code references (forked from color-rg.el)
  • lsp-bridge-popup-documentation: lookup documentation of symbol under the cursor
  • lsp-bridge-popup-documentation-scroll-up: scroll up popup document.
  • lsp-bridge-popup-documentation-scroll-down: scroll down popup document.
  • lsp-bridge-show-documentation: lookup documentation of symbol under the cursor, but using a buffer instead
  • lsp-bridge-rename: rename symbol under the cursor
  • lsp-bridge-diagnostic-jump-next: Jump to the next diagnostic position
  • lsp-bridge-diagnostic-jump-prev: Jump to the previous diagnostic position
  • lsp-bridge-diagnostic-list: List all diagnostic information
  • lsp-bridge-diagnostic-copy: Copy the current diagnostic information to the clipboard
  • lsp-bridge-code-action: Popup code action menu, you can pass special actin-kind to fix, action-kind can use one of "quickfix", "refactor", "refactor.extract", "refactor.inline", "refactor.rewrite", "source", "source.organizeImports", "source.fixAll"
  • lsp-bridge-workspace-list-symbol-at-point: Finds the definition of a symbol at the cursor point
  • lsp-bridge-workspace-list-symbols: List all symbols in workspace and jump to the symbol definition
  • lsp-bridge-signature-help-fetch: show signature help in minibuffer manually (move cursor to parameters area will show signature help automatically)
  • lsp-bridge-popup-complete-menu: Manually popup the completion menu, you only need this command when turn on option lsp-bridge-complete-manually
  • lsp-bridge-restart-process: restart lsp-bridge process (only used for development)
  • lsp-bridge-toggle-sdcv-helper: Switch dictionary completion assistant
  • lsp-bridge-peek-abort: Close peek window (default binding to C-g)
  • lsp-bridge-peek-list-next-line: Select the next definition or reference (default binding to M-S-n)
  • lsp-bridge-peek-list-prev-line: Select the previous definition or reference (default binding to M-S-p)
  • lsp-bridge-peek-file-content-next-line: Scroll down one line in the peek window file content (default binding to M-n)
  • lsp-bridge-peek-file-content-prev-line: Scroll up one line in the peek window file content (default binding to M-p)
  • lsp-bridge-peek-jump: Jump to the location of the definition or reference (default binding to M-l j)
  • lsp-bridge-peek-jump-back: Jump back to the original position (default bound to M-l b)
  • lsp-bridge-peek-through: View one symbol in the peek window
  • lsp-bridge-peek-tree-previous-branch: Select the previous branch at the same level in the browsing history (default binding to <up>)
  • lsp-bridge-peek-tree-next-branch: Select the next branch at the same level in the browsing history (default binding to <down>)
  • lsp-bridge-peek-tree-previous-node: Select the previous higher-level node in the browsing history (default binding to <left>)
  • lsp-bridge-peek-tree-next-node: Select the next lower-level node in the browsing history (default binding to <right>)
  • lsp-bridge-indent-left: Indents the pasted text to the left according to the indent values defined in lsp-bridge-formatting-indent-alist
  • lsp-bridge-indent-right: Indents the pasted text to the right according to the indent values defined in lsp-bridge-formatting-indent-alist
  • lsp-bridge-semantic-tokens-mode: Enables or disables semantic token highlighting, please ref to Semantic Tokens Wiki

Customize language server configuration

The configuration for the LSP server of each language in lsp-bridge is stored in lsp-bridge/langserver.

In most cases, you can customize the server configuration according to the following priority order:

  1. lsp-bridge-get-single-lang-server-by-project: A user-defined function that takes project-path and file-path as input parameters and returns the corresponding LSP server string. You can query the names of all LSP servers in the lsp-bridge-single-lang-server-mode-list list. By default, this function returns nil.
  2. lsp-bridge-single-lang-server-extension-list: Returns the server based on the file extension, for example, when opening a *.wxml file, we will use the wxml LSP server for completion.
  3. lsp-bridge-single-lang-server-mode-list: Returns the corresponding server based on Emacs’s major-mode.

If you are writing JavaScript code, you may need to customize multiple server configurations:

  1. lsp-bridge-get-multi-lang-server-by-project: A user-defined function that takes project-path and file-path as input parameters and returns the multiple server configuration names. You can search for them in the subdirectory lsp-bridge/multiserver.
  2. lsp-bridge-multi-lang-server-extension-list: Returns multiple server configuration names based on the file extension. For example, when opening a *.vue file, we will use volar_emmet to simultaneously utilize volar and emmet-ls for completion.
  3. lsp-bridge-multi-lang-server-mode-list: Returns the corresponding multiple server configuration names based on Emacs’s major-mode.

For example, we can enable the Deno LSP server for Deno scripts with the following configuration:

(setq lsp-bridge-get-multi-lang-server-by-project
      (lambda (project-path filepath)
        ;; If typescript file include deno.land url, then use Deno LSP server.
        (save-excursion
          (when (string-equal (file-name-extension filepath) "ts")
            (dolist (buf (buffer-list))
              (when (string-equal (buffer-file-name buf) filepath)
                (with-current-buffer buf
                  (goto-char (point-min))
                  (when (search-forward-regexp (regexp-quote "from \"https://deno.land") nil t)
                    (return "deno")))))))))

Customize language server configuration file

Copy the configuration files in lsp-bridge/langserver or lsp-bridge/multiserver to lsp-bridge-user-langserver-dir or lsp-bridge-user-multiserver-dir for customization. Lsp-bridge will prioritize reading the configuration files in lsp-bridge-user-langserver-dir or lsp-bridge-user-multiserver-dir.

We can set the value of lsp-bridge-user-langserver-dir or lsp-bridge-user-multiserver-dir before starting lsp-bridge-mode to achieve different project-specific configuration files.

(defun enable-lsp-bridge()
  (when-let* ((project (project-current))
              (project-root (nth 2 project)))
    (setq-local lsp-bridge-user-langserver-dir project-root
                lsp-bridge-user-multiserver-dir project-root))
  (lsp-bridge-mode))

LSP server options

lsp-bridge provides support for more than two language servers for many languages. You can customize the following options to choose the language server you prefer:

  • lsp-bridge-c-lsp-server: C language server, you can choose clangd orccls
  • lsp-bridge-elixir-lsp-server: Elixir language server, you can choose elixirLS(default) orlexical
  • lsp-bridge-python-lsp-server: Python language server, you can choose pyright, jedi, python-ms, pylsp, ruff, it's important to note that lsp-bridge-multi-lang-server-mode-list has a higher priority than lsp-bridge-single-lang-server-mode-list. If you only want to use a single server, please first remove the python-mode setting from lsp-bridge-multi-lang-server-mode-list.
  • lsp-bridge-php-lsp-server: PHP language server, you can choose intelephense or phpactor
  • lsp-bridge-tex-lsp-server: LaTeX language server, you can choose texlab ordigestif
  • lsp-bridge-csharp-lsp-server: C# language server, you can choose omnisharp-mono oromnisharp-dotnet, note that you need to give execute permissions to the OmniSharp file
  • lsp-bridge-python-multi-lsp-server: Python multi-language servers, you can choose pyright_ruff, jedi_ruff, python-ms_ruff, pylsp_ruff
  • lsp-bridge-nix-lsp-server: Nix language server, you can choose rnix-lsp or nil
  • lsp-bridge-markdown-lsp-server: Markdown language server, you can choose vale-ls or nil

Options

  • lsp-bridge-python-command: The path of the python command, if you use conda, you may customize this option. Windows platform using python.exe rather than python3, if lsp-bridge can’t work, try set to python3
  • lsp-bridge-complete-manually: Only popup completion menu when user call lsp-bridge-popup-complete-menu command, default is nil
  • lsp-bridge-enable-with-tramp: When this option is enabled, lsp-bridge provides remote autocompletion support for files opened by tramp. It requires the lsp_bridge.py to be installed and started on the server side in advance. Note that this option only uses tramp to open files, it does not use tramp technology to implement autocompletion, because the implementation principle of tramp has serious performance issues. 'One should note that if you usually use the command lsp-bridge-open-remote-file, you need to disable the option lsp-bridge-enable-with-tramp to ensure that the file opened by the command can correctly jump to the definitions or references.
  • lsp-bridge-remote-save-password: Saves the password for remote editing to the netrc file, disabled by default
  • lsp-bridge-remote-heartbeat-interval: Interval for sending heartbeat to server in seconds, disabled by default, set it to a suitable value for your server sshd if you want to keep the connection alive after a long idle time.
  • lsp-bridge-get-workspace-folder: You need to put multiple project in a workspace directory in Java before you can jump function defintion normally. This function can be customized, the function input is the project path and returns the workspace directory corresponding
  • lsp-bridge-default-mode-hooks: The list of modes that automatically start lsp-bridge, you can customize this option to control the scope of starting lsp-bridge
  • lsp-bridge-org-babel-lang-list: list of language to support org-mode code block completion, nil enable all languages, default is nil
  • lsp-bridge-find-def-fallback-function: When LSP cannot find a definition, you can customize this function for candidate jumping, such as binding the citre function
  • lsp-bridge-find-ref-fallback-function: When LSP cannot find a reference, you can customize this function for candidate jumping, such as binding the citre function
  • lsp-bridge-find-def-select-in-open-windows: If this option is turned on, when searching for function definitions, already open windows will be selected instead of switching buffers. disable by default
  • lsp-bridge-enable-completion-in-string: Enable completion pop-up within strings, default is off
  • lsp-bridge-enable-completion-in-minibuffer: Enable pop-completion up in Minibuffer, disabled by default
  • lsp-bridge-enable-diagnostics: code diagnostic, enable by default
  • lsp-bridge-enable-inlay-hint: inlay hint, disable by default, this option is use for strong type language, such as, Rust
  • lsp-bridge-enable-hover-diagnostic: show diagnostic tooltip when cursor hover diagnostic place, disable by default
  • lsp-bridge-enable-search-words: index the word of the file, enable by default
  • lsp-bridge-enable-auto-format-code: automatic format code, disable by default
  • lsp-bridge-enable-signature-help: show function parameter in minibufer, enable by default
  • lsp-bridge-enable-log: enable LSP message log, disable by default, only enable this option for development purposes, usually do not turn on this option to avoid affecting performance
  • lsp-bridge-enable-debug: enable program debugging, disable by default
  • lsp-bridge-disable-backup: forbidden version manage of emacs, enable by default
  • lsp-bridge-code-action-enable-popup-menu: enable code action popup menu, enable by default
  • lsp-bridge-diagnostic-fetch-idle: diagnostic delay, start pulling diagnostic information 0.5 second after stopping typing
  • lsp-bridge-signature-show-function: The function used for displaying signature info, default show message in minibuffer, set lsp-bridge-signature-show-with-frame to show signature info in frame
  • lsp-bridge-signature-show-with-frame-position: When using lsp-bridge-signature-show-with-frame to display signature information, this option defines the position of the pop-up signature information, the default is "bottom-right", you can also choose "top-left", "top-right", "bottom-left", "point"
  • lsp-bridge-completion-popup-predicates: the predicate function for completion menu, completion menu popup after all the functions pass
  • lsp-bridge-completion-stop-commands: completion menu will not popup if these commands are executed
  • lsp-bridge-completion-hide-characters: The default value is ‘(":" ";" "(" ")" "[" "]" "{" "}" ", " "\""), the completion menu does not pop up when the cursor is behind these characters. You can customize this option to remove this restriction, or call the lsp-bridge-popup-complete-menu command to force the menu to pop up. To make this option works, you need to set lsp-bridge-completion-obey-trigger-characters-p to nil.
  • lsp-bridge-user-langserver-dir: the dir where user place langserver configuration file, if the configuration file name in the dir is the same as that in lsp-bridge/langserver , lsp-bridge will use the configuration file in this dir
  • lsp-bridge-user-multiserver-dir: the dir where user place multiserver configuration file, if the configuration file name in the dir is the same as that in lsp-bridge/multiserver , lsp-bridge will use the configuration file in this dir
  • lsp-bridge-symbols-enable-which-func: Using lsp backend for which-func, disable by default
  • lsp-bridge-enable-org-babel: Use lsp completion in org babel, disable by default
  • lsp-bridge-peek-file-content-height: Display how many lines of file content in peek windows
  • lsp-bridge-peek-file-content-scroll-margin: Set how many lines of file content should be scroll up and down.
  • lsp-bridge-peek-list-height: Select the next option for definition and reference
  • lsp-bridge-peek-ace-keys: Keys to press when performing lsp-bridge-peek-through
  • lsp-bridge-peek-ace-cancel-keys: Keys to exit lsp-bridge-peek-through
  • acm-frame-background-dark-color: Menu background color in dark theme
  • acm-frame-background-light-color: Menu background color in light theme
  • acm-enable-doc: Whether the complete menu display the help document
  • acm-enable-doc-markdown-render: Richly render Markdown for completion popups, you can choose 'async, t or nil. When set to 'async, styles are applied asynchronously, choose t, styles are applied synchronously and will slow down the completion speed, default is 'async
  • acm-enable-icon: Whether the completion menu displays icons (Many macOS users have reported that emacs-plus28 cannot display icons properly, showing colored squares instead. There are two ways to solve this: install Emacs Mac Port or add the --with-rsvg option to the brew command when compiling Emacs yourself)
  • acm-enable-tabnine: Enable tabnine support, enable by default, when enable need execute lsp-bridge-install-tabnine command to install TabNine, and it can be used. TabNine will consume huge CPUs, causing your entire computer to be slow. If the computer performance is not good, it is not recommended to enable this option
  • acm-enable-codeium: Enable Codeium support, when enable need execute lsp-bridge-install-update-codeium command to install Codeium, then execute lsp-bridge-codeium-auth command to get auth token and execute lsp-bridge-codeium-input-auth-token command to get API Key, and it can be used.
  • acm-enable-copilot: Enable copilot support, firstly, purchase the Copilot service by https://github.com/features/copilot , when enable need install agent first npm install -g copilot-node-server, then execute lsp-bridge-copilot-login, lsp-bridge will display User Code in the Minibuffer, copy the User Code to the opened Copilot page to complete the login.
  • acm-enable-search-file-words: Whether the complete menu display the word of the file, enable by default
  • acm-enable-quick-access: Whether to display an index after the icon, quickly select candidate words using Alt + Number, default is off
  • acm-quick-access-use-number-select: Whether to use number keys for quick selection of candidate words, default is off, turning on this option may sometimes interfere with number input or accidentally select candidate words
  • acm-enable-yas: yasnippet completion, enable by default
  • acm-enable-citre: Integration with citre(ctags). Enable this to add citre (ctags) backend (disabled by default)
  • acm-doc-frame-max-lines: Max line number of help documentation, default is 20
  • acm-candidate-match-function: The complete menu matching algorithm, the algorithm prefix of orderless-* needs to be installed additional orderless
  • acm-completion-backend-merge-order: Customize the order of the completion backends, default order is: first part of mode candidate, first part of template candidates, tabnine/copilot/codeium, second part of template candidates, second part of mode candidates, set acm-completion-mode-candidates-merge-order customize mode candidates order
  • acm-completion-mode-candidates-merge-order: Customize the order of the mode candidates, the display order for mode candidates, default order: Elisp、 LSP、 Jupyter、 Ctags、 Citre、 ROAM、 Word、 Telegra
  • acm-backend-lsp-candidate-min-length: The minimum characters to trigger lsp completion, default is 0
  • acm-backend-lsp-block-kind-list: Filters certain types of LSP completion candidates. By default, it's a empty list. When the value is set to '(Snippet Enum), this means that Snippet and Enum completions will not be shown.
  • acm-backend-elisp-candidate-min-length: The minimum characters to trigger elisp completion, default is 0
  • acm-backend-yas-candidate-min-length: The minimum characters to trigger yasnippet completion, default is 0
  • acm-backend-search-file-words-candidate-min-length: The minimum characters to trigger search file words completion, default is 0
  • acm-backend-search-file-words-max-number: Search Words completion candidate limit, default is 10
  • acm-backend-search-file-words-enable-fuzzy-match: Search Words completion candidate fuzzy match, disable by default
  • acm-backend-search-file-words-enable-fuzzy-match-threshold: Search Words completion candidate fuzzy match threshold, Filter out words with a ratio lower than the threshold, default is 50
  • acm-backend-codeium-candidate-min-length: The minimum characters to trigger codeium completion, default is 0
  • acm-backend-lsp-enable-auto-import: automatic insert import code, enable by default
  • acm-backend-lsp-candidate-max-length: Maximum length of LSP candidate, some language, such as Java, argument list is very long, you can increase the value of this option to see clear argument list
  • acm-backend-yas-candidates-number: yasnippet display number, 2 by default
  • acm-backend-citre-keyword-complete: Completion is performed according to the keywords of each mode defined by acm-backend-citre-keywords-alist, which takes effect only after citre is enabled.
  • acm-backend-search-sdcv-words-dictionary: StarDict dictionary for word completion, default is kdic-ec-11w, you can replace it with StarDict dictionary path, example, if you have dictionary /usr/share/stardict/dic/stardict-oxford-gb-formated-2.4.2/oxford-gb-formated.ifo, you need set this value to /usr/share/stardict/dic/stardict-oxford-gb-formated-2.4.2/oxford-gb-formated, not include .ifo extension.
  • acm-backend-lsp-match-mode: The filtering mode for candidates in LSP backend, there are three options: "prefix", "prefixCaseSensitive", and "fuzzy". By default it is "fuzzy"
  • acm-backend-lsp-show-progress: show working progress, disable by default
  • acm-enable-preview: enable Tab-and-Go completion, commands like acm-select-* will select and preview other candidate and further input will then commit this candidate, disable by default

Add support for new language?

  1. Create a configuration file in the lsp-bridge/langserver directory. For example, pyright.json is the configuration file for the pyright server (use pyright_windows.json for Windows and pyright_darwin.json for macOS).
  2. Add (mode . server_name) to the lsp-bridge-single-lang-server-mode-list option in the lsp-bridge.el file, for example, (python-mode . "pyright").
  3. Add a new mode-hook to the lsp-bridge-default-mode-hooks option in the lsp-bridge.el file.
  4. Add a new indentation variable to the lsp-bridge-formatting-indent-alist option in the lsp-bridge.el file.

We welcome patches to help us support more LSP servers. Thank you for your help!

Supported language servers

You need to install the LSP server corresponding to each programming language, then lsp-bridge can provide code completion service.

If your language supports mixed multi-language servers, it is recommended to check the multi-language server definition under multiserver, and install multiple LSP servers to get a more complete experience. For example, for the Python language, according to the default pyright-background-analysis_ruff.json definition, you should install pyright and ruff.

Language LSP Server Note
Ansible ansible-language-server Ansible uses YAML as source code, you’ll need to customize lsp-bridge-get-single-lang-server-by-project to return "ansible-language-server".
Astro astro npm i -g @astrojs/language-server
Bash bash-language-server
Beancount beancount-language-server cargo install beancount-language-server
Clojure clojure-lsp If you use homebrew , please ensure install clojure-lsp/brew/clojure-lsp-native clojure-lsp-native
Cmake cmake-language-server pip install cmake-language-server
CSS emmet-ls npm install -g emmet-ls
vscode-css-language-server npm i -g vscode-langservers-extracted
C# omnisharp-dotnet OmniSharp is a .NET development platform based on Roslyn workspaces. use M-x lsp-bridge-install-omnisharp to install it. lsp-bridge-csharp-lsp-server set to omnisharp-dotnet (6.0)
omnisharp-mono OmniSharp is a .NET development platform based on Roslyn workspaces. use M-x lsp-bridge-install-omnisharp to install it. lsp-bridge-csharp-lsp-server set to omnisharp-mono
C++ clangd You need to configure compile_commandsjson or CMakeListstxt files in root directory of project
ccls lsp-bridge-c-lsp-server set to ccls, you need to configure compile_commands.json first
C clangd You need to configure compile_commandsjson or CMakeListstxt files in root directory of project
ccls lsp-bridge-c-lsp-server set to ccls, you need to configure compile_commands.json first
D serve-d serve-d does not support single file mode, please init .git repository under project root at first or custom lsp-bridge-get-project-path-by-filepath function
Dart dart-analysis-server
Deno deno Deno runtime use TypeScript as source code, you need customize option lsp-bridge-get-single-lang-server-by-project that return result "deno" when project-path match Deno project.
Dockerfiles docker-language-server
Elixir elixirLS Please ensure that the elixir-ls release directory is in your system PATH at first
lexical Kindly make sure that the lexical release directory is included in your system’s PATH and that lexical has been compiled using the same version of Elixir/Erlang as your project.
Elm elm-language-server
Erlang erlang-ls
Fortran fortls
F# fsautocomplete
Go gopls Make sure install go-mode and gopls in PATH, please do ln -s ~/go/bin/gopls ~/.local/bin, and do go mod init first
GraphQL graphql-lsp
Groovy groovy-language-server Create a script "groovy-language-server" in PATH, with $JAVA_HOME/bin/java -jar <path>/groovy-language-server-all.jar
Haskell hls
HTML emmet-ls npm install -g emmet-ls
vscode-html-language-server npm i -g vscode-langservers-extracted
Java eclipse.jdt.ls Please ensure that org.eclipse.jdt.ls.product/target/repository/bin is in your system PATH at first, please see the details at Wiki
Javascript typescript
vscode-eslint-language-server npm i -g vscode-langservers-extracted
JSON vscode-json-language-server npm i -g vscode-langservers-extracted
Julia julials
Kotlin kotlin-language-server If you want Inlay Hints feature, you need build with source code to return Inlay Hint information
Latex digestif lsp-bridge-tex-lsp-server set to digestif
texlab lsp-bridge-tex-lsp-server set to texlab
LESS emmet-ls npm install -g emmet-ls
Lua sumneko Please ensure bin under sumneko installation is in your system PATH at first
Markdown vale-ls Install vale first, then use cargo build and install vale-ls from github, and make sure vale-ls in PATH
Mojo mojo modular install mojo-lsp-server
Move move-analyzer The move-analyzer is included in the move language repository
Nickel nls cargo add nickel-lang-lsp
Nix nil lsp-bridge-nix-lsp-server set to nil
rnix-lsp lsp-bridge-nix-lsp-server set to rnix-lsp
Object-C clangd You need to configure compile_commandsjson or CMakeListstxt files in root directory of project
ccls lsp-bridge-c-lsp-server set to ccls, you need to configure compile_commands.json first
Ocaml ocamllsp
Org-mode ds-pinyin cargo install ds-pinyin-lsp, download dict.db3 of ds-pinyin, and save to ~/.emacs.d/ds-pinyin/ directory, then turn on option lsp-bridge-use-ds-pinyin-in-org-mode
Wen pip install pygls pypinyin, then turn on option lsp-bridge-use-wenls-in-org-mode
PHP intelephense npm i intelephense -g
Phpactor lsp-bridge-php-lsp-server set to phpactor
Python jedi lsp-bridge-python-lsp-server set to jedi
pylsp lsp-bridge-python-lsp-server set to pylsp
pyright lsp-bridge-python-lsp-server set to pyright, pyright-background-analysis is faster sometimes, but it can’t response diagnostic informations
python-ms Legacy language server for Python2
ruff pip install ruff-lsp, lsp-bridge-python-lsp-server is set to ruff, which only has the function of linter. If you need to complete the functions, install other Python language servers, and set the lsp-bridge-python-multi-lsp-server to [LSP NAME]_ruff
QML qmlls The qmlls binary should be part of the normal Qt packages since Qt 6.3.0 Ensure that the directory of qmlls binary file is in PATH
R rlanguageserver
Racket racket-langserver
Ruby solargraph
Rust rust-analyzer
SASS emmet-ls npm install -g emmet-ls
Scala metals
SCSS emmet-ls npm install -g emmet-ls
Svelte svelte
Swift sourcekit-lsp The SourceKit-LSP server is included with the Swift toolchain.
Tailwindcss tailwindcss-language-server npm install -g @tailwindcss/language-server , and need config tailwind.config.js follow install manual
Typescript typescript
Typst typst-lsp
Verilog verible
VHDL vhdl-tool
Vue volar npm install -g typescript @vue/language-server
Wxml wxml-language-server
Yaml yaml-language-server npm install -g yaml-language-server
Zig zls Execute zls config to generate configuration for zls. see Configuration Options

Join development

The following is the framework of lsp-bridge:

The following is the directory structure of the lsp-bridge project:

Filename Purpose
lsp-bridge.el The main Elisp logic part of lsp-bridge, providing custom options and Elisp functions for the python subprocess, such as code jump, rename, etc.
lsp-bridge-epc.el Code for communicating with the lsp-bridge python subprocess, mainly implementing Elisp IPC to dock with Python EPC, realizing data serialization, sending, receiving, and deserialization
lsp-bridge-call-hierarchy.el Display the call order relationship of the code in the pop-up Frame
lsp-bridge-code-action.el Code related to code correction
lsp-bridge-diagnostic.el Diagnostic information related code
lsp-bridge-ref.el Code reference viewing framework, providing reference viewing, batch renaming, reference result regular filtering, etc., core code forked from color-rg.el
lsp-bridge-inlay-hint.el Provides code type hints, more useful for static languages, such as Rust or Haskell
lsp-bridge-jdtls.el Provides third-party library jump function for Java language
lsp-bridge-dart.el Provides support for Dart's private protocols, such as Dart's Closing Labels protocol
lsp-bridge-semantic-tokens.el Flexible display of certain semantic symbols is especially useful for static languages such as C or C++.
lsp-bridge-lsp-installer.el Install TabNine and Omnisharp
lsp-bridge-peek.el Use peek windows to view definitions and references, similar to the experience of Code Lens in VSCode
lsp-bridge.py The main Python logic part of lsp-bridge, providing event loops, message scheduling, and status management
acm/acm.el Asynchronous completion menu, designed specifically for the lsp-bridge backend, supporting lsp, elisp, words, TabNine and other backends
core/fileaction.py Mainly records the status of each file, processes LSP response messages, and calls Emacs Elisp functions
core/lspserver.py LSP message processing module, mainly for parsing, sending and receiving LSP messages, and ensuring that LSP requests are in order according to LSP protocol specifications
core/remote_file.py Used to handle remote server file access and synchronization
core/utils.py Some global utility functions, convenient for various modules to call
core/mergedeep.py JSON information merging, mainly used to send custom options to the LSP server
core/handler/ Implementation of LSP message sending and receiving, where __init__.py is the base class
core/tabnine.py TabNine backend search and completion
core/codeium.py Codeium backend search and completion
core/copilot.py Copilot backend search and completion
core/search_file_words.py Asynchronous backend for file word search
core/search_paths.py Asynchronous backend for file path search
core/search_sdcv_words.py English word search backend, can be replaced with StarDict dictionaries of other languages
core/search_list.py Asynchronous search framework, can be used to write your own asynchronous search backend
langserver Mainly places the configuration of the LSP server, each server has a json file, defining the server's name, language ID, startup command, and setting options, etc.
multiserver Mainly places the configuration of multiple LSP servers
resources English dictionary data, mainly serving Chinese users

Please read below articles first:

Then turn on develop option lsp-bridge-enable-log and happy hacking! ;)

Report bug

For some common problems, please read Wiki first.

Please use emacs -q and load a minimal setup with only lsp-bridge to verify that the bug is reproducible. If emacs -q works fine, probably something is wrong with your Emacs config.

If the problem still exists:

  1. Turn on option lsp-bridge-enable-log
  2. Use lsp-bridge-restart-process to restart the LSP-BRIDGE process
  3. Report issue with *lsp-bridge* buffer content, it contains many clues that can help us locate the problem faster

If you get a segfault error, please use the following way to collect crash information:

  1. Install gdb and turn on option lsp-bridge-enable-debug
  2. Use the command lsp-bridge-restart-process to restart the LSP-BRIDGE process
  3. Send issue with *lsp-bridge* buffer content when next crash

Contributor

lsp-bridge's rapid development couldn't have been possible without the strong support and selfless contributions from the community's experts. Without the community’s support, lsp-bridge wouldn’t be where it is today. Thank you to the loveliest people in the world, happy hacking ;)

lsp-bridge's People

Contributors

50ways2sayhard avatar allthelife avatar archer-n avatar braineo avatar edmondfrank avatar getong avatar jixiuf avatar jordananthonyking avatar kongds avatar ksqsf avatar laampui avatar liuyinz avatar manateelazycat avatar matthewzmd avatar mrunhap avatar mumu-lhl avatar nohzafk avatar norris-young avatar pastnontra avatar smallzhan avatar thefool32 avatar twlz0ne avatar vritser avatar wcq062821 avatar werhner avatar wsw0108 avatar zerolfx avatar zonuexe avatar zsxh avatar zy9306 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

lsp-bridge's Issues

corfu-insert 后补全窗口没有关闭

猫哥,

在pyright 下使用 lsp-bridge ,按回车后仍然会继续补全。

Corfu 完成补全一般会用 corfu-completeTab ) 和 corfu-insertRET ) 这两个命令,目前 Tab 是可以正常工作,但是 RET 后,会继续弹出补全窗口。

切换分支后若当前所在的文件不存在了服务会崩溃

  1. A、B两个分支,若在A分支有一个新文件,停留在该文件,切换到B分支,此时该文件已经不存在了,但buffer还在;
  2. 此时,当鼠标重新聚焦该文件时,服务会崩溃
    image

尝试的方法:
image

遇到的问题:
当只打开了这一个文件,且该文件被主动didClose后,服务会自动退出,当从这个已经不存在的文件切换到项目里面另一个文件时,会重新初始化服务,此时总是初始化失败:
image

typescript server在mac下面报错

"message": "Request textDocument/completion failed with message: Error processing request. Debug Failure. False 

expression.\nError: Debug Failure. False expression.\n    at checkChangeRange 

(/usr/local/lib/node_modules/typescript/lib/tsserver.js:37870:26)\n    at Object.updateSourceFile 

(/usr/local/lib/node_modules/typescript/lib/tsserver.js:37460:13)\n    at Object.updateSourceFile 

(/usr/local/lib/node_modules/typescript/lib/tsserver.js:30497:47)\n    at Object.updateLanguageServiceSourceFile 

(/usr/local/lib/node_modules/typescript/lib/tsserver.js:161435:40)\n    at acquireOrUpdateDocument 

(/usr/local/lib/node_modules/typescript/lib/tsserver.js:133120:43)\n    at Object.updateDocumentWithKey 

(/usr/local/lib/node_modules/typescript/lib/tsserver.js:133062:20)\n    at Object.getOrCreateSourceFileByPath [as 

getSourceFileByPath] (/usr/local/lib/node_modules/typescript/lib/tsserver.js:161795:53)\n    at 

tryReuseStructureFromOldProgram (/usr/local/lib/node_modules/typescript/lib/tsserver.js:115146:28)\n    at 

Object.createProgram (/usr/local/lib/node_modules/typescript/lib/tsserver.js:114658:29)\n    at synchronizeHostData 

(/usr/local/lib/node_modules/typescript/lib/tsserver.js:161682:26)\n    at Object.getProgram 

(/usr/local/lib/node_modules/typescript/lib/tsserver.js:161814:13)\n    at Project.updateGraphWorker 

(/usr/local/lib/node_modules/typescript/lib/tsserver.js:166861:53)\n    at Project.updateGraph 

(/usr/local/lib/node_modules/typescript/lib/tsserver.js:166790:42)\n    at ConfiguredProject.updateGraph 

(/usr/local/lib/node_modules/typescript/lib/tsserver.js:167825:63)\n    at Object.updateProjectIfDirty 

(/usr/local/lib/node_modules/typescript/lib/tsserver.js:168314:45)\n    at Project.getLanguageService 

(/usr/local/lib/node_modules/typescript/lib/tsserver.js:166404:28)\n    at Session.getCompletions 

(/usr/local/lib/node_modules/typescript/lib/tsserver.js:173418:43)\n    at Session.handlers.ts.Map.ts.getEntries._a.

<computed> (/usr/local/lib/node_modules/typescript/lib/tsserver.js:172260:61)\n    at 

/usr/local/lib/node_modules/typescript/lib/tsserver.js:174067:88\n    at Session.executeWithRequestId (/usr/local/lib/node_modules/typescript/lib/tsserver.js:174058:28)\n    at Session.executeCommand (/usr/local/lib/node_modules/typescript/lib/tsserver.js:174067:33)\n    at Session.onMessage (/usr/local/lib/node_modules/typescript/lib/tsserver.js:174093:35)\n    at Interface.<anonymous> (/usr/local/lib/node_modules/typescript/lib/tsserver.js:176698:31)\n    at Interface.emit (node:events:527:28)\n    at [_onLine] [as _onLine] (node:internal/readline/interface:424:12)\n    at [_normalWrite] [as _normalWrite] (node:internal/readline/interface:613:59)\n    at Socket.ondata (node:internal/readline/interface:251:23)\n    at Socket.emit (node:events:527:28)\n    at addChunk (node:internal/streams/readable:324:12)\n    at readableAddChunk (node:internal/streams/readable:297:9)\n    at Readable.push (node:internal/streams/readable:234:10)\n    at Pipe.onStreamRead (node:internal/stream_base_commons:190:23)"
   }

Very large *lsp-bridge* buffer

I found that using lsp-bridge after a while the *lsp-bridge* buffer will become very large, with many packages info in it. and no completion comes out.

Maybe lsp-brige should filter message that is too long for a emacs buffer, or clean the *lsp-bridge* buffer from time to time?

image

I am using lsp-bridge at commit 0e642391, and use it to work on a typescript project.

Feature Request: Integration with corfu-doc

Loving lsp-bridge so far! Thanks!

I did notice a potential issue(?). At the moment, even if I try to toggle corfu-doc, nothing comes out
image

For reference, this is what it looks like with lsp-mode
image

Any ideas why it doesn't work with lsp-bridge?

Could you provide screenshots or a video in the README?

Provide modern UI: we use Qt technology build completion UI, to provide fantastic icon, both-end text alignment, web document preview, etc.

This sounds quite interesting!

In my environment I am apparently unable to test this out myself, but I would love to see some visual demonstration :)

无法正确补全 Elixir 包含 @ 的情况

System: MacOS 12.4
Language: Elixir
elixir-ls version: 0.8.2
lsp-bridge version: 20220530.1712
Emacs version:29.0.50

如图,当使用 corfu-complete 想补全 @callback 时,补全后不包含 @ ,只剩 callback 。(不确定是否还有其他符号有此现象)

image

Windows中文路径提示 UnicodeDecodeError: 'gbk' codec can't decode

win7 64, emacs 29.0.50,创建目录C:\Users\Administrator\Desktop\新建文件夹git init,创建个test.py,开启lsp-bridge-mode后,补全没反应,lsp buffer报错:

Exception in thread Thread-2:
Traceback (most recent call last):
  File "c:\Python38\lib\threading.py", line 932, in _bootstrap_inner
    self.run()
  File "c:\Python38\lib\threading.py", line 870, in run
    self._target(*self._args, **self._kwargs)
  File "c:/green/emacs/.emacs.d/packages/corfu/corfu-main/lsp-bridge-master/lsp-bridge.py", line 90, in postgui_dispatcher
    self._open_file(message["content"])
  File "c:/green/emacs/.emacs.d/packages/corfu/corfu-main/lsp-bridge-master/lsp-bridge.py", line 123, in _open_file
    action = FileAction(filepath, lang_server)
  File "c:\green\emacs\.emacs.d\packages\corfu\corfu-main\lsp-bridge-master\core\fileaction.py", line 88, in __init__
    self.project_path = get_command_result("git rev-parse --show-toplevel", dir_path)
  File "c:\green\emacs\.emacs.d\packages\corfu\corfu-main\lsp-bridge-master\core\utils.py", line 91, in get_command_result
    return "".join((process.stdout if ret == 0 else process.stderr).readlines()).strip()
UnicodeDecodeError: 'gbk' codec can't decode byte 0xb9 in position 45: illegal multibyte sequence
Cache action change_cursor, wait for file c:/Users/Administrator/Desktop/新建文件夹/test.py to open it before executing.

手动执行git rev-parse --show-toplevel:

C:\Users\Administrator\Desktop\新建文件夹>git rev-parse --show-toplevel
C:/Users/Administrator/Desktop/新建文件夹

Warning: Your console font probably doesn't support Unicode. If you experience s
trange characters in the output, consider switching to a TrueType font such as C
onsolas!

C:\Users\Administrator\Desktop\新建文件夹>

gopls和pyright对于prepareRename返回的response格式不一样

184e7b96b5d29da10fdb6496abab7f6
这是pyright的
ea46d3d20415d158cf8aff0cc8ee57e
这是gopls的

    def process_response(self, response: dict) -> None:
        eval_in_emacs(
            "lsp-bridge-rename-highlight",
            self.file_action.filepath,
            response["start"]["line"],
            response["start"]["character"],
            response["end"]["character"]
        )

lsp-bridge都是按pyright的格式处理的,对于gopls的response会有KeyError

textDocument/hover 返回的文档默认是markdown格式

hover.pyparse_hover_contents中当 content_type是字符串格式时,统一通过make_code_block包了一层text格式的声明,实际返回的格式有可能直接是 markdown 的,如下:

{
   "jsonrpc": "2.0",
   "id": 52731,
   "result": {
      "contents": [
         "```typescript\n(alias) ref<number>(value: number): Ref<number> (+2 overloads)\nimport ref\n```"
      ],
      "range": {
         "start": {
            "line": 33,
            "character": 14
         },
         "end": {
            "line": 33,
            "character": 17
         }
      }
   }
}

这样就出错了:

Eval in Emacs: (lsp-bridge-popup-documentation '"" '"ref" '"```text\n```typescript\n(alias) ref<number>(value: number): Ref<number> (+2 overloads)\nimport ref\n```\n```")
ERROR:epc:ReturnError([Symbol('wrong-type-argument'), Symbol('integer-or-marker-p'), []])

Java lsp-bridge-rename 存在奇怪的行为

测试代码,commit id :92db93f
测试代码:

public class Hello {
    private String hello;
    public void main() {
        hello = ""
        System.out.println("hello");
    }
}

image

我尝试对 filed hello 进行 rename 为 hello1。
结果:
image
应该是重命名过程中的补全存在问题。

c语言补全不能像yasnippet那样

图片

补全的时候直接把不全选项打印出来了,不能像yasnippet模板那样不全,要一个一个来改
ps: 其他语言我还没试过

clangd lsp server error

BrokenPipeError: [Errno 32] Broken pipe
Exception in thread textDocument/didChange:
Traceback (most recent call last):
  File "/usr/local/Cellar/[email protected]/3.9.12/Frameworks/Python.framework/Versions/3.9/lib/python3.9/threading.py", line 973, in _bootstrap_inner
    self.run()
  File "/Users/lionqu/Github/lsp-bridge/core/lspserver.py", line 159, in run
    self.process.stdin.flush()
BrokenPipeError: [Errno 32] Broken pipe
Exception in thread textDocument/completion:
Traceback (most recent call last):
  File "/usr/local/Cellar/[email protected]/3.9.12/Frameworks/Python.framework/Versions/3.9/lib/python3.9/threading.py", line 973, in _bootstrap_inner
    self.run()
  File "/Users/lionqu/Github/lsp-bridge/core/lspserver.py", line 131, in run
    self.process.stdin.flush()
BrokenPipeError: [Errno 32] Broken pipe

自定义tailwindcss服务器初始化出错

lsp-bridge代码用的是最新的commit。

我的tailwindcss.json配置如下:

{
  "name": "tailwindcss",
  "languageId": "html",
  "command": ["tailwindcss-language-server", "--stdio"],
  "settings": {},
  "initializationOptions": {
    "configuration": {
      "tailwindCSS": {
        "emmetCompletions": false,
        "showPixelEquivalents": true,
        "rootFontSize": 16,
        "validate": true,
        "lint": {
          "invalidScreen": "error",
          "invalidVariant": "error",
          "invalidTailwindDirective": "error",
          "invalidApply": "error",
          "invalidConfigPath": "error",
          "cssConflict": "warning",
          "recommendedVariantOrder": "warning"
        },
        "experimental": {
          "classRegex": ""
        },
        "classAttributes": ["class", "className", "ngClass"]
      }
    }
  }
}

其中的 initializationOptions 是tailwindcss必须要传递的。

从lsp-bridge的日志上看,初始化的参数配置如下:

{
   "id": 28384,
   "method": "initialize",
   "params": {
      "processId": 1352672,
      "rootPath": "/home/evanmeek/Documents/code/project/web/domeland-ui",
      "clientInfo": {
         "name": "emacs",
         "version": "GNU Emacs 28.1 (build 1, x86_64-pc-linux-gnu, GTK+ Version 3.24.33, cairo version 1.17.6)\n of 2022-04-28"
      },
      "rootUri": "file:///home/evanmeek/Documents/code/project/web/domeland-ui",
      "capabilities": {
         "workspace": {
            "configuration": true
         },
         "textDocument": {
            "completion": {
               "completionItem": {
                  "snippetSupport": true,
                  "deprecatedSupport": true,
                  "tagSupport": {
                     "valueSet": [
                        1
                     ]
                  }
               }
            }
         }
      },
      "initializationOptions": {
         "configuration": {
            "tailwindCSS": {
               "emmetCompletions": false,
               "showPixelEquivalents": true,
               "rootFontSize": 16,
               "validate": true,
               "lint": {
                  "invalidScreen": "error",
                  "invalidVariant": "error",
                  "invalidTailwindDirective": "error",
                  "invalidApply": "error",
                  "invalidConfigPath": "error",
                  "cssConflict": "warning",
                  "recommendedVariantOrder": "warning"
               },
               "experimental": {
                  "classRegex": ""
               },
               "classAttributes": [
                  "class",
                  "className",
                  "ngClass"
               ]
            }
         }
      }
   },
   "jsonrpc": "2.0"
}

可以看到自动加上了 capabilities 还做了一些额外的配置,例如 textDocument/completion

但是初始化失败了,得到如下返回数据:

{
   "jsonrpc": "2.0",
   "id": 28384,
   "error": {
      "code": -32603,
      "message": "Request initialize failed with message: Cannot read properties of undefined (reading 'dynamicRegistration')"
   }
}

我参考了一下 lsp 的文档 textDocument_completion

解决方法可能是: 还得加上 dynamicRegistration 字段? 从报错日志上来看是没有读取到这个属性才出现的问题。

连续快速输入,最新一次补全结果还没有更新 capf 的时候,选中的补全结果还是之前旧的内容

  1. 连续输入触发请求,得到服务器响应结果,执行 lsp-bridge-record-completion-items 后,去触发 corfu 补全接着执行 lsp-bridge-capf ;
  2. 存在一种情况是,当最近的一次输入得到了服务器最新的响应结果,但是 lsp-bridge-capf 还没执行,这时候里面的 candidates 还是旧的,而这时侯选中并补全的内容就是旧的了
    这种情况下,因为有了新的输入内容,用旧的补全就有可能出现非预期的结果
    image
    比如这个图中,最新返回的 insertText 已经是 name 了,但是因为 lsp-bridge-capf 还没执行,所以最终拿到的那个 item 的 insertText 还是 this.name ,所以最后出现了 this.this.name 的情况

gopls 无法补全

--- Recv response (20506): textDocument/completion
{
   "jsonrpc": "2.0",
   "result": {
      "isIncomplete": true,
      "itemDefaults": {
         "editRange": {
            "start": {
               "line": 0,
               "character": 0
            },
            "end": {
               "line": 0,
               "character": 0
            }
         }
      },
      "items": [
         {
            "label": "ReadSeekCloser",
            "labelDetails": {},
            "kind": 8,
            "detail": "interface{...}",
            "documentation": "ReadSeekCloser is the interface that groups the basic Read, Seek and Close\nmethods.\n",
            "preselect": true,
            "sortText": "00000",
            "filterText": "ReadSeekCloser",
            "insertTextFormat": 1,
            "textEdit": {
               "range": {
                  "start": {
                     "line": 14,
                     "character": 4
                  },
                  "end": {
                     "line": 14,
                     "character": 9
                  }
               },
               "newText": "ReadSeekCloser"
            }
         }
      ]
   },
   "id": 20506
}
ERROR:epc:ReturnError([Symbol('wrong-number-of-arguments'), [[True], [Symbol('filepath'), Symbol('prefix'), Symbol('common'), Symbol('items'), Symbol('trigger-characters')], [Symbol('let'), [[Symbol('buffer'), [Symbol('get-file-buffer'), Symbol('filepath')]]], [Symbol('if'), Symbol('buffer'), [Symbol('progn'), [Symbol('save-current-buffer'), [Symbol('set-buffer'), Symbol('buffer')], [Symbol('set'), [Symbol('make-local-variable'), Quoted(Symbol('lsp-bridge-completion-items'))], Symbol('items')], [Symbol('set'), [Symbol('make-local-variable'), Quoted(Symbol('lsp-bridge-completion-prefix'))], Symbol('prefix')], [Symbol('set'), [Symbol('make-local-variable'), Quoted(Symbol('lsp-bridge-completion-common'))], Symbol('common')], [Symbol('set'), [Symbol('make-local-variable'), Quoted(Symbol('lsp-bridge-completion-trigger-characters'))], Symbol('trigger-characters')], [Symbol('if'), [Symbol('or'), [Symbol('lsp-bridge-is-empty-list'), Symbol('items')], [Symbol('member'), Symbol('lsp-bridge-last-change-command'), Symbol('lsp-bridge-completion-stop-commands')]], [], [Symbol('if'), [Symbol('and'), [Symbol('not'), [Symbol('lsp-bridge-is-blank-before-cursor-p'), Symbol('prefix')]], [Symbol('not'), [Symbol('lsp-bridge-is-at-sentence-ending-p')]]], [Symbol('progn'), [Symbol('cond'), [[Symbol('eql'), Symbol('lsp-bridge-completion-provider'), Quoted(Symbol('company'))], [Symbol('company-manual-begin')]], [[Symbol('eql'), Symbol('lsp-bridge-completion-provider'), Quoted(Symbol('corfu'))], [Symbol('corfu--auto-complete'), Symbol('lsp-bridge-last-change-tick')]]]]]]]]]]], 4])

emacs 29
macos

commit:9fae1497f83b78a361c4ab1af3bf398edc262631

Some small bugs with using Corfu-doc

  1. Disable modeline shown in doc frame.
    q1
    Update: It (gfm-view-mode) can be disable by hide-mode-line package.

  2. Selecting the tabnine item (tabnine-capf) will promote error information in minibuffer due to no doc.
    q2

Thanks.

python utf-8编码含中文导致补全不起作用

终于重现中文函数名问题了,环境win7 python3.8,要求打开的py文件事先含中文,然后补全完全不起作用,lsp bridge buffer报错:

--- Send notification: initialized

--- Send notification: workspace/didChangeConfiguration
Traceback (most recent call last):
  File "c:\Users\Administrator\Desktop\lsp-bridge\core\lspserver.py", line 229, in lsp_message_dispatcher
    self.handle_send_notification(*message["content"])
  File "c:\Users\Administrator\Desktop\lsp-bridge\core\lspserver.py", line 488, in handle_send_notification
    self.send_did_open_notification(self.first_file_path)
  File "c:\Users\Administrator\Desktop\lsp-bridge\core\lspserver.py", line 260, in send_did_open_notification
    "text": f.read()
UnicodeDecodeError: 'gbk' codec can't decode byte 0xad in position 81: illegal multibyte sequence

--- Recv notification: window/logMessage

定位到代码:
图片
如果新建一个文件,然后写入中文是可以正常补全的。如果文件内容已存在中文再打开,那么上面send_did_open_notification里open就会出错,py用gbk编码去解码utf-8编码失败,然后导致这个线程挂了所以就没有补全了?
我太菜了不知道咋解决呀,看eglot的eglot--signal-textDocument/didOpen > eglot--TextDocumentItem是直接从emacs获取内容,emacs当然能处理编码,但python的话我也不太熟等大佬解决了
另外,py这边直接open没考虑编码的还有几处:
图片

Can't rename C++ variable

Try to rename a variable in a C++ file, receive error as below

--- Recv response (47120): textDocument/rename
* Failed information about rename response.
Traceback (most recent call last):
  File "/Users/foo/emacs-cfg/test-emacs/straight/repos/lsp-bridge/core/fileaction.py", line 278, in handle_rename_response
    (rename_file, rename_counter) = self.rename_symbol_in_file(rename_info)
  File "/Users/foo/emacs-cfg/test-emacs/straight/repos/lsp-bridge/core/fileaction.py", line 289, in rename_symbol_in_file
    rename_file = rename_info["textDocument"]["uri"]
TypeError: string indices must be integers

Backup file is opened in buffer after save

  1. Creating Hello World C++ program under ~/messAround/junk folder called cpp_tutorial.cc;
  2. Saving file, after which lsp-bridge immediately flows the backup file and opens it up in the buffer! In my case, it opens up ~/.saves/'!home!haidong!messAround!junk!cpp_tutorial.cc~'.

I turned on debugging, and this is the output. Note that I also tested a Python Hello World program and it did the same thing.

[yas] Prepared just-in-time loading of snippets (but no snippets found).
Turning on magit-auto-revert-mode...done
Using default formatter emacs-lisp
For information about GNU Emacs and the GNU system, type C-h C-a.
(New file)
Using default formatter clang-format
Wrote /home/haidong/messAround/junk/cpp_tutorial.cc
recover-file: Auto save file ~/messAround/junk/#cpp_tutorial.cc# does not exist
[LSP-Bridge] Start LSP server (clangd) for /home/haidong/messAround/junk/cpp_tutorial.cc...
[LSP-Bridge] Start LSP server (clangd) for /home/haidong/messAround/junk/cpp_tutorial.cc complete, enjoy hacking!
backward-delete-char-untabify: Beginning of buffer [5 times]
Quit
Save file /home/haidong/messAround/junk/cpp_tutorial.cc? (y, n, !, ., q, C-r, C-f, d or C-h) 
Save file /home/haidong/messAround/junk/cpp_tutorial.cc? (y, n, !, ., q, C-r, C-f, d or C-h) !
Saving file /home/haidong/messAround/junk/cpp_tutorial.cc...
Wrote /home/haidong/.saves/!home!haidong!messAround!junk!cpp_tutorial.cc~
[LSP-Bridge] Start LSP server (clangd) for /home/haidong/.saves/!home!haidong!messAround!junk!cpp_tutorial.cc~...
[LSP-Bridge] Start LSP server (clangd) for /home/haidong/.saves/!home!haidong!messAround!junk!cpp_tutorial.cc~ complete, enjoy hacking!
(New file)
Can’t guess python-indent-offset, using defaults: 4
Using default formatter black
Wrote /home/haidong/messAround/junk/hell.py
[LSP-Bridge] Start LSP server (pyright) for /home/haidong/messAround/junk/hell.py...
[LSP-Bridge] Start LSP server (pyright) for /home/haidong/messAround/junk/hell.py complete, enjoy hacking!
Save file /home/haidong/messAround/junk/hell.py? (y, n, !, ., q, C-r, C-f, d or C-h) 
Save file /home/haidong/messAround/junk/hell.py? (y, n, !, ., q, C-r, C-f, d or C-h) !
Saving file /home/haidong/messAround/junk/hell.py...
Wrote /home/haidong/.saves/!home!haidong!messAround!junk!hell.py~
[LSP-Bridge] Start LSP server (pyright) for /home/haidong/.saves/!home!haidong!messAround!junk!hell.py~...
[LSP-Bridge] Start LSP server (pyright) for /home/haidong/.saves/!home!haidong!messAround!junk!hell.py~ complete, enjoy hacking!

Here is init.el I used

Thanks!

查找引用时报:TypeError: 'NoneType' object is not iterable

--- Recv response (13451): textDocument/references
Error when processing response 13451
Traceback (most recent call last):
File "/Users/xxx/.config/emacs/cache/straight/repos/lsp-bridge/core/handler/init.py", line 63, in handle_response
self.process_response(response)
File "/Users/xxx/.config/emacs/cache/straight/repos/lsp-bridge/core/handler/find_references.py", line 22, in process_response
for uri_info in response:
TypeError: 'NoneType' object is not iterable

image

在go项目中查找一个未被引用的方法时会报以上错误,看着是要判断一下response?

workspace/configuration 需要支持嵌套的 section 名称

如:

--- Recv request (0): workspace/configuration
{
   "jsonrpc": "2.0",
   "id": 0,
   "method": "workspace/configuration",
   "params": {
      "items": [
         {
            "section": "volar.completion.autoImportComponent"
         }
      ]
   }
}
{
   "jsonrpc": "2.0",
   "id": 1,
   "method": "workspace/configuration",
   "params": {
      "items": [
         {
            "section": "html.customData"
         }
      ]
   }
}

Go 只能在 '.' '=' '\' 等符号以后才会触发代码补全

测试的 lsp-bridge commit: d491564
使用 README 当中推荐的配置,emacs -Q 启动。
测试代码如下:

package main
import "fmt"
func hello0001() {
	fmt.Println("hello world")
}

func main() {
	world := "new world"
	fmt.Println("hello world")
	
	
}

当我想要在 main 函数中,使用变量 ‘world’ 或者函数 ’hello0001‘,并不会进行代码补全。只有使用非英文字母时会弹出补全窗口。

image
image

其他,如果 hello0001 定义在 main 后面,hello函数无法补全。

Can i have u contact?

你好,可以留一个联系方式吗,有一个和deep screen saver相关的问题需要向你请教

csharp server can't not work

--- Recv notification: window/logMessage
{
   "jsonrpc": "2.0",
   "method": "window/logMessage",
   "params": {
      "type": 1,
      "message": "OmniSharp.Extensions.JsonRpc.InputHandler: Failed to handle request textDocument/didChange - 
System.InvalidOperationException: Cake.Bakery not initialized.\n  at OmniSharp.Cake.Services.CakeScriptService.Generate (Cake.Scripting.Abstractions.Models.FileChange fileChange) [0x00008] in <2a91490fa4974e2ebdf1d0e688719ad1>:0 \n  at OmniSharp.Cake.Services.RequestHandlers.Buffer.UpdateBufferHandler.Handle (OmniSharp.Models.UpdateBuffer.UpdateBufferRequest request) [0x00108] in <2a91490fa4974e2ebdf1d0e688719ad1>:0 \n  at OmniSharp.LanguageServerProtocol.Handlers.OmniSharpTextDocumentSyncHandler.Handle (OmniSharp.Extensions.LanguageServer.Protocol.Models.DidChangeTextDocumentParams notification, System.Threading.CancellationToken cancellationToken) [0x001ac] in <31632d627d154de684ac77f9d20db97e>:0 \n  at OmniSharp.Extensions.LanguageServer.Server.Pipelines.SemanticTokensDeltaPipeline`2[TRequest,TResponse].Handle (TRequest request, System.Threading.CancellationToken cancellationToken, MediatR.RequestHandlerDelegate`1[TResponse] next) [0x0031e] in <a65ee41ef84f44d8810b866724a97eec>:0 \n  at OmniSharp.Extensions.LanguageServer.Server.Pipelines.ResolveCommandPipeline`2[TRequest,TResponse].Handle (TRequest request, System.Threading.CancellationToken cancellationToken, MediatR.RequestHandlerDelegate`1[TResponse] next) [0x00077] in <a65ee41ef84f44d8810b866724a97eec>:0 \n  at MediatR.Pipeline.RequestPreProcessorBehavior`2[TRequest,TResponse].Handle (TRequest request, System.Threading.CancellationToken cancellationToken, MediatR.RequestHandlerDelegate`1[TResponse] next) [0x0013e] in <856ae299ee314304bc3affd17d8d5868>:0 \n  at MediatR.Pipeline.RequestPostProcessorBehavior`2[TRequest,TResponse].Handle (TRequest request, System.Threading.CancellationToken cancellationToken, MediatR.RequestHandlerDelegate`1[TResponse] next) [0x0007e] in <856ae299ee314304bc3affd17d8d5868>:0 \n  at MediatR.Pipeline.RequestExceptionProcessorBehavior`2[TRequest,TResponse].Handle (TRequest request, System.Threading.CancellationToken cancellationToken, MediatR.RequestHandlerDelegate`1[TResponse] next) [0x00084] in <856ae299ee314304bc3affd17d8d5868>:0 \n  at MediatR.Pipeline.RequestExceptionProcessorBehavior`2[TRequest,TResponse].Handle (TRequest request, System.Threading.CancellationToken cancellationToken, MediatR.RequestHandlerDelegate`1[TResponse] next) [0x00276] in <856ae299ee314304bc3affd17d8d5868>:0 \n  at MediatR.Pipeline.RequestExceptionActionProcessorBehavior`2[TRequest,TResponse].Handle (TRequest request, System.Threading.CancellationToken cancellationToken, MediatR.RequestHandlerDelegate`1[TResponse] next) [0x00084] in <856ae299ee314304bc3affd17d8d5868>:0 \n  at MediatR.Pipeline.RequestExceptionActionProcessorBehavior`2[TRequest,TResponse].Handle (TRequest request, System.Threading.CancellationToken cancellationToken, MediatR.RequestHandlerDelegate`1[TResponse] next) [0x001e7] in <856ae299ee314304bc3affd17d8d5868>:0 \n  at OmniSharp.Extensions.JsonRpc.RequestRouterBase`1[TDescriptor].<RouteNotification>g__InnerRoute|4_1 (Microsoft.Extensions.DependencyInjection.IServiceScopeFactory serviceScopeFactory, TDescriptor descriptor, System.Object params, System.Threading.CancellationToken token) [0x000dc] in <f52078c2a67749cdb3fc490a4675d4eb>:0 \n  at OmniSharp.Extensions.JsonRpc.RequestRouterBase`1[TDescriptor].RouteNotification (OmniSharp.Extensions.JsonRpc.IRequestDescriptor`1[TDescriptor] descriptors, OmniSharp.Extensions.JsonRpc.Server.Notification notification, System.Threading.CancellationToken token) [0x002d4] in <f52078c2a67749cdb3fc490a4675d4eb>:0 \n  at OmniSharp.Extensions.JsonRpc.InputHandler+<>c__DisplayClass39_0.<RouteNotification>b__3 (System.Threading.CancellationToken ct) [0x000c0] in <f52078c2a67749cdb3fc490a4675d4eb>:0  | Method='textDocument/didChange'"
   }
}


Trigger `IMPOSSIBLE HERE: handle_server_message`

日志可能不完整了,正常干活,突然没补全了,目前我也不清楚我做了啥,先贴上来吧

Exit server: /nix/store/1kxvwk77952rppirjn258z7s3i3680zx-go-1.16/share/go/src/strings/strings.go#gopls

--- Recv notification: window/logMessage

--- Recv notification: window/logMessage

--- Recv response (37146): textDocument/signatureHelp

--- Recv message (error):
{
   "jsonrpc": "2.0",
   "error": {
      "code": -32602,
      "message": "JSON RPC invalid params: expected no params: JSON RPC invalid params"
   },
   "id": 57852
}
--- Logging error ---
Traceback (most recent call last):
  File "/usr/local/lib/python3.7/logging/__init__.py", line 1025, in emit
    msg = self.format(record)
  File "/usr/local/lib/python3.7/logging/__init__.py", line 869, in format
    return fmt.format(record)
  File "/usr/local/lib/python3.7/logging/__init__.py", line 608, in format
    record.message = record.getMessage()
  File "/usr/local/lib/python3.7/logging/__init__.py", line 369, in getMessage
    msg = msg % self.args
TypeError: not all arguments converted during string formatting
Call stack:
gopls: remote disconnected: <nil>
  File "/usr/local/lib/python3.7/threading.py", line 890, in _bootstrap
    self._bootstrap_inner()
  File "/usr/local/lib/python3.7/threading.py", line 926, in _bootstrap_inner
    self.run()
  File "/usr/local/lib/python3.7/threading.py", line 870, in run
    self._target(*self._args, **self._kwargs)
  File "/Users/zy/.emacs.d/repo/lsp-bridge/lsp-bridge.py", line 110, in message_dispatcher
    self.handle_server_message(*message["content"])
  File "/Users/zy/.emacs.d/repo/lsp-bridge/lsp-bridge.py", line 198, in handle_server_message
    logger.error("IMPOSSIBLE HERE: handle_server_message %s %s", filepath, request_type, request_id, response_result)
Message: 'IMPOSSIBLE HERE: handle_server_message %s %s'
Arguments: ('/nix/store/1kxvwk77952rppirjn258z7s3i3680zx-go-1.16/share/go/src/strings/strings.go', 'signature_help', 37146, None)

--- Recv notification: window/logMessage

--- Lsp server exited, exit code: 2
b''
gopls: remote disconnected: <nil>

--- Lsp server exited, exit code: 2
b''

使用 insertText 作为 label 会导致补全列表里面有个点,以及补全后会多出来一个点

已知在ts-ls和volar都会出现这种情况,比如 volar 如下返回信息:

         {
            "label": "log",
            "kind": 2,
            "sortText": "11",
            "commitCharacters": [
               ".",
               ",",
               ";",
               "("
            ],
            "insertText": ".log",
            "insertTextFormat": 1,
            "filterText": ".log",
            "textEdit": {
               "range": {
                  "start": {
                     "line": 5,
                     "character": 7
                  },
                  "end": {
                     "line": 5,
                     "character": 8
                  }
               },
               "newText": ".log"
            },
            "data": {
               "uri": "file:///media/psf/Home/Documents/JadeStrong/volar-starter/src/main.ts",
               "originalItem": {
                  "label": "log",
                  "kind": 2,
                  "sortText": "11",
                  "commitCharacters": [
                     ".",
                     ",",
                     ";",
                     "("
                  ],
                  "insertText": ".log",
                  "insertTextFormat": 1,
                  "filterText": ".log",
                  "textEdit": {
                     "range": {
                        "start": {
                           "line": 5,
                           "character": 7
                        },
                        "end": {
                           "line": 5,
                           "character": 8
                        }
                     },
                     "newText": ".log"
                  },
                  "data": {
                     "uri": "file:///media/psf/Home/Documents/JadeStrong/volar-starter/src/main.ts",
                     "fileName": "/media/psf/Home/Documents/JadeStrong/volar-starter/src/main.ts",
                     "offset": 114,
                     "originalItem": {
                        "name": "log",
                        "kind": "method",
                        "kindModifiers": "declare",
                        "sortText": "11"
                     }
                  }
               },
               "pluginId": 13
            }
         },

展示:
image
选中之后:
image

删除字符过程中,触发自动补全,导致删掉的字符又被补了回来

在 volar 中,编辑 css 时,很容易触发这个问题。

比如,输入 padding: 2px ,在输入过程中,并没有选中候选项的操作,只是当输入完成 2px 的最后一个 x 之后,如果侯选项里面存在符合的选项时就会触发 corfu-insert 并调用 exit-function ;

所以,感觉是删除的时候,同样满足了这个条件时就会触发补全,所以会删不掉。

image

lsp-bridge-lang-server-list and lsp-bridge-default-mode-hooks sample config

I am still struggling getting this up and running. I think some sample config for lsp-bridge-lang-server-list and lsp-bridge-default-mode-hooks would be very useful. (Yes, I know I should learn elisp...).

For example, assuming clangd and pyright have been installed, get the config for C/C++/Python right. That'll help greatly in adaptation.

Thanks!

about whether expand candidate when user enters new character

下面这两行在 exit-function 中代码是否能够让用户自己设置 corfu-preview-current 替代呢。

lsp-bridge/lsp-bridge.el

Lines 650 to 652 in 54cc58d

;; Don't expand candidate if the user enters all characters manually.
((and (member candidate candidates)
(eq this-command 'self-insert-command)))

不然会出现下面这种情况,当 corfu-preview-current 为默认值时,选中选项时会插入 label,输入新字符后 label 并没有被删除。

图片

图片

`lsp-bridge-find-def` unexpected behavior

没有处理这种 uri

demo: https://github.com/vritser/lsp-java-demo

 {
   "uri": "jdt://contents/spring-boot-2.5.6.jar/org.springframework.boot/SpringApplication.class?=ghac/%5C/usr%5C/local%5C/Cellar%5C/maven%5C/3.8.1%5C/repo%5C/org%5C/springframework%5C/boot%5C/spring-boot%5C/2.5.6%5C/spring-boot-2.5.6.jar=/maven.pomderived=/true=/=/maven.pomderived=/true=/=/javadoc_location=/jar:file:%5C/usr%5C/local%5C/Cellar%5C/maven%5C/3.8.1%5C/repo%5C/org%5C/springframework%5C/boot%5C/spring-boot%5C/2.5.6%5C/spring-boot-2.5.6-javadoc.jar%5C!%5C/=/=/maven.groupId=/org.springframework.boot=/=/maven.artifactId=/spring-boot=/=/maven.version=/2.5.6=/=/maven.scope=/compile=/%3Corg.springframework.boot(SpringApplication.class",
   "range": {
     "start": {
       "line": 1330,
       "character": 46
     },
     "end": {
       "line": 1330,
       "character": 49
     }
   }
 }

MacOS 最新版更新后,lsp server 起不来了。

Emacs 28.1, MacOS 12.3.1, 打开 Python 文件,报下面的错。
commit 132d5d9
之前老版本是可以的。
好像是从 commit 53997b9 这个开始出问题的。上面一个版本还行。

Traceback (most recent call last):
  File "/Users/guoqiang/.asdf/installs/python/3.10.4/lib/python3.10/threading.py", line 1009, in _bootstrap_inner
    self.run()
  File "/Users/guoqiang/.asdf/installs/python/3.10.4/lib/python3.10/threading.py", line 946, in run
    self._target(*self._args, **self._kwargs)
  File "/Users/guoqiang/.emacs.d/site-lisp/lsp-bridge/lsp-bridge.py", line 104, in event_dispatcher
    getattr(self, func_name)(*func_args)
  File "/Users/guoqiang/.emacs.d/site-lisp/lsp-bridge/lsp-bridge.py", line 190, in _do
    self._open_file(filepath)  # _do is called inside event_loop, so we can block here.
  File "/Users/guoqiang/.emacs.d/site-lisp/lsp-bridge/lsp-bridge.py", line 140, in _open_file
    lang_server_info: dict = load_lang_server_info(lang_server)
  File "/Users/guoqiang/.emacs.d/site-lisp/lsp-bridge/lsp-bridge.py", line 256, in load_lang_server_info
    if os.path.exists(lang_server) and os.path.sep in lang_server:
  File "/Users/guoqiang/.asdf/installs/python/3.10.4/lib/python3.10/genericpath.py", line 19, in exists
    os.stat(path)
TypeError: stat: path should be string, bytes, os.PathLike or integer, not list

More flexable configuration?

Maybe support some default customizable variable in language server config file? like:

{
    "command": [
        "node", 
        "${workspace}/typescript-language-server",
        "--stdio"
    ]
}

Or maybe support system env like:

{
    "command": [
        "node", 
        "$HOME/typescript-language-server",
        "--stdio"
    ]
}

lsp-bridge 服务器创建逻辑重构

重构理由
举例, 正在打开一个 JavaProject/File.java 的文件,查找外部函数定义的时候,反汇编出来的文件定义在当前项目外的路径,按照 lsp-bridge 现在的服务器创建逻辑,lsp-bridge 认为新打开的文件和 JavaProject/File.java 路径位置不一致,而打开新的 Java LSP Server。

而外部文件必须和 JavaProject/File.java 共享一个 Java LSP Server 才能保证有完整的依赖关系而正常跳转。

重构逻辑

  1. 如果打开是一个单文件,就让一个单文件对应一个 LSP Server, 单文件定义查看需要跳转到外部目录 (比如 /usr) 时,能够跳转的语言(比如 Python )就打开外部目录文件打开一个新的 LSP Server, 不能够跳转的语言 (比如 Java) 就提示用户无法找到定义
  2. 如果打开是一个 .git 目录下的文件,不同的 .git 项目共享一个 LSP Sever, LSP Sever 启动时, initializationOptions 参数要携带文件对应的 workspaceFolders 参数来告诉 LSP Server 开始的工程目录
  3. 当打开 .git 目录下的文件时,LSP Sever 已经启动,就检查一下当前文件和最新激活的 workspaceFolder 是否一致? 不一致就像服务器发送 workspace/didChangeWorkspaceFolders 通知,通知 LSP Sever 切换工程目录
  4. 在 .git 目录下查看定义需要跳转到外部目录时,共享当前 LSP Sever (Java 需要针对 jdt:// uri 做转换)
  5. 注意 lspserver.py 下所有和 filepath 相关的 request/response/notification 都要先检查一下 workspaceFolder ,确保发送必要的 workspace/didChangeWorkspaceFolders 通知后,再执行对应的 textDocument/* 操作

lsp-bridge-rename错误

* Failed information about rename response.
Traceback (most recent call last):
  File "/home/matthewzmd/.emacs.d/site-elisp/lsp-bridge/core/fileaction.py", line 227, in handle_rename_response
    for rename_info in response_result["documentChanges"]:
KeyError: 'documentChanges'

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.