]> code.delx.au - gnu-emacs-elpa/blob - company-css.el
Added support for CSS.
[gnu-emacs-elpa] / company-css.el
1 (require 'company)
2 (eval-when-compile (require 'cl))
3
4 (defconst company-css-property-alist
5 ;; see http://www.w3.org/TR/CSS21/propidx.html
6 '(("azimuth" angle "left-side" "far-left" "left" "center-left" "center"
7 "center-right" "right" "far-right" "right-side" "behind" "leftwards"
8 "rightwards")
9 ("background" background-color background-image background-repeat
10 background-attachment background-position)
11 ("background-attachment" "scroll" "fixed")
12 ("background-color" color "transparent")
13 ("background-image" uri "none")
14 ("background-position" percentage length "left" "center" "right" percentage
15 length "top" "center" "bottom" "left" "center" "right" "top" "center"
16 "bottom")
17 ("background-repeat" "repeat" "repeat-x" "repeat-y" "no-repeat")
18 ("border" border-width border-style border-color)
19 ("border-bottom" border)
20 ("border-bottom-color" border-color)
21 ("border-bottom-style" border-style)
22 ("border-bottom-width" border-width)
23 ("border-collapse" "collapse" "separate")
24 ("border-color" color "transparent")
25 ("border-left" border)
26 ("border-left-color" border-color)
27 ("border-left-style" border-style)
28 ("border-left-width" border-width)
29 ("border-right" border)
30 ("border-right-color" border-color)
31 ("border-right-style" border-style)
32 ("border-right-width" border-width)
33 ("border-spacing" length length)
34 ("border-style" border-style)
35 ("border-top" border)
36 ("border-top-color" border-color)
37 ("border-top-style" border-style)
38 ("border-top-width" border-width)
39 ("border-width" border-width)
40 ("bottom" length percentage "auto")
41 ("caption-side" "top" "bottom")
42 ("clear" "none" "left" "right" "both")
43 ("clip" shape "auto")
44 ("color" color)
45 ("content" "normal" "none" string uri counter "attr()" "open-quote"
46 "close-quote" "no-open-quote" "no-close-quote")
47 ("counter-increment" identifier integer "none")
48 ("counter-reset" identifier integer "none")
49 ("cue" cue-before cue-after)
50 ("cue-after" uri "none")
51 ("cue-before" uri "none")
52 ("cursor" uri "*" "auto" "crosshair" "default" "pointer" "move" "e-resize"
53 "ne-resize" "nw-resize" "n-resize" "se-resize" "sw-resize" "s-resize"
54 "w-resize" "text" "wait" "help" "progress")
55 ("direction" "ltr" "rtl")
56 ("display" "inline" "block" "list-item" "run-in" "inline-block" "table"
57 "inline-table" "table-row-group" "table-header-group" "table-footer-group"
58 "table-row" "table-column-group" "table-column" "table-cell"
59 "table-caption" "none")
60 ("elevation" angle "below" "level" "above" "higher" "lower")
61 ("empty-cells" "show" "hide")
62 ("float" "left" "right" "none")
63 ("font" font-style font-variant font-weight font-size "/" line-height
64 font-family "caption" "icon" "menu" "message-box" "small-caption"
65 "status-bar")
66 ("font-family" family-name generic-family)
67 ("font-size" absolute-size relative-size length percentage)
68 ("font-style" "normal" "italic" "oblique")
69 ("font-variant" "normal" "small-caps")
70 ("font-weight" "normal" "bold" "bolder" "lighter" "100" "200" "300" "400"
71 "500" "600" "700" "800" "900")
72 ("height" length percentage "auto")
73 ("left" length percentage "auto")
74 ("letter-spacing" "normal" length)
75 ("line-height" "normal" number length percentage)
76 ("list-style" list-style-type list-style-position list-style-image)
77 ("list-style-image" uri "none")
78 ("list-style-position" "inside" "outside")
79 ("list-style-type" "disc" "circle" "square" "decimal" "decimal-leading-zero"
80 "lower-roman" "upper-roman" "lower-greek" "lower-latin" "upper-latin"
81 "armenian" "georgian" "lower-alpha" "upper-alpha" "none")
82 ("margin" margin-width)
83 ("margin-bottom" margin-width)
84 ("margin-left" margin-width)
85 ("margin-right" margin-width)
86 ("margin-top" margin-width)
87 ("max-height" length percentage "none")
88 ("max-width" length percentage "none")
89 ("min-height" length percentage)
90 ("min-width" length percentage)
91 ("orphans" integer)
92 ("outline" outline-color outline-style outline-width)
93 ("outline-color" color "invert")
94 ("outline-style" border-style)
95 ("outline-width" border-width)
96 ("overflow" "visible" "hidden" "scroll" "auto")
97 ("padding" padding-width)
98 ("padding-bottom" padding-width)
99 ("padding-left" padding-width)
100 ("padding-right" padding-width)
101 ("padding-top" padding-width)
102 ("page-break-after" "auto" "always" "avoid" "left" "right")
103 ("page-break-before" "auto" "always" "avoid" "left" "right")
104 ("page-break-inside" "avoid" "auto")
105 ("pause" time percentage)
106 ("pause-after" time percentage)
107 ("pause-before" time percentage)
108 ("pitch" frequency "x-low" "low" "medium" "high" "x-high")
109 ("pitch-range" number)
110 ("play-during" uri "mix" "repeat" "auto" "none")
111 ("position" "static" "relative" "absolute" "fixed")
112 ("quotes" string string "none")
113 ("richness" number)
114 ("right" length percentage "auto")
115 ("speak" "normal" "none" "spell-out")
116 ("speak-header" "once" "always")
117 ("speak-numeral" "digits" "continuous")
118 ("speak-punctuation" "code" "none")
119 ("speech-rate" number "x-slow" "slow" "medium" "fast" "x-fast" "faster"
120 "slower")
121 ("stress" number)
122 ("table-layout" "auto" "fixed")
123 ("text-align" "left" "right" "center" "justify")
124 ("text-decoration" "none" "underline" "overline" "line-through" "blink")
125 ("text-indent" length percentage)
126 ("text-transform" "capitalize" "uppercase" "lowercase" "none")
127 ("top" length percentage "auto")
128 ("unicode-bidi" "normal" "embed" "bidi-override")
129 ("vertical-align" "baseline" "sub" "super" "top" "text-top" "middle"
130 "bottom" "text-bottom" percentage length)
131 ("visibility" "visible" "hidden" "collapse")
132 ("voice-family" specific-voice generic-voice "*" specific-voice
133 generic-voice)
134 ("volume" number percentage "silent" "x-soft" "soft" "medium" "loud"
135 "x-loud")
136 ("white-space" "normal" "pre" "nowrap" "pre-wrap" "pre-line")
137 ("widows" integer)
138 ("width" length percentage "auto")
139 ("word-spacing" "normal" length)
140 ("z-index" "auto" integer))
141 "A list of CSS properties and their possible values.")
142
143 (defconst company-css-value-classes
144 '((absolute-size "xx-small" "x-small" "small" "medium" "large" "x-large"
145 "xx-large")
146 (border-style "none" "hidden" "dotted" "dashed" "solid" "double" "groove"
147 "ridge" "inset" "outset")
148 (color "aqua" "black" "blue" "fuchsia" "gray" "green" "lime" "maroon" "navy"
149 "olive" "orange" "purple" "red" "silver" "teal" "white" "yellow")
150 (counter "counter(,)")
151 (family-name "Courier" "Helvetica" "Times")
152 (generic-family "serif" "sans-serif" "cursive" "fantasy" "monospace")
153 (generic-voice "male" "female" "child")
154 (margin-width "auto") ;; length percentage
155 (relative-size "larger" "smaller")
156 (shape "rect(,,,)")
157 (uri "url()"))
158 "A list of CSS property value classes and their contents.")
159 ;; missing, because not completable
160 ;; <angle><frequency><identifier><integer><length><number><padding-width>
161 ;; <percentage><specific-voice><string><time><uri>
162
163 (defconst company-css-html-tags
164 '("a" "abbr" "acronym" "address" "applet" "area" "b" "base" "basefont" "bdo"
165 "big" "blockquote" "body" "br" "button" "caption" "center" "cite" "code"
166 "col" "colgroup" "dd" "del" "dfn" "dir" "div" "dl" "dt" "em" "fieldset"
167 "font" "form" "frame" "frameset" "h1" "h2" "h3" "h4" "h5" "h6" "head" "hr"
168 "html" "i" "iframe" "img" "input" "ins" "isindex" "kbd" "label" "legend"
169 "li" "link" "map" "menu" "meta" "noframes" "noscript" "object" "ol"
170 "optgroup" "option" "p" "param" "pre" "q" "s" "samp" "script" "select"
171 "small" "span" "strike" "strong" "style" "sub" "sup" "table" "tbody" "td"
172 "textarea" "tfoot" "th" "thead" "title" "tr" "tt" "u" "ul" "var")
173 "A list of HTML tags for use in CSS completion.")
174
175 (defconst company-css-pseudo-classes
176 '("active" "after" "before" "first" "first-child" "first-letter" "first-line"
177 "focus" "hover" "lang" "left" "link" "right" "visited")
178 "Identifiers for CSS pseudo-elements and pseudo-classes.")
179
180 (defconst company-css-property-cache (make-hash-table :size 115 :test 'equal))
181
182 (defun company-css-property-values (attribute)
183 "Access the `company-css-property-alist' cached and flattened."
184 (or (gethash attribute company-css-property-cache)
185 (let (results)
186 (dolist (value (cdr (assoc attribute company-css-property-alist)))
187 (if (symbolp value)
188 (dolist (child (or (cdr (assoc value company-css-value-classes))
189 (company-css-property-values
190 (symbol-name value))))
191 (add-to-list 'results child))
192 (add-to-list 'results value)))
193 (setq results (sort results 'string<))
194 (puthash attribute results company-css-property-cache)
195 results)))
196
197 ;;; bracket detection
198
199 (defconst company-css-braces-syntax-table
200 (let ((table (make-syntax-table)))
201 (setf (aref table ?{) '(4 . 125))
202 (setf (aref table ?}) '(5 . 123))
203 table)
204 "A syntax table giving { and } paren syntax.")
205
206 (defun company-css-inside-braces-p ()
207 "Return non-nil, if point is within matched { and }."
208 (ignore-errors
209 (with-syntax-table company-css-braces-syntax-table
210 (let ((parse-sexp-ignore-comments t))
211 (scan-lists (point) -1 1)))))
212
213 ;;; tags
214 (defconst company-css-tag-regexp
215 (concat "\\(?:\\`\\|}\\)[[:space:]]*"
216 ;; multiple
217 "\\(?:"
218 ;; previous tags:
219 "\\(?:#\\|\\_<[[:alpha:]]\\)[[:alnum:]-#]*\\(?:\\[[^]]*\\]\\)?"
220 ;; space or selectors
221 "\\(?:[[:space:]]+\\|[[:space:]]*[+,>][[:space:]]*\\)"
222 "\\)*"
223 "\\(\\(?:#\\|\\_<[[:alpha:]]\\)\\(?:[[:alnum:]-#]*\\_>\\)?\\_>\\|\\)"
224 "\\=")
225 "A regular expression matching CSS tags")
226
227 ;;; pseudo id
228 (defconst company-css-pseudo-regexp
229 (concat "\\(?:\\`\\|}\\)[[:space:]]*"
230 ;; multiple
231 "\\(?:"
232 ;; previous tags:
233 "\\(?:#\\|\\_<[[:alpha:]]\\)[[:alnum:]-#]*\\(?:\\[[^]]*\\]\\)?"
234 ;; space or delimiters
235 "\\(?:[[:space:]]+\\|[[:space:]]*[+,>][[:space:]]*\\)"
236 "\\)*"
237 "\\(?:\\(?:\\#\\|\\_<[[:alpha:]]\\)[[:alnum:]-#]*\\):"
238 "\\([[:alpha:]-]+\\_>\\|\\)\\_>\\=")
239 "A regular expression matching CSS pseudo classes")
240
241 ;;; properties
242
243 (defun company-css-grab-property ()
244 "Return the CSS property before point, if any.
245 Returns \"\" if no property found, but feasible at this position."
246 (when (company-css-inside-braces-p)
247 (or (company-grab "\\_<[[:alpha:]-]+\\_>\\=")
248 (company-grab "{\\|[[:space:]]" 1))))
249
250 ;;; values
251 (defconst company-css-property-value-regexp
252 "\\_<\\([[:alpha:]-]+\\):\\(?:[^};]*[[:space:]]+\\)?\\([^};]*\\_>\\|\\)\\="
253 "A regular expression matching CSS tags")
254
255 (defun company-css (command &optional arg &rest ignored)
256 (case command
257 ('prefix (and (eq major-mode 'css-mode)
258 (or (company-grab company-css-tag-regexp 1)
259 (company-grab company-css-pseudo-regexp 1)
260 (company-grab company-css-property-value-regexp 2)
261 (company-css-grab-property))))
262 ('candidates
263 (cond
264 ((company-grab company-css-tag-regexp 1)
265 (all-completions arg company-css-html-tags))
266 ((company-grab company-css-pseudo-regexp 1)
267 (all-completions arg company-css-pseudo-classes))
268 ((company-grab company-css-property-value-regexp 2)
269 (all-completions arg
270 (company-css-property-values
271 (company-grab company-css-property-value-regexp 1))))
272 ((company-css-grab-property)
273 (all-completions arg company-css-property-alist))))
274 ('sorted t)))
275
276 (provide 'company-css)
277 ;;; company-css.el ends here