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