* lisp/textmodes/css-mode.el (scss-mode): New major-mode.
(css-mode-syntax-table): Use d style comment, to ease the scss case. (css-ident-re): Allow things like @-moz-keyframes. (scss--hash-re): New const. (css--font-lock-keywords): New function, extracted from css-font-lock-keywords. (css-font-lock-keywords): Use it. (scss-mode-syntax-table, scss-font-lock-keywords): New vars. (scss-smie--not-interpolation-p): New function. (css-smie--forward-token, css-smie--backward-token): Use it. (css-mode): Remove left-over code. * test/indent/scss-mode.scss: New file. * test/indent/css-mode.css: Add a few uneventful examples.
This commit is contained in:
parent
57fe1632f0
commit
bc0e9e47b6
6 changed files with 164 additions and 25 deletions
1
etc/NEWS
1
etc/NEWS
|
@ -273,6 +273,7 @@ These emulations of old editors are believed to be no longer relevant
|
|||
|
||||
* New Modes and Packages in Emacs 25.1
|
||||
|
||||
** scss-mode (a minor variant of css-mode)
|
||||
|
||||
* Incompatible Lisp Changes in Emacs 25.1
|
||||
|
||||
|
|
|
@ -1,3 +1,12 @@
|
|||
2014-10-20 Stefan Monnier <monnier@iro.umontreal.ca>
|
||||
|
||||
* textmodes/css-mode.el (scss-mode): New major-mode.
|
||||
(css-mode-syntax-table): Use d style comment, to ease the scss case.
|
||||
(css-ident-re): Allow things like @-moz-keyframes.
|
||||
(scss--hash-re): New const.
|
||||
(css--font-lock-keywords): New function, extracted from
|
||||
css-font-lock-keywords.
|
||||
|
||||
2014-10-19 Ulf Jasper <ulf.jasper@web.de>
|
||||
|
||||
* net/newst-backend.el: Require url-parse.
|
||||
|
@ -26,8 +35,8 @@
|
|||
* net/newst-reader.el (newsticker-html-renderer): Whitespace.
|
||||
(newsticker--print-extra-elements)
|
||||
(newsticker--do-print-extra-element): Documentation
|
||||
(newsticker--image-read): Optionally limit image height. Use
|
||||
imagemagick if possible.
|
||||
(newsticker--image-read): Optionally limit image height.
|
||||
Use imagemagick if possible.
|
||||
(newsticker--icon-read): New.
|
||||
|
||||
* net/newst-treeview.el (newsticker--treeview-item-show): Limit height of feed logo.
|
||||
|
|
|
@ -185,7 +185,7 @@
|
|||
(let ((st (make-syntax-table)))
|
||||
;; C-style comments.
|
||||
(modify-syntax-entry ?/ ". 14" st)
|
||||
(modify-syntax-entry ?* ". 23" st)
|
||||
(modify-syntax-entry ?* ". 23b" st)
|
||||
;; Strings.
|
||||
(modify-syntax-entry ?\" "\"" st)
|
||||
(modify-syntax-entry ?\' "\"" st)
|
||||
|
@ -210,11 +210,15 @@
|
|||
"\\\\\\(?:[^\000-\037\177]\\|[0-9a-fA-F]+[ \n\t\r\f]?\\)")
|
||||
(defconst css-nmchar-re (concat "\\(?:[-[:alnum:]]\\|" css-escapes-re "\\)"))
|
||||
(defconst css-nmstart-re (concat "\\(?:[[:alpha:]]\\|" css-escapes-re "\\)"))
|
||||
(defconst css-ident-re (concat css-nmstart-re css-nmchar-re "*"))
|
||||
(defconst css-ident-re ;; (concat css-nmstart-re css-nmchar-re "*")
|
||||
;; Apparently, "at rules" names can start with a dash, e.g. @-moz-keyframes.
|
||||
(concat css-nmchar-re "+"))
|
||||
(defconst css-proprietary-nmstart-re ;; Vendor-specific properties.
|
||||
(concat "[-_]" (regexp-opt '("ms" "moz" "o" "khtml" "webkit")) "-"))
|
||||
(defconst css-name-re (concat css-nmchar-re "+"))
|
||||
|
||||
(defconst scss--hash-re "#\\(?:{[$-_[:alnum:]]+}\\|[[:alnum:]]+\\)")
|
||||
|
||||
(defface css-selector '((t :inherit font-lock-function-name-face))
|
||||
"Face to use for selectors."
|
||||
:group 'css)
|
||||
|
@ -224,24 +228,44 @@
|
|||
(defface css-proprietary-property '((t :inherit (css-property italic)))
|
||||
"Face to use for vendor-specific properties.")
|
||||
|
||||
(defvar css-font-lock-keywords
|
||||
`(("!\\s-*important" . font-lock-builtin-face)
|
||||
(defun css--font-lock-keywords (&optional sassy)
|
||||
`((,(concat "!\\s-*"
|
||||
(regexp-opt (append (if sassy '("global"))
|
||||
'("important"))))
|
||||
(0 font-lock-builtin-face))
|
||||
;; Atrules keywords. IDs not in css-at-ids are valid (ignored).
|
||||
;; In fact the regexp should probably be
|
||||
;; (,(concat "\\(@" css-ident-re "\\)\\([ \t\n][^;{]*\\)[;{]")
|
||||
;; (1 font-lock-builtin-face))
|
||||
;; Since "An at-rule consists of everything up to and including the next
|
||||
;; semicolon (;) or the next block, whichever comes first."
|
||||
(,(concat "@" css-ident-re) . font-lock-builtin-face)
|
||||
(,(concat "@" css-ident-re) (0 font-lock-builtin-face))
|
||||
;; Selectors.
|
||||
;; FIXME: attribute selectors don't work well because they may contain
|
||||
;; strings which have already been highlighted as f-l-string-face and
|
||||
;; thus prevent this highlighting from being applied (actually now that
|
||||
;; I use `append' this should work better). But really the part of the
|
||||
;; I use `keep' this should work better). But really the part of the
|
||||
;; selector between [...] should simply not be highlighted.
|
||||
(,(concat "^\\([ \t]*[^@:{}\n][^:{}]+\\(?::" (regexp-opt css-pseudo-ids t)
|
||||
"\\(?:([^)]+)\\)?[^:{\n]*\\)*\\)\\(?:\n[ \t]*\\)*{")
|
||||
(1 'css-selector append))
|
||||
(,(concat
|
||||
"^[ \t]*\\("
|
||||
(if (not sassy)
|
||||
;; We don't allow / as first char, so as not to
|
||||
;; take a comment as the beginning of a selector.
|
||||
"[^@/:{} \t\n][^:{}]+"
|
||||
;; Same as for non-sassy except we do want to allow { and }
|
||||
;; chars in selectors in the case of #{$foo}
|
||||
;; variable interpolation!
|
||||
(concat "\\(?:" scss--hash-re
|
||||
"\\|[^@/:{} \t\n#]\\)"
|
||||
"[^:{}#]*\\(?:" scss--hash-re "[^:{}#]*\\)*"))
|
||||
"\\(?::" (regexp-opt css-pseudo-ids t)
|
||||
"\\(?:([^\)]+)\\)?"
|
||||
(if (not sassy)
|
||||
"[^:{}\n]*"
|
||||
(concat "[^:{}\n#]*\\(?:" scss--hash-re "[^:{}\n#]*\\)*"))
|
||||
"\\)*"
|
||||
"\\)\\(?:\n[ \t]*\\)*{")
|
||||
(1 'css-selector keep))
|
||||
;; In the above rule, we allow the open-brace to be on some subsequent
|
||||
;; line. This will only work if we properly mark the intervening text
|
||||
;; as being part of a multiline element (and even then, this only
|
||||
|
@ -260,6 +284,8 @@
|
|||
"\\)\\s-*:")
|
||||
(1 (if (match-end 2) 'css-proprietary-property 'css-property)))))
|
||||
|
||||
(defvar css-font-lock-keywords (css--font-lock-keywords))
|
||||
|
||||
(defvar css-font-lock-defaults
|
||||
'(css-font-lock-keywords nil t))
|
||||
|
||||
|
@ -277,6 +303,7 @@
|
|||
(defun css-smie--forward-token ()
|
||||
(cond
|
||||
((and (eq (char-before) ?\})
|
||||
(scss-smie--not-interpolation-p)
|
||||
;; FIXME: If the next char is not whitespace, what should we do?
|
||||
(or (memq (char-after) '(?\s ?\t ?\n))
|
||||
(looking-at comment-start-skip)))
|
||||
|
@ -293,7 +320,8 @@
|
|||
(forward-comment (- (point)))
|
||||
(cond
|
||||
;; FIXME: If the next char is not whitespace, what should we do?
|
||||
((and (eq (char-before) ?\}) (> pos (point))) ";")
|
||||
((and (eq (char-before) ?\}) (scss-smie--not-interpolation-p)
|
||||
(> pos (point))) ";")
|
||||
((memq (char-before) '(?\; ?\, ?\:))
|
||||
(forward-char -1) (string (char-after)))
|
||||
(t (smie-default-backward-token)))))
|
||||
|
@ -315,7 +343,6 @@
|
|||
(setq-local comment-end "*/")
|
||||
(setq-local comment-end-skip "[ \t]*\\*+/")
|
||||
(setq-local parse-sexp-ignore-comments t)
|
||||
(setq-local indent-line-function 'css-indent-line)
|
||||
(setq-local fill-paragraph-function 'css-fill-paragraph)
|
||||
(setq-local add-log-current-defun-function #'css-current-defun-name)
|
||||
(smie-setup css-smie-grammar #'css-smie-rules
|
||||
|
@ -406,5 +433,35 @@
|
|||
(if (looking-at "^[ \t]*\\([^{\r\n]*[^ {\t\r\n]\\)")
|
||||
(match-string-no-properties 1))))))
|
||||
|
||||
;;; SCSS mode
|
||||
|
||||
(defvar scss-mode-syntax-table
|
||||
(let ((st (make-syntax-table css-mode-syntax-table)))
|
||||
(modify-syntax-entry ?/ ". 124" st)
|
||||
(modify-syntax-entry ?\n ">" st)
|
||||
st))
|
||||
|
||||
(defvar scss-font-lock-keywords
|
||||
(append `((,(concat "$" css-ident-re) (0 font-lock-variable-name-face)))
|
||||
(css--font-lock-keywords 'sassy)
|
||||
`((,(concat "@mixin[ \t]+\\(" css-ident-re "\\)[ \t]*(")
|
||||
(1 font-lock-function-name-face)))))
|
||||
|
||||
(defun scss-smie--not-interpolation-p ()
|
||||
(save-excursion
|
||||
(forward-char -1)
|
||||
(or (zerop (skip-chars-backward "[:alnum:]"))
|
||||
(not (looking-back "#{\\$" (- (point) 3))))))
|
||||
|
||||
;;;###autoload (add-to-list 'auto-mode-alist '("\\.scss\\'" . scss-mode))
|
||||
;;;###autoload
|
||||
(define-derived-mode scss-mode css-mode "SCSS"
|
||||
"Major mode to edit \"Sassy CSS\" files."
|
||||
(setq-local comment-start "// ")
|
||||
(setq-local comment-end "")
|
||||
(setq-local comment-start-skip "/[*/]+[ t]*")
|
||||
(setq-local comment-end-skip "[ \t]*\\(?:\n\\|\\*+/\\)")
|
||||
(setq-local font-lock-defaults '(scss-font-lock-keywords nil t)))
|
||||
|
||||
(provide 'css-mode)
|
||||
;;; css-mode.el ends here
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
2014-10-20 Stefan Monnier <monnier@iro.umontreal.ca>
|
||||
|
||||
* indent/scss-mode.scss: New file.
|
||||
* indent/css-mode.css: Add a few uneventful examples.
|
||||
|
||||
2014-10-15 Eli Zaretskii <eliz@gnu.org>
|
||||
|
||||
* BidiCharacterTest.txt: New file, from Unicode.
|
||||
|
@ -28,8 +33,8 @@
|
|||
|
||||
2014-09-26 Leo Liu <sdl.web@gmail.com>
|
||||
|
||||
* automated/cl-lib.el (cl-digit-char-p, cl-parse-integer): New
|
||||
tests. (Bug#18557)
|
||||
* automated/cl-lib.el (cl-digit-char-p, cl-parse-integer):
|
||||
New tests. (Bug#18557)
|
||||
|
||||
2014-09-24 Ulf Jasper <ulf.jasper@web.de>
|
||||
|
||||
|
@ -39,8 +44,8 @@
|
|||
|
||||
2014-09-09 Eli Zaretskii <eliz@gnu.org>
|
||||
|
||||
* automated/fns-tests.el (fns-tests-collate-sort): Bind
|
||||
w32-collate-ignore-punctuation to t when sorting according to
|
||||
* automated/fns-tests.el (fns-tests-collate-sort):
|
||||
Bind w32-collate-ignore-punctuation to t when sorting according to
|
||||
UTS#10 rules.
|
||||
|
||||
2014-09-07 Michael Albinus <michael.albinus@gmx.de>
|
||||
|
@ -555,8 +560,8 @@
|
|||
|
||||
* automated/subword-tests.el (subword-tests2): More subword tests.
|
||||
|
||||
* automated/cl-lib.el (cl-lib-keyword-names-versus-values): New
|
||||
test: correct parsing of keyword arguments.
|
||||
* automated/cl-lib.el (cl-lib-keyword-names-versus-values):
|
||||
New test: correct parsing of keyword arguments.
|
||||
|
||||
2014-03-22 Dmitry Gutov <dgutov@yandex.ru>
|
||||
|
||||
|
@ -651,8 +656,8 @@
|
|||
|
||||
2014-02-17 Michael Albinus <michael.albinus@gmx.de>
|
||||
|
||||
* automated/tramp-tests.el (tramp-test28-shell-command): Perform
|
||||
an initial `sit-for' prior the while loop.
|
||||
* automated/tramp-tests.el (tramp-test28-shell-command):
|
||||
Perform an initial `sit-for' prior the while loop.
|
||||
|
||||
2014-02-16 Michael Albinus <michael.albinus@gmx.de>
|
||||
|
||||
|
@ -674,8 +679,8 @@
|
|||
|
||||
* automated/tramp-tests.el (tramp-test26-process-file): Improve test.
|
||||
(tramp-test27-start-file-process): Use "_p" as argument of lambda.
|
||||
(tramp-test28-shell-command): Improve `shell-command' test. Add
|
||||
`async-shell-command' tests.
|
||||
(tramp-test28-shell-command): Improve `shell-command' test.
|
||||
Add `async-shell-command' tests.
|
||||
|
||||
2014-02-04 Michael Albinus <michael.albinus@gmx.de>
|
||||
|
||||
|
@ -731,8 +736,8 @@
|
|||
|
||||
2014-01-13 Michael Albinus <michael.albinus@gmx.de>
|
||||
|
||||
* automated/ert-tests.el (ert-test-record-backtrace): Reenable
|
||||
test case with adapted test string. (Bug#13064)
|
||||
* automated/ert-tests.el (ert-test-record-backtrace):
|
||||
Reenable test case with adapted test string. (Bug#13064)
|
||||
|
||||
2013-12-28 Glenn Morris <rgm@gnu.org>
|
||||
|
||||
|
|
|
@ -1,7 +1,17 @@
|
|||
/* asdfasdf */
|
||||
|
||||
.xxx
|
||||
{
|
||||
}
|
||||
|
||||
article[role="main"] {
|
||||
width: 60%;
|
||||
}
|
||||
|
||||
/* asdfasdf */
|
||||
@foo x2 {
|
||||
bla:toto;
|
||||
}
|
||||
.x2
|
||||
{
|
||||
foo: bar;
|
||||
|
|
57
test/indent/scss-mode.scss
Normal file
57
test/indent/scss-mode.scss
Normal file
|
@ -0,0 +1,57 @@
|
|||
// Comment!
|
||||
|
||||
nav {
|
||||
ul {
|
||||
margin: 0; /* More comment */
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
li { display: inline-block; }
|
||||
|
||||
a {
|
||||
display: block;
|
||||
padding: 6px 12px;
|
||||
text-decoration: none;
|
||||
}
|
||||
}
|
||||
nav ul {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
nav li {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
nav a var
|
||||
{
|
||||
display: block;
|
||||
padding: 6px 12px;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
$name: foo;
|
||||
$attr: border;
|
||||
p.#{$name} var
|
||||
{
|
||||
x#{$attr}-color: blue;
|
||||
}
|
||||
article[role="main"] {
|
||||
$toto: 500 !global;
|
||||
float: left;
|
||||
width: 600px / 888px * 100%;
|
||||
height: 100px / 888px * 100%;
|
||||
}
|
||||
|
||||
@import 'reset';
|
||||
|
||||
@mixin border-radius($radius) {
|
||||
-webkit-border-radius: $radius;
|
||||
-moz-border-radius: $radius;
|
||||
-ms-border-radius: $radius;
|
||||
border-radius: $radius;
|
||||
}
|
||||
|
||||
.box { @include border-radius(10px); }
|
Loading…
Add table
Reference in a new issue