;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Emmet minor mode (defgroup emmet nil "Customization group for emmet-mode." :group 'convenience) (defun emmet-expr-on-line () "Extract a emmet expression and the corresponding bounds for the current line." (let* ((end (point)) (start (emmet-find-left-bound)) (line (buffer-substring-no-properties start end)) (expr (emmet-regex "\\([ \t]*\\)\\([^\n]+\\)" line 2))) (if (first expr) (list (first expr) start end)))) (defun emmet-find-left-bound () "Find the left bound of an emmet expr" (save-excursion (save-match-data (let ((char (char-before)) (last-gt (point)) (in-style-attr (looking-back "style=[\"'][^\"']*"))) (while char (cond ((and in-style-attr (member char '(?\" ?\'))) (setq char nil)) ((member char '(?\} ?\] ?\))) (with-syntax-table (standard-syntax-table) (backward-sexp) (setq char (char-before)))) ((eq char ?\>) (setq last-gt (point)) (backward-char) (setq char (char-before))) ((eq char ?\<) (goto-char last-gt) (setq char nil)) ((not (string-match-p "[[:space:]\n;]" (string char))) (backward-char) (setq char (char-before))) (t (setq char nil)))) (point))))) (defcustom emmet-indentation 4 "Number of spaces used for indentation." :type '(number :tag "Spaces") :group 'emmet) (defcustom emmet-indent-after-insert t "Indent region after insert?" :type 'boolean :group 'emmet) (defcustom emmet-use-style-tag-and-attr-detection t "When true, enables detection of style tags and attributes in HTML to provide proper CSS abbreviations completion." :type 'boolean :group 'emmet) (defvar emmet-use-css-transform nil "When true, transform Emmet snippets into CSS, instead of the usual HTML.") (make-variable-buffer-local 'emmet-use-css-transform) (defvar emmet-use-sass-syntax nil "When true, uses Sass syntax for CSS abbreviations expanding, e. g. without semicolons") (make-variable-buffer-local 'emmet-use-sass-syntax) (defvar emmet-css-major-modes '(css-mode scss-mode sass-mode less-mode less-css-mode) "Major modes that use emmet for CSS, rather than HTML.") (defun emmet-transform (input) (if (or (emmet-detect-style-tag-and-attr) emmet-use-css-transform) (emmet-css-transform input) (emmet-html-transform input))) (defun emmet-reposition-cursor (expr) (let ((output-markup (buffer-substring-no-properties (second expr) (point)))) (when emmet-move-cursor-after-expanding (let ((p (point)) (new-pos (if (emmet-html-text-p output-markup) (emmet-html-next-insert-point output-markup) (emmet-css-next-insert-point output-markup)))) (goto-char (+ (- p (length output-markup)) new-pos)))))) (defun emmet-detect-style-tag-and-attr () (let* ((style-attr-end "[^=][\"']") (style-attr-begin "style=[\"']") (style-tag-end "") (style-tag-begin "