Mercurial > emacs
annotate lisp/textmodes/css-mode.el @ 107189:a48b193e3b5f
(tramp-handle-insert-file-contents): Set always the permissions of the
temporary file to "0600". In case the remote
file has no read permissions for the owner, there might be
problems otherwise. Reported by Ole Laursen <olau@iola.dk>.
author | Michael Albinus <michael.albinus@gmx.de> |
---|---|
date | Thu, 18 Feb 2010 11:03:12 +0100 |
parents | 1d1d5d9bd884 |
children | 8ceadb47c51e 376148b31b5e |
rev | line source |
---|---|
77923 | 1 ;;; css-mode.el --- Major mode to edit CSS files |
2 | |
106815 | 3 ;; Copyright (C) 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. |
77923 | 4 |
5 ;; Author: Stefan Monnier <monnier@iro.umontreal.ca> | |
6 ;; Keywords: hypermedia | |
7 | |
94670
f4a69fedbd46
Switch to recommended form of GPLv3 permissions notice.
Glenn Morris <rgm@gnu.org>
parents:
92692
diff
changeset
|
8 ;; This file is part of GNU Emacs. |
f4a69fedbd46
Switch to recommended form of GPLv3 permissions notice.
Glenn Morris <rgm@gnu.org>
parents:
92692
diff
changeset
|
9 |
f4a69fedbd46
Switch to recommended form of GPLv3 permissions notice.
Glenn Morris <rgm@gnu.org>
parents:
92692
diff
changeset
|
10 ;; GNU Emacs is free software: you can redistribute it and/or modify |
77923 | 11 ;; it under the terms of the GNU General Public License as published by |
94670
f4a69fedbd46
Switch to recommended form of GPLv3 permissions notice.
Glenn Morris <rgm@gnu.org>
parents:
92692
diff
changeset
|
12 ;; the Free Software Foundation, either version 3 of the License, or |
f4a69fedbd46
Switch to recommended form of GPLv3 permissions notice.
Glenn Morris <rgm@gnu.org>
parents:
92692
diff
changeset
|
13 ;; (at your option) any later version. |
77923 | 14 |
94670
f4a69fedbd46
Switch to recommended form of GPLv3 permissions notice.
Glenn Morris <rgm@gnu.org>
parents:
92692
diff
changeset
|
15 ;; GNU Emacs is distributed in the hope that it will be useful, |
77923 | 16 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of |
17 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
18 ;; GNU General Public License for more details. | |
19 | |
20 ;; You should have received a copy of the GNU General Public License | |
94670
f4a69fedbd46
Switch to recommended form of GPLv3 permissions notice.
Glenn Morris <rgm@gnu.org>
parents:
92692
diff
changeset
|
21 ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. |
77923 | 22 |
23 ;;; Commentary: | |
24 | |
25 ;; Yet another CSS mode. | |
26 | |
27 ;;; Todo: | |
28 | |
29 ;; - electric ; and } | |
30 ;; - filling code with auto-fill-mode | |
31 ;; - completion | |
32 ;; - fix font-lock errors with multi-line selectors | |
33 | |
34 ;;; Code: | |
35 | |
84579 | 36 (defgroup css nil |
37 "Cascading Style Sheets (CSS) editing mode." | |
38 :group 'languages) | |
39 | |
79187 | 40 (eval-when-compile (require 'cl)) |
41 | |
77923 | 42 (defun css-extract-keyword-list (res) |
43 (with-temp-buffer | |
44 (url-insert-file-contents "http://www.w3.org/TR/REC-CSS2/css2.txt") | |
45 (goto-char (point-max)) | |
46 (search-backward "Appendix H. Index") | |
47 (forward-line) | |
48 (delete-region (point-min) (point)) | |
49 (let ((result nil) | |
50 keys) | |
51 (dolist (re res) | |
52 (goto-char (point-min)) | |
53 (setq keys nil) | |
54 (while (re-search-forward (cdr re) nil t) | |
55 (push (match-string 1) keys)) | |
56 (push (cons (car re) (sort keys 'string-lessp)) result)) | |
57 (nreverse result)))) | |
58 | |
59 (defun css-extract-parse-val-grammar (string env) | |
60 (let ((start 0) | |
61 (elems ()) | |
62 name) | |
63 (while (string-match | |
64 (concat "\\(?:" | |
65 (concat "<a [^>]+><span [^>]+>\\(?:" | |
66 "<\\([^&]+\\)>\\|'\\([^']+\\)'" | |
67 "\\)</span></a>") | |
68 "\\|" "\\(\\[\\)" | |
69 "\\|" "\\(]\\)" | |
70 "\\|" "\\(||\\)" | |
71 "\\|" "\\(|\\)" | |
72 "\\|" "\\([*+?]\\)" | |
73 "\\|" "\\({[^}]+}\\)" | |
74 "\\|" "\\(\\w+\\(?:-\\w+\\)*\\)" | |
75 "\\)[ \t\n]*") | |
76 string start) | |
77 ;; (assert (eq start (match-beginning 0))) | |
78 (setq start (match-end 0)) | |
79 (cond | |
80 ;; Reference to a type of value. | |
81 ((setq name (match-string-no-properties 1 string)) | |
82 (push (intern name) elems)) | |
83 ;; Reference to another property's values. | |
84 ((setq name (match-string-no-properties 2 string)) | |
85 (setq elems (delete-dups (append (cdr (assoc name env)) elems)))) | |
86 ;; A literal | |
87 ((setq name (match-string-no-properties 9 string)) | |
88 (push name elems)) | |
89 ;; We just ignore the rest. I.e. we ignore the structure because | |
90 ;; it's too difficult to exploit anyway (it would allow us to only | |
91 ;; complete top/center/bottom after one of left/center/right and | |
92 ;; vice-versa). | |
93 (t nil))) | |
94 elems)) | |
101279
1d661f541768
* textmodes/css-mode.el (css-backward-sexp): Stop once
Juanma Barranquero <lekktu@gmail.com>
parents:
100908
diff
changeset
|
95 |
77923 | 96 |
97 (defun css-extract-props-and-vals () | |
98 (with-temp-buffer | |
99 (url-insert-file-contents "http://www.w3.org/TR/CSS21/propidx.html") | |
100 (goto-char (point-min)) | |
101 (let ((props ())) | |
102 (while (re-search-forward "#propdef-\\([^\"]+\\)\"><span class=\"propinst-\\1 xref\">'\\1'</span></a>" nil t) | |
103 (let ((prop (match-string-no-properties 1))) | |
104 (save-excursion | |
105 (goto-char (match-end 0)) | |
106 (search-forward "<td>") | |
107 (let ((vals-string (buffer-substring (point) | |
108 (progn | |
109 (re-search-forward "[ \t\n]+|[ \t\n]+<a href=\"cascade.html#value-def-inherit\" class=\"noxref\"><span class=\"value-inst-inherit\">inherit</span></a>") | |
110 (match-beginning 0))))) | |
101279
1d661f541768
* textmodes/css-mode.el (css-backward-sexp): Stop once
Juanma Barranquero <lekktu@gmail.com>
parents:
100908
diff
changeset
|
111 ;; |
77923 | 112 (push (cons prop (css-extract-parse-val-grammar vals-string props)) |
113 props))))) | |
114 props))) | |
115 | |
116 ;; Extraction was done with: | |
117 ;; (css-extract-keyword-list | |
118 ;; '((pseudo . "^ +\\* :\\([^ \n,]+\\)") | |
119 ;; (at . "^ +\\* @\\([^ \n,]+\\)") | |
120 ;; (descriptor . "^ +\\* '\\([^ '\n]+\\)' (descriptor)") | |
121 ;; (media . "^ +\\* '\\([^ '\n]+\\)' media group") | |
122 ;; (property . "^ +\\* '\\([^ '\n]+\\)',"))) | |
123 | |
124 (defconst css-pseudo-ids | |
125 '("active" "after" "before" "first" "first-child" "first-letter" "first-line" | |
126 "focus" "hover" "lang" "left" "link" "right" "visited") | |
127 "Identifiers for pseudo-elements and pseudo-classes.") | |
128 | |
129 (defconst css-at-ids | |
130 '("charset" "font-face" "import" "media" "page") | |
131 "Identifiers that appear in the form @foo.") | |
132 | |
133 (defconst css-descriptor-ids | |
134 '("ascent" "baseline" "bbox" "cap-height" "centerline" "definition-src" | |
135 "descent" "font-family" "font-size" "font-stretch" "font-style" | |
136 "font-variant" "font-weight" "mathline" "panose-1" "slope" "src" "stemh" | |
137 "stemv" "topline" "unicode-range" "units-per-em" "widths" "x-height") | |
138 "Identifiers for font descriptors.") | |
139 | |
140 (defconst css-media-ids | |
141 '("all" "aural" "bitmap" "continuous" "grid" "paged" "static" "tactile" | |
142 "visual") | |
143 "Identifiers for types of media.") | |
144 | |
145 (defconst css-property-ids | |
146 '("azimuth" "background" "background-attachment" "background-color" | |
147 "background-image" "background-position" "background-repeat" "block" | |
148 "border" "border-bottom" "border-bottom-color" "border-bottom-style" | |
149 "border-bottom-width" "border-collapse" "border-color" "border-left" | |
150 "border-left-color" "border-left-style" "border-left-width" "border-right" | |
151 "border-right-color" "border-right-style" "border-right-width" | |
152 "border-spacing" "border-style" "border-top" "border-top-color" | |
153 "border-top-style" "border-top-width" "border-width" "bottom" | |
154 "caption-side" "clear" "clip" "color" "compact" "content" | |
155 "counter-increment" "counter-reset" "cue" "cue-after" "cue-before" | |
156 "cursor" "dashed" "direction" "display" "dotted" "double" "elevation" | |
157 "empty-cells" "float" "font" "font-family" "font-size" "font-size-adjust" | |
158 "font-stretch" "font-style" "font-variant" "font-weight" "groove" "height" | |
159 "hidden" "inline" "inline-table" "inset" "left" "letter-spacing" | |
160 "line-height" "list-item" "list-style" "list-style-image" | |
161 "list-style-position" "list-style-type" "margin" "margin-bottom" | |
162 "margin-left" "margin-right" "margin-top" "marker-offset" "marks" | |
163 "max-height" "max-width" "min-height" "min-width" "orphans" "outline" | |
164 "outline-color" "outline-style" "outline-width" "outset" "overflow" | |
165 "padding" "padding-bottom" "padding-left" "padding-right" "padding-top" | |
166 "page" "page-break-after" "page-break-before" "page-break-inside" "pause" | |
167 "pause-after" "pause-before" "pitch" "pitch-range" "play-during" "position" | |
168 "quotes" "richness" "ridge" "right" "run-in" "size" "solid" "speak" | |
169 "speak-header" "speak-numeral" "speak-punctuation" "speech-rate" "stress" | |
170 "table" "table-caption" "table-cell" "table-column" "table-column-group" | |
171 "table-footer-group" "table-header-group" "table-layout" "table-row" | |
172 "table-row-group" "text-align" "text-decoration" "text-indent" | |
173 "text-shadow" "text-transform" "top" "unicode-bidi" "vertical-align" | |
174 "visibility" "voice-family" "volume" "white-space" "widows" "width" | |
175 "word-spacing" "z-index") | |
176 "Identifiers for properties.") | |
177 | |
78825
6ba709e4adda
(css-electric-keys): electrick->electric.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
78225
diff
changeset
|
178 (defcustom css-electric-keys '(?\} ?\;) ;; '() |
77923 | 179 "Self inserting keys which should trigger re-indentation." |
80261
4af0bb174714
* textmodes/css-mode.el (css-indent-offset, css-electric-keys):
Dan Nicolaescu <dann@ics.uci.edu>
parents:
79719
diff
changeset
|
180 :version "22.2" |
77923 | 181 :type '(repeat character) |
84579 | 182 :options '((?\} ?\;)) |
183 :group 'css) | |
77923 | 184 |
185 (defvar css-mode-syntax-table | |
186 (let ((st (make-syntax-table))) | |
187 ;; C-style comments. | |
188 (modify-syntax-entry ?/ ". 14" st) | |
189 (modify-syntax-entry ?* ". 23" st) | |
190 ;; Strings. | |
191 (modify-syntax-entry ?\" "\"" st) | |
192 (modify-syntax-entry ?\' "\"" st) | |
193 ;; Blocks. | |
194 (modify-syntax-entry ?\{ "(}" st) | |
195 (modify-syntax-entry ?\} "){" st) | |
196 ;; Args in url(...) thingies and other "function calls". | |
197 (modify-syntax-entry ?\( "()" st) | |
198 (modify-syntax-entry ?\) ")(" st) | |
199 ;; To match attributes in selectors. | |
200 (modify-syntax-entry ?\[ "(]" st) | |
201 (modify-syntax-entry ?\] ")[" st) | |
202 ;; Special chars that sometimes come at the beginning of words. | |
203 (modify-syntax-entry ?@ "'" st) | |
204 ;; (modify-syntax-entry ?: "'" st) | |
205 (modify-syntax-entry ?# "'" st) | |
206 ;; Distinction between words and symbols. | |
207 (modify-syntax-entry ?- "_" st) | |
208 st)) | |
209 | |
210 (defconst css-escapes-re | |
211 "\\\\\\(?:[^\000-\037\177]\\|[0-9a-fA-F]+[ \n\t\r\f]?\\)") | |
212 (defconst css-nmchar-re (concat "\\(?:[-[:alnum:]]\\|" css-escapes-re "\\)")) | |
213 (defconst css-nmstart-re (concat "\\(?:[[:alpha:]]\\|" css-escapes-re "\\)")) | |
214 (defconst css-ident-re (concat css-nmstart-re css-nmchar-re "*")) | |
215 (defconst css-name-re (concat css-nmchar-re "+")) | |
216 | |
217 (defface css-selector '((t :inherit font-lock-function-name-face)) | |
84579 | 218 "Face to use for selectors." |
219 :group 'css) | |
77923 | 220 (defface css-property '((t :inherit font-lock-variable-name-face)) |
84579 | 221 "Face to use for properties." |
222 :group 'css) | |
77923 | 223 |
224 (defvar css-font-lock-keywords | |
225 `(("!\\s-*important" . font-lock-builtin-face) | |
226 ;; Atrules keywords. IDs not in css-at-ids are valid (ignored). | |
227 ;; In fact the regexp should probably be | |
228 ;; (,(concat "\\(@" css-ident-re "\\)\\([ \t\n][^;{]*\\)[;{]") | |
229 ;; (1 font-lock-builtin-face)) | |
230 ;; Since "An at-rule consists of everything up to and including the next | |
231 ;; semicolon (;) or the next block, whichever comes first." | |
232 (,(concat "@" css-ident-re) . font-lock-builtin-face) | |
233 ;; Selectors. | |
234 ;; FIXME: attribute selectors don't work well because they may contain | |
235 ;; strings which have already been highlighted as f-l-string-face and | |
236 ;; thus prevent this highlighting from being applied (actually now that | |
237 ;; I use `append' this should work better). But really the part of hte | |
238 ;; selector between [...] should simply not be highlighted. | |
239 (,(concat "^\\([ \t]*[^@:{\n][^:{\n]+\\(?::" (regexp-opt css-pseudo-ids t) | |
240 "\\(?:([^)]+)\\)?[^:{\n]*\\)*\\)\\(?:\n[ \t]*\\)*{") | |
241 (1 'css-selector append)) | |
242 ;; In the above rule, we allow the open-brace to be on some subsequent | |
243 ;; line. This will only work if we properly mark the intervening text | |
244 ;; as being part of a multiline element (and even then, this only | |
245 ;; ensures proper refontification, but not proper discovery). | |
246 ("^[ \t]*{" (0 (save-excursion | |
247 (goto-char (match-beginning 0)) | |
248 (skip-chars-backward " \n\t") | |
249 (put-text-property (point) (match-end 0) | |
250 'font-lock-multiline t) | |
251 ;; No face. | |
252 nil))) | |
253 ;; Properties. Again, we don't limit ourselves to css-property-ids. | |
254 (,(concat "\\(?:[{;]\\|^\\)[ \t]*\\(" css-ident-re "\\)\\s-*:") | |
255 (1 'css-property)))) | |
256 | |
257 (defvar css-font-lock-defaults | |
258 '(css-font-lock-keywords nil t)) | |
259 | |
105965
3f64b8380468
* textmodes/ispell.el (ispell-skip-region-alist):
Dan Nicolaescu <dann@ics.uci.edu>
parents:
101279
diff
changeset
|
260 ;;;###autoload (add-to-list 'auto-mode-alist (cons (purecopy "\\.css\\'") 'css-mode)) |
77923 | 261 ;;;###autoload |
86820 | 262 (define-derived-mode css-mode fundamental-mode "CSS" |
77923 | 263 "Major mode to edit Cascading Style Sheets." |
264 (set (make-local-variable 'font-lock-defaults) css-font-lock-defaults) | |
265 (set (make-local-variable 'comment-start) "/*") | |
266 (set (make-local-variable 'comment-start-skip) "/\\*+[ \t]*") | |
267 (set (make-local-variable 'comment-end) "*/") | |
268 (set (make-local-variable 'comment-end-skip) "[ \t]*\\*+/") | |
269 (set (make-local-variable 'forward-sexp-function) 'css-forward-sexp) | |
270 (set (make-local-variable 'parse-sexp-ignore-comments) t) | |
271 (set (make-local-variable 'indent-line-function) 'css-indent-line) | |
272 (set (make-local-variable 'fill-paragraph-function) | |
273 'css-fill-paragraph) | |
78825
6ba709e4adda
(css-electric-keys): electrick->electric.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
78225
diff
changeset
|
274 (when css-electric-keys |
77923 | 275 (let ((fc (make-char-table 'auto-fill-chars))) |
276 (set-char-table-parent fc auto-fill-chars) | |
78825
6ba709e4adda
(css-electric-keys): electrick->electric.
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
78225
diff
changeset
|
277 (dolist (c css-electric-keys) |
77923 | 278 (aset fc c 'indent-according-to-mode)) |
279 (set (make-local-variable 'auto-fill-chars) fc)))) | |
280 | |
79187 | 281 (defvar comment-continue) |
282 | |
77923 | 283 (defun css-fill-paragraph (&optional justify) |
284 (save-excursion | |
285 (let ((ppss (syntax-ppss)) | |
286 (eol (line-end-position))) | |
287 (cond | |
288 ((and (nth 4 ppss) | |
289 (save-excursion | |
290 (goto-char (nth 8 ppss)) | |
291 (forward-comment 1) | |
292 (prog1 (not (bolp)) | |
293 (setq eol (point))))) | |
294 ;; Filling inside a comment whose comment-end marker is not \n. | |
295 ;; This code is meant to be generic, so that it works not only for | |
296 ;; css-mode but for all modes. | |
297 (save-restriction | |
298 (narrow-to-region (nth 8 ppss) eol) | |
79187 | 299 (comment-normalize-vars) ;Will define comment-continue. |
77923 | 300 (let ((fill-paragraph-function nil) |
301 (paragraph-separate | |
302 (if (and comment-continue | |
303 (string-match "[^ \t]" comment-continue)) | |
304 (concat "\\(?:[ \t]*" (regexp-quote comment-continue) | |
305 "\\)?\\(?:" paragraph-separate "\\)") | |
306 paragraph-separate)) | |
307 (paragraph-start | |
308 (if (and comment-continue | |
309 (string-match "[^ \t]" comment-continue)) | |
310 (concat "\\(?:[ \t]*" (regexp-quote comment-continue) | |
311 "\\)?\\(?:" paragraph-start "\\)") | |
312 paragraph-start))) | |
313 (fill-paragraph justify) | |
314 ;; Don't try filling again. | |
315 t))) | |
101279
1d661f541768
* textmodes/css-mode.el (css-backward-sexp): Stop once
Juanma Barranquero <lekktu@gmail.com>
parents:
100908
diff
changeset
|
316 |
77923 | 317 ((and (null (nth 8 ppss)) |
318 (or (nth 1 ppss) | |
319 (and (ignore-errors | |
320 (down-list 1) | |
321 (when (<= (point) eol) | |
322 (setq ppss (syntax-ppss))))))) | |
323 (goto-char (nth 1 ppss)) | |
324 (let ((end (save-excursion | |
325 (ignore-errors (forward-sexp 1) (copy-marker (point) t))))) | |
326 (when end | |
327 (while (re-search-forward "[{;}]" end t) | |
328 (cond | |
329 ;; This is a false positive inside a string or comment. | |
330 ((nth 8 (syntax-ppss)) nil) | |
331 ((eq (char-before) ?\}) | |
332 (save-excursion | |
333 (forward-char -1) | |
334 (skip-chars-backward " \t") | |
335 (unless (bolp) (newline)))) | |
336 (t | |
337 (while | |
338 (progn | |
339 (setq eol (line-end-position)) | |
340 (and (forward-comment 1) | |
341 (> (point) eol) | |
342 ;; A multi-line comment should be on its own line. | |
343 (save-excursion (forward-comment -1) | |
344 (when (< (point) eol) | |
345 (newline) | |
346 t))))) | |
347 (if (< (point) eol) (newline))))) | |
348 (goto-char (nth 1 ppss)) | |
349 (indent-region (line-beginning-position 2) end) | |
350 ;; Don't use the default filling code. | |
351 t))))))) | |
352 | |
353 ;;; Navigation and indentation. | |
354 | |
355 (defconst css-navigation-syntax-table | |
356 (let ((st (make-syntax-table css-mode-syntax-table))) | |
357 (map-char-table (lambda (c v) | |
358 ;; Turn punctuation (code = 1) into symbol (code = 1). | |
359 (if (eq (car-safe v) 1) | |
81288
a8ba55c33235
(css-navigation-syntax-table):
Stefan Monnier <monnier@iro.umontreal.ca>
parents:
77923
diff
changeset
|
360 (set-char-table-range st c (cons 3 (cdr v))))) |
77923 | 361 st) |
362 st)) | |
363 | |
364 (defun css-backward-sexp (n) | |
365 (let ((forward-sexp-function nil)) | |
366 (if (< n 0) (css-forward-sexp (- n)) | |
367 (while (> n 0) | |
368 (setq n (1- n)) | |
369 (forward-comment (- (point-max))) | |
370 (if (not (eq (char-before) ?\;)) | |
371 (backward-sexp 1) | |
372 (while (progn (backward-sexp 1) | |
373 (save-excursion | |
374 (forward-comment (- (point-max))) | |
375 ;; FIXME: We should also skip punctuation. | |
101279
1d661f541768
* textmodes/css-mode.el (css-backward-sexp): Stop once
Juanma Barranquero <lekktu@gmail.com>
parents:
100908
diff
changeset
|
376 (not (or (bobp) (memq (char-before) '(?\; ?\{)))))))))))) |
77923 | 377 |
378 (defun css-forward-sexp (n) | |
379 (let ((forward-sexp-function nil)) | |
380 (if (< n 0) (css-backward-sexp (- n)) | |
381 (while (> n 0) | |
382 (setq n (1- n)) | |
383 (forward-comment (point-max)) | |
384 (if (not (eq (char-after) ?\;)) | |
385 (forward-sexp 1) | |
386 (while (progn (forward-sexp 1) | |
387 (save-excursion | |
388 (forward-comment (point-max)) | |
389 ;; FIXME: We should also skip punctuation. | |
390 (not (memq (char-after) '(?\; ?\}))))))))))) | |
391 | |
392 (defun css-indent-calculate-virtual () | |
393 (if (or (save-excursion (skip-chars-backward " \t") (bolp)) | |
394 (if (looking-at "\\s(") | |
395 (save-excursion | |
396 (forward-char 1) (skip-chars-forward " \t") | |
397 (not (or (eolp) (looking-at comment-start-skip)))))) | |
398 (current-column) | |
399 (css-indent-calculate))) | |
400 | |
401 (defcustom css-indent-offset 4 | |
402 "Basic size of one indentation step." | |
80261
4af0bb174714
* textmodes/css-mode.el (css-indent-offset, css-electric-keys):
Dan Nicolaescu <dann@ics.uci.edu>
parents:
79719
diff
changeset
|
403 :version "22.2" |
84579 | 404 :type 'integer |
405 :group 'css) | |
77923 | 406 |
407 (defun css-indent-calculate () | |
408 (let ((ppss (syntax-ppss)) | |
409 pos) | |
410 (with-syntax-table css-navigation-syntax-table | |
411 (save-excursion | |
412 (cond | |
413 ;; Inside a string. | |
414 ((nth 3 ppss) 'noindent) | |
415 ;; Inside a comment. | |
416 ((nth 4 ppss) | |
417 (setq pos (point)) | |
418 (forward-line -1) | |
419 (skip-chars-forward " \t") | |
420 (if (>= (nth 8 ppss) (point)) | |
421 (progn | |
422 (goto-char (nth 8 ppss)) | |
423 (if (eq (char-after pos) ?*) | |
424 (forward-char 1) | |
425 (if (not (looking-at comment-start-skip)) | |
426 (error "Internal css-mode error") | |
427 (goto-char (match-end 0)))) | |
428 (current-column)) | |
429 (if (and (eq (char-after pos) ?*) (eq (char-after) ?*)) | |
430 (current-column) | |
431 ;; 'noindent | |
432 (current-column) | |
433 ))) | |
434 ;; In normal code. | |
435 (t | |
436 (or | |
437 (when (looking-at "\\s)") | |
438 (forward-char 1) | |
439 (backward-sexp 1) | |
440 (css-indent-calculate-virtual)) | |
441 (when (looking-at comment-start-skip) | |
442 (forward-comment (point-max)) | |
443 (css-indent-calculate)) | |
444 (when (save-excursion (forward-comment (- (point-max))) | |
445 (setq pos (point)) | |
446 (eq (char-syntax (preceding-char)) ?\()) | |
447 (goto-char (1- pos)) | |
448 (if (not (looking-at "\\s([ \t]*")) | |
449 (error "Internal css-mode error") | |
450 (if (or (memq (char-after (match-end 0)) '(?\n nil)) | |
451 (save-excursion (goto-char (match-end 0)) | |
452 (looking-at comment-start-skip))) | |
453 (+ (css-indent-calculate-virtual) css-indent-offset) | |
454 (progn (goto-char (match-end 0)) (current-column))))) | |
455 (progn | |
456 (css-backward-sexp 1) | |
457 (if (looking-at "\\s(") | |
458 (css-indent-calculate) | |
459 (css-indent-calculate-virtual)))))))))) | |
101279
1d661f541768
* textmodes/css-mode.el (css-backward-sexp): Stop once
Juanma Barranquero <lekktu@gmail.com>
parents:
100908
diff
changeset
|
460 |
77923 | 461 |
462 (defun css-indent-line () | |
463 "Indent current line according to CSS indentation rules." | |
464 (interactive) | |
465 (let* ((savep (point)) | |
466 (forward-sexp-function nil) | |
467 (indent (condition-case nil | |
468 (save-excursion | |
469 (forward-line 0) | |
470 (skip-chars-forward " \t") | |
471 (if (>= (point) savep) (setq savep nil)) | |
472 (css-indent-calculate)) | |
473 (error nil)))) | |
474 (if (not (numberp indent)) 'noindent | |
475 (if savep | |
476 (save-excursion (indent-line-to indent)) | |
477 (indent-line-to indent))))) | |
478 | |
479 (provide 'css-mode) | |
480 ;; arch-tag: b4d8b8e2-b130-4e74-b3aa-cd8f1ab659d0 | |
481 ;;; css-mode.el ends here |