2016-05-11 22:49:06 -04:00
|
|
|
;;; defuns-scss.el
|
|
|
|
|
|
|
|
;;;###autoload
|
2016-05-20 22:37:30 -04:00
|
|
|
(defun doom/css-toggle-inline-or-block ()
|
2016-05-11 22:49:06 -04:00
|
|
|
"Toggles between a SCSS multiline block and one-line block."
|
|
|
|
(interactive)
|
|
|
|
(save-excursion
|
|
|
|
(let* ((bounds (ignore-errors (evil-a-curly)))
|
|
|
|
beg end)
|
|
|
|
(unless bounds
|
|
|
|
(user-error "No block found"))
|
|
|
|
(setq beg (car bounds)
|
|
|
|
end (cadr bounds))
|
|
|
|
(if (= (line-number-at-pos beg) (line-number-at-pos end))
|
|
|
|
(save-excursion
|
|
|
|
(goto-char (1+ beg)) (insert "\n")
|
|
|
|
(unless (string-match ";[\s\t]*}$" (buffer-substring-no-properties beg (1+ end)))
|
|
|
|
(goto-char end) (insert "\n"))
|
|
|
|
(replace-regexp ";[\s\t]*" ";\n" nil beg (1+ end))
|
|
|
|
(setq end (cadr (evil-a-curly)))
|
|
|
|
(evil-indent beg end)
|
|
|
|
(delete-trailing-whitespace beg end))
|
|
|
|
(goto-char beg)
|
|
|
|
(evil-join beg end)
|
|
|
|
(goto-char (1+ beg))
|
|
|
|
(just-one-space)
|
|
|
|
(goto-char (cadr (evil-inner-curly)))
|
|
|
|
(just-one-space)))))
|
|
|
|
|
|
|
|
;;;###autoload
|
2016-05-20 22:37:30 -04:00
|
|
|
(defalias 'doom/sass-build 'doom/scss-build)
|
2016-05-11 22:49:06 -04:00
|
|
|
|
|
|
|
;;;###autoload
|
2016-05-20 22:37:30 -04:00
|
|
|
(defun doom/scss-build ()
|
2016-05-11 22:49:06 -04:00
|
|
|
"Compile all sass/scss files in project"
|
|
|
|
(interactive)
|
2016-06-29 02:57:43 -04:00
|
|
|
(if (bound-and-true-p gulpjs-project-mode)
|
|
|
|
(let ((default-directory (doom/project-root)))
|
|
|
|
(compile "gulp sass"))
|
|
|
|
(let ((scss-dir (f-slash (or (f-traverse-upwards (lambda (d)
|
|
|
|
(string-match-p "/\\(\\(s[ca]\\|c\\)ss\\|styles\\)/?$" d))
|
|
|
|
default-directory)
|
|
|
|
default-directory))))
|
|
|
|
(compile (format "%s %s --update '%s':'%s'"
|
|
|
|
scss-sass-command
|
|
|
|
(mapconcat 'identity scss-sass-options " ")
|
|
|
|
scss-dir
|
|
|
|
(or scss-output-directory
|
|
|
|
(awhen (f-traverse-upwards (lambda (d)
|
|
|
|
(f-dir? (format "%s/css" d)))
|
|
|
|
default-directory)
|
|
|
|
(format "%s/css" it))
|
|
|
|
"."))))))
|
|
|
|
|
|
|
|
(defface doom/counsel-css-selector-depth-face-1
|
|
|
|
'((((class color) (background dark)) (:foreground "#ffff00"))
|
|
|
|
(((class color) (background light)) (:foreground "#0000ff"))
|
|
|
|
(t (:foreground "#ffff00")))
|
|
|
|
"Selector depth 1")
|
|
|
|
(defface doom/counsel-css-selector-depth-face-2
|
|
|
|
'((((class color) (background dark)) (:foreground "#ffdd00"))
|
|
|
|
(((class color) (background light)) (:foreground "#3300ff"))
|
|
|
|
(t (:foreground "#ffdd00")))
|
|
|
|
"Selector depth 2")
|
|
|
|
(defface doom/counsel-css-selector-depth-face-3
|
|
|
|
'((((class color) (background dark)) (:foreground "#ffbb00"))
|
|
|
|
(((class color) (background light)) (:foreground "#6600ff"))
|
|
|
|
(t (:foreground "#ffbb00")))
|
|
|
|
"Selector depth 3")
|
|
|
|
(defface doom/counsel-css-selector-depth-face-4
|
|
|
|
'((((class color) (background dark)) (:foreground "#ff9900"))
|
|
|
|
(((class color) (background light)) (:foreground "#9900ff"))
|
|
|
|
(t (:foreground "#ff9900")))
|
|
|
|
"Selector depth 4")
|
|
|
|
(defface doom/counsel-css-selector-depth-face-5
|
|
|
|
'((((class color) (background dark)) (:foreground "#ff7700"))
|
|
|
|
(((class color) (background light)) (:foreground "#cc00ff"))
|
|
|
|
(t (:foreground "#ff7700")))
|
|
|
|
"Selector depth 5")
|
|
|
|
(defface doom/counsel-css-selector-depth-face-6
|
|
|
|
'((((class color) (background dark)) (:foreground "#ff5500"))
|
|
|
|
(((class color) (background light)) (:foreground "#ff00ff"))
|
|
|
|
(t (:foreground "#ff5500")))
|
|
|
|
"Selector depth 6")
|
|
|
|
|
|
|
|
(cl-defun doom/counsel-css--open-brace-forward (&optional $bound)
|
|
|
|
"Move to next open brace, skip commented brace"
|
|
|
|
(interactive)
|
|
|
|
(let ($ret)
|
|
|
|
(setq $ret (re-search-forward "[^#]{" $bound t))
|
|
|
|
(unless $ret (cl-return-from doom/counsel-css--open-brace-forward nil))
|
|
|
|
(backward-char)
|
|
|
|
(if (doom/counsel-css--comment-p (point))
|
|
|
|
(doom/counsel-css--open-brace-forward $bound)
|
|
|
|
$ret)))
|
|
|
|
|
|
|
|
(defun doom/counsel-css--substr-last-string ($text $key)
|
|
|
|
"Return the tail of $text without $key strings"
|
|
|
|
(while (string-match $key $text)
|
|
|
|
(setq $text (substring $text (1+ (string-match $key $text)))))
|
|
|
|
$text)
|
|
|
|
|
|
|
|
(cl-defun doom/counsel-css--fetch-previous-line (&optional $prev $noexcursion)
|
|
|
|
"Return previous nth ($prev) line strings.
|
|
|
|
If $noexcursion is not-nil cursor doesn't move."
|
|
|
|
;; In compressed Css without this return, it takes long time
|
|
|
|
(if (eq 1 (line-number-at-pos))
|
|
|
|
(cl-return-from doom/counsel-css--fetch-previous-line ""))
|
|
|
|
(or $prev (setq $prev 1))
|
|
|
|
(if $noexcursion (setq $noexcursion (point)))
|
|
|
|
(move-beginning-of-line (- 1 $prev))
|
|
|
|
(let (($po (point)) $res)
|
|
|
|
(move-end-of-line 1)
|
|
|
|
(setq $res (buffer-substring-no-properties $po (point)))
|
|
|
|
(if $noexcursion (goto-char $noexcursion))
|
|
|
|
$res))
|
|
|
|
|
|
|
|
(defun doom/counsel-css--comment-p (&optional $pos)
|
|
|
|
(or $pos (setq $pos (point)))
|
|
|
|
(nth 4 (parse-partial-sexp (point-min) $pos)))
|
|
|
|
|
|
|
|
(cl-defun doom/counsel-css--extract-selector ()
|
|
|
|
"Return selector infomation at the point"
|
|
|
|
(let (($multi "") $s $po1 $po2 $po3 $str $commentp)
|
|
|
|
;; Collect multiple selector across previous lines
|
|
|
|
;; (i.e. "div, \n p, \n span {...}")
|
|
|
|
(save-excursion
|
|
|
|
(while (string-match ",[\s\t]*$"
|
|
|
|
(setq $s (doom/counsel-css--fetch-previous-line)))
|
|
|
|
;; Skip commented selector (i.e. " // .blue,")
|
|
|
|
(save-excursion
|
|
|
|
(move-beginning-of-line 1)
|
|
|
|
(setq $po3 (point))
|
|
|
|
(setq $commentp (doom/counsel-css--comment-p (search-forward ","))))
|
|
|
|
(unless $commentp
|
|
|
|
(setq $multi (format "%s %s" (string-trim $s) $multi)))))
|
|
|
|
;; Extract selector include one-line-nesting (i.e. "div { p {...} }")
|
|
|
|
(save-excursion
|
|
|
|
(skip-chars-backward "^{};\n")
|
|
|
|
(setq $po1 (point))
|
|
|
|
;; (setq $beg2 $po1)
|
|
|
|
(skip-chars-forward "^{")
|
|
|
|
(setq $po2 (point))
|
|
|
|
(setq $str (buffer-substring-no-properties $po1 $po2))
|
|
|
|
;; i.e. "div { .box { p" -> " p"
|
|
|
|
(setq $str (doom/counsel-css--substr-last-string $str "{\\|}"))
|
|
|
|
(setq $str (string-trim $str))
|
|
|
|
;; Return (selector-name . (selector-beginning-point . selector-end-point))
|
|
|
|
(if (equal $multi "")
|
|
|
|
(cons (format "%s" $str) (cons $po1 $po2))
|
|
|
|
(cons (format "%s %s" (string-trim $multi) $str)
|
|
|
|
(cons $po3 $po2))))))
|
|
|
|
|
|
|
|
(cl-defun doom/counsel-css--selector-next (&optional $bound)
|
|
|
|
"Return and goto next selector."
|
|
|
|
(unless (doom/counsel-css--open-brace-forward $bound)
|
|
|
|
(cl-return-from doom/counsel-css--selector-next nil))
|
|
|
|
(doom/counsel-css--extract-selector))
|
|
|
|
|
|
|
|
(defun doom/counsel-css--selector-to-hash (&optional no-line-numbers)
|
|
|
|
"Collect all selectors and make hash table"
|
|
|
|
(let ($selector $paren-beg $paren-end $hash $dep $max $sl
|
|
|
|
$selector-name $selector-beg $selector-end
|
|
|
|
$selector-line)
|
|
|
|
(setq $hash (make-hash-table :test 'equal))
|
|
|
|
(save-excursion
|
|
|
|
(goto-char (point-min))
|
|
|
|
(while (setq $selector (doom/counsel-css--selector-next))
|
|
|
|
(setq $paren-beg (point))
|
|
|
|
(setq $paren-end (scan-sexps $paren-beg 1))
|
|
|
|
(setq $max (cons $paren-end $max))
|
|
|
|
(setq $max (mapcar (lambda ($p) (if (< $p $paren-beg) nil $p)) $max))
|
|
|
|
(setq $max (delq nil $max))
|
|
|
|
(setq $dep (length $max))
|
|
|
|
(setq $selector-name (car $selector))
|
|
|
|
(setq
|
|
|
|
$selector-name
|
|
|
|
(cl-case $dep
|
|
|
|
(1 (propertize $selector-name 'face 'doom/counsel-css-selector-depth-face-1))
|
|
|
|
(2 (propertize $selector-name 'face 'doom/counsel-css-selector-depth-face-2))
|
|
|
|
(3 (propertize $selector-name 'face 'doom/counsel-css-selector-depth-face-3))
|
|
|
|
(4 (propertize $selector-name 'face 'doom/counsel-css-selector-depth-face-4))
|
|
|
|
(5 (propertize $selector-name 'face 'doom/counsel-css-selector-depth-face-5))
|
|
|
|
(6 (propertize $selector-name 'face 'doom/counsel-css-selector-depth-face-6))))
|
|
|
|
(setq $selector-beg (cadr $selector))
|
|
|
|
(setq $selector-end (cddr $selector))
|
|
|
|
(setq $selector-line (line-number-at-pos $selector-beg))
|
|
|
|
(if (<= $dep (length $sl))
|
|
|
|
(cl-loop repeat (- (1+ (length $sl)) $dep) do (pop $sl)))
|
|
|
|
(setq $sl (cons $selector-name $sl))
|
|
|
|
(puthash
|
|
|
|
(if no-line-numbers
|
|
|
|
(mapconcat 'identity (reverse $sl) " ")
|
|
|
|
(format "%s: %s"
|
|
|
|
(propertize (number-to-string $selector-line)
|
|
|
|
'face 'font-lock-function-name-face)
|
|
|
|
(mapconcat 'identity (reverse $sl) " ")))
|
|
|
|
(list $paren-beg $paren-end $dep $selector-beg $selector-end $selector-line)
|
|
|
|
$hash)))
|
|
|
|
$hash))
|
|
|
|
|
|
|
|
(defun doom/counsel-css--imenu-create-index-function ()
|
|
|
|
(let (($hash (doom/counsel-css--selector-to-hash t)))
|
|
|
|
(cl-loop for $k being hash-key in $hash using (hash-values $v)
|
|
|
|
collect (cons $k $v))))
|
|
|
|
|
|
|
|
;;;###autoload
|
|
|
|
(defun doom|counsel-css-imenu-setup ()
|
|
|
|
(when (memq major-mode '(css-mode scss-mode less-css-mode))
|
|
|
|
(setq imenu-create-index-function 'doom/counsel-css--imenu-create-index-function)))
|
|
|
|
|
|
|
|
;;;###autoload
|
|
|
|
(defun doom/counsel-css ()
|
|
|
|
(interactive)
|
|
|
|
(require 'counsel)
|
|
|
|
(ivy-read "Selectors: "
|
|
|
|
(let (($hash (doom/counsel-css--selector-to-hash)))
|
|
|
|
(cl-loop for $k being hash-key in $hash using (hash-values $v)
|
|
|
|
collect (cons $k $v)))
|
|
|
|
:require-match t
|
|
|
|
:caller 'doom/counsel-css))
|
2016-05-11 22:49:06 -04:00
|
|
|
|
|
|
|
(provide 'defuns-scss)
|
|
|
|
;;; defuns-scss.el ends here
|