]> code.delx.au - gnu-emacs-elpa/blob - packages/company/company-css.el
Update packages/yasnippet by subtree-merging from its github-based upstream
[gnu-emacs-elpa] / packages / company / company-css.el
1 ;;; company-css.el --- company-mode completion back-end for css-mode -*- lexical-binding: t -*-
2
3 ;; Copyright (C) 2009, 2011, 2014 Free Software Foundation, Inc.
4
5 ;; Author: Nikolaj Schumacher
6
7 ;; This file is part of GNU Emacs.
8
9 ;; GNU Emacs is free software: you can redistribute it and/or modify
10 ;; it under the terms of the GNU General Public License as published by
11 ;; the Free Software Foundation, either version 3 of the License, or
12 ;; (at your option) any later version.
13
14 ;; GNU Emacs is distributed in the hope that it will be useful,
15 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
16 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 ;; GNU General Public License for more details.
18
19 ;; You should have received a copy of the GNU General Public License
20 ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
21
22 ;;; Commentary:
23
24 ;;; Code:
25
26 (require 'company)
27 (require 'cl-lib)
28
29 (defconst company-css-property-alist
30 ;; see http://www.w3.org/TR/CSS21/propidx.html
31 '(("azimuth" angle "left-side" "far-left" "left" "center-left" "center"
32 "center-right" "right" "far-right" "right-side" "behind" "leftwards"
33 "rightwards")
34 ("background" background-color background-image background-repeat
35 background-attachment background-position
36 background-clip background-origin background-size)
37 ("background-attachment" "scroll" "fixed")
38 ("background-color" color "transparent")
39 ("background-image" uri "none")
40 ("background-position" percentage length "left" "center" "right" percentage
41 length "top" "center" "bottom" "left" "center" "right" "top" "center"
42 "bottom")
43 ("background-repeat" "repeat" "repeat-x" "repeat-y" "no-repeat")
44 ("border" border-width border-style border-color)
45 ("border-bottom" border)
46 ("border-bottom-color" border-color)
47 ("border-bottom-style" border-style)
48 ("border-bottom-width" border-width)
49 ("border-collapse" "collapse" "separate")
50 ("border-color" color "transparent")
51 ("border-left" border)
52 ("border-left-color" border-color)
53 ("border-left-style" border-style)
54 ("border-left-width" border-width)
55 ("border-right" border)
56 ("border-right-color" border-color)
57 ("border-right-style" border-style)
58 ("border-right-width" border-width)
59 ("border-spacing" length length)
60 ("border-style" border-style)
61 ("border-top" border)
62 ("border-top-color" border-color)
63 ("border-top-style" border-style)
64 ("border-top-width" border-width)
65 ("border-width" border-width)
66 ("bottom" length percentage "auto")
67 ("caption-side" "top" "bottom")
68 ("clear" "none" "left" "right" "both")
69 ("clip" shape "auto")
70 ("color" color)
71 ("content" "normal" "none" string uri counter "attr()" "open-quote"
72 "close-quote" "no-open-quote" "no-close-quote")
73 ("counter-increment" identifier integer "none")
74 ("counter-reset" identifier integer "none")
75 ("cue" cue-before cue-after)
76 ("cue-after" uri "none")
77 ("cue-before" uri "none")
78 ("cursor" uri "*" "auto" "crosshair" "default" "pointer" "move" "e-resize"
79 "ne-resize" "nw-resize" "n-resize" "se-resize" "sw-resize" "s-resize"
80 "w-resize" "text" "wait" "help" "progress")
81 ("direction" "ltr" "rtl")
82 ("display" "inline" "block" "list-item" "run-in" "inline-block" "table"
83 "inline-table" "table-row-group" "table-header-group" "table-footer-group"
84 "table-row" "table-column-group" "table-column" "table-cell"
85 "table-caption" "none")
86 ("elevation" angle "below" "level" "above" "higher" "lower")
87 ("empty-cells" "show" "hide")
88 ("float" "left" "right" "none")
89 ("font" font-style font-weight font-size "/" line-height
90 font-family "caption" "icon" "menu" "message-box" "small-caption"
91 "status-bar" "normal" "small-caps"
92 ;; CSS3
93 font-stretch)
94 ("font-family" family-name generic-family)
95 ("font-size" absolute-size relative-size length percentage)
96 ("font-style" "normal" "italic" "oblique")
97 ("font-weight" "normal" "bold" "bolder" "lighter" "100" "200" "300" "400"
98 "500" "600" "700" "800" "900")
99 ("height" length percentage "auto")
100 ("left" length percentage "auto")
101 ("letter-spacing" "normal" length)
102 ("line-height" "normal" number length percentage)
103 ("list-style" list-style-type list-style-position list-style-image)
104 ("list-style-image" uri "none")
105 ("list-style-position" "inside" "outside")
106 ("list-style-type" "disc" "circle" "square" "decimal" "decimal-leading-zero"
107 "lower-roman" "upper-roman" "lower-greek" "lower-latin" "upper-latin"
108 "armenian" "georgian" "lower-alpha" "upper-alpha" "none")
109 ("margin" margin-width)
110 ("margin-bottom" margin-width)
111 ("margin-left" margin-width)
112 ("margin-right" margin-width)
113 ("margin-top" margin-width)
114 ("max-height" length percentage "none")
115 ("max-width" length percentage "none")
116 ("min-height" length percentage)
117 ("min-width" length percentage)
118 ("orphans" integer)
119 ("outline" outline-color outline-style outline-width)
120 ("outline-color" color "invert")
121 ("outline-style" border-style)
122 ("outline-width" border-width)
123 ("overflow" "visible" "hidden" "scroll" "auto"
124 ;; CSS3:
125 "no-display" "no-content")
126 ("padding" padding-width)
127 ("padding-bottom" padding-width)
128 ("padding-left" padding-width)
129 ("padding-right" padding-width)
130 ("padding-top" padding-width)
131 ("page-break-after" "auto" "always" "avoid" "left" "right")
132 ("page-break-before" "auto" "always" "avoid" "left" "right")
133 ("page-break-inside" "avoid" "auto")
134 ("pause" time percentage)
135 ("pause-after" time percentage)
136 ("pause-before" time percentage)
137 ("pitch" frequency "x-low" "low" "medium" "high" "x-high")
138 ("pitch-range" number)
139 ("play-during" uri "mix" "repeat" "auto" "none")
140 ("position" "static" "relative" "absolute" "fixed")
141 ("quotes" string string "none")
142 ("richness" number)
143 ("right" length percentage "auto")
144 ("speak" "normal" "none" "spell-out")
145 ("speak-header" "once" "always")
146 ("speak-numeral" "digits" "continuous")
147 ("speak-punctuation" "code" "none")
148 ("speech-rate" number "x-slow" "slow" "medium" "fast" "x-fast" "faster"
149 "slower")
150 ("stress" number)
151 ("table-layout" "auto" "fixed")
152 ("text-align" "left" "right" "center" "justify")
153 ("text-indent" length percentage)
154 ("text-transform" "capitalize" "uppercase" "lowercase" "none")
155 ("top" length percentage "auto")
156 ("unicode-bidi" "normal" "embed" "bidi-override")
157 ("vertical-align" "baseline" "sub" "super" "top" "text-top" "middle"
158 "bottom" "text-bottom" percentage length)
159 ("visibility" "visible" "hidden" "collapse")
160 ("voice-family" specific-voice generic-voice "*" specific-voice
161 generic-voice)
162 ("volume" number percentage "silent" "x-soft" "soft" "medium" "loud"
163 "x-loud")
164 ("white-space" "normal" "pre" "nowrap" "pre-wrap" "pre-line")
165 ("widows" integer)
166 ("width" length percentage "auto")
167 ("word-spacing" "normal" length)
168 ("z-index" "auto" integer)
169 ;; CSS3
170 ("align-content" align-stretch "space-between" "space-around")
171 ("align-items" align-stretch "baseline")
172 ("align-self" align-items "auto")
173 ("animation" animation-name animation-duration animation-timing-function
174 animation-delay animation-iteration-count animation-direction
175 animation-fill-mode)
176 ("animation-delay" time)
177 ("animation-direction" "normal" "reverse" "alternate" "alternate-reverse")
178 ("animation-duration" time)
179 ("animation-fill-mode" "none" "forwards" "backwards" "both")
180 ("animation-iteration-count" integer "infinite")
181 ("animation-name" "none")
182 ("animation-play-state" "paused" "running")
183 ("animation-timing-function" transition-timing-function
184 "step-start" "step-end" "steps(,)")
185 ("backface-visibility" "visible" "hidden")
186 ("background-clip" background-origin)
187 ("background-origin" "border-box" "padding-box" "content-box")
188 ("background-size" length percentage "auto" "cover" "contain")
189 ("border-image" border-image-outset border-image-repeat border-image-source
190 border-image-slice border-image-width)
191 ("border-image-outset" length)
192 ("border-image-repeat" "stretch" "repeat" "round" "space")
193 ("border-image-source" uri "none")
194 ("border-image-slice" length)
195 ("border-image-width" length percentage)
196 ("border-radius" length)
197 ("border-top-left-radius" length)
198 ("border-top-right-radius" length)
199 ("border-bottom-left-radius" length)
200 ("border-bottom-right-radius" length)
201 ("box-decoration-break" "slice" "clone")
202 ("box-shadow" length color)
203 ("box-sizing" "content-box" "border-box")
204 ("break-after" "auto" "always" "avoid" "left" "right" "page" "column"
205 "avoid-page" "avoid-column")
206 ("break-before" break-after)
207 ("break-inside" "avoid" "auto")
208 ("columns" column-width column-count)
209 ("column-count" integer)
210 ("column-fill" "auto" "balance")
211 ("column-gap" length "normal")
212 ("column-rule" column-rule-width column-rule-style column-rule-color)
213 ("column-rule-color" color)
214 ("column-rule-style" border-style)
215 ("column-rule-width" border-width)
216 ("column-span" "all" "none")
217 ("column-width" length "auto")
218 ("filter" url "blur()" "brightness()" "contrast()" "drop-shadow()"
219 "grayscale()" "hue-rotate()" "invert()" "opacity()" "saturate()" "sepia()")
220 ("flex" flex-grow flex-shrink flex-basis)
221 ("flex-basis" percentage length "auto")
222 ("flex-direction" "row" "row-reverse" "column" "column-reverse")
223 ("flex-flow" flex-direction flex-wrap)
224 ("flex-grow" number)
225 ("flex-shrink" number)
226 ("flex-wrap" "nowrap" "wrap" "wrap-reverse")
227 ("font-feature-setting" normal string number)
228 ("font-kerning" "auto" "normal" "none")
229 ("font-language-override" "normal" string)
230 ("font-size-adjust" "none" number)
231 ("font-stretch" "normal" "ultra-condensed" "extra-condensed" "condensed"
232 "semi-condensed" "semi-expanded" "expanded" "extra-expanded" "ultra-expanded")
233 ("font-synthesis" "none" "weight" "style")
234 ("font-variant" font-variant-alternates font-variant-caps
235 font-variant-east-asian font-variant-ligatures font-variant-numeric
236 font-variant-position)
237 ("font-variant-alternates" "normal" "historical-forms" "stylistic()"
238 "styleset()" "character-variant()" "swash()" "ornaments()" "annotation()")
239 ("font-variant-caps" "normal" "small-caps" "all-small-caps" "petite-caps"
240 "all-petite-caps" "unicase" "titling-caps")
241 ("font-variant-east-asian" "jis78" "jis83" "jis90" "jis04" "simplified"
242 "traditional" "full-width" "proportional-width" "ruby")
243 ("font-variant-ligatures" "normal" "none" "common-ligatures"
244 "no-common-ligatures" "discretionary-ligatures" "no-discretionary-ligatures"
245 "historical-ligatures" "no-historical-ligatures" "contextual" "no-contextual")
246 ("font-variant-numeric" "normal" "ordinal" "slashed-zero"
247 "lining-nums" "oldstyle-nums" "proportional-nums" "tabular-nums"
248 "diagonal-fractions" "stacked-fractions")
249 ("font-variant-position" "normal" "sub" "super")
250 ("hyphens" "none" "manual" "auto")
251 ("justify-content" align-common "space-between" "space-around")
252 ("line-break" "auto" "loose" "normal" "strict")
253 ("marquee-direction" "forward" "reverse")
254 ("marquee-play-count" integer "infinite")
255 ("marquee-speed" "slow" "normal" "fast")
256 ("marquee-style" "scroll" "slide" "alternate")
257 ("opacity" number)
258 ("order" number)
259 ("outline-offset" length)
260 ("overflow-x" overflow)
261 ("overflow-y" overflow)
262 ("overflow-style" "auto" "marquee-line" "marquee-block")
263 ("overflow-wrap" "normal" "break-word")
264 ("perspective" "none" length)
265 ("perspective-origin" percentage length "left" "center" "right" "top" "bottom")
266 ("resize" "none" "both" "horizontal" "vertical")
267 ("tab-size" integer length)
268 ("text-align-last" "auto" "start" "end" "left" "right" "center" "justify")
269 ("text-decoration" text-decoration-color text-decoration-line text-decoration-style)
270 ("text-decoration-color" color)
271 ("text-decoration-line" "none" "underline" "overline" "line-through" "blink")
272 ("text-decoration-style" "solid" "double" "dotted" "dashed" "wavy")
273 ("text-overflow" "clip" "ellipsis")
274 ("text-shadow" color length)
275 ("text-underline-position" "auto" "under" "left" "right")
276 ("transform" "matrix(,,,,,)" "translate(,)" "translateX()" "translateY()"
277 "scale()" "scaleX()" "scaleY()" "rotate()" "skewX()" "skewY()" "none")
278 ("transform-origin" perspective-origin)
279 ("transform-style" "flat" "preserve-3d")
280 ("transition" transition-property transition-duration
281 transition-timing-function transition-delay)
282 ("transition-delay" time)
283 ("transition-duration" time)
284 ("transition-timing-function"
285 "ease" "linear" "ease-in" "ease-out" "ease-in-out" "cubic-bezier(,,,)")
286 ("transition-property" "none" "all" identifier)
287 ("word-wrap" overflow-wrap)
288 ("word-break" "normal" "break-all" "keep-all"))
289 "A list of CSS properties and their possible values.")
290
291 (defconst company-css-value-classes
292 '((absolute-size "xx-small" "x-small" "small" "medium" "large" "x-large"
293 "xx-large")
294 (align-common "flex-start" "flex-end" "center")
295 (align-stretch align-common "stretch")
296 (border-style "none" "hidden" "dotted" "dashed" "solid" "double" "groove"
297 "ridge" "inset" "outset")
298 (border-width "thick" "medium" "thin")
299 (color "aqua" "black" "blue" "fuchsia" "gray" "green" "lime" "maroon" "navy"
300 "olive" "orange" "purple" "red" "silver" "teal" "white" "yellow")
301 (counter "counter(,)")
302 (family-name "Courier" "Helvetica" "Times")
303 (generic-family "serif" "sans-serif" "cursive" "fantasy" "monospace")
304 (generic-voice "male" "female" "child")
305 (margin-width "auto") ;; length percentage
306 (relative-size "larger" "smaller")
307 (shape "rect(,,,)")
308 (uri "url()"))
309 "A list of CSS property value classes and their contents.")
310 ;; missing, because not completable
311 ;; <angle><frequency><identifier><integer><length><number><padding-width>
312 ;; <percentage><specific-voice><string><time><uri>
313
314 (defconst company-css-html-tags
315 '("a" "abbr" "acronym" "address" "applet" "area" "b" "base" "basefont" "bdo"
316 "big" "blockquote" "body" "br" "button" "caption" "center" "cite" "code"
317 "col" "colgroup" "dd" "del" "dfn" "dir" "div" "dl" "dt" "em" "fieldset"
318 "font" "form" "frame" "frameset" "h1" "h2" "h3" "h4" "h5" "h6" "head" "hr"
319 "html" "i" "iframe" "img" "input" "ins" "isindex" "kbd" "label" "legend"
320 "li" "link" "map" "menu" "meta" "noframes" "noscript" "object" "ol"
321 "optgroup" "option" "p" "param" "pre" "q" "s" "samp" "script" "select"
322 "small" "span" "strike" "strong" "style" "sub" "sup" "table" "tbody" "td"
323 "textarea" "tfoot" "th" "thead" "title" "tr" "tt" "u" "ul" "var"
324 ;; HTML5
325 "section" "article" "aside" "header" "footer" "nav" "figure" "figcaption"
326 "time" "mark" "main")
327 "A list of HTML tags for use in CSS completion.")
328
329 (defconst company-css-pseudo-classes
330 '("active" "after" "before" "first" "first-child" "first-letter" "first-line"
331 "focus" "hover" "lang" "left" "link" "right" "visited")
332 "Identifiers for CSS pseudo-elements and pseudo-classes.")
333
334 (defconst company-css-property-cache (make-hash-table :size 115 :test 'equal))
335
336 (defun company-css-property-values (attribute)
337 "Access the `company-css-property-alist' cached and flattened."
338 (or (gethash attribute company-css-property-cache)
339 (let (results)
340 (dolist (value (cdr (assoc attribute company-css-property-alist)))
341 (if (symbolp value)
342 (dolist (child (or (cdr (assoc value company-css-value-classes))
343 (company-css-property-values
344 (symbol-name value))))
345 (push child results))
346 (push value results)))
347 (setq results (sort results 'string<))
348 (puthash attribute
349 (if (fboundp 'delete-consecutive-dups)
350 (delete-consecutive-dups results)
351 (delete-dups results))
352 company-css-property-cache)
353 results)))
354
355 ;;; bracket detection
356
357 (defconst company-css-braces-syntax-table
358 (let ((table (make-syntax-table)))
359 (setf (aref table ?{) '(4 . 125))
360 (setf (aref table ?}) '(5 . 123))
361 table)
362 "A syntax table giving { and } paren syntax.")
363
364 (defun company-css-inside-braces-p ()
365 "Return non-nil, if point is within matched { and }."
366 (ignore-errors
367 (with-syntax-table company-css-braces-syntax-table
368 (let ((parse-sexp-ignore-comments t))
369 (scan-lists (point) -1 1)))))
370
371 ;;; tags
372 (defconst company-css-tag-regexp
373 (concat "\\(?:\\`\\|}\\)[[:space:]]*"
374 ;; multiple
375 "\\(?:"
376 ;; previous tags:
377 "\\(?:#\\|\\_<[[:alpha:]]\\)[[:alnum:]-#]*\\(?:\\[[^]]*\\]\\)?"
378 ;; space or selectors
379 "\\(?:[[:space:]]+\\|[[:space:]]*[+,>][[:space:]]*\\)"
380 "\\)*"
381 "\\(\\(?:#\\|\\_<[[:alpha:]]\\)\\(?:[[:alnum:]-#]*\\_>\\)?\\_>\\|\\)"
382 "\\=")
383 "A regular expression matching CSS tags.")
384
385 ;;; pseudo id
386 (defconst company-css-pseudo-regexp
387 (concat "\\(?:\\`\\|}\\)[[:space:]]*"
388 ;; multiple
389 "\\(?:"
390 ;; previous tags:
391 "\\(?:#\\|\\_<[[:alpha:]]\\)[[:alnum:]-#]*\\(?:\\[[^]]*\\]\\)?"
392 ;; space or delimiters
393 "\\(?:[[:space:]]+\\|[[:space:]]*[+,>][[:space:]]*\\)"
394 "\\)*"
395 "\\(?:\\(?:\\#\\|\\_<[[:alpha:]]\\)[[:alnum:]-#]*\\):"
396 "\\([[:alpha:]-]+\\_>\\|\\)\\_>\\=")
397 "A regular expression matching CSS pseudo classes.")
398
399 ;;; properties
400
401 (defun company-css-grab-property ()
402 "Return the CSS property before point, if any.
403 Returns \"\" if no property found, but feasible at this position."
404 (when (company-css-inside-braces-p)
405 (company-grab-symbol)))
406
407 ;;; values
408 (defconst company-css-property-value-regexp
409 "\\_<\\([[:alpha:]-]+\\):\\(?:[^{};]*[[:space:]]+\\)?\\([^{};]*\\_>\\|\\)\\="
410 "A regular expression matching CSS tags.")
411
412 ;;;###autoload
413 (defun company-css (command &optional arg &rest ignored)
414 "`company-mode' completion back-end for `css-mode'."
415 (interactive (list 'interactive))
416 (cl-case command
417 (interactive (company-begin-backend 'company-css))
418 (prefix (and (derived-mode-p 'css-mode)
419 (or (company-grab company-css-tag-regexp 1)
420 (company-grab company-css-pseudo-regexp 1)
421 (company-grab company-css-property-value-regexp 2)
422 (company-css-grab-property))))
423 (candidates
424 (cond
425 ((company-grab company-css-tag-regexp 1)
426 (all-completions arg company-css-html-tags))
427 ((company-grab company-css-pseudo-regexp 1)
428 (all-completions arg company-css-pseudo-classes))
429 ((company-grab company-css-property-value-regexp 2)
430 (all-completions arg
431 (company-css-property-values
432 (company-grab company-css-property-value-regexp 1))))
433 ((company-css-grab-property)
434 (all-completions arg company-css-property-alist))))
435 (sorted t)))
436
437 (provide 'company-css)
438 ;;; company-css.el ends here