Refactor def-setting!/set!; now evaluates its arguments on set!

This commit is contained in:
Henrik Lissner 2017-02-08 02:22:51 -05:00
parent 5d1013d317
commit f053980e85
6 changed files with 96 additions and 24 deletions

57
core/autoload/set.el Normal file
View file

@ -0,0 +1,57 @@
;;; set.el
(provide 'doom-lib-set)
;; This provides a centralized configuration system that a) won't evaluate its
;; arguments if it doesn't need to (performance), b) won't complain if the
;; setting doesn't exist and c) is more elegant than a bunch of `after!' blocks,
;; which can cause intermittent stuttering in large quantities. I'm a fan of
;; concise, do-what-I-mean front-facing configuration, believe it or not.
;;
;; Plus, it can benefit from byte-compilation.
;;;###autoload
(defvar doom-settings nil
"An alist of settings, mapping setting keywords to setter functions, which can
be a lambda or symbol.")
;;;###autoload
(defmacro def-setting! (keyword arglist &optional docstring &rest forms)
"Define a setting macro. Like `defmacro', this should return a form to be
executed when called with `set!'. FORMS are not evaluated until `set!' calls it."
(declare (indent defun) (doc-string 3))
(unless (keywordp keyword)
(error "Not a valid property name: %s" keyword))
(let ((sym (intern (format "doom-setting--setter%s" keyword))))
(setq doom-settings (assq-delete-all keyword doom-settings))
(prog1
`(progn
(defun ,sym ,arglist
,docstring
,@forms)
(push ',(list keyword
:source (__FILE__)
:docstring docstring
:fn sym)
doom-settings))
(let (byte-compile-warnings)
(byte-compile sym)))))
;;;###autoload
(defmacro set! (keyword &rest values)
"Set an option defined by `def-setting!'. Skip if doesn't exist."
(declare (indent defun))
(unless values
(error "Empty set! for %s" keyword))
(cond ((not values)
(error "Empty set! for %s" keyword))
((not (assq keyword doom-settings))
(when doom-debug-mode
(warn "No setting found for %s" keyword)))
(t
(let* ((plist (cdr (assq keyword doom-settings)))
(fn (plist-get plist :fn)))
(if fn
(let ((values (eval `(list ,@values))))
(apply fn values))
(error "No setting function where one was expected for %s" keyword))))))

View file

@ -189,7 +189,7 @@
(package! wgrep
:commands (wgrep-setup wgrep-change-to-wgrep-mode)
:config
(set! :popup ("^\\*ivy-occur counsel-ag" :size 25 :select t :regexp t))
(set! :popup "^\\*ivy-occur counsel-ag" :size 25 :select t :regexp t)
(setq wgrep-auto-save-buffer t)
(advice-add 'wgrep-abort-changes :after 'doom/popup-close)
(advice-add 'wgrep-finish-edit :after 'doom/popup-close))

View file

@ -36,18 +36,23 @@
map)
"Active keymap in popup windows.")
(def-setting! :popup (&rest rule)
(def-setting! :popup (&rest rules)
"Prepend a new popup rule to `shackle-rules'."
(let ((pattern (car rule))
(plist (cdr rule)))
;; Align popups by default (error if this doesn't happen)
(unless (plist-member plist :align)
(plist-put plist :align t))
;; Select popups by default
(unless (or (plist-member plist :select)
(plist-member plist :noselect))
(plist-put plist :select t))
(push (cons pattern plist) shackle-rules)))
(if (not (-all-p 'listp rules))
`(cl-pushnew ',rules shackle-rules :key 'car :test 'equal)
(let (real-rules)
(dolist (rule rules)
(let ((pattern (car rule))
(plist (cdr rule)))
;; Align popups by default (error if this doesn't happen)
(unless (plist-member plist :align)
(plist-put plist :align t))
;; Select popups by default
(unless (or (plist-member plist :select)
(plist-member plist :noselect))
(plist-put plist :select t))
(push (cons pattern plist) real-rules)))
`(setq shackle-rules (append ',real-rules shackle-rules)))))
;;