lsp-erlang.el (8610B)
1 ;;; lsp-erlang.el --- Erlang Client settings -*- lexical-binding: t; -*- 2 3 ;; Copyright (C) 2019-2023 Roberto Aloi, Alan Zimmerman 4 5 ;; Author: Roberto Aloi, Alan Zimmerman 6 ;; Keywords: erlang lsp 7 8 ;; This program is free software; you can redistribute it and/or modify 9 ;; it under the terms of the GNU General Public License as published by 10 ;; the Free Software Foundation, either version 3 of the License, or 11 ;; (at your option) any later version. 12 13 ;; This program is distributed in the hope that it will be useful, 14 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 15 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 ;; GNU General Public License for more details. 17 18 ;; You should have received a copy of the GNU General Public License 19 ;; along with this program. If not, see <https://www.gnu.org/licenses/>. 20 21 ;;; Commentary: 22 23 ;; lsp-erlang client 24 25 ;;; Code: 26 27 (require 'lsp-mode) 28 (require 'lsp-semantic-tokens) 29 30 (defgroup lsp-erlang nil 31 "LSP support for the Erlang programming language. 32 It can use erlang-ls or erlang-language-platform (ELP)." 33 :group 'lsp-mode) 34 35 (defgroup lsp-erlang-ls nil 36 "LSP support for the Erlang programming language using erlang-ls." 37 :group 'lsp-mode 38 :link '(url-link "https://github.com/erlang-ls/erlang_ls")) 39 40 (defgroup lsp-erlang-elp nil 41 "LSP support for the Erlang programming language using erlang-language-platform (ELP)." 42 :group 'lsp-mode 43 :link '(url-link "https://github.com/WhatsApp/erlang-language-platform")) 44 45 (defgroup lsp-erlang-elp-semantic-tokens nil 46 "LSP semantic tokens support for ELP." 47 :group 'lsp-erlang-elp 48 :link '(url-link "https://github.com/WhatsApp/erlang-language-platform") 49 :package-version '(lsp-mode . "9.0.0")) 50 51 (defcustom lsp-erlang-server 'erlang-ls 52 "Choose LSP server." 53 :type '(choice (const :tag "erlang-ls" erlang-ls) 54 (const :tag "erlang-language-platform" erlang-language-platform)) 55 :group 'lsp-erlang 56 :package-version '(lsp-mode . "6.2")) 57 58 ;; erlang-ls 59 60 (defcustom lsp-erlang-ls-server-path 61 "erlang_ls" 62 "Path to the Erlang Language Server binary." 63 :group 'lsp-erlang-ls 64 :risky t 65 :type 'file) 66 67 (defcustom lsp-erlang-ls-server-connection-type 68 'stdio 69 "Type of connection to use with the Erlang Language Server: tcp or stdio." 70 :group 'lsp-erlang-ls 71 :risky t 72 :type 'symbol) 73 74 (defun lsp-erlang-ls-server-start-fun (port) 75 "Command to start erlang_ls in TCP mode on the given PORT." 76 `(,lsp-erlang-ls-server-path 77 "--transport" "tcp" 78 "--port" ,(number-to-string port))) 79 80 (defun lsp-erlang-ls-server-connection () 81 "Command to start erlang_ls in stdio mode." 82 (if (eq lsp-erlang-ls-server-connection-type 'tcp) 83 (lsp-tcp-connection 'lsp-erlang-ls-server-start-fun) 84 (lsp-stdio-connection `(,lsp-erlang-ls-server-path "--transport" "stdio")))) 85 86 (lsp-register-client 87 (make-lsp-client :new-connection (lsp-erlang-ls-server-connection) 88 :major-modes '(erlang-mode) 89 :priority -1 90 :server-id 'erlang-ls)) 91 92 93 ;; erlang-language-platform 94 95 (lsp-defcustom lsp-erlang-elp-types-on-hover t 96 "Show eqWAlizer types on hover." 97 :type 'boolean 98 :group 'lsp-erlang-elp 99 :package-version '(lsp-mode . "9.0.0") 100 :lsp-path "elp.typesOnHover.enable") 101 102 (defcustom lsp-erlang-elp-server-command '("elp" "server") 103 "Command to start erlang-language-platform." 104 :type '(repeat string) 105 :group 'lsp-erlang-elp 106 :package-version '(lsp-mode . "8.0.0")) 107 108 (defcustom lsp-erlang-elp-download-url 109 (format "https://github.com/WhatsApp/erlang-language-platform/releases/latest/download/%s" 110 (pcase system-type 111 ('gnu/linux "elp-linux-x86_64-unknown-linux-gnu-otp-26.tar.gz") 112 ('darwin 113 (if (string-match "^aarch64-.*" system-configuration) 114 "elp-macos-aarch64-apple-darwin-otp-25.3.tar.gz" 115 "elp-macos-x86_64-apple-darwin-otp-25.3.tar.gz")))) 116 "Automatic download url for erlang-language-platform." 117 :type 'string 118 :group 'lsp-erlang-elp 119 :package-version '(lsp-mode . "8.0.0")) 120 121 (defcustom lsp-erlang-elp-store-path (f-join lsp-server-install-dir 122 "erlang" 123 (if (eq system-type 'windows-nt) 124 "elp.exe" 125 "elp")) 126 "The path to the file in which `elp' will be stored." 127 :type 'file 128 :group 'lsp-erlang-elp 129 :package-version '(lsp-mode . "8.0.0")) 130 131 (lsp-dependency 132 'erlang-language-platform 133 `(:download :url lsp-erlang-elp-download-url 134 :decompress :targz 135 :store-path lsp-erlang-elp-store-path 136 :set-executable? t) 137 '(:system "elp")) 138 139 ;; Semantic tokens 140 141 ;; Modifier faces 142 143 (defface lsp-erlang-elp-bound-modifier-face 144 '((t :underline t)) 145 "The face modification to use for bound variables in patterns." 146 :group 'lsp-erlang-elp-semantic-tokens) 147 148 (defface lsp-erlang-elp-exported-function-modifier-face 149 '((t :underline t)) 150 "The face modification to use for exported functions." 151 :group 'lsp-erlang-elp-semantic-tokens) 152 153 (defface lsp-erlang-elp-deprecated-function-modifier-face 154 '((t :strike-through t)) 155 "The face modification to use for deprecated functions." 156 :group 'lsp-erlang-elp-semantic-tokens) 157 158 159 ;; --------------------------------------------------------------------- 160 ;; Semantic token modifier face customization 161 162 (defcustom lsp-erlang-elp-bound-modifier 'lsp-erlang-elp-bound-modifier-face 163 "Face for semantic token modifier for `bound' attribute." 164 :type 'face 165 :group 'lsp-erlang-elp-semantic-tokens 166 :package-version '(lsp-mode . "9.0.0")) 167 168 (defcustom lsp-erlang-elp-exported-function-modifier 'lsp-erlang-elp-exported-function-modifier-face 169 "Face for semantic token modifier for `exported_function' attribute." 170 :type 'face 171 :group 'lsp-erlang-elp-semantic-tokens 172 :package-version '(lsp-mode . "9.0.0")) 173 174 (defcustom lsp-erlang-elp-deprecated-function-modifier 'lsp-erlang-elp-deprecated-function-modifier-face 175 "Face for semantic token modifier for `deprecated_function' attribute." 176 :type 'face 177 :group 'lsp-erlang-elp-semantic-tokens 178 :package-version '(lsp-mode . "9.0.0")) 179 180 ;; --------------------------------------------------------------------- 181 182 (defun lsp-erlang-elp--semantic-modifiers () 183 "Mapping between rust-analyzer keywords and fonts to apply. 184 The keywords are sent in the initialize response, in the semantic 185 tokens legend." 186 `( 187 ("bound" . ,lsp-erlang-elp-bound-modifier) 188 ("exported_function" . ,lsp-erlang-elp-exported-function-modifier) 189 ("deprecated_function" . ,lsp-erlang-elp-deprecated-function-modifier))) 190 191 ;; --------------------------------------------------------------------- 192 ;; Client 193 194 (lsp-register-client 195 (make-lsp-client 196 :new-connection (lsp-stdio-connection 197 (lambda () 198 `(,(or (executable-find 199 (cl-first lsp-erlang-elp-server-command)) 200 (lsp-package-path 'erlang-language-platform) 201 "elp") 202 ,@(cl-rest lsp-erlang-elp-server-command)))) 203 :activation-fn (lsp-activate-on "erlang") 204 :priority (if (eq lsp-erlang-server 'erlang-language-platform) 1 -2) 205 :semantic-tokens-faces-overrides `(:discard-default-modifiers t 206 :modifiers 207 ,(lsp-erlang-elp--semantic-modifiers)) 208 :server-id 'elp 209 :custom-capabilities `((experimental . ((snippetTextEdit . ,(and lsp-enable-snippet (fboundp 'yas-minor-mode)))))) 210 :download-server-fn (lambda (_client callback error-callback _update?) 211 (lsp-package-ensure 'erlang-language-platform callback error-callback)))) 212 213 (defun lsp-erlang-switch-server (&optional lsp-server) 214 "Switch priorities of lsp servers, unless LSP-SERVER is already active." 215 (interactive) 216 (let ((current-server (if (> (lsp--client-priority (gethash 'erlang-ls lsp-clients)) 0) 217 'erlang-ls 218 'erlang-language-platform))) 219 (unless (eq lsp-server current-server) 220 (dolist (server '(erlang-ls erlang-language-platform)) 221 (when (natnump (setf (lsp--client-priority (gethash server lsp-clients)) 222 (* (lsp--client-priority (gethash server lsp-clients)) -1))) 223 (message (format "Switched to server %s." server))))))) 224 225 (lsp-consistency-check lsp-erlang) 226 227 (provide 'lsp-erlang) 228 ;;; lsp-erlang.el ends here