unofficial mirror of bug-gnu-emacs@gnu.org 
 help / color / mirror / code / Atom feed
* bug#20226: 25.0.50; [PATCH] Make (S)CSS mode require final newline
@ 2015-03-29 21:15 Simen Heggestøyl
  2015-03-30  1:06 ` Stefan Monnier
  0 siblings, 1 reply; 6+ messages in thread
From: Simen Heggestøyl @ 2015-03-29 21:15 UTC (permalink / raw)
  To: 20226

[-- Attachment #1: Type: text/plain, Size: 2156 bytes --]

This patch makes CSS mode and its sister mode, SCSS mode, require
final newlines. I was surprised to find that the modes didn't do this
already. I think that final newlines play nicer with version control
systems such as Git, in that adding new lines won't be interpreted as
changes to the line that used to be last. Final newlines are also
mandated by at least one SCSS linter [1].

By the way, maybe it would make sense for CSS mode to derive from
`prog-mode' instead of `fundamental-mode'? With this patch, it is
already setting `require-final-newline' and
`parse-sexp-ignore-comments'. I can see that it used to derive from
`prog-mode', but this was changed in 2007 by Glenn Morris. Glenn, can
you remember the reason for this change?

[1] https://github.com/causes/scss-lint


 From e960348b679ba5743743afc7a0fdd3f55b098358 Mon Sep 17 00:00:00 2001
 From: =?UTF-8?q?Simen=20Heggest=C3=B8yl?= <simenheg@gmail.com>
Date: Sun, 29 Mar 2015 22:50:19 +0200
Subject: [PATCH] Make (S)CSS mode require final newline

* textmodes/css-mode.el (css-mode): Require final newline.
---
 lisp/ChangeLog             | 4 ++++
 lisp/textmodes/css-mode.el | 1 +
 2 files changed, 5 insertions(+)

diff --git a/lisp/ChangeLog b/lisp/ChangeLog
index c8e84a3..babdbde 100644
--- a/lisp/ChangeLog
+++ b/lisp/ChangeLog
@@ -1,3 +1,7 @@
+2015-03-29  Simen Heggestøyl  <simenheg@gmail.com>
+
+	* textmodes/css-mode.el (css-mode): Require final newline.
+
 2015-03-28  Jan Djärv  <jan.h.d@swipnet.se>

 	* emacs-lisp/package.el (package-refresh-contents): Fix spelling
diff --git a/lisp/textmodes/css-mode.el b/lisp/textmodes/css-mode.el
index 3e7612a..6004d84 100644
--- a/lisp/textmodes/css-mode.el
+++ b/lisp/textmodes/css-mode.el
@@ -372,6 +372,7 @@ pseudo-classes, and at-rules."
 ;;;###autoload
 (define-derived-mode css-mode fundamental-mode "CSS"
   "Major mode to edit Cascading Style Sheets."
+  (setq-local require-final-newline mode-require-final-newline)
   (setq-local font-lock-defaults css-font-lock-defaults)
   (setq-local comment-start "/*")
   (setq-local comment-start-skip "/\\*+[ \t]*")
-- 
2.1.4



[-- Attachment #2: Type: text/html, Size: 3004 bytes --]

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* bug#20226: 25.0.50; [PATCH] Make (S)CSS mode require final newline
  2015-03-29 21:15 bug#20226: 25.0.50; [PATCH] Make (S)CSS mode require final newline Simen Heggestøyl
@ 2015-03-30  1:06 ` Stefan Monnier
  2015-03-30 20:50   ` Simen Heggestøyl
  0 siblings, 1 reply; 6+ messages in thread
From: Stefan Monnier @ 2015-03-30  1:06 UTC (permalink / raw)
  To: Simen Heggestøyl; +Cc: 20226

> By the way, maybe it would make sense for CSS mode to derive from
> `prog-mode' instead of `fundamental-mode'?

That sounds right.

> `parse-sexp-ignore-comments'.  I can see that it used to derive from
> `prog-mode', but this was changed in 2007 by Glenn Morris.  Glenn, can
> you remember the reason for this change?

That's because when css-mode.el was added to Emacs, prog-mode didn't
exist yet (it was only added to Emacs in 2010).


        Stefan





^ permalink raw reply	[flat|nested] 6+ messages in thread

* bug#20226: 25.0.50; [PATCH] Make (S)CSS mode require final newline
  2015-03-30  1:06 ` Stefan Monnier
@ 2015-03-30 20:50   ` Simen Heggestøyl
  2015-03-30 22:03     ` Stefan Monnier
  0 siblings, 1 reply; 6+ messages in thread
From: Simen Heggestøyl @ 2015-03-30 20:50 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: 20226

[-- Attachment #1: Type: text/plain, Size: 47073 bytes --]

On Mon, Mar 30, 2015 at 3:06 AM, Stefan Monnier 
<monnier@iro.umontreal.ca> wrote:
>>  By the way, maybe it would make sense for CSS mode to derive from
>>  `prog-mode' instead of `fundamental-mode'?
> 
> That sounds right.

Good! Then I propose the following two patches:


 From 6c340b625258e45f81ce10b2ede73e402190758f Mon Sep 17 00:00:00 2001
 From: =?UTF-8?q?Simen=20Heggest=C3=B8yl?= <simenheg@gmail.com>
Date: Mon, 30 Mar 2015 22:32:58 +0200
Subject: [PATCH 1/2] Derive `css-mode' from `prog-mode'

* textmodes/css-mode.el (css-mode): Derive from `prog-mode'.
---
 lisp/ChangeLog             | 4 ++++
 lisp/textmodes/css-mode.el | 3 +--
 2 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/lisp/ChangeLog b/lisp/ChangeLog
index 649e884..f95139c 100644
--- a/lisp/ChangeLog
+++ b/lisp/ChangeLog
@@ -1,3 +1,7 @@
+2015-03-30  Simen Heggestøyl  <simenheg@gmail.com>
+
+	* textmodes/css-mode.el (css-mode): Derive from `prog-mode'.
+
 2015-03-30  Alan Mackenzie  <acm@muc.de>

 	Correct calculation of CC Mode's font-lock region.
diff --git a/lisp/textmodes/css-mode.el b/lisp/textmodes/css-mode.el
index 3e7612a..7280080 100644
--- a/lisp/textmodes/css-mode.el
+++ b/lisp/textmodes/css-mode.el
@@ -370,14 +370,13 @@ pseudo-classes, and at-rules."
       (css--complete-at-rule)))

 ;;;###autoload
-(define-derived-mode css-mode fundamental-mode "CSS"
+(define-derived-mode css-mode prog-mode "CSS"
   "Major mode to edit Cascading Style Sheets."
   (setq-local font-lock-defaults css-font-lock-defaults)
   (setq-local comment-start "/*")
   (setq-local comment-start-skip "/\\*+[ \t]*")
   (setq-local comment-end "*/")
   (setq-local comment-end-skip "[ \t]*\\*+/")
-  (setq-local parse-sexp-ignore-comments t)
   (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
-- 
2.1.4


 From adad951e4b139c27accb00fa7a0f47c25594c9f7 Mon Sep 17 00:00:00 2001
 From: =?UTF-8?q?Simen=20Heggest=C3=B8yl?= <simenheg@gmail.com>
Date: Mon, 30 Mar 2015 22:38:10 +0200
Subject: [PATCH 2/2] Move `css-mode.el' from `textmodes' to `progmodes'

---
 lisp/ChangeLog             |   2 +
 lisp/progmodes/css-mode.el | 508 
+++++++++++++++++++++++++++++++++++++++++++++
 lisp/textmodes/css-mode.el | 508 
---------------------------------------------
 3 files changed, 510 insertions(+), 508 deletions(-)
 create mode 100644 lisp/progmodes/css-mode.el
 delete mode 100644 lisp/textmodes/css-mode.el

diff --git a/lisp/ChangeLog b/lisp/ChangeLog
index f95139c..00d618c 100644
--- a/lisp/ChangeLog
+++ b/lisp/ChangeLog
@@ -1,5 +1,7 @@
 2015-03-30  Simen Heggestøyl  <simenheg@gmail.com>

+	* textmodes/css-mode.el: Move file to the `progmodes' directory.
+
 	* textmodes/css-mode.el (css-mode): Derive from `prog-mode'.

 2015-03-30  Alan Mackenzie  <acm@muc.de>
diff --git a/lisp/progmodes/css-mode.el b/lisp/progmodes/css-mode.el
new file mode 100644
index 0000000..7280080
--- /dev/null
+++ b/lisp/progmodes/css-mode.el
@@ -0,0 +1,508 @@
+;;; css-mode.el --- Major mode to edit CSS files  -*- lexical-binding: 
t -*-
+
+;; Copyright (C) 2006-2015 Free Software Foundation, Inc.
+
+;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
+;; Maintainer: Simen Heggestøyl <simenheg@gmail.com>
+;; Keywords: hypermedia
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; Yet another CSS mode.
+
+;;; Todo:
+
+;; - electric ; and }
+;; - filling code with auto-fill-mode
+;; - attribute value completion
+;; - fix font-lock errors with multi-line selectors
+
+;;; Code:
+
+(defgroup css nil
+  "Cascading Style Sheets (CSS) editing mode."
+  :group 'languages)
+
+(defconst css-pseudo-class-ids
+  '("active" "checked" "disabled" "empty" "enabled" "first"
+    "first-child" "first-of-type" "focus" "hover" "indeterminate" 
"lang"
+    "last-child" "last-of-type" "left" "link" "nth-child"
+    "nth-last-child" "nth-last-of-type" "nth-of-type" "only-child"
+    "only-of-type" "right" "root" "target" "visited")
+  "Identifiers for pseudo-classes.")
+
+(defconst css-pseudo-element-ids
+  '("after" "before" "first-letter" "first-line")
+  "Identifiers for pseudo-elements.")
+
+(defconst css-at-ids
+  '("charset" "font-face" "import" "media" "namespace" "page")
+  "Identifiers that appear in the form @foo.")
+
+(defconst css-descriptor-ids
+  '("ascent" "baseline" "bbox" "cap-height" "centerline" 
"definition-src"
+    "descent" "font-family" "font-size" "font-stretch" "font-style"
+    "font-variant" "font-weight" "mathline" "panose-1" "slope" "src" 
"stemh"
+    "stemv" "topline" "unicode-range" "units-per-em" "widths" 
"x-height")
+  "Identifiers for font descriptors.")
+
+(defconst css-media-ids
+  '("all" "aural" "bitmap" "continuous" "grid" "paged" "static" 
"tactile"
+    "visual")
+  "Identifiers for types of media.")
+
+(defconst css-property-ids
+  '(;; CSS 2.1 properties (http://www.w3.org/TR/CSS21/propidx.html).
+    ;;
+    ;; Properties duplicated by any of the CSS3 modules below have
+    ;; been removed.
+    "azimuth" "border-collapse" "border-spacing" "bottom"
+    "caption-side" "clear" "clip" "content" "counter-increment"
+    "counter-reset" "cue" "cue-after" "cue-before" "direction" 
"display"
+    "elevation" "empty-cells" "float" "height" "left" "line-height"
+    "list-style" "list-style-image" "list-style-position"
+    "list-style-type" "margin" "margin-bottom" "margin-left"
+    "margin-right" "margin-top" "max-height" "max-width" "min-height"
+    "min-width" "orphans" "overflow" "padding" "padding-bottom"
+    "padding-left" "padding-right" "padding-top" "page-break-after"
+    "page-break-before" "page-break-inside" "pause" "pause-after"
+    "pause-before" "pitch" "pitch-range" "play-during" "position"
+    "quotes" "richness" "right" "speak" "speak-header" "speak-numeral"
+    "speak-punctuation" "speech-rate" "stress" "table-layout" "top"
+    "unicode-bidi" "vertical-align" "visibility" "voice-family" 
"volume"
+    "widows" "width" "z-index"
+
+    ;; CSS Animations
+    ;; (http://www.w3.org/TR/css3-animations/#property-index)
+    "animation" "animation-delay" "animation-direction"
+    "animation-duration" "animation-fill-mode"
+    "animation-iteration-count" "animation-name"
+    "animation-play-state" "animation-timing-function"
+
+    ;; CSS Backgrounds and Borders Module Level 3
+    ;; (http://www.w3.org/TR/css3-background/#property-index)
+    "background" "background-attachment" "background-clip"
+    "background-color" "background-image" "background-origin"
+    "background-position" "background-repeat" "background-size"
+    "border" "border-bottom" "border-bottom-color"
+    "border-bottom-left-radius" "border-bottom-right-radius"
+    "border-bottom-style" "border-bottom-width" "border-color"
+    "border-image" "border-image-outset" "border-image-repeat"
+    "border-image-slice" "border-image-source" "border-image-width"
+    "border-left" "border-left-color" "border-left-style"
+    "border-left-width" "border-radius" "border-right"
+    "border-right-color" "border-right-style" "border-right-width"
+    "border-style" "border-top" "border-top-color"
+    "border-top-left-radius" "border-top-right-radius"
+    "border-top-style" "border-top-width" "border-width" "box-shadow"
+
+    ;; CSS Basic User Interface Module Level 3 (CSS3 UI)
+    ;; (http://www.w3.org/TR/css3-ui/#property-index)
+    "box-sizing" "caret-color" "cursor" "nav-down" "nav-left"
+    "nav-right" "nav-up" "outline" "outline-color" "outline-offset"
+    "outline-style" "outline-width" "resize" "text-overflow"
+
+    ;; CSS Color Module Level 3
+    ;; (http://www.w3.org/TR/css3-color/#property)
+    "color" "opacity"
+
+    ;; CSS Flexible Box Layout Module Level 1
+    ;; (http://www.w3.org/TR/css-flexbox-1/#property-index)
+    "align-content" "align-items" "align-self" "flex" "flex-basis"
+    "flex-direction" "flex-flow" "flex-grow" "flex-shrink" "flex-wrap"
+    "justify-content" "order"
+
+    ;; CSS Fonts Module Level 3
+    ;; (http://www.w3.org/TR/css3-fonts/#property-index)
+    "font" "font-family" "font-feature-settings" "font-kerning"
+    "font-language-override" "font-size" "font-size-adjust"
+    "font-stretch" "font-style" "font-synthesis" "font-variant"
+    "font-variant-alternates" "font-variant-caps"
+    "font-variant-east-asian" "font-variant-ligatures"
+    "font-variant-numeric" "font-variant-position" "font-weight"
+
+    ;; CSS Text Decoration Module Level 3
+    ;; (http://dev.w3.org/csswg/css-text-decor-3/#property-index)
+    "text-decoration" "text-decoration-color" "text-decoration-line"
+    "text-decoration-skip" "text-decoration-style" "text-emphasis"
+    "text-emphasis-color" "text-emphasis-position" 
"text-emphasis-style"
+    "text-shadow" "text-underline-position"
+
+    ;; CSS Text Module Level 3
+    ;; (http://www.w3.org/TR/css3-text/#property-index)
+    "hanging-punctuation" "hyphens" "letter-spacing" "line-break"
+    "overflow-wrap" "tab-size" "text-align" "text-align-last"
+    "text-indent" "text-justify" "text-transform" "white-space"
+    "word-break" "word-spacing" "word-wrap"
+
+    ;; CSS Transforms Module Level 1
+    ;; (http://www.w3.org/TR/css3-2d-transforms/#property-index)
+    "backface-visibility" "perspective" "perspective-origin"
+    "transform" "transform-origin" "transform-style"
+
+    ;; CSS Transitions
+    ;; (http://www.w3.org/TR/css3-transitions/#property-index)
+    "transition" "transition-delay" "transition-duration"
+    "transition-property" "transition-timing-function"
+
+    ;; Filter Effects Module Level 1
+    ;; (http://www.w3.org/TR/filter-effects/#property-index)
+    "color-interpolation-filters" "filter" "flood-color"
+    "flood-opacity" "lighting-color")
+  "Identifiers for properties.")
+
+(defcustom css-electric-keys '(?\} ?\;) ;; '()
+  "Self inserting keys which should trigger re-indentation."
+  :version "22.2"
+  :type '(repeat character)
+  :options '((?\} ?\;))
+  :group 'css)
+
+(defvar css-mode-syntax-table
+  (let ((st (make-syntax-table)))
+    ;; C-style comments.
+    (modify-syntax-entry ?/ ". 14" st)
+    (modify-syntax-entry ?* ". 23b" st)
+    ;; Strings.
+    (modify-syntax-entry ?\" "\"" st)
+    (modify-syntax-entry ?\' "\"" st)
+    ;; Blocks.
+    (modify-syntax-entry ?\{ "(}" st)
+    (modify-syntax-entry ?\} "){" st)
+    ;; Args in url(...) thingies and other "function calls".
+    (modify-syntax-entry ?\( "()" st)
+    (modify-syntax-entry ?\) ")(" st)
+    ;; To match attributes in selectors.
+    (modify-syntax-entry ?\[ "(]" st)
+    (modify-syntax-entry ?\] ")[" st)
+    ;; Special chars that sometimes come at the beginning of words.
+    (modify-syntax-entry ?@ "'" st)
+    ;; (modify-syntax-entry ?: "'" st)
+    (modify-syntax-entry ?# "'" st)
+    ;; Distinction between words and symbols.
+    (modify-syntax-entry ?- "_" st)
+    st))
+
+(defconst css-escapes-re
+  "\\\\\\(?:[^\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 "*")
+  ;; 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)
+(defface css-property '((t :inherit font-lock-variable-name-face))
+  "Face to use for properties."
+  :group 'css)
+(defface css-proprietary-property '((t :inherit (css-property italic)))
+  "Face to use for vendor-specific properties.")
+
+(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) (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 `keep' this should work better).  But really the part of 
the
+    ;; selector between [...] should simply not be highlighted.
+    (,(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 "[^:{}#]*\\)*"))
+       ;; Even though pseudo-elements should be prefixed by ::, a
+       ;; single colon is accepted for backward compatibility.
+       "\\(?:\\(:" (regexp-opt (append css-pseudo-class-ids
+                                       css-pseudo-element-ids) t)
+       "\\|\\::" (regexp-opt css-pseudo-element-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
+    ;; ensures proper refontification, but not proper discovery).
+    ("^[ \t]*{" (0 (save-excursion
+                     (goto-char (match-beginning 0))
+                     (skip-chars-backward " \n\t")
+                     (put-text-property (point) (match-end 0)
+                                        'font-lock-multiline t)
+                     ;; No face.
+                     nil)))
+    ;; Properties.  Again, we don't limit ourselves to 
css-property-ids.
+    (,(concat "\\(?:[{;]\\|^\\)[ \t]*\\("
+              "\\(?:\\(" css-proprietary-nmstart-re "\\)\\|"
+              css-nmstart-re "\\)" css-nmchar-re "*"
+              "\\)\\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))
+
+(defcustom css-indent-offset 4
+  "Basic size of one indentation step."
+  :version "22.2"
+  :type 'integer)
+
+(require 'smie)
+
+(defconst css-smie-grammar
+  (smie-prec2->grammar
+   (smie-precs->prec2 '((assoc ";") (assoc ",") (left ":")))))
+
+(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)))
+    (if (memq (char-after) '(?\s ?\t ?\n))
+        (forward-char 1) (forward-comment 1))
+    ";")
+   ((progn (forward-comment (point-max))
+           (looking-at "[;,:]"))
+    (forward-char 1) (match-string 0))
+   (t (smie-default-forward-token))))
+
+(defun css-smie--backward-token ()
+  (let ((pos (point)))
+    (forward-comment (- (point)))
+    (cond
+     ;; FIXME: If the next char is not whitespace, what should we do?
+     ((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)))))
+
+(defun css-smie-rules (kind token)
+  (pcase (cons kind token)
+    (`(:elem . basic) css-indent-offset)
+    (`(:elem . arg) 0)
+    (`(:list-intro . ,(or `";" `"")) t) ;"" stands for BOB (bug#15467).
+    (`(:before . ,(or "{" "("))
+     (if (smie-rule-hanging-p) (smie-rule-parent 0)))))
+
+;;; Completion
+
+(defun css--complete-property ()
+  "Complete property at point."
+  (save-excursion
+    (let ((pos (point)))
+      (skip-chars-backward "-[:alnum:]")
+      (let ((start (point)))
+        (skip-chars-backward " \t\r\n")
+        (when (memq (char-before) '(?\{ ?\;))
+          (list start pos css-property-ids))))))
+
+(defun css--complete-pseudo-element-or-class ()
+  "Complete pseudo-element or pseudo-class at point."
+  (save-excursion
+    (let ((pos (point)))
+      (skip-chars-backward "-[:alnum:]")
+      (when (eq (char-before) ?\:)
+        (list (point) pos
+              (if (eq (char-before (- (point) 1)) ?\:)
+                  css-pseudo-element-ids
+                css-pseudo-class-ids))))))
+
+(defun css--complete-at-rule ()
+  "Complete at-rule (statement beginning with `@') at point."
+  (save-excursion
+    (let ((pos (point)))
+      (skip-chars-backward "-[:alnum:]")
+      (when (eq (char-before) ?\@)
+        (list (point) pos css-at-ids)))))
+
+(defun css-completion-at-point ()
+  "Complete current symbol at point.
+Currently supports completion of CSS properties, pseudo-elements,
+pseudo-classes, and at-rules."
+  (or (css--complete-property)
+      (css--complete-pseudo-element-or-class)
+      (css--complete-at-rule)))
+
+;;;###autoload
+(define-derived-mode css-mode prog-mode "CSS"
+  "Major mode to edit Cascading Style Sheets."
+  (setq-local font-lock-defaults css-font-lock-defaults)
+  (setq-local comment-start "/*")
+  (setq-local comment-start-skip "/\\*+[ \t]*")
+  (setq-local comment-end "*/")
+  (setq-local comment-end-skip "[ \t]*\\*+/")
+  (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
+              :forward-token #'css-smie--forward-token
+              :backward-token #'css-smie--backward-token)
+  (setq-local electric-indent-chars
+              (append css-electric-keys electric-indent-chars))
+  (add-hook 'completion-at-point-functions
+            #'css-completion-at-point nil 'local))
+
+(defvar comment-continue)
+
+(defun css-fill-paragraph (&optional justify)
+  (save-excursion
+    (let ((ppss (syntax-ppss))
+          (eol (line-end-position)))
+      (cond
+       ((and (nth 4 ppss)
+             (save-excursion
+               (goto-char (nth 8 ppss))
+               (forward-comment 1)
+               (prog1 (not (bolp))
+                 (setq eol (point)))))
+        ;; Filling inside a comment whose comment-end marker is not \n.
+        ;; This code is meant to be generic, so that it works not only 
for
+        ;; css-mode but for all modes.
+        (save-restriction
+          (narrow-to-region (nth 8 ppss) eol)
+          (comment-normalize-vars)      ;Will define comment-continue.
+          (let ((fill-paragraph-function nil)
+                (paragraph-separate
+                 (if (and comment-continue
+                          (string-match "[^ \t]" comment-continue))
+                     (concat "\\(?:[ \t]*" (regexp-quote 
comment-continue)
+                             "\\)?\\(?:" paragraph-separate "\\)")
+                   paragraph-separate))
+                (paragraph-start
+                 (if (and comment-continue
+                          (string-match "[^ \t]" comment-continue))
+                     (concat "\\(?:[ \t]*" (regexp-quote 
comment-continue)
+                             "\\)?\\(?:" paragraph-start "\\)")
+                   paragraph-start)))
+            (fill-paragraph justify)
+            ;; Don't try filling again.
+            t)))
+
+       ((and (null (nth 8 ppss))
+             (or (nth 1 ppss)
+                 (and (ignore-errors
+                        (down-list 1)
+                        (when (<= (point) eol)
+                          (setq ppss (syntax-ppss)))))))
+        (goto-char (nth 1 ppss))
+        (let ((end (save-excursion
+                     (ignore-errors (forward-sexp 1) (copy-marker 
(point) t)))))
+          (when end
+            (while (re-search-forward "[{;}]" end t)
+              (cond
+               ;; This is a false positive inside a string or comment.
+               ((nth 8 (syntax-ppss)) nil)
+               ;; This is a false positive when encountering an
+               ;; interpolated variable (bug#19751).
+               ((eq (char-before (- (point) 1)) ?#) nil)
+               ((eq (char-before) ?\})
+                (save-excursion
+                  (forward-char -1)
+                  (skip-chars-backward " \t")
+                  (when (and (not (bolp))
+                             (scss-smie--not-interpolation-p))
+                    (newline))))
+               (t
+                (while
+                    (progn
+                      (setq eol (line-end-position))
+                      (and (forward-comment 1)
+                           (> (point) eol)
+                           ;; A multi-line comment should be on its 
own line.
+                           (save-excursion (forward-comment -1)
+                                           (when (< (point) eol)
+                                             (newline)
+                                             t)))))
+                (if (< (point) eol) (newline)))))
+            (goto-char (nth 1 ppss))
+            (indent-region (line-beginning-position 2) end)
+            ;; Don't use the default filling code.
+            t)))))))
+
+(defun css-current-defun-name ()
+  "Return the name of the CSS section at point, or nil."
+  (save-excursion
+    (let ((max (max (point-min) (- (point) 1600))))  ; approx 20 lines 
back
+      (when (search-backward "{" max t)
+	(skip-chars-backward " \t\r\n")
+	(beginning-of-line)
+	(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
diff --git a/lisp/textmodes/css-mode.el b/lisp/textmodes/css-mode.el
deleted file mode 100644
index 7280080..0000000
--- a/lisp/textmodes/css-mode.el
+++ /dev/null
@@ -1,508 +0,0 @@
-;;; css-mode.el --- Major mode to edit CSS files  -*- lexical-binding: 
t -*-
-
-;; Copyright (C) 2006-2015 Free Software Foundation, Inc.
-
-;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
-;; Maintainer: Simen Heggestøyl <simenheg@gmail.com>
-;; Keywords: hypermedia
-
-;; This file is part of GNU Emacs.
-
-;; GNU Emacs is free software: you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation, either version 3 of the License, or
-;; (at your option) any later version.
-
-;; GNU Emacs is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.
-
-;;; Commentary:
-
-;; Yet another CSS mode.
-
-;;; Todo:
-
-;; - electric ; and }
-;; - filling code with auto-fill-mode
-;; - attribute value completion
-;; - fix font-lock errors with multi-line selectors
-
-;;; Code:
-
-(defgroup css nil
-  "Cascading Style Sheets (CSS) editing mode."
-  :group 'languages)
-
-(defconst css-pseudo-class-ids
-  '("active" "checked" "disabled" "empty" "enabled" "first"
-    "first-child" "first-of-type" "focus" "hover" "indeterminate" 
"lang"
-    "last-child" "last-of-type" "left" "link" "nth-child"
-    "nth-last-child" "nth-last-of-type" "nth-of-type" "only-child"
-    "only-of-type" "right" "root" "target" "visited")
-  "Identifiers for pseudo-classes.")
-
-(defconst css-pseudo-element-ids
-  '("after" "before" "first-letter" "first-line")
-  "Identifiers for pseudo-elements.")
-
-(defconst css-at-ids
-  '("charset" "font-face" "import" "media" "namespace" "page")
-  "Identifiers that appear in the form @foo.")
-
-(defconst css-descriptor-ids
-  '("ascent" "baseline" "bbox" "cap-height" "centerline" 
"definition-src"
-    "descent" "font-family" "font-size" "font-stretch" "font-style"
-    "font-variant" "font-weight" "mathline" "panose-1" "slope" "src" 
"stemh"
-    "stemv" "topline" "unicode-range" "units-per-em" "widths" 
"x-height")
-  "Identifiers for font descriptors.")
-
-(defconst css-media-ids
-  '("all" "aural" "bitmap" "continuous" "grid" "paged" "static" 
"tactile"
-    "visual")
-  "Identifiers for types of media.")
-
-(defconst css-property-ids
-  '(;; CSS 2.1 properties (http://www.w3.org/TR/CSS21/propidx.html).
-    ;;
-    ;; Properties duplicated by any of the CSS3 modules below have
-    ;; been removed.
-    "azimuth" "border-collapse" "border-spacing" "bottom"
-    "caption-side" "clear" "clip" "content" "counter-increment"
-    "counter-reset" "cue" "cue-after" "cue-before" "direction" 
"display"
-    "elevation" "empty-cells" "float" "height" "left" "line-height"
-    "list-style" "list-style-image" "list-style-position"
-    "list-style-type" "margin" "margin-bottom" "margin-left"
-    "margin-right" "margin-top" "max-height" "max-width" "min-height"
-    "min-width" "orphans" "overflow" "padding" "padding-bottom"
-    "padding-left" "padding-right" "padding-top" "page-break-after"
-    "page-break-before" "page-break-inside" "pause" "pause-after"
-    "pause-before" "pitch" "pitch-range" "play-during" "position"
-    "quotes" "richness" "right" "speak" "speak-header" "speak-numeral"
-    "speak-punctuation" "speech-rate" "stress" "table-layout" "top"
-    "unicode-bidi" "vertical-align" "visibility" "voice-family" 
"volume"
-    "widows" "width" "z-index"
-
-    ;; CSS Animations
-    ;; (http://www.w3.org/TR/css3-animations/#property-index)
-    "animation" "animation-delay" "animation-direction"
-    "animation-duration" "animation-fill-mode"
-    "animation-iteration-count" "animation-name"
-    "animation-play-state" "animation-timing-function"
-
-    ;; CSS Backgrounds and Borders Module Level 3
-    ;; (http://www.w3.org/TR/css3-background/#property-index)
-    "background" "background-attachment" "background-clip"
-    "background-color" "background-image" "background-origin"
-    "background-position" "background-repeat" "background-size"
-    "border" "border-bottom" "border-bottom-color"
-    "border-bottom-left-radius" "border-bottom-right-radius"
-    "border-bottom-style" "border-bottom-width" "border-color"
-    "border-image" "border-image-outset" "border-image-repeat"
-    "border-image-slice" "border-image-source" "border-image-width"
-    "border-left" "border-left-color" "border-left-style"
-    "border-left-width" "border-radius" "border-right"
-    "border-right-color" "border-right-style" "border-right-width"
-    "border-style" "border-top" "border-top-color"
-    "border-top-left-radius" "border-top-right-radius"
-    "border-top-style" "border-top-width" "border-width" "box-shadow"
-
-    ;; CSS Basic User Interface Module Level 3 (CSS3 UI)
-    ;; (http://www.w3.org/TR/css3-ui/#property-index)
-    "box-sizing" "caret-color" "cursor" "nav-down" "nav-left"
-    "nav-right" "nav-up" "outline" "outline-color" "outline-offset"
-    "outline-style" "outline-width" "resize" "text-overflow"
-
-    ;; CSS Color Module Level 3
-    ;; (http://www.w3.org/TR/css3-color/#property)
-    "color" "opacity"
-
-    ;; CSS Flexible Box Layout Module Level 1
-    ;; (http://www.w3.org/TR/css-flexbox-1/#property-index)
-    "align-content" "align-items" "align-self" "flex" "flex-basis"
-    "flex-direction" "flex-flow" "flex-grow" "flex-shrink" "flex-wrap"
-    "justify-content" "order"
-
-    ;; CSS Fonts Module Level 3
-    ;; (http://www.w3.org/TR/css3-fonts/#property-index)
-    "font" "font-family" "font-feature-settings" "font-kerning"
-    "font-language-override" "font-size" "font-size-adjust"
-    "font-stretch" "font-style" "font-synthesis" "font-variant"
-    "font-variant-alternates" "font-variant-caps"
-    "font-variant-east-asian" "font-variant-ligatures"
-    "font-variant-numeric" "font-variant-position" "font-weight"
-
-    ;; CSS Text Decoration Module Level 3
-    ;; (http://dev.w3.org/csswg/css-text-decor-3/#property-index)
-    "text-decoration" "text-decoration-color" "text-decoration-line"
-    "text-decoration-skip" "text-decoration-style" "text-emphasis"
-    "text-emphasis-color" "text-emphasis-position" 
"text-emphasis-style"
-    "text-shadow" "text-underline-position"
-
-    ;; CSS Text Module Level 3
-    ;; (http://www.w3.org/TR/css3-text/#property-index)
-    "hanging-punctuation" "hyphens" "letter-spacing" "line-break"
-    "overflow-wrap" "tab-size" "text-align" "text-align-last"
-    "text-indent" "text-justify" "text-transform" "white-space"
-    "word-break" "word-spacing" "word-wrap"
-
-    ;; CSS Transforms Module Level 1
-    ;; (http://www.w3.org/TR/css3-2d-transforms/#property-index)
-    "backface-visibility" "perspective" "perspective-origin"
-    "transform" "transform-origin" "transform-style"
-
-    ;; CSS Transitions
-    ;; (http://www.w3.org/TR/css3-transitions/#property-index)
-    "transition" "transition-delay" "transition-duration"
-    "transition-property" "transition-timing-function"
-
-    ;; Filter Effects Module Level 1
-    ;; (http://www.w3.org/TR/filter-effects/#property-index)
-    "color-interpolation-filters" "filter" "flood-color"
-    "flood-opacity" "lighting-color")
-  "Identifiers for properties.")
-
-(defcustom css-electric-keys '(?\} ?\;) ;; '()
-  "Self inserting keys which should trigger re-indentation."
-  :version "22.2"
-  :type '(repeat character)
-  :options '((?\} ?\;))
-  :group 'css)
-
-(defvar css-mode-syntax-table
-  (let ((st (make-syntax-table)))
-    ;; C-style comments.
-    (modify-syntax-entry ?/ ". 14" st)
-    (modify-syntax-entry ?* ". 23b" st)
-    ;; Strings.
-    (modify-syntax-entry ?\" "\"" st)
-    (modify-syntax-entry ?\' "\"" st)
-    ;; Blocks.
-    (modify-syntax-entry ?\{ "(}" st)
-    (modify-syntax-entry ?\} "){" st)
-    ;; Args in url(...) thingies and other "function calls".
-    (modify-syntax-entry ?\( "()" st)
-    (modify-syntax-entry ?\) ")(" st)
-    ;; To match attributes in selectors.
-    (modify-syntax-entry ?\[ "(]" st)
-    (modify-syntax-entry ?\] ")[" st)
-    ;; Special chars that sometimes come at the beginning of words.
-    (modify-syntax-entry ?@ "'" st)
-    ;; (modify-syntax-entry ?: "'" st)
-    (modify-syntax-entry ?# "'" st)
-    ;; Distinction between words and symbols.
-    (modify-syntax-entry ?- "_" st)
-    st))
-
-(defconst css-escapes-re
-  "\\\\\\(?:[^\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 "*")
-  ;; 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)
-(defface css-property '((t :inherit font-lock-variable-name-face))
-  "Face to use for properties."
-  :group 'css)
-(defface css-proprietary-property '((t :inherit (css-property italic)))
-  "Face to use for vendor-specific properties.")
-
-(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) (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 `keep' this should work better).  But really the part of 
the
-    ;; selector between [...] should simply not be highlighted.
-    (,(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 "[^:{}#]*\\)*"))
-       ;; Even though pseudo-elements should be prefixed by ::, a
-       ;; single colon is accepted for backward compatibility.
-       "\\(?:\\(:" (regexp-opt (append css-pseudo-class-ids
-                                       css-pseudo-element-ids) t)
-       "\\|\\::" (regexp-opt css-pseudo-element-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
-    ;; ensures proper refontification, but not proper discovery).
-    ("^[ \t]*{" (0 (save-excursion
-                     (goto-char (match-beginning 0))
-                     (skip-chars-backward " \n\t")
-                     (put-text-property (point) (match-end 0)
-                                        'font-lock-multiline t)
-                     ;; No face.
-                     nil)))
-    ;; Properties.  Again, we don't limit ourselves to 
css-property-ids.
-    (,(concat "\\(?:[{;]\\|^\\)[ \t]*\\("
-              "\\(?:\\(" css-proprietary-nmstart-re "\\)\\|"
-              css-nmstart-re "\\)" css-nmchar-re "*"
-              "\\)\\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))
-
-(defcustom css-indent-offset 4
-  "Basic size of one indentation step."
-  :version "22.2"
-  :type 'integer)
-
-(require 'smie)
-
-(defconst css-smie-grammar
-  (smie-prec2->grammar
-   (smie-precs->prec2 '((assoc ";") (assoc ",") (left ":")))))
-
-(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)))
-    (if (memq (char-after) '(?\s ?\t ?\n))
-        (forward-char 1) (forward-comment 1))
-    ";")
-   ((progn (forward-comment (point-max))
-           (looking-at "[;,:]"))
-    (forward-char 1) (match-string 0))
-   (t (smie-default-forward-token))))
-
-(defun css-smie--backward-token ()
-  (let ((pos (point)))
-    (forward-comment (- (point)))
-    (cond
-     ;; FIXME: If the next char is not whitespace, what should we do?
-     ((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)))))
-
-(defun css-smie-rules (kind token)
-  (pcase (cons kind token)
-    (`(:elem . basic) css-indent-offset)
-    (`(:elem . arg) 0)
-    (`(:list-intro . ,(or `";" `"")) t) ;"" stands for BOB (bug#15467).
-    (`(:before . ,(or "{" "("))
-     (if (smie-rule-hanging-p) (smie-rule-parent 0)))))
-
-;;; Completion
-
-(defun css--complete-property ()
-  "Complete property at point."
-  (save-excursion
-    (let ((pos (point)))
-      (skip-chars-backward "-[:alnum:]")
-      (let ((start (point)))
-        (skip-chars-backward " \t\r\n")
-        (when (memq (char-before) '(?\{ ?\;))
-          (list start pos css-property-ids))))))
-
-(defun css--complete-pseudo-element-or-class ()
-  "Complete pseudo-element or pseudo-class at point."
-  (save-excursion
-    (let ((pos (point)))
-      (skip-chars-backward "-[:alnum:]")
-      (when (eq (char-before) ?\:)
-        (list (point) pos
-              (if (eq (char-before (- (point) 1)) ?\:)
-                  css-pseudo-element-ids
-                css-pseudo-class-ids))))))
-
-(defun css--complete-at-rule ()
-  "Complete at-rule (statement beginning with `@') at point."
-  (save-excursion
-    (let ((pos (point)))
-      (skip-chars-backward "-[:alnum:]")
-      (when (eq (char-before) ?\@)
-        (list (point) pos css-at-ids)))))
-
-(defun css-completion-at-point ()
-  "Complete current symbol at point.
-Currently supports completion of CSS properties, pseudo-elements,
-pseudo-classes, and at-rules."
-  (or (css--complete-property)
-      (css--complete-pseudo-element-or-class)
-      (css--complete-at-rule)))
-
-;;;###autoload
-(define-derived-mode css-mode prog-mode "CSS"
-  "Major mode to edit Cascading Style Sheets."
-  (setq-local font-lock-defaults css-font-lock-defaults)
-  (setq-local comment-start "/*")
-  (setq-local comment-start-skip "/\\*+[ \t]*")
-  (setq-local comment-end "*/")
-  (setq-local comment-end-skip "[ \t]*\\*+/")
-  (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
-              :forward-token #'css-smie--forward-token
-              :backward-token #'css-smie--backward-token)
-  (setq-local electric-indent-chars
-              (append css-electric-keys electric-indent-chars))
-  (add-hook 'completion-at-point-functions
-            #'css-completion-at-point nil 'local))
-
-(defvar comment-continue)
-
-(defun css-fill-paragraph (&optional justify)
-  (save-excursion
-    (let ((ppss (syntax-ppss))
-          (eol (line-end-position)))
-      (cond
-       ((and (nth 4 ppss)
-             (save-excursion
-               (goto-char (nth 8 ppss))
-               (forward-comment 1)
-               (prog1 (not (bolp))
-                 (setq eol (point)))))
-        ;; Filling inside a comment whose comment-end marker is not \n.
-        ;; This code is meant to be generic, so that it works not only 
for
-        ;; css-mode but for all modes.
-        (save-restriction
-          (narrow-to-region (nth 8 ppss) eol)
-          (comment-normalize-vars)      ;Will define comment-continue.
-          (let ((fill-paragraph-function nil)
-                (paragraph-separate
-                 (if (and comment-continue
-                          (string-match "[^ \t]" comment-continue))
-                     (concat "\\(?:[ \t]*" (regexp-quote 
comment-continue)
-                             "\\)?\\(?:" paragraph-separate "\\)")
-                   paragraph-separate))
-                (paragraph-start
-                 (if (and comment-continue
-                          (string-match "[^ \t]" comment-continue))
-                     (concat "\\(?:[ \t]*" (regexp-quote 
comment-continue)
-                             "\\)?\\(?:" paragraph-start "\\)")
-                   paragraph-start)))
-            (fill-paragraph justify)
-            ;; Don't try filling again.
-            t)))
-
-       ((and (null (nth 8 ppss))
-             (or (nth 1 ppss)
-                 (and (ignore-errors
-                        (down-list 1)
-                        (when (<= (point) eol)
-                          (setq ppss (syntax-ppss)))))))
-        (goto-char (nth 1 ppss))
-        (let ((end (save-excursion
-                     (ignore-errors (forward-sexp 1) (copy-marker 
(point) t)))))
-          (when end
-            (while (re-search-forward "[{;}]" end t)
-              (cond
-               ;; This is a false positive inside a string or comment.
-               ((nth 8 (syntax-ppss)) nil)
-               ;; This is a false positive when encountering an
-               ;; interpolated variable (bug#19751).
-               ((eq (char-before (- (point) 1)) ?#) nil)
-               ((eq (char-before) ?\})
-                (save-excursion
-                  (forward-char -1)
-                  (skip-chars-backward " \t")
-                  (when (and (not (bolp))
-                             (scss-smie--not-interpolation-p))
-                    (newline))))
-               (t
-                (while
-                    (progn
-                      (setq eol (line-end-position))
-                      (and (forward-comment 1)
-                           (> (point) eol)
-                           ;; A multi-line comment should be on its 
own line.
-                           (save-excursion (forward-comment -1)
-                                           (when (< (point) eol)
-                                             (newline)
-                                             t)))))
-                (if (< (point) eol) (newline)))))
-            (goto-char (nth 1 ppss))
-            (indent-region (line-beginning-position 2) end)
-            ;; Don't use the default filling code.
-            t)))))))
-
-(defun css-current-defun-name ()
-  "Return the name of the CSS section at point, or nil."
-  (save-excursion
-    (let ((max (max (point-min) (- (point) 1600))))  ; approx 20 lines 
back
-      (when (search-backward "{" max t)
-	(skip-chars-backward " \t\r\n")
-	(beginning-of-line)
-	(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
-- 
2.1.4



[-- Attachment #2: Type: text/html, Size: 73682 bytes --]

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* bug#20226: 25.0.50; [PATCH] Make (S)CSS mode require final newline
  2015-03-30 20:50   ` Simen Heggestøyl
@ 2015-03-30 22:03     ` Stefan Monnier
  2015-03-31 18:05       ` Simen Heggestøyl
  0 siblings, 1 reply; 6+ messages in thread
From: Stefan Monnier @ 2015-03-30 22:03 UTC (permalink / raw)
  To: Simen Heggestøyl; +Cc: 20226

> Good! Then I propose the following two patches:

The first looks good.  I think the second is kind of pointless.


        Stefan





^ permalink raw reply	[flat|nested] 6+ messages in thread

* bug#20226: 25.0.50; [PATCH] Make (S)CSS mode require final newline
  2015-03-30 22:03     ` Stefan Monnier
@ 2015-03-31 18:05       ` Simen Heggestøyl
  2015-03-31 21:12         ` Stefan Monnier
  0 siblings, 1 reply; 6+ messages in thread
From: Simen Heggestøyl @ 2015-03-31 18:05 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: 20226-done

[-- Attachment #1: Type: text/plain, Size: 394 bytes --]

On Tue, Mar 31, 2015 at 12:03 AM, Stefan Monnier 
<monnier@iro.umontreal.ca> wrote:
>>  Good! Then I propose the following two patches:
> 
> The first looks good.  I think the second is kind of pointless.
> 
> 
>         Stefan

I would find it more logical for `css-mode.el' to reside in `progmodes' 
together with the other progmodes, but it's not important. I've 
installed the first patch!

[-- Attachment #2: Type: text/html, Size: 522 bytes --]

^ permalink raw reply	[flat|nested] 6+ messages in thread

* bug#20226: 25.0.50; [PATCH] Make (S)CSS mode require final newline
  2015-03-31 18:05       ` Simen Heggestøyl
@ 2015-03-31 21:12         ` Stefan Monnier
  0 siblings, 0 replies; 6+ messages in thread
From: Stefan Monnier @ 2015-03-31 21:12 UTC (permalink / raw)
  To: Simen Heggestøyl; +Cc: 20226-done

> I would find it more logical for `css-mode.el' to reside in `progmodes'
> together with the other progmodes,

There's some logic to it, but:

> but it's not important.

That's the main point.  Moving files just because it's marginally more
logical is just making history-digging harder for very little benefit.

[ The textmodes directory has many such "borderline" cases.
  E.g. tex-mode.el can just as well be considered a programming mode.  ]

> I've installed the first patch!

Thanks,


        Stefan





^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2015-03-31 21:12 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-03-29 21:15 bug#20226: 25.0.50; [PATCH] Make (S)CSS mode require final newline Simen Heggestøyl
2015-03-30  1:06 ` Stefan Monnier
2015-03-30 20:50   ` Simen Heggestøyl
2015-03-30 22:03     ` Stefan Monnier
2015-03-31 18:05       ` Simen Heggestøyl
2015-03-31 21:12         ` Stefan Monnier

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).