Rethink setting system

This commit is contained in:
Henrik Lissner 2017-02-04 02:53:57 -05:00
parent 89c7ee0273
commit 093fa1b5a3
4 changed files with 75 additions and 67 deletions

View file

@ -26,23 +26,19 @@ during compilation."
HOOK can be one hook or a list of hooks. If the hook(s) are not quoted, -hook is
appended to them automatically. If they are quoted, they are used verbatim.
FUNC-OR-FORMS can be a quoted symbol, a list of quoted symbols, or forms. Forms will be
wrapped in a lambda. A list of symbols will expand into a series of add-hook calls.
FUNC-OR-FORMS can be a quoted symbol, a list of quoted symbols, or forms. Forms
will be wrapped in a lambda. A list of symbols will expand into a series of
add-hook calls.
Examples:
(add-hook! 'some-mode-hook 'enable-something)
(add-hook! some-mode '(enable-something and-another))
(add-hook! '(one-mode-hook second-mode-hook) 'enable-something)
(add-hook! (one-mode second-mode) 'enable-something)
(add-hook! (one-mode second-mode) (setq v 5) (setq a 2))
If HOOK is omitted, then default to `__PACKAGE__' to determine HOOK."
(add-hook! (one-mode second-mode) (setq v 5) (setq a 2))"
(declare (indent defun) (debug t))
(unless func-or-forms
(unless (bound-and-true-p __PACKAGE__)
(error "add-hook!: FUNC-OR-FORMS is empty"))
(setq func-or-forms hook
hook __PACKAGE__))
(error "add-hook!: FUNC-OR-FORMS is empty"))
(let* ((val (car func-or-forms))
(quoted-p (eq (car-safe hook) 'quote))
(hook (if quoted-p (cadr hook) hook))
@ -60,15 +56,14 @@ If HOOK is omitted, then default to `__PACKAGE__' to determine HOOK."
(-list hook)))))
funcs))))
(defmacro associate! (&rest rest)
(defmacro associate! (mode &rest plist)
"Associate a major or minor mode to certain patterns and project files."
(declare (indent 1))
(let* ((mode (if (keywordp (car rest)) __PACKAGE__ (pop rest)))
(minor (plist-get rest :minor))
(in (plist-get rest :in))
(match (plist-get rest :match))
(files (plist-get rest :files))
(pred (plist-get rest :when)))
(let* ((minor (plist-get plist :minor))
(in (plist-get plist :in))
(match (plist-get plist :match))
(files (plist-get plist :files))
(pred (plist-get plist :when)))
(cond ((or files in pred)
(when (and files (not (or (listp files) (stringp files))))
(user-error "associate! :files expects a string or list of strings"))

View file

@ -37,27 +37,33 @@
"Active keymap in popup windows.")
;;
;; Bootstrap
;;
(doom-def-setting :popup
(lambda (&rest rule)
(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)))
"Prepend a new popup rule to `shackle-rules'.")
(package! shackle :demand t
:config
(shackle-mode 1)
:init
(setq shackle-default-alignment 'below
shackle-select-reused-windows t)
(def-setting! :popup (rule)
"Prepend a new popup rule to `shackle-rules'."
;; Ensure some default attributes are set for window rules
(let ((pattern (car rule))
(ruleset (cdr rule)))
;; Align popups by default (error if this doesn't happen)
(unless (plist-member ruleset :align)
(plist-put ruleset :align shackle-default-alignment))
;; Select popups by default
(unless (or (plist-member ruleset :select)
(plist-member ruleset :noselect))
(plist-put ruleset :select t))
(setq rule (append (list pattern) ruleset))
`(push ',rule shackle-rules)))
:config
(shackle-mode 1)
;;; Baseline popup-window rules
;; :noesc and :modeline are custom settings and are not part of shackle. See
;; `doom*popup-init' and `doom-popup-buffer' for how they're used.
(set! :popup

View file

@ -9,27 +9,31 @@
"An alist of settings, mapping setting keywords to setter functions, which can
be a lambda or symbol.")
(defmacro def-setting! (keyword arglist &optional docstring &rest body)
(defun doom-def-setting (keyword setter-fn &optional docstring)
"Define a setting macro. Takes the same arguments as `defmacro'. This should
return forms, which will be run when `set!' is used to call this setting."
(declare (indent defun))
(unless (keywordp keyword)
(error "Not a valid property name: %s" name))
(let ((sym (intern (format "doom--set%s" keyword))))
(setq doom-settings (assq-delete-all keyword doom-settings))
`(push (cons ,keyword
(defun ,sym ,arglist
,docstring
,@body))
doom-settings)))
(error "Not a valid property name: %s" keyword))
(unless (or (symbolp setter-fn)
(functionp setter-fn))
(error "Not a valid setting function for %s" keyword))
(push (list keyword
:source load-file-name
:docstring docstring
:fn setter-fn)
doom-settings))
(defmacro set! (keyword &rest rest)
"Set an option defined by `doom-define-settings'. Skip if doesn't exist."
"Set an option defined by `def-setting!'. Skip if doesn't exist."
(declare (indent defun))
(let ((set-fn (cdr (assq keyword doom-settings))))
(when set-fn
(let* ((plist (cdr (assq keyword doom-settings)))
(fn (plist-get plist :fn)))
(when (and doom-debug-mode (not fn))
(message "No setting found for %s" keyword))
(when fn
(macroexp-progn
(mapcar (lambda (&rest args) (apply set-fn args))
(mapcar (lambda (args) `(apply #',fn ',(-list args)))
rest)))))
(provide 'core-set)