2021-11-22 05:57:41 +00:00
|
|
|
;;; +init.el --- extra init.el stuff -*- lexical-binding: t -*-
|
|
|
|
|
|
|
|
;;; Commentary:
|
|
|
|
|
|
|
|
;; Yes, I edit my init.el often enough I need to write a mode for it.
|
|
|
|
|
|
|
|
;;; Code:
|
|
|
|
|
|
|
|
(require '+lisp)
|
|
|
|
|
|
|
|
;;; Sort `setup' forms
|
|
|
|
|
|
|
|
(defun +init--sexp-setup-p (sexp-str &optional head)
|
|
|
|
"Is SEXP-STR a `setup' form, optionally with a HEAD form?"
|
|
|
|
(let ((head (if (and head (symbolp head))
|
|
|
|
(symbol-name head)
|
|
|
|
head)))
|
|
|
|
(and (string-match-p (rx (: bos (* whitespace) "(setup")) sexp-str)
|
|
|
|
(if head
|
|
|
|
(string-match-p (concat "\\`.*" head) sexp-str)
|
|
|
|
t))))
|
|
|
|
|
|
|
|
(defun +init-sort ()
|
|
|
|
"Sort init.el.
|
|
|
|
Sort based on the following heuristic: `setup' forms (the
|
|
|
|
majority of my init.el) are sorted after everything else, and
|
|
|
|
within that group, forms with a HEAD of `:require' are sorted
|
|
|
|
first, and `:straight' HEADs are sorted last. All other forms
|
|
|
|
are sorted lexigraphically."
|
|
|
|
(interactive)
|
|
|
|
(save-excursion
|
|
|
|
(save-restriction
|
|
|
|
(widen)
|
|
|
|
(+lisp-sort-sexps
|
|
|
|
(point-min) (point-max)
|
|
|
|
;; Key function
|
|
|
|
nil
|
|
|
|
;; Sort function
|
|
|
|
(lambda (s1 s2)
|
|
|
|
(let ((s1 (cdr s1)) (s2 (cdr s2)))
|
|
|
|
(cond
|
|
|
|
;; Sort everything /not/ `setup' /before/ `setup'
|
|
|
|
((and (+init--sexp-setup-p s1)
|
|
|
|
(not (+init--sexp-setup-p s2)))
|
|
|
|
nil)
|
|
|
|
((and (+init--sexp-setup-p s2)
|
|
|
|
(not (+init--sexp-setup-p s1)))
|
|
|
|
t)
|
|
|
|
;; otherwise...
|
|
|
|
(t (let ((s1-straight (+init--sexp-setup-p s1 :straight))
|
|
|
|
(s2-straight (+init--sexp-setup-p s2 :straight))
|
|
|
|
(s1-require (+init--sexp-setup-p s1 :require))
|
|
|
|
(s2-require (+init--sexp-setup-p s2 :require)))
|
|
|
|
(cond
|
|
|
|
;; `:straight' setups have extra processing
|
|
|
|
((and s1-straight s2-straight)
|
|
|
|
(let* ((r (rx (: ":straight" (? "-when") (* space) (? "("))))
|
|
|
|
(s1 (replace-regexp-in-string r "" s1))
|
|
|
|
(s2 (replace-regexp-in-string r "" s2)))
|
|
|
|
(string< s1 s2)))
|
|
|
|
;; `:require' setups go first
|
|
|
|
((and s1-require (not s2-require)) t)
|
|
|
|
((and s2-require (not s1-require)) nil)
|
|
|
|
;; `:straight' setups go last
|
|
|
|
((and s1-straight (not s2-straight)) nil)
|
|
|
|
((and s2-straight (not s1-straight)) t)
|
|
|
|
;; otherwise, sort lexigraphically
|
|
|
|
(t (string< s1 s2))))))))))))
|
|
|
|
|
2021-12-30 04:55:55 +00:00
|
|
|
(defun +init-sort-then-save ()
|
|
|
|
"Sort init.el, then save it."
|
|
|
|
(interactive)
|
|
|
|
(+init-sort)
|
|
|
|
(save-buffer))
|
|
|
|
|
2021-11-22 05:57:41 +00:00
|
|
|
;;; Add `setup' forms to `imenu-generic-expression'
|
|
|
|
|
|
|
|
(defun +init-add-setup-to-imenu ()
|
|
|
|
"Recognize `setup' forms in `imenu'."
|
|
|
|
;; `imenu-generic-expression' automatically becomes buffer-local when set
|
|
|
|
(setf (alist-get "Setup" imenu-generic-expression nil nil 'string-equal)
|
|
|
|
(list
|
|
|
|
(rx (: bol (* space)
|
|
|
|
"(setup" (+ space)
|
|
|
|
(group (? "(") (* nonl))))
|
|
|
|
1)))
|
|
|
|
|
|
|
|
;;; Major mode
|
|
|
|
|
|
|
|
;;;###autoload
|
|
|
|
(define-derived-mode +init-mode emacs-lisp-mode "Init.el"
|
|
|
|
"`emacs-lisp-mode', but with a few specialized bits and bobs for init.el.")
|
|
|
|
|
|
|
|
;;;###autoload
|
|
|
|
(add-to-list 'auto-mode-alist '("/init\\.el\\'" . +init-mode))
|
|
|
|
|
|
|
|
(provide '+init)
|
|
|
|
;;; +init.el ends here
|