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