aboutsummaryrefslogtreecommitdiffstats
path: root/elpa/lsp-mode-20220505.630/lsp-yaml.el
blob: 76ef4baf9a5bfca5c1c5371b5c56ab76c36387ad (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
;;; lsp-yaml.el --- LSP YAML server integration        -*- lexical-binding: t; -*-

;; Copyright (C) 2019  Aya Igarashi

;; Author: Aya Igarashi <ladiclexxx@gmail.com>
;; Keywords:

;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.

;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;; GNU General Public License for more details.

;; You should have received a copy of the GNU General Public License
;; along with this program.  If not, see <https://www.gnu.org/licenses/>.

;;; Commentary:

;;

;;; Code:

(require 'lsp-mode)
(require 'dash)

(defgroup lsp-yaml nil
  "LSP support for YAML, using yaml-language-server."
  :group 'lsp-mode
  :link '(url-link "https://github.com/redhat-developer/yaml-language-server")
  :package-version '(lsp-mode . "6.2"))

(defcustom lsp-yaml-format-enable t
  "Enable/disable default YAML formatter."
  :type 'boolean
  :group 'lsp-yaml
  :package-version '(lsp-mode . "6.2"))

(defcustom lsp-yaml-single-quote nil
  "Use single quote instead of double quotes."
  :type 'boolean
  :group 'lsp-yaml
  :package-version '(lsp-mode . "6.2"))

(defcustom lsp-yaml-bracket-spacing t
  "Print spaces between brackets in objects."
  :type 'boolean
  :group 'lsp-yaml
  :package-version '(lsp-mode . "6.2"))

(defcustom lsp-yaml-prose-wrap "preserve"
  "Options for prose-wrap.
   Always: wrap prose if it exceeds the print width.
   Never: never wrap the prose.
   Preserve: wrap prose as-is."
  :type '(choice
          (const "always")
          (const "never")
          (const "preserve"))
  :group 'lsp-yaml
  :package-version '(lsp-mode . "6.2"))

(defcustom lsp-yaml-print-width 80
  "Specify the line length that the printer will wrap on."
  :type 'number
  :group 'lsp-yaml
  :package-version '(lsp-mode . "6.2"))

(defcustom lsp-yaml-validate t
  "Enable/disable validation feature."
  :type 'boolean
  :group 'lsp-yaml
  :package-version '(lsp-mode . "6.2"))

(defcustom lsp-yaml-hover t
  "Enable/disable hover feature."
  :type 'boolean
  :group 'lsp-yaml
  :package-version '(lsp-mode . "6.2"))

(defcustom lsp-yaml-completion t
  "Enable/disable completion feature."
  :type 'boolean
  :group 'lsp-yaml
  :package-version '(lsp-mode . "6.2"))

(defcustom lsp-yaml-schemas '()
  "Associate schemas to YAML files in a glob pattern."
  :type '(alist :key-type (symbol :tag "schema") :value-type (lsp-string-vector :tag "files (glob)"))
  :group 'lsp-yaml
  :package-version '(lsp-mode . "6.2"))

(defcustom lsp-yaml-schema-store-enable t
  "Enable/disable JSON Schema store. When set to true, available YAML
   schemas will be automatically pulled from the store."
  :type 'boolean
  :group 'lsp-yaml
  :package-version '(lsp-mode . "6.2"))

(defcustom lsp-yaml-custom-tags nil
  "Custom tags for the parser to use."
  :type '(lsp-repeatable-vector string)
  :group 'lsp-yaml
  :package-version '(lsp-mode . "6.2"))

(defcustom lsp-yaml-schema-store-uri "https://www.schemastore.org/api/json/catalog.json"
  "URL of schema store catalog to use."
  :type 'string
  :group 'lsp-yaml)

(defcustom lsp-yaml-schema-store-local-db (expand-file-name
                                           (locate-user-emacs-file
                                            (f-join ".cache" "lsp" "lsp-yaml-schemas.json")))
  "Cached databse of schema store."
  :type 'file
  :group 'lsp-yaml)

(defcustom lsp-yaml-max-items-computed 5000
  "The maximum number of outline symbols and folding regions computed.
Limited for performance reasons."
  :type 'number
  :group 'lsp-yaml
  :package-version '(lsp-mode . "8.0.0"))


(defvar lsp-yaml--schema-store-schemas-alist nil
  "A list of schemas fetched from schema stores.")

(lsp-register-custom-settings
 '(("yaml.format.enable" lsp-yaml-format-enable t)
   ("yaml.format.singleQuote" lsp-yaml-single-quote t)
   ("yaml.format.bracketSpacing" lsp-yaml-bracket-spacing)
   ("yaml.format.proseWrap" lsp-yaml-prose-wrap)
   ("yaml.format.printWidth" lsp-yaml-print-width)
   ("yaml.validate" lsp-yaml-validate t)
   ("yaml.hover" lsp-yaml-hover t)
   ("yaml.completion" lsp-yaml-completion t)
   ("yaml.schemas" lsp-yaml-schemas)
   ("yaml.schemaStore.enable" lsp-yaml-schema-store-enable t)
   ("yaml.schemaStore.url" lsp-yaml-schema-store-uri)
   ("yaml.customTags" lsp-yaml-custom-tags)
   ("yaml.maxItemsComputed" lsp-yaml-max-items-computed)))

(defcustom lsp-yaml-server-command '("yaml-language-server" "--stdio")
  "Command to start yaml-languageserver."
  :type '(repeat string)
  :group 'lsp-yaml
  :package-version '(lsp-mode . "6.2"))

(lsp-dependency 'yaml-language-server
                '(:system "yaml-language-server")
                '(:npm :package "yaml-language-server"
                       :path "yaml-language-server"))

(lsp-register-client
 (make-lsp-client :new-connection (lsp-stdio-connection
                                   (lambda ()
                                     `(,(or (executable-find (cl-first lsp-yaml-server-command))
                                            (lsp-package-path 'yaml-language-server))
                                       ,@(cl-rest lsp-yaml-server-command))))
                  :major-modes '(yaml-mode k8s-mode)
                  :priority 0
                  :server-id 'yamlls
                  :initialized-fn (lambda (workspace)
                                    (with-lsp-workspace workspace
                                      (lsp--set-configuration
                                       (lsp-configuration-section "yaml"))))
                  :download-server-fn (lambda (_client callback error-callback _update?)
                                        (lsp-package-ensure 'yaml-language-server
                                                            callback error-callback))))

(defconst lsp-yaml--built-in-kubernetes-schema
  '((name . "Kubernetes")
    (description . "Built-in kubernetes manifest schema definition")
    (url . "kubernetes")
    (fileMatch . ["*-k8s.yaml" "*-k8s.yml"])))

(defun lsp-yaml-download-schema-store-db (&optional force-downloading)
  "Download the remote schema store at `lsp-yaml-schema-store-uri' into local cache.
Set FORCE-DOWNLOADING to non-nil to force re-download the database."
  (interactive "P")
  (when (or force-downloading (not (file-exists-p lsp-yaml-schema-store-local-db)))
    (unless (file-directory-p (file-name-directory lsp-yaml-schema-store-local-db))
      (mkdir (file-name-directory lsp-yaml-schema-store-local-db) t))
    (url-copy-file lsp-yaml-schema-store-uri lsp-yaml-schema-store-local-db force-downloading)))

(defun lsp-yaml--get-supported-schemas ()
  "Get out the list of supported schemas."
  (when (and lsp-yaml-schema-store-enable
             (not lsp-yaml--schema-store-schemas-alist))
    (lsp-yaml-download-schema-store-db)
    (setq lsp-yaml--schema-store-schemas-alist
          (alist-get 'schemas (json-read-file lsp-yaml-schema-store-local-db))))
  (seq-concatenate 'list (list lsp-yaml--built-in-kubernetes-schema) lsp-yaml--schema-store-schemas-alist))

(defun lsp-yaml-set-buffer-schema (uri-string)
  "Set yaml schema for the current buffer to URI-STRING."
  (interactive "MURI: ")
  (let* ((uri (intern uri-string))
         (workspace-path (file-relative-name
                          (lsp--uri-to-path (lsp--buffer-uri))
                          (lsp-workspace-root (lsp--buffer-uri))))
         (glob (concat "/" workspace-path))
         (current-config (assoc uri lsp-yaml-schemas))
         (current-patterns (and current-config (cdr current-config))))
    (if current-config
        (or (member glob (append current-patterns nil))
            (setq lsp-yaml-schemas
                  (cl-acons uri
                            (vconcat (vector glob) current-patterns)
                            (assq-delete-all uri
                                             (mapcar (lambda (x) (lsp-yaml--remove-glob x glob))
                                                     lsp-yaml-schemas)))))
      (setq lsp-yaml-schemas
            (cl-acons uri (vector glob) (mapcar (lambda (x) (lsp-yaml--remove-glob x glob))
                                                lsp-yaml-schemas))))
    (lsp--set-configuration (lsp-configuration-section "yaml"))))

(defun lsp-yaml-select-buffer-schema ()
  "Select schema for the current buffer based on the list of supported schemas."
  (interactive)
  (let* ((schema (lsp--completing-read "Select buffer schema: "
                                       (lsp-yaml--get-supported-schemas)
                                       (lambda (schema)
                                         (format "%s: %s" (alist-get 'name schema)(alist-get 'description schema)))
                                       nil t))
         (uri (alist-get 'url schema)))
    (lsp-yaml-set-buffer-schema uri)))

(defun lsp-yaml--remove-glob (mapping glob)
  (let ((patterns (cdr mapping)))
    (cons (car mapping)
          (vconcat (-filter (lambda (p) (not (equal p glob)))
                            (append patterns nil)) nil))))

(lsp-consistency-check lsp-yaml)

(provide 'lsp-yaml)
;;; lsp-yaml.el ends here