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__))
(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)

View file

@ -14,6 +14,10 @@
;; evil-mode
;;
(doom-def-setting :evil-state
'evil-set-initial-state
"Set the initialize STATE of MODE using `evil-set-initial-state'.")
(use-package! evil :demand t
:init
(setq evil-want-C-u-scroll t
@ -316,8 +320,8 @@ if on a delimiter, jump to the matching one (`evilmi-jump-items')."
(evil-snipe-mode 1)
(evil-snipe-override-mode 1)
;; Switch to evil-easymotion/avy after first snipe
(define-key evil-snipe-parent-transient-map (kbd "C-;")
(λ! (require 'evil-easymotion)
(map! :map evil-snipe-parent-transient-map
"C-;" (λ! (require 'evil-easymotion)
(call-interactively +evil--snipe-repeat-fn))))
@ -369,28 +373,27 @@ if on a delimiter, jump to the matching one (`evilmi-jump-items')."
"^#.*#$"))
:config
(evil-set-initial-state 'neotree-mode 'motion)
(set! :evil-state (neotree-mode motion))
;; Adding keybindings to `neotree-mode-map' wouldn't work for me (they get
;; overridden when the neotree buffer is spawned). So we bind them in a hook.
(add-hook 'neo-after-create-hook '+evil|neotree-init-keymap)
(defun +evil|neotree-init-keymap (&rest _)
(let ((map evil-motion-state-local-map))
(define-key map (kbd "\\\\") 'evil-window-prev)
(define-key map (kbd "RET") 'neotree-enter)
(define-key map (kbd "<return>") 'neotree-enter)
(define-key map (kbd "ESC ESC") 'neotree-hide)
(define-key map [return] 'neotree-enter)
(define-key map "q" 'neotree-hide)
(define-key map "J" 'neotree-select-next-sibling-node)
(define-key map "K" 'neotree-select-previous-sibling-node)
(define-key map "H" 'neotree-select-up-node)
(define-key map "L" 'neotree-select-down-node)
(define-key map "v" 'neotree-enter-vertical-split)
(define-key map "s" 'neotree-enter-horizontal-split)
(define-key map "c" 'neotree-create-node)
(define-key map "d" 'neotree-delete-node)
(define-key map "\C-r" 'neotree-refresh)
(define-key map "r" 'neotree-rename-node)
(define-key map "R" 'neotree-change-root))))
(map! :Lm "\\\\" 'evil-window-prev
:Lm "RET" 'neotree-enter
:Lm "<return>" 'neotree-enter
:Lm "ESC ESC" 'neotree-hide
:Lm [return] 'neotree-enter
:Lm "q" 'neotree-hide
:Lm "J" 'neotree-select-next-sibling-node
:Lm "K" 'neotree-select-previous-sibling-node
:Lm "H" 'neotree-select-up-node
:Lm "L" 'neotree-select-down-node
:Lm "v" 'neotree-enter-vertical-split
:Lm "s" 'neotree-enter-horizontal-split
:Lm "c" 'neotree-create-node
:Lm "d" 'neotree-delete-node
:Lm "\C-r" 'neotree-refresh
:Lm "r" 'neotree-rename-node
:Lm "R" 'neotree-change-root)))