emacs-lsp-proxy 0.1.1 → 0.5.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/README.md +232 -0
  2. package/package.json +11 -7
package/README.md ADDED
@@ -0,0 +1,232 @@
1
+ # LSP-PROXY (formerly LSP-COPILOT)
2
+
3
+ *This project has been renamed from lsp-copilot to lsp-proxy to better reflect its core functionality as a communication proxy and aggregator between Emacs and multiple LSP servers. The name change does not affect the project's features or goals.*
4
+
5
+ ## Introduction
6
+ Lsp-Proxy is an LSP (Language Server Protocol) client for Emacs, implemented in Rust and inspired by [lsp-bridge](https://github.com/manateelazycat/lsp-bridge). It uses `jsonrpc.el` to facilitate communication between Emacs and the Lsp-Proxy Server. The Lsp-Proxy Server acts as an intermediary between Emacs and various language servers, handling communication with the language servers, processing the responses, and returning them to Emacs.
7
+
8
+ The features it supports are:
9
+ - find definitions/references/implementatoins/type-definition/declaration (as a xref backend)
10
+ - completion (as a capf function) support snippet and auto import, reuse requests that are already being processed, while caching the results to improve response speed, before returning all the completion candidates, the server will do fuzzy matching and filter out entries with no match.
11
+ - diagnostics (as a flycheck backend default or flymake) process diagnostics when idle.
12
+ - hover (triggered by `lsp-proxy-describe-thing-at-point`)
13
+ - code action (triggered by `lsp-proxy-execute-code-action`)
14
+ - rename (triggered by `lsp-proxy-rename`)
15
+ - format buffer (triggered by `lsp-proxy-format-buffer`)
16
+ - workspace command, such as `typescript.restartTsServer(vtsls)` 、 `reloadWorkspace(rust-analyzer)` (triggered by `lsp-proxy-execute-command`)
17
+ - inlay hints (triggered by `lsp-proxy-inlay-hints-mode`)
18
+ - documentHighlight/signature (baesd on `eldoc`)
19
+ - documentSymbols (triggered by `imenu`)
20
+
21
+ ![Demo](images/show.gif)
22
+
23
+ ## Prerequisites
24
+ ### Emacs30.1 or 29 + eglot@latest (Reused some capabilities of eglot to reduce code duplication.)
25
+
26
+ ## Installation
27
+ ### Via npm (Recommended)
28
+ LSP-PROXY is now available via npm with prebuilt binaries for all major platforms:
29
+
30
+ ```bash
31
+ npm install -g emacs-lsp-proxy
32
+ ```
33
+
34
+ This will automatically install the appropriate binary for your platform (Linux x64/ARM64, macOS x64/ARM64, Windows x64) and make the `emacs-lsp-proxy` command available in your PATH.
35
+
36
+ ### Manually
37
+ Before installing LSP-PROXY manually, you should install rust and cargo first.
38
+ ```bash
39
+ git clone https://github.com/jadestrong/emacs-lsp-proxy.git ./your-directory
40
+ cd ./your-directory
41
+ cargo build --release
42
+ # delete old file if exist
43
+ rm emacs-lsp-proxy
44
+ # cp ./target/release/emacs-lsp-proxy.exe ./
45
+ cp ./target/release/emacs-lsp-proxy ./
46
+ ```
47
+
48
+ ### Download prebuilt binary
49
+ You can download the prebuilt binary from [releases](https://github.com/jadestrong/lsp-copilot/releases). For MacOS users, you should allow this binary to run first time, like this:
50
+ > The application cannot be opened because it is from an unidentified developer. You can allow this app to run by going to System Settings > Privacy & Security and selecting 'Allow Anyway' for this app.
51
+
52
+ ## How to use
53
+ ```emacs-lisp
54
+ (use-package lsp-proxy
55
+ ;; :load-path "/path/to/lsp-proxy"
56
+ :config
57
+ (add-hook 'tsx-ts-mode-hook #'lsp-proxy-mode)
58
+ (add-hook 'js-ts-mode-hook #'lsp-proxy-mode)
59
+ (add-hook 'typescript-mode-hook #'lsp-proxy-mode)
60
+ (add-hook 'typescript-ts-mode-hook #'lsp-proxy-mode))
61
+ ```
62
+
63
+ ```elisp
64
+ ;; Doom Emacs
65
+ (package! lsp-proxy :recipe (:host github :repo "jadestrong/lsp-proxy"
66
+ :files ("lsp-proxy.el" "emacs-lsp-proxy")
67
+ :pre-build (("cargo" "build" "--release") ("cp" "./target/release/emacs-lsp-proxy" "./"))))
68
+
69
+ (set-lookup-handlers! 'lsp-proxy-mode
70
+ :definition '(lsp-proxy-find-definition :async t)
71
+ :references '(lsp-proxy-find-references :async t)
72
+ :implementations '(lsp-proxy-find-implementations :async t)
73
+ :type-definition '(lsp-proxy-find-type-definition :async t)
74
+ :documentation '(lsp-proxy-describe-thing-at-point :async t))
75
+ ```
76
+
77
+ ## Add a new language
78
+ Performed simple tests on Windows 11 and Arch Linux, it works properly. I have tested it on macOS and use it for daily development in JavaScript, Rust, etc. Therefore, tools like vtsls, typescript-language-server, eslint, tailwindcss, css, and others work fine
79
+ - JavaScript/Typescript: [vtsls](https://github.com/yioneko/vtsls) (built-in)、[typescript-language-server](https://github.com/typescript-language-server/typescript-language-server)
80
+ - eslint、html、css、html: [vscode-langservers-extracted](https://github.com/hrsh7th/vscode-langservers-extracted) +the latest vscode-eslint has removed the publishDiagnostics method and only supports the pullDiagnostics method, so currently we can only use `vscode-langservers-extracted@4.8`+.
81
+ - tailwindcss: [@tailwindcss/language-server](https://www.npmjs.com/package/@tailwindcss/language-server)
82
+
83
+ The configuration for a new language can refer to the [Helix configuration](https://github.com/helix-editor/helix/blob/master/languages.toml). Supported fields are based on [the built-in configuration file](https://github.com/jadestrong/lsp-copilot/blob/main/languages.toml), and only LSP-related fields are supported.
84
+ Open custom language config file by `lsp-proxy-open-config-file` and add your config, then execute `lsp-proxy-restart`.
85
+
86
+ The configuration fields for adding language support are: `name、roots、language-id、file-types、language-servers` . Other fields in the Helix configuration are not supported.
87
+
88
+
89
+ - Vue2:
90
+ ```toml
91
+ [languge-server.vls]
92
+ command = "vls"
93
+ args = ["--stdio"]
94
+
95
+ [[language]]
96
+ name = "vue"
97
+ roots = ["package.json"]
98
+ language-id = "vue"
99
+ file-types = ["vue"]
100
+ language-servers = ["vls"]
101
+ ```
102
+
103
+ - Vue3
104
+ ```sh
105
+ yarn global add @vue/language-server @vue/typescript-plugin
106
+ ```
107
+
108
+ ```toml
109
+ [language-server.typescript-language-server]
110
+ config.plugins = [
111
+ { name = "@vue/typescript-plugin", location = "${your-path}/node_modules/@vue/typescript-plugin", languages = ["vue"]}
112
+ ]
113
+
114
+ [language-server.vue-language-server]
115
+ command = "vue-language-server"
116
+ args = ["--stdio"]
117
+ config.typescript = { tsdk = "${your-path}/node_modules/typescript/lib" }
118
+ config.vue = { hybridMode = false }
119
+
120
+ [[language]]
121
+ name = "vue"
122
+ roots = ["package.json"]
123
+ language-id = "vue"
124
+ file-types = ["vue", "ts"]
125
+ language-servers = ["vue-language-server", "typescript-language-server"]
126
+
127
+ # Override the build-in config. The built-in configuration uses vtsls, but it seems incompatible with vue-language-server. It could also be that my configuration is incorrect.
128
+ # Others, such as JavaScript and TSX, can be added as needed.
129
+ [[language]]
130
+ name = "typescript"
131
+ language-id = "typescript"
132
+ file-types = ["ts", "mts", "cts"]
133
+ roots = ["package.json"]
134
+ language-servers = [
135
+ { name = "typescript-language-server", except-features = [
136
+ "format",
137
+ ] },
138
+ { name = "eslint", support-workspace = true, config-files = [".eslintrc.js", ".eslintrc.cjs", ".eslintrc.yaml", ".eslintrc.yml", ".eslintrc", ".eslintrc.json", , "eslint.config.js", "eslint.config.mjs", "eslint.config.cjs", "eslint.config.ts", "eslint.config.mts", "eslint.config.cts"] },
139
+ ]
140
+ ```
141
+
142
+ - `except-features` can disable server's feature, view the [supported features](https://github.com/jadestrong/lsp-copilot/blob/c3d314d9bc1778b35c6ad2a046fa8b76cad94db4/src/syntax.rs#L150-L168).
143
+
144
+ ## Debug
145
+ ### Server bug
146
+ - `(setq lsp-proxy-log-level 3)`
147
+ - M-x `lsp-proxy-restart`
148
+ - M-x `lsp-proxy-open-log-file`
149
+ ### Server crash
150
+ - Open `*lsp-proxy-events*` buffer
151
+ ### Lsp server message
152
+ - Open `*lsp-proxy-log*`
153
+
154
+ ## Commands
155
+ - `lsp-proxy-find-definition`
156
+ - `lsp-proxy-find-references`
157
+ - `lsp-proxy-find-declaration`
158
+ - `lsp-proxy-find-type-definition`
159
+ - `lsp-proxy-find-implementations`
160
+ - `lsp-proxy-format-buffer`
161
+ - `lsp-proxy-rename`
162
+ - `lsp-proxy-execute-code-action`
163
+ - `lsp-proxy-execute-command`
164
+ - `lsp-proxy-describe-thing-at-point`
165
+ - `lsp-proxy-show-project-diagnostics`
166
+
167
+ -----
168
+ - lsp-proxy-open-log-file
169
+ - lsp-proxy-open-config-file
170
+ - lsp-proxy-restart: Restart the server
171
+ - lsp-proxy-workspace-restart: Restart the LSP server for the current project
172
+
173
+ ## Customization
174
+ | Variable | Default | Description |
175
+ | lsp-proxy-user-languages-config | `user-emacs-directory/lsp-proxy/languages.toml` | Where custom language server configurations are stored |
176
+ | lsp-proxy-log-file-directory | temporary-file-directory | Log file storage directory |
177
+ | lsp-proxy-log-level | 1 | A number indicating the log level. Defaults to 1. Warn = 0, Info = 1, Debug = 2, Trace = 3 |
178
+
179
+
180
+ ## Recommend config
181
+ ### Company and Corfu
182
+ ```elisp
183
+ ;; company
184
+ (setq company-idle-delay 0)
185
+ ;; If you encounter issues when typing Vue directives (e.g., v-), you can try setting it to 1. I'm not sure if it's a problem with Volar.
186
+ (setq company-minimum-prefix-length 2)
187
+ (setq company-tooltip-idle-delay 0)
188
+
189
+ ;; corfu
190
+ (setq corfu-auto-delay 0)
191
+ (setq corfu-popupinfo-delay '(0.1 . 0.1))
192
+ ```
193
+
194
+ ### company-box
195
+ ```elisp
196
+ (defun company-box-icons--lsp-proxy (candidate)
197
+ (-when-let* ((proxy-item (get-text-property 0 'lsp-proxy--item candidate))
198
+ (lsp-item (plist-get proxy-item :item))
199
+ (kind-num (plist-get lsp-item :kind)))
200
+ (alist-get kind-num company-box-icons--lsp-alist)))
201
+
202
+ (setq company-box-icons-functions
203
+ (cons #'company-box-icons--lsp-proxy company-box-icons-functions))
204
+ ```
205
+
206
+ ### tabnine
207
+ Install [tabnine](https://github.com/shuxiao9058/tabnine) package first, then add the following configuration to your config:
208
+ ```elisp
209
+ (when (fboundp #'tabnine-completion-at-point)
210
+ (add-hook 'lsp-proxy-mode-hook
211
+ (defun lsp-proxy-capf ()
212
+ (remove-hook 'completion-at-point-functions #'lsp-proxy-completion-at-point t)
213
+ (add-hook 'completion-at-point-functions
214
+ (cape-capf-super
215
+ #'lsp-proxy-completion-at-point
216
+ #'tabnine-completion-at-point) nil t))))
217
+ ```
218
+
219
+ ### flycheck / flymake
220
+ Flycheck enabled default if flycheck-mode is installed. You can also select *flymake* by:
221
+ ```elisp
222
+ (setq lsp-proxy-diagnostics-provider :flymake)
223
+ ```
224
+
225
+ ## Acknowledgements
226
+ Thanks to [Helix](https://github.com/helix-editor/helix), the architecture of Lsp-Proxy Server is entirely based on Helix's implementation. Language configuration and communication with different language servers are all dependent on Helix. As a Rust beginner, I've gained a lot from this approach during the implementation.
227
+
228
+ Regarding the communication between Emacs and Lsp-Proxy, I would like to especially thank [copilot.el](https://github.com/copilot-emacs/copilot.el) and [rust-analyzer](https://github.com/rust-lang/rust-analyzer). The usage of jsonrpc.el was learned from copilot.el, while the approach to receiving and handling Emacs requests was inspired by the implementation in rust-analyzer.
229
+
230
+ The various methods used to implement LSP-related functionality on the Emacs side were learned from [lsp-mode](https://github.com/emacs-lsp/lsp-mode) and [eglot](https://github.com/joaotavora/eglot). Without their guidance, many of these features would have been difficult to implement.
231
+
232
+ Regarding the communication data format between Emacs and Lsp-Proxy, I would like to especially thank [emacs-lsp-booster](https://github.com/blahgeek/emacs-lsp-booster). The project integrates the implementation of emacs-lsp-booster, which encodes the JSON data returned to Emacs, further reducing the load on Emacs.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "emacs-lsp-proxy",
3
- "version": "0.1.1",
3
+ "version": "0.5.3",
4
4
  "scripts": {
5
5
  "postinstall": "node ./install.js"
6
6
  },
@@ -10,14 +10,18 @@
10
10
  "publicConfig": {
11
11
  "access": "public"
12
12
  },
13
- "keywords": ["emacs", "lsp", "rust"],
13
+ "keywords": [
14
+ "emacs",
15
+ "lsp",
16
+ "rust"
17
+ ],
14
18
  "author": "jadestrong",
15
19
  "optionalDependencies": {
16
- "@emacs-lsp-proxy/darwin-x64": "0.1.0",
17
- "@emacs-lsp-proxy/darwin-arm64": "0.1.0",
18
- "@emacs-lsp-proxy/linux-x64": "0.1.0",
19
- "@emacs-lsp-proxy/linux-arm64": "0.1.0",
20
- "@emacs-lsp-proxy/win32-x64": "0.1.0"
20
+ "@emacs-lsp-proxy/darwin-x64": "0.5.3",
21
+ "@emacs-lsp-proxy/darwin-arm64": "0.5.3",
22
+ "@emacs-lsp-proxy/linux-x64": "0.5.3",
23
+ "@emacs-lsp-proxy/linux-arm64": "0.5.3",
24
+ "@emacs-lsp-proxy/win32-x64": "0.5.3"
21
25
  },
22
26
  "license": "ISC",
23
27
  "description": "An LSP client for Emacs implemented in Rust."