lsp-yaml.el (9428B)
1 ;;; lsp-yaml.el --- LSP YAML server integration -*- lexical-binding: t; -*- 2 3 ;; Copyright (C) 2019 Aya Igarashi 4 5 ;; Author: Aya Igarashi <ladiclexxx@gmail.com> 6 ;; Keywords: 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 ;; 24 25 ;;; Code: 26 27 (require 'lsp-mode) 28 (require 'dash) 29 30 (defgroup lsp-yaml nil 31 "LSP support for YAML, using yaml-language-server." 32 :group 'lsp-mode 33 :link '(url-link "https://github.com/redhat-developer/yaml-language-server") 34 :package-version '(lsp-mode . "6.2")) 35 36 (defcustom lsp-yaml-format-enable t 37 "Enable/disable default YAML formatter." 38 :type 'boolean 39 :group 'lsp-yaml 40 :package-version '(lsp-mode . "6.2")) 41 42 (defcustom lsp-yaml-single-quote nil 43 "Use single quote instead of double quotes." 44 :type 'boolean 45 :group 'lsp-yaml 46 :package-version '(lsp-mode . "6.2")) 47 48 (defcustom lsp-yaml-bracket-spacing t 49 "Print spaces between brackets in objects." 50 :type 'boolean 51 :group 'lsp-yaml 52 :package-version '(lsp-mode . "6.2")) 53 54 (defcustom lsp-yaml-prose-wrap "preserve" 55 "Options for prose-wrap. 56 Always: wrap prose if it exceeds the print width. 57 Never: never wrap the prose. 58 Preserve: wrap prose as-is." 59 :type '(choice 60 (const "always") 61 (const "never") 62 (const "preserve")) 63 :group 'lsp-yaml 64 :package-version '(lsp-mode . "6.2")) 65 66 (defcustom lsp-yaml-print-width 80 67 "Specify the line length that the printer will wrap on." 68 :type 'number 69 :group 'lsp-yaml 70 :package-version '(lsp-mode . "6.2")) 71 72 (defcustom lsp-yaml-validate t 73 "Enable/disable validation feature." 74 :type 'boolean 75 :group 'lsp-yaml 76 :package-version '(lsp-mode . "6.2")) 77 78 (defcustom lsp-yaml-hover t 79 "Enable/disable hover feature." 80 :type 'boolean 81 :group 'lsp-yaml 82 :package-version '(lsp-mode . "6.2")) 83 84 (defcustom lsp-yaml-completion t 85 "Enable/disable completion feature." 86 :type 'boolean 87 :group 'lsp-yaml 88 :package-version '(lsp-mode . "6.2")) 89 90 (defcustom lsp-yaml-schemas '() 91 "Associate schemas to YAML files in a glob pattern." 92 :type '(alist :key-type (symbol :tag "schema") :value-type (lsp-string-vector :tag "files (glob)")) 93 :group 'lsp-yaml 94 :package-version '(lsp-mode . "6.2")) 95 96 (defcustom lsp-yaml-schema-store-enable t 97 "Enable/disable JSON Schema store. When set to true, available YAML 98 schemas will be automatically pulled from the store." 99 :type 'boolean 100 :group 'lsp-yaml 101 :package-version '(lsp-mode . "6.2")) 102 103 (defcustom lsp-yaml-custom-tags nil 104 "Custom tags for the parser to use." 105 :type '(lsp-repeatable-vector string) 106 :group 'lsp-yaml 107 :package-version '(lsp-mode . "6.2")) 108 109 (defcustom lsp-yaml-schema-store-uri "https://www.schemastore.org/api/json/catalog.json" 110 "URL of schema store catalog to use." 111 :type 'string 112 :group 'lsp-yaml) 113 114 (defcustom lsp-yaml-schema-store-local-db (expand-file-name 115 (locate-user-emacs-file 116 (f-join ".cache" "lsp" "lsp-yaml-schemas.json"))) 117 "Cached database of schema store." 118 :type 'file 119 :group 'lsp-yaml) 120 121 (defcustom lsp-yaml-max-items-computed 5000 122 "The maximum number of outline symbols and folding regions computed. 123 Limited for performance reasons." 124 :type 'number 125 :group 'lsp-yaml 126 :package-version '(lsp-mode . "8.0.0")) 127 128 129 (defvar lsp-yaml--schema-store-schemas-alist nil 130 "A list of schemas fetched from schema stores.") 131 132 (lsp-register-custom-settings 133 '(("yaml.format.enable" lsp-yaml-format-enable t) 134 ("yaml.format.singleQuote" lsp-yaml-single-quote t) 135 ("yaml.format.bracketSpacing" lsp-yaml-bracket-spacing) 136 ("yaml.format.proseWrap" lsp-yaml-prose-wrap) 137 ("yaml.format.printWidth" lsp-yaml-print-width) 138 ("yaml.validate" lsp-yaml-validate t) 139 ("yaml.hover" lsp-yaml-hover t) 140 ("yaml.completion" lsp-yaml-completion t) 141 ("yaml.schemas" lsp-yaml-schemas) 142 ("yaml.schemaStore.enable" lsp-yaml-schema-store-enable t) 143 ("yaml.schemaStore.url" lsp-yaml-schema-store-uri) 144 ("yaml.customTags" lsp-yaml-custom-tags) 145 ("yaml.maxItemsComputed" lsp-yaml-max-items-computed))) 146 147 (defcustom lsp-yaml-server-command '("yaml-language-server" "--stdio") 148 "Command to start yaml-languageserver." 149 :type '(repeat string) 150 :group 'lsp-yaml 151 :package-version '(lsp-mode . "6.2")) 152 153 (lsp-dependency 'yaml-language-server 154 '(:system "yaml-language-server") 155 '(:npm :package "yaml-language-server" 156 :path "yaml-language-server")) 157 158 (lsp-register-client 159 (make-lsp-client :new-connection (lsp-stdio-connection 160 (lambda () 161 `(,(or (executable-find (cl-first lsp-yaml-server-command)) 162 (lsp-package-path 'yaml-language-server)) 163 ,@(cl-rest lsp-yaml-server-command)))) 164 :activation-fn (lsp-activate-on "yaml") 165 :priority 0 166 :server-id 'yamlls 167 :initialized-fn (lambda (workspace) 168 (with-lsp-workspace workspace 169 (lsp--set-configuration 170 (lsp-configuration-section "yaml")))) 171 :download-server-fn (lambda (_client callback error-callback _update?) 172 (lsp-package-ensure 'yaml-language-server 173 callback error-callback)))) 174 175 (defconst lsp-yaml--built-in-kubernetes-schema 176 '((name . "Kubernetes") 177 (description . "Built-in kubernetes manifest schema definition") 178 (url . "kubernetes") 179 (fileMatch . ["*-k8s.yaml" "*-k8s.yml"]))) 180 181 (defun lsp-yaml-download-schema-store-db (&optional force-downloading) 182 "Download remote schema store at `lsp-yaml-schema-store-uri' into local cache. 183 Set FORCE-DOWNLOADING to non-nil to force re-download the database." 184 (interactive "P") 185 (when (or force-downloading (not (file-exists-p lsp-yaml-schema-store-local-db))) 186 (unless (file-directory-p (file-name-directory lsp-yaml-schema-store-local-db)) 187 (mkdir (file-name-directory lsp-yaml-schema-store-local-db) t)) 188 (url-copy-file lsp-yaml-schema-store-uri lsp-yaml-schema-store-local-db force-downloading))) 189 190 (defun lsp-yaml--get-supported-schemas () 191 "Get out the list of supported schemas." 192 (when (and lsp-yaml-schema-store-enable 193 (not lsp-yaml--schema-store-schemas-alist)) 194 (lsp-yaml-download-schema-store-db) 195 (setq lsp-yaml--schema-store-schemas-alist 196 (alist-get 'schemas (json-read-file lsp-yaml-schema-store-local-db)))) 197 (seq-concatenate 'list (list lsp-yaml--built-in-kubernetes-schema) lsp-yaml--schema-store-schemas-alist)) 198 199 (defun lsp-yaml-set-buffer-schema (uri-string) 200 "Set yaml schema for the current buffer to URI-STRING." 201 (interactive "MURI: ") 202 (let* ((uri (intern uri-string)) 203 (workspace-path (file-relative-name 204 (lsp--uri-to-path (lsp--buffer-uri)) 205 (lsp-workspace-root (lsp--buffer-uri)))) 206 (glob (concat "/" workspace-path)) 207 (current-config (assoc uri lsp-yaml-schemas)) 208 (current-patterns (and current-config (cdr current-config)))) 209 (if current-config 210 (or (member glob (append current-patterns nil)) 211 (setq lsp-yaml-schemas 212 (cl-acons uri 213 (vconcat (vector glob) current-patterns) 214 (assq-delete-all uri 215 (mapcar (lambda (x) (lsp-yaml--remove-glob x glob)) 216 lsp-yaml-schemas))))) 217 (setq lsp-yaml-schemas 218 (cl-acons uri (vector glob) (mapcar (lambda (x) (lsp-yaml--remove-glob x glob)) 219 lsp-yaml-schemas)))) 220 (lsp--set-configuration (lsp-configuration-section "yaml")))) 221 222 (defun lsp-yaml-select-buffer-schema () 223 "Select schema for the current buffer based on the list of supported schemas." 224 (interactive) 225 (let* ((schema (lsp--completing-read "Select buffer schema: " 226 (lsp-yaml--get-supported-schemas) 227 (lambda (schema) 228 (format "%s: %s" (alist-get 'name schema)(alist-get 'description schema))) 229 nil t)) 230 (uri (alist-get 'url schema))) 231 (lsp-yaml-set-buffer-schema uri))) 232 233 (defun lsp-yaml--remove-glob (mapping glob) 234 (let ((patterns (cdr mapping))) 235 (cons (car mapping) 236 (vconcat (-filter (lambda (p) (not (equal p glob))) 237 (append patterns nil)) nil)))) 238 239 (lsp-consistency-check lsp-yaml) 240 241 (provide 'lsp-yaml) 242 ;;; lsp-yaml.el ends here