From unknown Thu Jun 19 14:13:42 2025 Content-Disposition: inline Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 X-Mailer: MIME-tools 5.509 (Entity 5.509) Content-Type: text/plain; charset=utf-8 From: bug#20226 <20226@debbugs.gnu.org> To: bug#20226 <20226@debbugs.gnu.org> Subject: Status: 25.0.50; [PATCH] Make (S)CSS mode require final newline Reply-To: bug#20226 <20226@debbugs.gnu.org> Date: Thu, 19 Jun 2025 21:13:42 +0000 retitle 20226 25.0.50; [PATCH] Make (S)CSS mode require final newline reassign 20226 emacs submitter 20226 Simen Heggest=C3=B8yl severity 20226 normal tag 20226 patch thanks From debbugs-submit-bounces@debbugs.gnu.org Sun Mar 29 17:15:30 2015 Received: (at submit) by debbugs.gnu.org; 29 Mar 2015 21:15:30 +0000 Received: from localhost ([127.0.0.1]:39838 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.80) (envelope-from ) id 1YcKYL-0007p5-NL for submit@debbugs.gnu.org; Sun, 29 Mar 2015 17:15:30 -0400 Received: from eggs.gnu.org ([208.118.235.92]:52864) by debbugs.gnu.org with esmtp (Exim 4.80) (envelope-from ) id 1YcKYI-0007oq-An for submit@debbugs.gnu.org; Sun, 29 Mar 2015 17:15:27 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1YcKYB-0003XB-Cp for submit@debbugs.gnu.org; Sun, 29 Mar 2015 17:15:20 -0400 X-Spam-Checker-Version: SpamAssassin 3.3.2 (2011-06-06) on eggs.gnu.org X-Spam-Level: X-Spam-Status: No, score=0.8 required=5.0 tests=BAYES_50,FREEMAIL_FROM, HTML_MESSAGE,T_DKIM_INVALID autolearn=disabled version=3.3.2 Received: from lists.gnu.org ([2001:4830:134:3::11]:47182) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1YcKYB-0003X3-A7 for submit@debbugs.gnu.org; Sun, 29 Mar 2015 17:15:19 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:54565) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1YcKYA-0006md-1O for bug-gnu-emacs@gnu.org; Sun, 29 Mar 2015 17:15:19 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1YcKY6-0003WN-NR for bug-gnu-emacs@gnu.org; Sun, 29 Mar 2015 17:15:17 -0400 Received: from mail-wi0-x236.google.com ([2a00:1450:400c:c05::236]:38439) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1YcKY6-0003WE-E6; Sun, 29 Mar 2015 17:15:14 -0400 Received: by wibgn9 with SMTP id gn9so100230635wib.1; Sun, 29 Mar 2015 14:15:13 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=date:from:subject:to:cc:message-id:mime-version:content-type; bh=lCbtVRIdk9Cwl/j0HB7xy8dbp+eOTkafPM7gdWZ6ik8=; b=qiln/pPSkdOw5xx4REYgL9RfIlWNa7+tPKG/tQRHW0whag56YBSw1DMWsPl4n7igIb ZVrnJ1jSQNncJYEsFlt13Ykzc7Ok4iv3jQMxO/E896qgQaeL3bgPPa1m7voaXyuHNClx 7WvOocxpMcfIy23OKRkrBqGuK9v2Ixbd09A5/JfZqWsNIAlk1dPTwHIkk6gn1+b7XDEE 27rljN/QTXTjopOZ4MET7xP+ESO9Rg4Ch64BloBMn9v7YVDrLC9O2IVWLEk0ED7Iaf1f xx72d0DvYSEr5OkyRBH6PM7tXYsCU8nsWEC1cVZuDVKv2JwvWvYppzlZLxRRo6xVTvIA 0pSQ== X-Received: by 10.194.80.40 with SMTP id o8mr55546523wjx.34.1427663713555; Sun, 29 Mar 2015 14:15:13 -0700 (PDT) Received: from [192.168.1.114] (cm-84.215.44.110.getinternet.no. [84.215.44.110]) by mx.google.com with ESMTPSA id c3sm12769771wiz.2.2015.03.29.14.15.11 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Sun, 29 Mar 2015 14:15:12 -0700 (PDT) Date: Sun, 29 Mar 2015 23:15:10 +0200 From: Simen =?iso-8859-1?q?Heggest=F8yl?= Subject: 25.0.50; [PATCH] Make (S)CSS mode require final newline To: bug-gnu-emacs@gnu.org Message-Id: <1427663710.9451.0@smtp.gmail.com> X-Mailer: geary/0.8.2 MIME-Version: 1.0 Content-Type: multipart/alternative; boundary="=-9277Qu3ovYyKmVJmmLGN" X-detected-operating-system: by eggs.gnu.org: Error: Malformed IPv6 address (bad octet value). X-detected-operating-system: by eggs.gnu.org: Error: Malformed IPv6 address (bad octet value). X-Received-From: 2001:4830:134:3::11 X-Spam-Score: -4.0 (----) X-Debbugs-Envelope-To: submit Cc: rgm@gnu.org X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -4.0 (----) --=-9277Qu3ovYyKmVJmmLGN Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: quoted-printable 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: =3D?UTF-8?q?Simen=3D20Heggest=3DC3=3DB8yl?=3D 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=C3=B8yl + + * textmodes/css-mode.el (css-mode): Require final newline. + 2015-03-28 Jan Dj=C3=A4rv * 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]*") --=20 2.1.4 = --=-9277Qu3ovYyKmVJmmLGN Content-Type: text/html; charset=utf-8 Content-Transfer-Encoding: quoted-printable
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 con= trol
systems such as Git, in that adding new lines won't be inter= preted as
changes to the line that used to be last. Final newline= s are also
mandated by at least one SCSS linter [1].
By the way, maybe it would make sense for CSS mode to derive f= rom
`prog-mode' instead of `fundamental-mode'? With this patch, i= t is
already setting `require-final-newline' and
`parse= -sexp-ignore-comments'. I can see that it used to derive from
`pr= og-mode', but this was changed in 2007 by Glenn Morris. Glenn, can
you remember the reason for this change?



From e960348b679ba5743743= afc7a0fdd3f55b098358 Mon Sep 17 00:00:00 2001
From: =3D?UTF-8?q?S= imen=3D20Heggest=3DC3=3DB8yl?=3D <simenheg@gmail.com>
Date:= Sun, 29 Mar 2015 22:50:19 +0200
Subject: [PATCH] Make (S)CSS mod= e require final newline

* textmodes/css-mode.el (c= ss-mode): Require final newline.
---
 lisp/ChangeL= og             | 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 &nb= sp;Simen Heggest=C3=B8yl  <simenheg@gmail.com>
+
=
+ * te= xtmodes/css-mode.el (css-mode): Require final newline.
+
 2015-03-28  Jan Dj=C3=A4rv  <jan.h.d@swipnet.se>
 
  * emacs-lisp/package.el (package-refresh-contents): Fi= x spelling
diff --git a/lisp/textmodes/css-mode.el b/lisp/textmod= es/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."
 ;;;###a= utoload
 (define-derived-mode css-mode fundamental-mode "CSS= "
   "Major mode to edit Cascading Style Sheets."
=
+  (setq-local require-final-newline mode-require-final-newline)<= /div>
   (setq-local font-lock-defaults css-font-lock-default= s)
   (setq-local comment-start "/*")
  =  (setq-local comment-start-skip "/\\*+[ \t]*")
-- 
2.1.4

= --=-9277Qu3ovYyKmVJmmLGN-- From debbugs-submit-bounces@debbugs.gnu.org Sun Mar 29 21:06:10 2015 Received: (at 20226) by debbugs.gnu.org; 30 Mar 2015 01:06:10 +0000 Received: from localhost ([127.0.0.1]:39905 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.80) (envelope-from ) id 1YcO9a-00063H-4b for submit@debbugs.gnu.org; Sun, 29 Mar 2015 21:06:10 -0400 Received: from ironport2-out.teksavvy.com ([206.248.154.181]:33464) by debbugs.gnu.org with esmtp (Exim 4.80) (envelope-from ) id 1YcO9X-00062t-P6 for 20226@debbugs.gnu.org; Sun, 29 Mar 2015 21:06:08 -0400 X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: AnEFAGvvdVRBbthL/2dsb2JhbAA3gVOfQYIugQiBdQEBBAFWIwULCzQSFBgNJIgTohGMG0kJAwECgz4Dg3AEqDs X-IPAS-Result: AnEFAGvvdVRBbthL/2dsb2JhbAA3gVOfQYIugQiBdQEBBAFWIwULCzQSFBgNJIgTohGMG0kJAwECgz4Dg3AEqDs X-IronPort-AV: E=Sophos;i="5.01,1,1400040000"; d="scan'208";a="114909154" Received: from 65-110-216-75.cpe.pppoe.ca (HELO pastel.home) ([65.110.216.75]) by ironport2-out.teksavvy.com with ESMTP/TLS/DHE-RSA-AES256-SHA; 29 Mar 2015 21:06:01 -0400 Received: by pastel.home (Postfix, from userid 20848) id 2EEC3DB0; Sun, 29 Mar 2015 21:06:01 -0400 (EDT) From: Stefan Monnier To: Simen =?windows-1252?Q?Heggest=F8yl?= Subject: Re: bug#20226: 25.0.50; [PATCH] Make (S)CSS mode require final newline Message-ID: References: <1427663710.9451.0@smtp.gmail.com> Date: Sun, 29 Mar 2015 21:06:01 -0400 In-Reply-To: <1427663710.9451.0@smtp.gmail.com> ("Simen =?windows-1252?Q?H?= =?windows-1252?Q?eggest=F8yl=22's?= message of "Sun, 29 Mar 2015 23:15:10 +0200") User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/25.0.50 (gnu/linux) MIME-Version: 1.0 Content-Type: text/plain X-Spam-Score: 0.3 (/) X-Debbugs-Envelope-To: 20226 Cc: 20226@debbugs.gnu.org X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: 0.3 (/) > 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 From debbugs-submit-bounces@debbugs.gnu.org Mon Mar 30 16:51:07 2015 Received: (at 20226) by debbugs.gnu.org; 30 Mar 2015 20:51:07 +0000 Received: from localhost ([127.0.0.1]:40713 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.80) (envelope-from ) id 1YcgeI-0002Ur-Pm for submit@debbugs.gnu.org; Mon, 30 Mar 2015 16:51:06 -0400 Received: from mail-la0-f43.google.com ([209.85.215.43]:35733) by debbugs.gnu.org with esmtp (Exim 4.80) (envelope-from ) id 1YcgeF-0002UL-J6 for 20226@debbugs.gnu.org; Mon, 30 Mar 2015 16:51:04 -0400 Received: by lahp7 with SMTP id p7so94498097lah.2 for <20226@debbugs.gnu.org>; Mon, 30 Mar 2015 13:50:57 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=date:from:subject:to:cc:message-id:in-reply-to:references :mime-version:content-type; bh=Ep/kWcYCqxGLyjvZ4jOrCA4fXDO3YBvsMlp2B2CsNUQ=; b=NfHxw5DlXkVwQl1MltNrMAiKwzDFuzp2w0bnolEpYz6oS0av0y6/qu/rhPzeZMcrNN 2Oo7BVUW2oKp8rc+YKDI78HXUT203fZrRG3ZxwHWiob4rbcQ9yWnWcXfFqdN+0409WxB TKCpZZpizwto91HSkRPLMTf4NYwoXvr1FlxN3B1+18AnWsMRDmRYkNXE2/E7/pVkOYJr gR9LP9Fa0+259Egi4geF2vE7DgZ/hALwqr9lg74zUza8M7/IpMJiSLTEYXyuXVa9nvrw 3Rs8XCJ4Tz4t7+VrJwR/5r9x0YNSJ7XQqve9N7RIQbUutLDbScsWmn4RBg8rL1mm514c bR7Q== X-Received: by 10.152.206.72 with SMTP id lm8mr7910299lac.33.1427748657179; Mon, 30 Mar 2015 13:50:57 -0700 (PDT) Received: from [192.168.1.114] (cm-84.215.44.110.getinternet.no. [84.215.44.110]) by mx.google.com with ESMTPSA id ay16sm2232551lab.27.2015.03.30.13.50.53 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 30 Mar 2015 13:50:56 -0700 (PDT) Date: Mon, 30 Mar 2015 22:50:52 +0200 From: Simen =?iso-8859-1?q?Heggest=F8yl?= Subject: Re: bug#20226: 25.0.50; [PATCH] Make (S)CSS mode require final newline To: Stefan Monnier Message-Id: <1427748652.1775.0@smtp.gmail.com> In-Reply-To: References: X-Mailer: geary/0.8.2 MIME-Version: 1.0 Content-Type: multipart/alternative; boundary="=-negPAn0+66EZt3OPm6ZF" X-Debbugs-Envelope-To: 20226 Cc: 20226@debbugs.gnu.org X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" --=-negPAn0+66EZt3OPm6ZF Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: quoted-printable On Mon, Mar 30, 2015 at 3:06 AM, Stefan Monnier=20 wrote: >> By the way, maybe it would make sense for CSS mode to derive from >> `prog-mode' instead of `fundamental-mode'? >=20 > That sounds right. Good! Then I propose the following two patches: From 6c340b625258e45f81ce10b2ede73e402190758f Mon Sep 17 00:00:00 2001 From: =3D?UTF-8?q?Simen=3D20Heggest=3DC3=3DB8yl?=3D 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=C3=B8yl + + * textmodes/css-mode.el (css-mode): Derive from `prog-mode'. + 2015-03-30 Alan Mackenzie 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 --=20 2.1.4 From adad951e4b139c27accb00fa7a0f47c25594c9f7 Mon Sep 17 00:00:00 2001 From: =3D?UTF-8?q?Simen=3D20Heggest=3DC3=3DB8yl?=3D 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=20 +++++++++++++++++++++++++++++++++++++++++++++ lisp/textmodes/css-mode.el | 508=20 --------------------------------------------- 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=C3=B8yl + * 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 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:=20 t -*- + +;; Copyright (C) 2006-2015 Free Software Foundation, Inc. + +;; Author: Stefan Monnier +;; Maintainer: Simen Heggest=C3=B8yl +;; 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 . + +;;; 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"=20 "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"=20 "definition-src" + "descent" "font-family" "font-size" "font-stretch" "font-style" + "font-variant" "font-weight" "mathline" "panose-1" "slope" "src"=20 "stemh" + "stemv" "topline" "unicode-range" "units-per-em" "widths"=20 "x-height") + "Identifiers for font descriptors.") + +(defconst css-media-ids + '("all" "aural" "bitmap" "continuous" "grid" "paged" "static"=20 "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"=20 "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"=20 "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"=20 "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=20 "\\)")) +(defconst css-nmstart-re (concat "\\(?:[[:alpha:]]\\|" css-escapes-re=20 "\\)")) +(defconst css-ident-re ;; (concat css-nmstart-re css-nmchar-re "*") + ;; Apparently, "at rules" names can start with a dash, e.g.=20 @-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=20 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=20 contain + ;; strings which have already been highlighted as f-l-string-face=20 and + ;; thus prevent this highlighting from being applied (actually now=20 that + ;; I use `keep' this should work better). But really the part of=20 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=20 subsequent + ;; line. This will only work if we properly mark the intervening=20 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=20 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=20 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=20 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=20 comment-continue) + "\\)?\\(?:" paragraph-separate "\\)") + paragraph-separate)) + (paragraph-start + (if (and comment-continue + (string-match "[^ \t]" comment-continue)) + (concat "\\(?:[ \t]*" (regexp-quote=20 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 (<=3D (point) eol) + (setq ppss (syntax-ppss))))))) + (goto-char (nth 1 ppss)) + (let ((end (save-excursion + (ignore-errors (forward-sexp 1) (copy-marker=20 (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=20 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=20 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=20 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\\'" .=20 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:=20 t -*- - -;; Copyright (C) 2006-2015 Free Software Foundation, Inc. - -;; Author: Stefan Monnier -;; Maintainer: Simen Heggest=C3=B8yl -;; 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 . - -;;; 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"=20 "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"=20 "definition-src" - "descent" "font-family" "font-size" "font-stretch" "font-style" - "font-variant" "font-weight" "mathline" "panose-1" "slope" "src"=20 "stemh" - "stemv" "topline" "unicode-range" "units-per-em" "widths"=20 "x-height") - "Identifiers for font descriptors.") - -(defconst css-media-ids - '("all" "aural" "bitmap" "continuous" "grid" "paged" "static"=20 "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"=20 "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"=20 "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"=20 "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=20 "\\)")) -(defconst css-nmstart-re (concat "\\(?:[[:alpha:]]\\|" css-escapes-re=20 "\\)")) -(defconst css-ident-re ;; (concat css-nmstart-re css-nmchar-re "*") - ;; Apparently, "at rules" names can start with a dash, e.g.=20 @-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=20 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=20 contain - ;; strings which have already been highlighted as f-l-string-face=20 and - ;; thus prevent this highlighting from being applied (actually now=20 that - ;; I use `keep' this should work better). But really the part of=20 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=20 subsequent - ;; line. This will only work if we properly mark the intervening=20 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=20 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=20 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=20 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=20 comment-continue) - "\\)?\\(?:" paragraph-separate "\\)") - paragraph-separate)) - (paragraph-start - (if (and comment-continue - (string-match "[^ \t]" comment-continue)) - (concat "\\(?:[ \t]*" (regexp-quote=20 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 (<=3D (point) eol) - (setq ppss (syntax-ppss))))))) - (goto-char (nth 1 ppss)) - (let ((end (save-excursion - (ignore-errors (forward-sexp 1) (copy-marker=20 (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=20 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=20 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=20 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\\'" .=20 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 --=20 2.1.4 = --=-negPAn0+66EZt3OPm6ZF Content-Type: text/html; charset=utf-8 Content-Transfer-Encoding: quoted-printable On Mon, Mar 30, 2015 at 3:06 AM, Stefan Monnier <monnier@iro.umontreal.c= a> 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 foll= owing two patches:


From 6c340b= 625258e45f81ce10b2ede73e402190758f Mon Sep 17 00:00:00 2001
From:= =3D?UTF-8?q?Simen=3D20Heggest=3DC3=3DB8yl?=3D <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'.
---
&n= bsp;lisp/ChangeLog             | 4 ++++
=
 lisp/textmodes/css-mode.el | 3 +--
 2 files chang= ed, 5 insertions(+), 2 deletions(-)

diff --git a/l= isp/ChangeLog b/lisp/ChangeLog
index 649e884..f95139c 100644
--- a/lisp/ChangeLog
+++ b/lisp/ChangeLog
@@ -1,3= +1,7 @@
+2015-03-30  Simen Heggest=C3=B8yl  <simenh= eg@gmail.com>
+
+ * textmodes/css-mode.el (css-mode): Derive fr= om `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
<= div>--- a/lisp/textmodes/css-mode.el
+++ b/lisp/textmodes/css-mod= e.el
@@ -370,14 +370,13 @@ pseudo-classes, and at-rules."
       (css--complete-at-rule)))
 
 ;;;###autoload
-(define-derived-mode css-mode funda= mental-mode "CSS"
+(define-derived-mode css-mode prog-mode "CSS"<= /div>
   "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-l= ocal comment-end "*/")
   (setq-local comment-end-skip = "[ \t]*\\*+/")
-  (setq-local parse-sexp-ignore-comments t)<= /div>
   (setq-local fill-paragraph-function 'css-fill-paragr= aph)
   (setq-local add-log-current-defun-function #'cs= s-current-defun-name)
   (smie-setup css-smie-grammar #= 'css-smie-rules
-- 
2.1.4


From adad951e4b139c27accb00fa7a0f47c25594c9f7 Mo= n Sep 17 00:00:00 2001
From: =3D?UTF-8?q?Simen=3D20Heggest=3DC3= =3DB8yl?=3D <simenheg@gmail.com>
Date: Mon, 30 Mar 2015 22:= 38:10 +0200
Subject: [PATCH 2/2] Move `css-mode.el' from `textmod= es' to `progmodes'

---
 lisp/Change= Log             |   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-mod= e.el
 delete mode 100644 lisp/textmodes/css-mode.el

diff --git a/lisp/ChangeLog b/lisp/ChangeLog
ind= ex f95139c..00d618c 100644
--- a/lisp/ChangeLog
+++ b/l= isp/ChangeLog
@@ -1,5 +1,7 @@
 2015-03-30  Si= men Heggest=C3=B8yl  <simenheg@gmail.com>
 
=
+ * te= xtmodes/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 fil= es  -*- lexical-binding: t -*-
+
+;; Copyright (C)= 2006-2015 Free Software Foundation, Inc.
+
+;; Author:= Stefan Monnier <monnier@iro.umontreal.ca>
+;; Maintainer: = Simen Heggest=C3=B8yl <simenheg@gmail.com>
+;; Keywords: hy= permedia
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/o= r 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 w= arranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOS= E.  See the
+;; GNU General Public License for more details.=
+
+;; You should have received a copy of the GNU Gener= al Public License
+;; along with GNU Emacs.  If not, see <= ;http://www.gnu.org/licenses/&= gt;.
+
+;;; Commentary:
+
+;; Yet a= nother CSS mode.
+
+;;; Todo:
+
+;;= - electric ; and }
+;; - filling code with auto-fill-mode
<= div>+;; - attribute value completion
+;; - fix font-lock errors w= ith multi-line selectors
+
+;;; Code:
+
=
+(defgroup css nil
+  "Cascading Style Sheets (CSS) edi= ting mode."
+  :group 'languages)
+
+(de= fconst css-pseudo-class-ids
+  '("active" "checked" "disable= d" "empty" "enabled" "first"
+    "first-child" "first-= of-type" "focus" "hover" "indeterminate" "lang"
+    "l= ast-child" "last-of-type" "left" "link" "nth-child"
+   &nbs= p;"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.")
<= div>+
+(defconst css-at-ids
+  '("charset" "font-f= ace" "import" "media" "namespace" "page")
+  "Identifiers th= at appear in the form @foo.")
+
+(defconst css-descript= or-ids
+  '("ascent" "baseline" "bbox" "cap-height" "centerl= ine" "definition-src"
+    "descent" "font-family" "fon= t-size" "font-stretch" "font-style"
+    "font-variant"= "font-weight" "mathline" "panose-1" "slope" "src" "stemh"
+ &nbs= p;  "stemv" "topline" "unicode-range" "units-per-em" "widths" "x-heigh= t")
+  "Identifiers for font descriptors.")
+
+(defconst css-media-ids
+  '("all" "aural" "bitmap" "= continuous" "grid" "paged" "static" "tactile"
+    "vis= ual")
+  "Identifiers for types of media.")
+
+(defconst css-property-ids
+  '(;; CSS 2.1 properties= (http://www.w3.org/TR/= CSS21/propidx.html).
+    ;;
+   &nb= sp;;; 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"
+    "co= unter-reset" "cue" "cue-after" "cue-before" "direction" "display"
+    "elevation" "empty-cells" "float" "height" "left" "line-hei= ght"
+    "list-style" "list-style-image" "list-style-p= osition"
+    "list-style-type" "margin" "margin-bottom= " "margin-left"
+    "margin-right" "margin-top" "max-h= eight" "max-width" "min-height"
+    "min-width" "orpha= ns" "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" "posit= ion"
+    "quotes" "richness" "right" "speak" "speak-he= ader" "speak-numeral"
+    "speak-punctuation" "speech-= rate" "stress" "table-layout" "top"
+    "unicode-bidi"= "vertical-align" "visibility" "voice-family" "volume"
+   &= nbsp;"widows" "width" "z-index"
+
+    ;; CSS= Animations
+    "animation" "animation-delay" "anima= tion-direction"
+    "animation-duration" "animation-fi= ll-mode"
+    "animation-iteration-count" "animation-na= me"
+    "animation-play-state" "animation-timing-funct= ion"
+
+    ;; CSS Backgrounds and Borders Mo= dule Level 3
+    "background" "background-attachment= " "background-clip"
+    "background-color" "background= -image" "background-origin"
+    "background-position" = "background-repeat" "background-size"
+    "border" "bo= rder-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"
+ &nb= sp;  "border-image-slice" "border-image-source" "border-image-width"
+    "border-left" "border-left-color" "border-left-styl= e"
+    "border-left-width" "border-radius" "border-rig= ht"
+    "border-right-color" "border-right-style" "bor= der-right-width"
+    "border-style" "border-top" "bord= er-top-color"
+    "border-top-left-radius" "border-top= -right-radius"
+    "border-top-style" "border-top-widt= h" "border-width" "box-shadow"
+
+    ;; CSS = Basic User Interface Module Level 3 (CSS3 UI)
+    "box-sizing" "care= t-color" "cursor" "nav-down" "nav-left"
+    "nav-right= " "nav-up" "outline" "outline-color" "outline-offset"
+   &n= bsp;"outline-style" "outline-width" "resize" "text-overflow"
+
+    ;; CSS Color Module Level 3
+    "color" "opacity"
+
+    ;; CSS Flexible Box Layout Module Level= 1
+    "align-content" "align-items" "align-self" "flex"= "flex-basis"
+    "flex-direction" "flex-flow" "flex-g= row" "flex-shrink" "flex-wrap"
+    "justify-content" "= order"
+
+    ;; CSS Fonts Module Level 3
+=    "font" "font-family" "font-feature-settings" "font-kerning"
+    "font-language-override" "font-size" "font-size-adj= ust"
+    "font-stretch" "font-style" "font-synthesis" = "font-variant"
+    "font-variant-alternates" "font-var= iant-caps"
+    "font-variant-east-asian" "font-variant= -ligatures"
+    "font-variant-numeric" "font-variant-p= osition" "font-weight"
+
+    ;; CSS Text Dec= oration Module Level 3
+    "text-decoration"= "text-decoration-color" "text-decoration-line"
+    "t= ext-decoration-skip" "text-decoration-style" "text-emphasis"
+ &n= bsp;  "text-emphasis-color" "text-emphasis-position" "text-emphasis-st= yle"
+    "text-shadow" "text-underline-position"
=
+
+    ;; CSS Text Module Level 3
+    "= hanging-punctuation" "hyphens" "letter-spacing" "line-break"
+ &n= bsp;  "overflow-wrap" "tab-size" "text-align" "text-align-last"
<= div>+    "text-indent" "text-justify" "text-transform" "white-spa= ce"
+    "word-break" "word-spacing" "word-wrap"
<= div>+
+    ;; CSS Transforms Module Level 1
+=    ;; (http://www.w3.org/TR/css3-2d-transforms/#property-index)
+    "backface-visibility" "perspective" "perspective-orig= in"
+    "transform" "transform-origin" "transform-styl= e"
+
+    ;; CSS Transitions
+ =    "transition" "transition-delay" "transition-duration"
+    "transition-property" "transition-timing-function"
+
+    ;; Filter Effects Module Level 1
+ =    "color-interpolation-filters" "filter" "flood-color"
+    "flood-opacity" "lighting-color")
+  "Identi= fiers for properties.")
+
+(defcustom css-electric-keys= '(?\} ?\;) ;; '()
+  "Self inserting keys which should trig= ger re-indentation."
+  :version "22.2"
+  :t= ype '(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-entr= y ?\{ "(}" st)
+    (modify-syntax-entry ?\} "){" st)
+    ;; Args in url(...) thingies and other "function ca= lls".
+    (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 be= ginning of words.
+    (modify-syntax-entry ?@ "'" st)<= /div>
+    ;; (modify-syntax-entry ?: "'" st)
+ &nb= sp;  (modify-syntax-entry ?# "'" st)
+    ;; Disti= nction between words and symbols.
+    (modify-syntax-e= ntry ?- "_" st)
+    st))
+
+(defco= nst css-escapes-re
+  "\\\\\\(?:[^\000-\037\177]\\|[0-9a-fA-= F]+[ \n\t\r\f]?\\)")
+(defconst css-nmchar-re (concat "\\(?:[-[:a= lnum:]]\\|" css-escapes-re "\\)"))
+(defconst css-nmstart-re (con= cat "\\(?:[[:alpha:]]\\|" css-escapes-re "\\)"))
+(defconst css-i= dent-re ;; (concat css-nmstart-re css-nmchar-re "*")
+  ;; A= pparently, "at rules" names can start with a dash, e.g. @-moz-keyframes.
+  (concat css-nmchar-re "+"))
+(defconst css-propri= etary-nmstart-re ;; Vendor-specific properties.
+  (concat "= [-_]" (regexp-opt '("ms" "moz" "o" "khtml" "webkit")) "-"))
+(def= const css-name-re (concat css-nmchar-re "+"))
+
+(defco= nst scss--hash-re "#\\(?:{[$-_[:alnum:]]+}\\|[[:alnum:]]+\\)")
+<= /div>
+(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-nam= e-face))
+  "Face to use for properties."
+  = :group 'css)
+(defface css-proprietary-property '((t :inherit (cs= s-property italic)))
+  "Face to use for vendor-specific pro= perties.")
+
+(defun css--font-lock-keywords (&opti= onal sassy)
+  `((,(concat "!\\s-*"
+    = ;          (regexp-opt (append (if sassy '("global= "))
+                 &nb= sp;                '("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 incl= uding the next
+    ;; semicolon (;) or the next block,= whichever comes first."
+    (,(concat "@" css-ident-r= e) (0 font-lock-builtin-face))
+    ;; Selectors.
=
+    ;; FIXME: attribute selectors don't work well because t= hey may contain
+    ;; strings which have already been= highlighted as f-l-string-face and
+    ;; thus preven= t 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 no= t be highlighted.
+    (,(concat
+   &nb= sp;   "^[ \t]*\\("
+       (if (not sassy)
+           ;; We don't allow / as first c= har, so as not to
+           ;; take a = comment as the beginning of a selector.
+       &n= bsp;   "[^@/:{} \t\n][^:{}]+"
+         = ;; Same as for non-sassy except we do want to allow { and }
+ &nb= sp;       ;; chars in selectors in the case of #{$foo}
=
+         ;; variable interpolation!
+ &= nbsp;       (concat "\\(?:" scss--hash-re
+  =               "\\|[^@/:{} \t\n#]\\)"
+                 "[^:{}#]*= \\(?:" scss--hash-re "[^:{}#]*\\)*"))
+       ;; E= ven though pseudo-elements should be prefixed by ::, a
+   &= nbsp;   ;; single colon is accepted for backward compatibility.
<= div>+       "\\(?:\\(:" (regexp-opt (append css-pseudo-class= -ids
+                 &n= bsp;                     = css-pseudo-element-ids) t)
+       "\\|\\::" (rege= xp-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 o= n some subsequent
+    ;; line.  This will only wo= rk if we properly mark the intervening text
+    ;; as = being part of a multiline element (and even then, this only
+ &nb= sp;  ;; ensures proper refontification, but not proper discovery).
+    ("^[ \t]*{" (0 (save-excursion
+   &nb= sp;                 (goto-char (mat= ch-beginning 0))
+             &nbs= p;       (skip-chars-backward " \n\t")
+   &n= bsp;                 (put-text-prop= erty (point) (match-end 0)
+           &= nbsp;                    =        'font-lock-multiline t)
+   &nbs= p;                 ;; No face.
+                   &nbs= p; nil)))
+    ;; Properties.  Again, we don't lim= it ourselves to css-property-ids.
+    (,(concat "\\(?:= [{;]\\|^\\)[ \t]*\\("
+            =  "\\(?:\\(" css-proprietary-nmstart-re "\\)\\|"
+   &n= bsp;          css-nmstart-re "\\)" css-nmchar-re "= *"
+              "\\)\\s-*:")=
+     (1 (if (match-end 2) 'css-proprietary-property '= css-property)))))
+
+(defvar css-font-lock-keywords (cs= s--font-lock-keywords))
+
+(defvar css-font-lock-defaul= ts
+  '(css-font-lock-keywords nil t))
+
+(defcustom css-indent-offset 4
+  "Basic size of one inden= tation step."
+  :version "22.2"
+  :type 'in= teger)
+
+(require 'smie)
+
+(defco= nst 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)
+     &n= bsp;   ;; FIXME: If the next char is not whitespace, what should we do= ?
+         (or (memq (char-after) '(?\s ?\t = ?\n))
+             (looking-at com= ment-start-skip)))
+    (if (memq (char-after) '(?\s ?\= t ?\n))
+        (forward-char 1) (forward-co= mment 1))
+    ";")
+   ((progn (forward= -comment (point-max))
+           (looki= ng-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 wh= itespace, what should we do?
+     ((and (eq (char-befo= re) ?\}) (scss-smie--not-interpolation-p)
+       =     (> pos (point))) ";")
+     ((memq (ch= ar-before) '(?\; ?\, ?\:))
+      (forward-char -1= ) (string (char-after)))
+     (t (smie-default-backwar= d-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."
+ &nb= sp;(save-excursion
+    (let ((pos (point)))
= +      (skip-chars-backward "-[:alnum:]")
+  =    (let ((start (point)))
+        = ;(skip-chars-backward " \t\r\n")
+        (wh= en (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)))
+      (s= kip-chars-backward "-[:alnum:]")
+      (when (eq = (char-before) ?\:)
+        (list (point) pos=
+              (if (eq (char-= before (- (point) 1)) ?\:)
+           &= nbsp;      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:]")
+     &= nbsp;(when (eq (char-before) ?\@)
+        (l= ist (point) pos css-at-ids)))))
+
+(defun css-completio= n-at-point ()
+  "Complete current symbol at point.
+Currently supports completion of CSS properties, pseudo-elements,
<= div>+pseudo-classes, and at-rules."
+  (or (css--complete-pr= operty)
+      (css--complete-pseudo-element-or-cl= ass)
+      (css--complete-at-rule)))
+<= /div>
+;;;###autoload
+(define-derived-mode css-mode prog-mod= e "CSS"
+  "Major mode to edit Cascading Style Sheets."
+  (setq-local font-lock-defaults css-font-lock-defaults)
<= div>+  (setq-local comment-start "/*")
+  (setq-local c= omment-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-n= ame)
+  (smie-setup css-smie-grammar #'css-smie-rules
<= div>+              :forward-token #'css-= smie--forward-token
+             &= nbsp;:backward-token #'css-smie--backward-token)
+  (setq-lo= cal electric-indent-chars
+           &n= bsp;  (append css-electric-keys electric-indent-chars))
+ &n= bsp;(add-hook 'completion-at-point-functions
+     &nbs= p;      #'css-completion-at-point nil 'local))
+
+(defvar comment-continue)
+
+(defun css-fill-= paragraph (&optional justify)
+  (save-excursion
+    (let ((ppss (syntax-ppss))
+     &nbs= p;    (eol (line-end-position)))
+      = (cond
+       ((and (nth 4 ppss)
+  = ;           (save-excursion
+   &nb= sp;           (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<= /div>
+        ;; css-mode but for all modes.
=
+        (save-restriction
+   &nbs= p;      (narrow-to-region (nth 8 ppss) eol)
+ &nbs= p;        (comment-normalize-vars)      = ;Will define comment-continue.
+         &nbs= p;(let ((fill-paragraph-function nil)
+       &nbs= p;        (paragraph-separate
+    =             (if (and comment-continue
<= div>+                    =      (string-match "[^ \t]" comment-continue))
+ =                     (conc= at "\\(?:[ \t]*" (regexp-quote comment-continue)
+     =                      = ;   "\\)?\\(?:" paragraph-separate "\\)")
+     &n= bsp;             paragraph-separate))
+                (paragraph-star= t
+                 (if (= and comment-continue
+             =              (string-match "[^ \t]" comm= ent-continue))
+              =       (concat "\\(?:[ \t]*" (regexp-quote comment-continue)=
+                  =           "\\)?\\(?:" paragraph-start "\\)")
+                   para= graph-start)))
+            (fill-p= aragraph justify)
+            ;; D= on't try filling again.
+           &nbs= p;t)))
+
+       ((and (null (nth 8 ppss= ))
+             (or (nth 1 ppss)
+                 (and (ig= nore-errors
+               &n= bsp;        (down-list 1)
+     &nb= sp;                  (when (&l= t;=3D (point) eol)
+             &n= bsp;            (setq ppss (syntax-ppss))))))= )
+        (goto-char (nth 1 ppss))
+        (let ((end (save-excursion
+  =                   (ignore-err= ors (forward-sexp 1) (copy-marker (point) t)))))
+     =      (when end
+          = ;  (while (re-search-forward "[{;}]" end t)
+     =          (cond
+       &n= bsp;       ;; This is a false positive inside a string or co= mment.
+               ((nth 8= (syntax-ppss)) nil)
+             =   ;; This is a false positive when encountering an
+   =             ;; interpolated variable (bug#197= 51).
+               ((eq (cha= r-before (- (point) 1)) ?#) nil)
+         &n= bsp;     ((eq (char-before) ?\})
+      =          (save-excursion
+    = ;              (forward-char -1)
+                  (skip-ch= ars-backward " \t")
+             &= nbsp;    (when (and (not (bolp))
+      =                     &nbs= p; (scss-smie--not-interpolation-p))
+        = ;            (newline))))
+   =             (t
+     &nbs= p;          (while
+      = ;              (progn
+  =                    (setq= eol (line-end-position))
+           &n= bsp;          (and (forward-comment 1)
+=                     &nbs= p;     (> (point) eol)
+        =                   ;; A multi-= line comment should be on its own line.
+       &n= bsp;                   (save-e= xcursion (forward-comment -1)
+          = ;                     &nb= sp;           (when (< (point) eol)
+=                     &nbs= p;                     &n= bsp; (newline)
+              =                     &nbs= p;         t)))))
+       &nbs= p;        (if (< (point) eol) (newline)))))
+            (goto-char (nth 1 ppss))
=
+            (indent-region (line-beginn= ing-position 2) end)
+            ;= ; Don't use the default filling code.
+       &nbs= p;    t)))))))
+
+(defun css-current-defun-na= me ()
+  "Return the name of the CSS section at point, or ni= l."
+  (save-excursion
+    (let ((max (= max (point-min) (- (point) 1600))))  ; approx 20 lines back
= +      (when (search-backward "{" max t)
+ (skip-chars-backwa= rd " \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
+ &nb= sp;(append `((,(concat "$" css-ident-re) (0 font-lock-variable-name-face)))=
+          (css--font-lock-keywords 'sa= ssy)
+          `((,(concat "@mixin[ \t]= +\\(" css-ident-re "\\)[ \t]*(")
+         &n= bsp;   (1 font-lock-function-name-face)))))
+
+(de= fun 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))
<= div>+;;;###autoload
+(define-derived-mode scss-mode css-mode "SCS= S"
+  "Major mode to edit \"Sassy CSS\" files."
+ =  (setq-local comment-start "// ")
+  (setq-local commen= t-end "")
+  (setq-local comment-start-skip "/[*/]+[ \t]*")<= /div>
+  (setq-local comment-end-skip "[ \t]*\\(?:\n\\|\\*+/\\)")<= /div>
+  (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/text= modes/css-mode.el
deleted file mode 100644
index 728008= 0..0000000
--- a/lisp/textmodes/css-mode.el
+++ /dev/nu= ll
@@ -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=C3=B8yl <simenheg@gmail.com>
-;;= Keywords: hypermedia
-
-;; This file is part of GNU Em= acs.
-
-;; GNU Emacs is free software: you can redistri= bute it and/or modify
-;; it under the terms of the GNU General P= ublic License as published by
-;; the Free Software Foundation, e= ither version 3 of the License, or
-;; (at your option) any later= version.
-
-;; GNU Emacs is distributed in the hope th= at it will be useful,
-;; but WITHOUT ANY WARRANTY; without even = the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PART= ICULAR 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/l= icenses/>.
-
-;;; Commentary:
-
<= div>-;; Yet another CSS mode.
-
-;;; Todo:
-<= /div>
-;; - electric ; and }
-;; - filling code with auto-fil= l-mode
-;; - attribute value completion
-;; - fix font-= lock errors with multi-line selectors
-
-;;; Code:
-
-(defgroup css nil
-  "Cascading Style She= ets (CSS) editing mode."
-  :group 'languages)
-
-(defconst css-pseudo-class-ids
-  '("active" "chec= ked" "disabled" "empty" "enabled" "first"
-    "first-c= hild" "first-of-type" "focus" "hover" "indeterminate" "lang"
- &n= bsp;  "last-child" "last-of-type" "left" "link" "nth-child"
= -    "nth-last-child" "nth-last-of-type" "nth-of-type" "only-chil= d"
-    "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-eleme= nts.")
-
-(defconst css-at-ids
-  '("cha= rset" "font-face" "import" "media" "namespace" "page")
-  "I= dentifiers that appear in the form @foo.")
-
-(defconst= css-descriptor-ids
-  '("ascent" "baseline" "bbox" "cap-hei= ght" "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" "wid= ths" "x-height")
-  "Identifiers for font descriptors.")
-
-(defconst css-media-ids
-  '("all" "aura= l" "bitmap" "continuous" "grid" "paged" "static" "tactile"
- &nbs= p;  "visual")
-  "Identifiers for types of media.")
-
-(defconst css-property-ids
-  '(;; CSS 2= .1 properties (http://w= ww.w3.org/TR/CSS21/propidx.html).
-    ;;
-    ;; Properties duplicated by any of the CSS3 modules below h= ave
-    ;; been removed.
-    "azi= muth" "border-collapse" "border-spacing" "bottom"
-    = "caption-side" "clear" "clip" "content" "counter-increment"
- &nb= sp;  "counter-reset" "cue" "cue-after" "cue-before" "direction" "displ= ay"
-    "elevation" "empty-cells" "float" "height" "le= ft" "line-height"
-    "list-style" "list-style-image" = "list-style-position"
-    "list-style-type" "margin" "= margin-bottom" "margin-left"
-    "margin-right" "margi= n-top" "max-height" "max-width" "min-height"
-    "min-= width" "orphans" "overflow" "padding" "padding-bottom"
-   &= nbsp;"padding-left" "padding-right" "padding-top" "page-break-after"
<= div>-    "page-break-before" "page-break-inside" "pause" "pause-a= fter"
-    "pause-before" "pitch" "pitch-range" "play-d= uring" "position"
-    "quotes" "richness" "right" "spe= ak" "speak-header" "speak-numeral"
-    "speak-punctuat= ion" "speech-rate" "stress" "table-layout" "top"
-    "= unicode-bidi" "vertical-align" "visibility" "voice-family" "volume"
-    "widows" "width" "z-index"
-
-  =  ;; CSS Animations
-    "animation" "animation-= delay" "animation-direction"
-    "animation-duration" = "animation-fill-mode"
-    "animation-iteration-count" = "animation-name"
-    "animation-play-state" "animation= -timing-function"
-
-    ;; CSS Backgrounds a= nd Borders Module Level 3
-    "background" "backgrou= nd-attachment" "background-clip"
-    "background-color= " "background-image" "background-origin"
-    "backgrou= nd-position" "background-repeat" "background-size"
-    = ;"border" "border-bottom" "border-bottom-color"
-    "b= order-bottom-left-radius" "border-bottom-right-radius"
-   &= nbsp;"border-bottom-style" "border-bottom-width" "border-color"
-=    "border-image" "border-image-outset" "border-image-repeat"
-    "border-image-slice" "border-image-source" "border-i= mage-width"
-    "border-left" "border-left-color" "bor= der-left-style"
-    "border-left-width" "border-radius= " "border-right"
-    "border-right-color" "border-righ= t-style" "border-right-width"
-    "border-style" "bord= er-top" "border-top-color"
-    "border-top-left-radius= " "border-top-right-radius"
-    "border-top-style" "bo= rder-top-width" "border-width" "box-shadow"
-
-   =  ;; CSS Basic User Interface Module Level 3 (CSS3 UI)
-    "box-= sizing" "caret-color" "cursor" "nav-down" "nav-left"
-   &nb= sp;"nav-right" "nav-up" "outline" "outline-color" "outline-offset"
-    "outline-style" "outline-width" "resize" "text-overflow"
-
-    ;; CSS Color Module Level 3
-    "color= " "opacity"
-
-    ;; CSS Flexible Box Layout= Module Level 1
-    "align-content" "align-items" "align= -self" "flex" "flex-basis"
-    "flex-direction" "flex-= flow" "flex-grow" "flex-shrink" "flex-wrap"
-    "justi= fy-content" "order"
-
-    ;; CSS Fonts Modul= e Level 3
-    "font" "font-family" "font-feature-settings" "fo= nt-kerning"
-    "font-language-override" "font-size" "= font-size-adjust"
-    "font-stretch" "font-style" "fon= t-synthesis" "font-variant"
-    "font-variant-alternat= es" "font-variant-caps"
-    "font-variant-east-asian" = "font-variant-ligatures"
-    "font-variant-numeric" "f= ont-variant-position" "font-weight"
-
-    ;;= CSS Text Decoration Module Level 3
-    "tex= t-decoration" "text-decoration-color" "text-decoration-line"
- &n= bsp;  "text-decoration-skip" "text-decoration-style" "text-emphasis"
-    "text-emphasis-color" "text-emphasis-position" "tex= t-emphasis-style"
-    "text-shadow" "text-underline-po= sition"
-
-    ;; CSS Text Module Level 3
- &= nbsp;  "hanging-punctuation" "hyphens" "letter-spacing" "line-break"
-    "overflow-wrap" "tab-size" "text-align" "text-align= -last"
-    "text-indent" "text-justify" "text-transfor= m" "white-space"
-    "word-break" "word-spacing" "word= -wrap"
-
-    ;; CSS Transforms Module Level = 1
-    "backface-visibility" "perspective" "per= spective-origin"
-    "transform" "transform-origin" "t= ransform-style"
-
-    ;; CSS Transitions
-    "transition" "transition-delay" "transition-durat= ion"
-    "transition-property" "transition-timing-func= tion"
-
-    ;; Filter Effects Module Level 1=
-    "color-interpolation-filters" "filter" "flood-col= or"
-    "flood-opacity" "lighting-color")
- =  "Identifiers for properties.")
-
-(defcustom css-= electric-keys '(?\} ?\;) ;; '()
-  "Self inserting keys whic= h should trigger re-indentation."
-  :version "22.2"
-  :type '(repeat character)
-  :options '((?\} ?\;)= )
-  :group 'css)
-
-(defvar css-mode-sy= ntax-table
-  (let ((st (make-syntax-table)))
- &n= bsp;  ;; C-style comments.
-    (modify-syntax-ent= ry ?/ ". 14" st)
-    (modify-syntax-entry ?* ". 23b" s= t)
-    ;; Strings.
-    (modify-sy= ntax-entry ?\" "\"" st)
-    (modify-syntax-entry ?\' "= \"" st)
-    ;; Blocks.
-    (modif= y-syntax-entry ?\{ "(}" st)
-    (modify-syntax-entry ?= \} "){" st)
-    ;; Args in url(...) thingies and other= "function calls".
-    (modify-syntax-entry ?\( "()" s= t)
-    (modify-syntax-entry ?\) ")(" st)
- &= nbsp;  ;; To match attributes in selectors.
-    (= modify-syntax-entry ?\[ "(]" st)
-    (modify-syntax-en= try ?\] ")[" st)
-    ;; Special chars that sometimes c= ome at the beginning of words.
-    (modify-syntax-entr= y ?@ "'" st)
-    ;; (modify-syntax-entry ?: "'" st)
-    (modify-syntax-entry ?# "'" st)
-   &= nbsp;;; Distinction between words and symbols.
-    (mo= dify-syntax-entry ?- "_" st)
-    st))
-
-(defconst css-escapes-re
-  "\\\\\\(?:[^\000-\037\177= ]\\|[0-9a-fA-F]+[ \n\t\r\f]?\\)")
-(defconst css-nmchar-re (conca= t "\\(?:[-[:alnum:]]\\|" css-escapes-re "\\)"))
-(defconst css-nm= start-re (concat "\\(?:[[:alpha:]]\\|" css-escapes-re "\\)"))
-(d= efconst 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 "+"))
-(defcon= st css-proprietary-nmstart-re ;; Vendor-specific properties.
- &n= bsp;(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-funct= ion-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-keywor= ds (&optional sassy)
-  `((,(concat "!\\s-*"
-=              (regexp-opt (append (if sa= ssy '("global"))
-             &nbs= p;                    '("= important"))))
-     (0 font-lock-builtin-face))
<= div>-    ;; Atrules keywords.  IDs not in css-at-ids are val= id (ignored).
-    ;; In fact the regexp should probabl= y be
-    ;; (,(concat "\\(@" css-ident-re "\\)\\([ \t\= n][^;{]*\\)[;{]")
-    ;;  (1 font-lock-builtin-fa= ce))
-    ;; Since "An at-rule consists of everything u= p to and including the next
-    ;; semicolon (;) or th= e next block, whichever comes first."
-    (,(concat "@= " css-ident-re) (0 font-lock-builtin-face))
-    ;; Sel= ectors.
-    ;; FIXME: attribute selectors don't work w= ell 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 re= ally the part of the
-    ;; selector between [...] sho= uld simply not be highlighted.
-    (,(concat
-       "^[ \t]*\\("
-       (if (= not sassy)
-           ;; We don't allow= / as first char, so as not to
-         &nbs= p; ;; take a comment as the beginning of a selector.
-   &nb= sp;       "[^@/:{} \t\n][^:{}]+"
-     &= nbsp;   ;; Same as for non-sassy except we do want to allow { and }
-         ;; chars in selectors in the case of = #{$foo}
-         ;; variable interpolation!<= /div>
-         (concat "\\(?:" scss--hash-re
=
-                 "\\|[^@/:{} = \t\n#]\\)"
-               &nb= sp; "[^:{}#]*\\(?:" scss--hash-re "[^:{}#]*\\)*"))
-    = ;   ;; Even though pseudo-elements should be prefixed by ::, a
-       ;; single colon is accepted for backward compatib= ility.
-       "\\(?:\\(:" (regexp-opt (append css= -pseudo-class-ids
-             &nb= sp;                     &= nbsp;   css-pseudo-element-ids) t)
-       "\= \|\\::" (regexp-opt css-pseudo-element-ids t) "\\)"
-   &nbs= p;   "\\(?:([^\)]+)\\)?"
-       (if (not sas= sy)
-           "[^:{}\n]*"
- =         (concat "[^:{}\n#]*\\(?:" scss--hash-re "[^:{}\= n#]*\\)*"))
-       "\\)*"
-   &nbs= p;   "\\)\\(?:\n[ \t]*\\)*{")
-     (1 'css-select= or 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 di= scovery).
-    ("^[ \t]*{" (0 (save-excursion
-                     (g= oto-char (match-beginning 0))
-          = ;           (skip-chars-backward " \n\t")
-                     (= put-text-property (point) (match-end 0)
-       &n= bsp;                     =            '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 "\\)" cs= s-nmchar-re "*"
-              = ;"\\)\\s-*:")
-     (1 (if (match-end 2) 'css-proprieta= ry-property 'css-property)))))
-
-(defvar css-font-lock= -keywords (css--font-lock-keywords))
-
-(defvar css-fon= t-lock-defaults
-  '(css-font-lock-keywords nil t))
-
-(defcustom css-indent-offset 4
-  "Basic size= of one indentation step."
-  :version "22.2"
- &n= bsp;: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) ?\})
- &= nbsp;       (scss-smie--not-interpolation-p)
- &nb= sp;       ;; FIXME: If the next char is not whitespace, what= should we do?
-         (or (memq (char-afte= r) '(?\s ?\t ?\n))
-             (l= ooking-at comment-start-skip)))
-    (if (memq (char-af= ter) '(?\s ?\t ?\n))
-        (forward-char 1= ) (forward-comment 1))
-    ";")
-   ((p= rogn (forward-comment (point-max))
-         =   (looking-at "[;,:]"))
-    (forward-char 1) (mat= ch-string 0))
-   (t (smie-default-forward-token))))
-
-(defun css-smie--backward-token ()
-  (let (= (pos (point)))
-    (forward-comment (- (point)))
=
-    (cond
-     ;; FIXME: If the next c= har is not whitespace, what should we do?
-     ((and (= eq (char-before) ?\}) (scss-smie--not-interpolation-p)
-   &= nbsp;       (> pos (point))) ";")
-   &nbs= p; ((memq (char-before) '(?\; ?\, ?\:))
-      (fo= rward-char -1) (string (char-after)))
-     (t (smie-de= fault-backward-token)))))
-
-(defun css-smie-rules (kin= d token)
-  (pcase (cons kind token)
-   &nbs= p;(`(:elem . basic) css-indent-offset)
-    (`(:elem . = arg) 0)
-    (`(:list-intro . ,(or `";" `"")) t) ;"" st= ands for BOB (bug#15467).
-    (`(:before . ,(or "{" "(= "))
-     (if (smie-rule-hanging-p) (smie-rule-parent 0= )))))
-
-;;; Completion
-
-(defun c= ss--complete-property ()
-  "Complete property at point."
-  (save-excursion
-    (let ((pos (point)= ))
-      (skip-chars-backward "-[:alnum:]")
=
-      (let ((start (point)))
-    =    (skip-chars-backward " \t\r\n")
-     &nb= sp;  (when (memq (char-before) '(?\{ ?\;))
-     &= nbsp;    (list start pos css-property-ids))))))
-
=
-(defun css--complete-pseudo-element-or-class ()
-  "Co= mplete pseudo-element or pseudo-class at point."
-  (save-ex= cursion
-    (let ((pos (point)))
-   &n= bsp;  (skip-chars-backward "-[:alnum:]")
-     &nb= sp;(when (eq (char-before) ?\:)
-        (lis= t (point) pos
-              (= if (eq (char-before (- (point) 1)) ?\:)
-       &n= bsp;          css-pseudo-element-ids
- &= nbsp;              css-pseudo-class-ids)= )))))
-
-(defun css--complete-at-rule ()
- &n= bsp;"Complete at-rule (statement beginning with `@') at point."
-=  (save-excursion
-    (let ((pos (point)))
<= div>-      (skip-chars-backward "-[:alnum:]")
- &n= bsp;    (when (eq (char-before) ?\@)
-     &n= bsp;  (list (point) pos css-at-ids)))))
-
-(defun = css-completion-at-point ()
-  "Complete current symbol at po= int.
-Currently supports completion of CSS properties, pseudo-ele= ments,
-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-def= aults)
-  (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-parag= raph)
-  (setq-local add-log-current-defun-function #'css-cu= rrent-defun-name)
-  (smie-setup css-smie-grammar #'css-smie= -rules
-              :forward= -token #'css-smie--forward-token
-         &n= bsp;    :backward-token #'css-smie--backward-token)
- &= nbsp;(setq-local electric-indent-chars
-       &nb= sp;      (append css-electric-keys electric-indent-chars))
-  (add-hook 'completion-at-point-functions
-  = ;          #'css-completion-at-point nil 'local))<= /div>
-
-(defvar comment-continue)
-
-(de= fun css-fill-paragraph (&optional justify)
-  (save-excu= rsion
-    (let ((ppss (syntax-ppss))
-  = ;        (eol (line-end-position)))
-   =    (cond
-       ((and (nth 4 ppss)
-             (save-excursion
-               (goto-char (nth 8 ppss)= )
-               (forward-com= ment 1)
-               (prog1= (not (bolp))
-               =   (setq eol (point)))))
-        ;; Fill= ing 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-co= ntinue
-                 =          (string-match "[^ \t]" comment-continue))=
-                  =   (concat "\\(?:[ \t]*" (regexp-quote comment-continue)
- &= nbsp;                    =       "\\)?\\(?:" paragraph-separate "\\)")
- &nb= sp;                 paragraph-separ= ate))
-                (p= aragraph-start
-              =   (if (and comment-continue
-         &= nbsp;                (string-match = "[^ \t]" comment-continue))
-           =           (concat "\\(?:[ \t]*" (regexp-quote comm= ent-continue)
-               =               "\\)?\\(?:" paragraph-star= t "\\)")
-                = ;   paragraph-start)))
-           =  (fill-paragraph justify)
-         &nbs= p;  ;; Don't try filling again.
-        = ;    t)))
-
-       ((and (nul= l (nth 8 ppss))
-             (or (= nth 1 ppss)
-               &n= bsp; (and (ignore-errors
-           &nb= sp;            (down-list 1)
- &nbs= p;                     &n= bsp;(when (<=3D (point) eol)
-         &nb= sp;                (setq ppss (synt= ax-ppss)))))))
-        (goto-char (nth 1 pps= s))
-        (let ((end (save-excursion
=
-                    = ; (ignore-errors (forward-sexp 1) (copy-marker (point) t)))))
- &= nbsp;        (when end
-      =      (while (re-search-forward "[{;}]" end t)
- &= nbsp;            (cond
-   &nb= sp;           ;; This is a false positive inside a= string or comment.
-             &= nbsp; ((nth 8 (syntax-ppss)) nil)
-         &= nbsp;     ;; This is a false positive when encountering an
<= div>-               ;; interpolated vari= able (bug#19751).
-             &nb= sp; ((eq (char-before (- (point) 1)) ?#) nil)
-     &nb= sp;         ((eq (char-before) ?\})
-   =              (save-excursion
-=                  (forward-cha= r -1)
-                 &= nbsp;(skip-chars-backward " \t")
-         &n= bsp;        (when (and (not (bolp))
-   =                      = ;     (scss-smie--not-interpolation-p))
-    =                (newline))))
<= div>-               (t
-  = ;              (while
-  =                  (progn
=
-                    = ;  (setq eol (line-end-position))
-       &nb= sp;              (and (forward-comment 1= )
-                  = ;         (> (point) eol)
-     =                      = ; ;; A multi-line comment should be on its own line.
-   &nb= sp;                     &= nbsp; (save-excursion (forward-comment -1)
-      =                     &nbs= p;               (when (< (point) eol= )
-                  = ;                     &nb= sp;     (newline)
-           =                      = ;             t)))))
-    = ;            (if (< (point) eol) (newline)= ))))
-            (goto-char (nth 1= ppss))
-            (indent-region= (line-beginning-position 2) end)
-         &= nbsp;  ;; Don't use the default filling code.
-    = ;        t)))))))
-
-(defun css-cur= rent-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 ba= ck
-      (when (search-backward "{" max t)
<= div>- (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 scs= s-mode-syntax-table
-  (let ((st (make-syntax-table css-mode= -syntax-table)))
-    (modify-syntax-entry ?/ ". 124" s= t)
-    (modify-syntax-entry ?\n ">" st)
-=    st))
-
-(defvar scss-font-lock-keywords
-  (append `((,(concat "$" css-ident-re) (0 font-lock-variabl= e-name-face)))
-          (css--font-loc= k-keywords 'sassy)
-          `((,(conca= t "@mixin[ \t]+\\(" css-ident-re "\\)[ \t]*(")
-     &n= bsp;       (1 font-lock-function-name-face)))))
-<= /div>
-(defun scss-smie--not-interpolation-p ()
-  (save= -excursion
-    (forward-char -1)
-   &n= bsp;(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 "// ")
-  (set= q-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
= --=-negPAn0+66EZt3OPm6ZF-- From debbugs-submit-bounces@debbugs.gnu.org Mon Mar 30 18:04:02 2015 Received: (at 20226) by debbugs.gnu.org; 30 Mar 2015 22:04:02 +0000 Received: from localhost ([127.0.0.1]:40732 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.80) (envelope-from ) id 1Ychmr-0004FF-Ty for submit@debbugs.gnu.org; Mon, 30 Mar 2015 18:04:02 -0400 Received: from ironport2-out.teksavvy.com ([206.248.154.181]:45787) by debbugs.gnu.org with esmtp (Exim 4.80) (envelope-from ) id 1Ychmp-0004Eq-NL for 20226@debbugs.gnu.org; Mon, 30 Mar 2015 18:04:00 -0400 X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: AnEFAGvvdVRBbthL/2dsb2JhbAA3gVOfQYIugQiBdQEBBAFWIwULCzQSFBgNJIgTohGMawEBAQIBAoM+AwODbQSoOw X-IPAS-Result: AnEFAGvvdVRBbthL/2dsb2JhbAA3gVOfQYIugQiBdQEBBAFWIwULCzQSFBgNJIgTohGMawEBAQIBAoM+AwODbQSoOw X-IronPort-AV: E=Sophos;i="5.01,1,1400040000"; d="scan'208";a="114995584" Received: from 65-110-216-75.cpe.pppoe.ca (HELO fmsmemgm.homelinux.net) ([65.110.216.75]) by ironport2-out.teksavvy.com with ESMTP/TLS/DHE-RSA-AES256-SHA; 30 Mar 2015 18:03:53 -0400 Received: by fmsmemgm.homelinux.net (Postfix, from userid 20848) id C2A42AE0BC; Mon, 30 Mar 2015 18:03:53 -0400 (EDT) From: Stefan Monnier To: Simen =?windows-1252?Q?Heggest=F8yl?= Subject: Re: bug#20226: 25.0.50; [PATCH] Make (S)CSS mode require final newline Message-ID: References: <1427748652.1775.0@smtp.gmail.com> Date: Mon, 30 Mar 2015 18:03:53 -0400 In-Reply-To: <1427748652.1775.0@smtp.gmail.com> ("Simen =?windows-1252?Q?H?= =?windows-1252?Q?eggest=F8yl=22's?= message of "Mon, 30 Mar 2015 22:50:52 +0200") User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/25.0.50 (gnu/linux) MIME-Version: 1.0 Content-Type: text/plain X-Spam-Score: 0.3 (/) X-Debbugs-Envelope-To: 20226 Cc: 20226@debbugs.gnu.org X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: 0.3 (/) > Good! Then I propose the following two patches: The first looks good. I think the second is kind of pointless. Stefan From debbugs-submit-bounces@debbugs.gnu.org Tue Mar 31 14:05:14 2015 Received: (at 20226-done) by debbugs.gnu.org; 31 Mar 2015 18:05:14 +0000 Received: from localhost ([127.0.0.1]:41396 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.80) (envelope-from ) id 1Yd0XJ-0001ko-Tj for submit@debbugs.gnu.org; Tue, 31 Mar 2015 14:05:14 -0400 Received: from mail-lb0-f172.google.com ([209.85.217.172]:33272) by debbugs.gnu.org with esmtp (Exim 4.80) (envelope-from ) id 1Yd0XH-0001kN-Q2 for 20226-done@debbugs.gnu.org; Tue, 31 Mar 2015 14:05:12 -0400 Received: by lbbzk7 with SMTP id zk7so2298458lbb.0 for <20226-done@debbugs.gnu.org>; Tue, 31 Mar 2015 11:05:05 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=date:from:subject:to:cc:message-id:in-reply-to:references :mime-version:content-type; bh=aTXzKGScThVKemF33X+v6+feM4sBzv+hIpneKQA66/4=; b=prGz1wuNxFRa9ZayeeBRJZQVOfsxABfYao7KmzvBcrrY+BFHaQkE1hrAOYlJfRAZdT LyycFwmfieRfHCnMeF39Dd4BRu8xHvrurMq/2zYBrsH0/8/Ry0mDTBjo3PB9hXBFy9ET wsedErOxdL9cXlsy/btnrNZQncjrfvrFtcLRfwzMM2tVqH57C8UdwKcxtUS/cov0p8Ht p8xiCMb33QDCzSz/getrKfUkcoB4c9DgVQB0/ufg0kw6RtDTPh0BPRp0vDaqzryCuv51 QUMvlhM1wQD5cE9dy+70OKXy99SHolkuxZL2RuPc0/H/e739969ftnrGHhWijwBQseP1 Ewog== X-Received: by 10.152.120.202 with SMTP id le10mr31459424lab.115.1427825105653; Tue, 31 Mar 2015 11:05:05 -0700 (PDT) Received: from [192.168.1.114] (cm-84.215.44.110.getinternet.no. [84.215.44.110]) by mx.google.com with ESMTPSA id ao5sm2758331lac.48.2015.03.31.11.05.04 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 31 Mar 2015 11:05:04 -0700 (PDT) Date: Tue, 31 Mar 2015 20:05:02 +0200 From: Simen =?iso-8859-1?q?Heggest=F8yl?= Subject: Re: bug#20226: 25.0.50; [PATCH] Make (S)CSS mode require final newline To: Stefan Monnier Message-Id: <1427825102.12013.0@smtp.gmail.com> In-Reply-To: References: X-Mailer: geary/0.8.2 MIME-Version: 1.0 Content-Type: multipart/alternative; boundary="=-91NgUBjh9qYeg3fLx0Qj" X-Spam-Score: -0.7 (/) X-Debbugs-Envelope-To: 20226-done Cc: 20226-done@debbugs.gnu.org X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -0.7 (/) --=-91NgUBjh9qYeg3fLx0Qj Content-Type: text/plain; charset=utf-8; format=flowed On Tue, Mar 31, 2015 at 12:03 AM, Stefan Monnier 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! --=-91NgUBjh9qYeg3fLx0Qj Content-Type: text/html; charset=utf-8 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!
--=-91NgUBjh9qYeg3fLx0Qj-- From debbugs-submit-bounces@debbugs.gnu.org Tue Mar 31 17:12:23 2015 Received: (at 20226-done) by debbugs.gnu.org; 31 Mar 2015 21:12:23 +0000 Received: from localhost ([127.0.0.1]:41470 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.80) (envelope-from ) id 1Yd3SR-00083G-4Q for submit@debbugs.gnu.org; Tue, 31 Mar 2015 17:12:23 -0400 Received: from ironport2-out.teksavvy.com ([206.248.154.181]:29138) by debbugs.gnu.org with esmtp (Exim 4.80) (envelope-from ) id 1Yd3SP-000832-BZ for 20226-done@debbugs.gnu.org; Tue, 31 Mar 2015 17:12:21 -0400 X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: AnEFAGvvdVRBbthL/2dsb2JhbAA3gVOfQYIugQiBdQEBBAFWIwULCzQSFBgNJIgTohGMZAkDAQKDPgODcASoOw X-IPAS-Result: AnEFAGvvdVRBbthL/2dsb2JhbAA3gVOfQYIugQiBdQEBBAFWIwULCzQSFBgNJIgTohGMZAkDAQKDPgODcASoOw X-IronPort-AV: E=Sophos;i="5.01,1,1400040000"; d="scan'208";a="115083966" Received: from 65-110-216-75.cpe.pppoe.ca (HELO pastel.home) ([65.110.216.75]) by ironport2-out.teksavvy.com with ESMTP/TLS/DHE-RSA-AES256-SHA; 31 Mar 2015 17:12:16 -0400 Received: by pastel.home (Postfix, from userid 20848) id C72181054; Tue, 31 Mar 2015 17:12:15 -0400 (EDT) From: Stefan Monnier To: Simen =?windows-1252?Q?Heggest=F8yl?= Subject: Re: bug#20226: 25.0.50; [PATCH] Make (S)CSS mode require final newline Message-ID: References: <1427825102.12013.0@smtp.gmail.com> Date: Tue, 31 Mar 2015 17:12:15 -0400 In-Reply-To: <1427825102.12013.0@smtp.gmail.com> ("Simen =?windows-1252?Q?Heggest=F8yl=22's?= message of "Tue, 31 Mar 2015 20:05:02 +0200") User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/25.0.50 (gnu/linux) MIME-Version: 1.0 Content-Type: text/plain X-Spam-Score: 0.3 (/) X-Debbugs-Envelope-To: 20226-done Cc: 20226-done@debbugs.gnu.org X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: 0.3 (/) > 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 From unknown Thu Jun 19 14:13:42 2025 Received: (at fakecontrol) by fakecontrolmessage; To: internal_control@debbugs.gnu.org From: Debbugs Internal Request Subject: Internal Control Message-Id: bug archived. Date: Wed, 29 Apr 2015 11:24:05 +0000 User-Agent: Fakemail v42.6.9 # This is a fake control message. # # The action: # bug archived. thanks # This fakemail brought to you by your local debbugs # administrator