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