config

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

lsp-volar.el (6786B)


      1 ;;; lsp-volar.el --- A lsp-mode client for Vue3 -*- lexical-binding: t; -*-
      2 ;;
      3 ;; Copyright (C) 2021 JadeStrong
      4 ;;
      5 ;; Author: JadeStrong <https://github.com/jadestrong>
      6 ;; Maintainer: JadeStrong <jadestrong@163.com>
      7 ;; Created: November 08, 2021
      8 ;; Modified: November 08, 2021
      9 ;; Keywords: abbrev bib c calendar comm convenience data docs emulations extensions faces files frames games hardware help hypermedia i18n internal languages lisp local maint mail matching mouse multimedia news outlines processes terminals tex tools unix vc wp
     10 ;; Homepage: https://github.com/jadestrong/lsp-volar
     11 ;; Package-Requires: ((emacs "25.1"))
     12 ;;
     13 ;; This file is not part of GNU Emacs.
     14 
     15 ;; This file is free software; you can redistribute it and/or modify
     16 ;; it under the terms of the GNU General Public License as published by
     17 ;; the Free Software Foundation; either version 3, or (at your option)
     18 ;; any later version.
     19 
     20 ;; This program is distributed in the hope that it will be useful,
     21 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
     22 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     23 ;; GNU General Public License for more details.
     24 
     25 ;; For a full copy of the GNU General Public License
     26 ;; see <http://www.gnu.org/licenses/>.
     27 
     28 ;;
     29 ;;; Commentary:
     30 ;;
     31 ;; provide the connection to lsp-mode and volar language server
     32 ;;
     33 ;;; Code:
     34 (require 'lsp-mode)
     35 (require 'json)
     36 
     37 (defgroup lsp-volar nil
     38   "Lsp support for vue3."
     39   :group 'lsp-mode
     40   :link '(url-link "https://github.com/vuejs/language-tools")
     41   :package-version '(lsp-mode . "9.0.0"))
     42 
     43 (defcustom lsp-volar-take-over-mode t
     44   "Enable Take Over Mode."
     45   :type 'boolean
     46   :group 'lsp-volar
     47   :package-version '(lsp-mode . "9.0.0"))
     48 
     49 (defcustom lsp-volar-hybrid-mode nil
     50   "Enable Hybrid Mode."
     51   :type 'boolean
     52   :group 'lsp-volar
     53   :package-version '(lsp-mode . "9.0.1"))
     54 
     55 (defcustom lsp-volar-activate-file ".volarrc"
     56   "A file with a custom name placed in WORKSPACE-ROOT is used to force enable
     57  volar when there is no package.json in the WORKSPACE-ROOT."
     58   :type 'string
     59   :group 'lsp-volar
     60   :package-version '(lsp-mode . "9.0.0"))
     61 
     62 (defconst lsp-volar--is-windows (memq system-type '(cygwin windows-nt ms-dos)))
     63 (defun lsp-volar-get-typescript-tsdk-path ()
     64   "Get tsserver lib*.d.ts directory path."
     65   (if-let* ((package-path (lsp-package-path 'typescript))
     66            (system-tsdk-path (f-join (file-truename package-path)
     67                                      (if lsp-volar--is-windows
     68                                          "../node_modules/typescript/lib"
     69                                        "../../lib")))
     70            ((file-exists-p system-tsdk-path)))
     71       system-tsdk-path
     72     (prog1 ""
     73       (lsp--error "[lsp-volar] Typescript is not detected correctly. Please ensure the npm package typescript is installed in your project or system (npm install -g typescript), otherwise open an issue"))))
     74 
     75 (lsp-dependency 'typescript
     76                 '(:system "tsserver")
     77                 '(:npm :package "typescript"
     78                        :path "tsserver"))
     79 
     80 (lsp-dependency 'volar-language-server
     81                 '(:system "vue-language-server")
     82                 '(:npm :package "@vue/language-server" :path "vue-language-server"))
     83 
     84 (lsp-register-custom-settings
     85  '(("typescript.tsdk"
     86     (lambda ()
     87       (if-let* ((project-root (lsp-workspace-root))
     88                (tsdk-path (f-join project-root "node_modules/typescript/lib"))
     89                ((file-exists-p tsdk-path)))
     90           tsdk-path
     91         (lsp-volar-get-typescript-tsdk-path)))
     92     t)))
     93 
     94 (lsp-register-custom-settings
     95  '(("vue.hybridMode" lsp-volar-hybrid-mode t)))
     96 
     97 (defun lsp-volar--vue-project-p (workspace-root)
     98   "Check if the `Vue' package is present in the package.json file
     99 in the WORKSPACE-ROOT."
    100   (if-let* ((package-json (f-join workspace-root "package.json"))
    101            (exist (f-file-p package-json))
    102            (config (json-read-file package-json))
    103            (dependencies (alist-get 'dependencies config)))
    104       (alist-get 'vue (append dependencies (alist-get 'devDependencies config)))
    105   nil))
    106 
    107 (defun lsp-volar--activate-p (filename &optional _)
    108   "Check if the volar-language-server should be enabled base on FILENAME."
    109   (if lsp-volar-take-over-mode
    110       (or (or
    111            (and (lsp-workspace-root) (lsp-volar--vue-project-p (lsp-workspace-root)))
    112            (and (lsp-workspace-root) lsp-volar-activate-file (f-file-p (f-join (lsp-workspace-root) lsp-volar-activate-file))))
    113           (or (or (string-match-p "\\.mjs\\|\\.[jt]sx?\\'" filename)
    114                   (and (derived-mode-p 'js-mode 'typescript-mode 'typescript-ts-mode)
    115                        (not (derived-mode-p 'json-mode))))
    116               (string= (file-name-extension filename) "vue")))
    117     (string= (file-name-extension filename) "vue")))
    118 
    119 (lsp-register-client
    120  (make-lsp-client
    121   :new-connection (lsp-stdio-connection
    122                    (lambda ()
    123                      `(,(lsp-package-path 'volar-language-server) "--stdio")))
    124   :activation-fn 'lsp-volar--activate-p
    125   :priority 0
    126   :multi-root nil
    127   :server-id 'vue-semantic-server
    128   :initialization-options (lambda () (ht-merge (lsp-configuration-section "typescript")
    129                                                (lsp-configuration-section "vue")
    130                                                (ht ("serverMode" 0)
    131                                                    ("diagnosticModel" 1)
    132                                                    ("textDocumentSync" 2))))
    133   :initialized-fn (lambda (workspace)
    134                     (with-lsp-workspace workspace
    135                       (lsp--server-register-capability
    136                        (lsp-make-registration
    137                         :id "random-id"
    138                         :method "workspace/didChangeWatchedFiles"
    139                         :register-options? (lsp-make-did-change-watched-files-registration-options
    140                                             :watchers
    141                                             `[,(lsp-make-file-system-watcher :glob-pattern "**/*.js")
    142                                               ,(lsp-make-file-system-watcher :glob-pattern "**/*.ts")
    143                                               ,(lsp-make-file-system-watcher :glob-pattern "**/*.vue")
    144                                               ,(lsp-make-file-system-watcher :glob-pattern "**/*.jsx")
    145                                               ,(lsp-make-file-system-watcher :glob-pattern "**/*.tsx")
    146                                               ,(lsp-make-file-system-watcher :glob-pattern "**/*.json")])))))
    147   :download-server-fn (lambda (_client callback error-callback _update?)
    148                         (lsp-package-ensure 'volar-language-server
    149                                             callback error-callback))))
    150 
    151 (provide 'lsp-volar)
    152 ;;; lsp-volar.el ends here