config

Personal configuration.
git clone git://code.dwrz.net/config
Log | Files | Refs

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