2009-01-14 10:49:41 -08:00
|
|
|
;;; sass-mode.el --- Major mode for editing Sass files
|
|
|
|
|
|
|
|
;; Copyright (c) 2007, 2008 Nathan Weizenbaum
|
|
|
|
|
|
|
|
;; Author: Nathan Weizenbaum
|
|
|
|
;; URL: http://github.com/nex3/haml/tree/master
|
|
|
|
;; Version: 1.0
|
|
|
|
;; Keywords: markup, language
|
|
|
|
|
|
|
|
;;; Commentary:
|
|
|
|
|
|
|
|
;; Because Sass's indentation schema is similar
|
|
|
|
;; to that of YAML and Python, many indentation-related
|
|
|
|
;; functions are similar to those in yaml-mode and python-mode.
|
|
|
|
|
|
|
|
;; To install, save this on your load path and add the following to
|
|
|
|
;; your .emacs file:
|
|
|
|
;;
|
|
|
|
;; (require 'sass-mode)
|
2007-03-16 04:00:47 +00:00
|
|
|
|
|
|
|
;;; Code:
|
|
|
|
|
2008-04-22 18:43:31 -07:00
|
|
|
(require 'haml-mode)
|
|
|
|
|
2007-03-16 04:00:47 +00:00
|
|
|
;; User definable variables
|
|
|
|
|
|
|
|
(defgroup sass nil
|
|
|
|
"Support for the Sass template language."
|
|
|
|
:group 'languages
|
|
|
|
:prefix "sass-")
|
|
|
|
|
|
|
|
(defcustom sass-mode-hook nil
|
2008-04-22 16:36:51 -07:00
|
|
|
"Hook run when entering Sass mode."
|
2007-03-16 04:00:47 +00:00
|
|
|
:type 'hook
|
|
|
|
:group 'sass)
|
|
|
|
|
|
|
|
(defcustom sass-indent-offset 2
|
2008-04-22 16:36:51 -07:00
|
|
|
"Amount of offset per level of indentation."
|
2007-03-16 04:00:47 +00:00
|
|
|
:type 'integer
|
|
|
|
:group 'sass)
|
|
|
|
|
2008-04-24 09:09:42 -07:00
|
|
|
(defvar sass-non-block-openers
|
|
|
|
'("^ *:[^ \t]+[ \t]+[^ \t]"
|
|
|
|
"^ *[^ \t:]+[ \t]*[=:][ \t]*[^ \t]")
|
|
|
|
"A list of regexps that match lines of Sass that couldn't have
|
|
|
|
text nested beneath them.")
|
|
|
|
|
2008-02-16 17:31:10 +07:00
|
|
|
;; Font lock
|
|
|
|
|
2009-03-17 18:07:16 -07:00
|
|
|
(defconst sass-selector-font-lock-keywords
|
|
|
|
'(("&" 0 font-lock-constant-face)
|
|
|
|
("\\.\\w+" 0 font-lock-type-face)
|
|
|
|
("#\\w+" 0 font-lock-keyword-face)
|
|
|
|
;; Pseudo-selectors, optionally with arguments (e.g. :first, :nth-child(12))
|
|
|
|
("\\(::?\\w+\\)" (1 font-lock-function-name-face)
|
|
|
|
("(\\([^)]+\\))" nil nil (1 font-lock-string-face)))
|
|
|
|
;; Attribute selectors (e.g. p[foo=bar])
|
|
|
|
("\\[\\([^]=]+\\)" (1 font-lock-variable-name-face)
|
|
|
|
("[~|$^*]?=\\([^]=]+\\)" nil nil (1 font-lock-string-face)))))
|
|
|
|
|
2009-03-28 10:33:31 -07:00
|
|
|
(defconst sass-syntax-table
|
|
|
|
(let ((st (make-syntax-table)))
|
|
|
|
(modify-syntax-entry ?- "w" st)
|
|
|
|
st))
|
|
|
|
|
2008-04-22 16:36:51 -07:00
|
|
|
(defconst sass-font-lock-keywords
|
2009-03-17 18:07:16 -07:00
|
|
|
'((sass-highlight-line 1 nil nil t)))
|
|
|
|
|
|
|
|
(defconst sass-line-keywords
|
2009-03-28 10:32:29 -07:00
|
|
|
'(("@\\w+" 0 font-lock-constant-face)
|
2009-03-17 18:07:16 -07:00
|
|
|
("/[/*].*" 0 font-lock-comment-face)
|
|
|
|
(".*" sass-highlight-selector))
|
|
|
|
"A list of full-line Sass syntax to highlight,
|
|
|
|
used by `sass-highlight-line'.
|
|
|
|
|
|
|
|
Each item is either of the form (REGEXP SUBEXP FACE) or (REGEXP FN).
|
|
|
|
Each REGEXP is run successively on the beginning of non-whitespace
|
|
|
|
on the current line until one matches. If it has SUBEXP and FACE,
|
|
|
|
then SUBEXP is highlighted using FACE. Otherwise, FN is run.")
|
|
|
|
|
|
|
|
(defun sass-highlight-line (limit)
|
|
|
|
"Highlight a single line using some Sass single-line syntax,
|
|
|
|
taken from `sass-line-keywords'."
|
|
|
|
(save-match-data
|
|
|
|
(when (re-search-forward "^ *\\(.+\\)$" limit t)
|
|
|
|
(goto-char (match-beginning 1))
|
|
|
|
(dolist (keyword sass-line-keywords)
|
|
|
|
(destructuring-bind (keyword subexp-or-fn &optional face) keyword
|
|
|
|
(when (looking-at keyword)
|
|
|
|
(if (integerp subexp-or-fn)
|
|
|
|
(put-text-property (match-beginning subexp-or-fn)
|
|
|
|
(match-end subexp-or-fn)
|
|
|
|
'face face)
|
|
|
|
(funcall subexp-or-fn))
|
|
|
|
(end-of-line)
|
|
|
|
(return t)))))))
|
|
|
|
|
|
|
|
(defun sass-highlight-selector ()
|
|
|
|
"Highlight a CSS selector starting at `point'
|
|
|
|
and ending at `end-of-line'."
|
|
|
|
(end-of-line)
|
2009-03-28 10:33:31 -07:00
|
|
|
(let ((font-lock-keywords sass-selector-font-lock-keywords))
|
2009-03-17 18:07:16 -07:00
|
|
|
(font-lock-fontify-region
|
|
|
|
(point) (progn (end-of-line) (point))))
|
|
|
|
t)
|
2008-02-16 17:31:10 +07:00
|
|
|
|
2007-03-16 04:00:47 +00:00
|
|
|
;; Constants
|
|
|
|
|
|
|
|
;; Mode setup
|
|
|
|
|
2008-11-27 22:57:30 -08:00
|
|
|
;;;###autoload
|
2008-04-22 18:43:31 -07:00
|
|
|
(define-derived-mode sass-mode haml-mode "Sass"
|
|
|
|
"Major mode for editing Sass files."
|
2009-03-28 10:33:31 -07:00
|
|
|
(set-syntax-table sass-syntax-table)
|
2009-03-17 18:06:54 -07:00
|
|
|
(setq font-lock-extend-region-functions
|
|
|
|
'(font-lock-extend-region-wholelines font-lock-extend-region-multiline))
|
|
|
|
(setq font-lock-multiline nil)
|
|
|
|
(setq comment-start "/*")
|
2008-04-24 09:09:42 -07:00
|
|
|
(set (make-local-variable 'haml-indent-function) 'sass-indent-p)
|
2008-04-22 18:43:31 -07:00
|
|
|
(set (make-local-variable 'haml-indent-offset) sass-indent-offset)
|
2008-04-22 18:44:47 -07:00
|
|
|
(setq font-lock-defaults '(sass-font-lock-keywords nil t)))
|
2007-03-16 04:00:47 +00:00
|
|
|
|
2008-04-24 09:09:42 -07:00
|
|
|
;; Indentation
|
|
|
|
|
|
|
|
(defun sass-indent-p ()
|
2009-03-06 11:04:45 -08:00
|
|
|
"Returns t if the current line can have lines nested beneath it."
|
2008-04-24 09:09:42 -07:00
|
|
|
(loop for opener in sass-non-block-openers
|
|
|
|
unless (looking-at opener) return t
|
|
|
|
return nil))
|
2007-03-16 04:00:47 +00:00
|
|
|
|
2009-01-14 10:50:29 -08:00
|
|
|
;;;###autoload
|
|
|
|
(add-to-list 'auto-mode-alist '("\\.sass$" . sass-mode))
|
2007-03-16 04:00:47 +00:00
|
|
|
|
2009-01-14 10:50:29 -08:00
|
|
|
;; Setup/Activation
|
2007-03-16 04:00:47 +00:00
|
|
|
(provide 'sass-mode)
|
2009-01-14 10:50:29 -08:00
|
|
|
;;; sass-mode.el ends here
|