💥 Refactor add-hook! macro & change arg order

This update may potentially break your usage of add-hook! if you pass
the :local or :append properties to it. This is how they used to work:

  (add-hook! :append 'some-mode-hook #'do-something)

Thsoe properties must now follow the hooks, e.g.

  (add-hook! 'some-mode-hook :append #'do-something)

Other changes:
- Various add-hook calls have been renamed to add-hook! because I
  incorrectly assumed `defun` always returned its definition's symbol,
  when in fact, its return value is "undefined" (so sayeth the
  documentation). This should fix #1597.
- This update adds the ability to add multiple functions to hooks
  without a list:

    (add-hook! 'some-mode-hook
               #'do-something
               #'do-something-else)

- The indentation logic has been changed so that consecutive function
  symbols at indented at the same level as the first argument, but forms
  are indent like a defun.

    (add-hook! 'some-mode-hook
               #'do-something
               #'do-something-else)

    (add-hook! 'some-mode-hook
      (message "Hello"))
This commit is contained in:
Henrik Lissner 2019-07-26 19:57:13 +02:00
parent c2ae6f30a5
commit a3e262c7ac
No known key found for this signature in database
GPG key ID: 5F6C0EA160557395
42 changed files with 248 additions and 225 deletions

View file

@ -155,7 +155,7 @@ localleader prefix."
;; Bind `doom-leader-key' and `doom-leader-alt-key' as late as possible to give
;; the user a chance to modify them.
(add-hook 'doom-after-init-modules-hook
(add-hook! 'doom-after-init-modules-hook
(defun doom-init-leader-keys-h ()
"Bind `doom-leader-key' and `doom-leader-alt-key'."
(let ((map general-override-mode-map))

View file

@ -256,7 +256,7 @@ advised)."
(put ',fn 'permanent-local-hook t)
(add-hook sym #',fn ,append))))))
(defmacro add-hook! (&rest args)
(defmacro add-hook! (hooks &rest rest)
"A convenience macro for adding N functions to M hooks.
If N and M = 1, there's no benefit to using this macro over `add-hook'.
@ -272,45 +272,51 @@ This macro accepts, in order:
list of `defun's, or body forms (implicitly wrapped in a closure).
\(fn [:append :local] HOOKS FUNCTIONS)"
(declare (indent defun) (debug t))
(let ((hook-fn 'add-hook)
append-p local-p)
(while (keywordp (car args))
(pcase (pop args)
(declare (indent (lambda (indent-point state)
(goto-char indent-point)
(when (looking-at-p "\\s-*(")
(lisp-indent-defform state indent-point))))
(debug t))
(let* ((hook-forms (doom--resolve-hook-forms hooks))
(func-forms ())
(defn-forms ())
append-p
local-p
remove-p
forms)
(while (keywordp (car rest))
(pcase (pop rest)
(:append (setq append-p t))
(:local (setq local-p t))
(:remove (setq hook-fn 'remove-hook))))
(let* ((defun-forms nil)
(hooks (doom--resolve-hook-forms (pop args)))
(funcs
(let ((val (car args)))
(if (memq (car-safe val) '(quote function))
(if (cdr-safe (cadr val))
(cadr val)
(list (cadr val)))
(or (and (eq (car-safe val) 'defun)
(cl-loop for arg in args
if (not (eq (car-safe arg) 'defun))
return nil
else
collect (cadr arg)
and do (push arg defun-forms)))
(list args)))))
forms)
(dolist (fn funcs)
(setq fn (if (symbolp fn)
`(function ,fn)
`(lambda (&rest _) ,@args)))
(dolist (hook hooks)
(push (if (eq hook-fn 'remove-hook)
`(remove-hook ',hook ,fn ,local-p)
`(add-hook ',hook ,fn ,append-p ,local-p))
(:remove (setq remove-p t))))
(let ((first (car-safe (car rest))))
(cond ((null first)
(setq func-forms rest))
((eq first 'defun)
(setq func-forms (mapcar #'cadr rest)
defn-forms rest))
((memq first '(quote function))
(setq func-forms
(if (cdr rest)
(mapcar #'doom-unquote rest)
(doom-enlist (doom-unquote (car rest))))))
((setq func-forms (list `(lambda () ,@rest)))))
(dolist (hook hook-forms)
(dolist (func func-forms)
(push (if remove-p
`(remove-hook ',hook #',func ,local-p)
`(add-hook ',hook #',func ,append-p ,local-p))
forms)))
(macroexp-progn
(append (nreverse defun-forms)
(if append-p (nreverse forms) forms))))))
(append defn-forms
(if append-p
(nreverse forms)
forms))))))
(defmacro remove-hook! (&rest args)
(defmacro remove-hook! (hooks &rest rest)
"A convenience macro for removing N functions from M hooks.
Takes the same arguments as `add-hook!'.
@ -319,7 +325,7 @@ If N and M = 1, there's no benefit to using this macro over `remove-hook'.
\(fn [:append :local] HOOKS FUNCTIONS)"
(declare (indent defun) (debug t))
`(add-hook! :remove ,@args))
`(add-hook! ,hooks :remove ,@rest))
(defmacro setq-hook! (hooks &rest var-vals)
"Sets buffer-local variables on HOOKS.

View file

@ -472,11 +472,11 @@ to have them return non-nil (or exploit that to overwrite Doom's config)."
(error "'%s' isn't a valid hook for use-package-hook!" when))
`(progn
(setq use-package-inject-hooks t)
(add-hook!
',(intern (format "use-package--%s--%s-hook"
package
(substring (symbol-name when) 1)))
,@body)))
(add-hook ',(intern (format "use-package--%s--%s-hook"
package
(substring (symbol-name when) 1)))
(lambda () ,@body)
'append)))
(defmacro require! (category module &rest flags)
"Loads the CATEGORY MODULE module with FLAGS.

View file

@ -384,14 +384,13 @@ treat Emacs as a non-application window."
:config
(defvar doom--ediff-saved-wconf nil)
;; Restore window config after quitting ediff
(add-hook 'ediff-before-setup-hook
(add-hook! 'ediff-before-setup-hook
(defun doom-ediff-save-wconf-h ()
(setq doom--ediff-saved-wconf (current-window-configuration))))
(add-hook! '(ediff-quit-hook ediff-suspend-hook)
(add-hook! '(ediff-quit-hook ediff-suspend-hook) :append
(defun doom-ediff-restore-wconf-h ()
(when (window-configuration-p doom--ediff-saved-wconf)
(set-window-configuration doom--ediff-saved-wconf)))
'append))
(set-window-configuration doom--ediff-saved-wconf)))))
(use-package! hl-line
@ -468,7 +467,7 @@ treat Emacs as a non-application window."
;;;###package hide-mode-line-mode
(add-hook! '(completion-list-mode-hook Man-mode-hook)
#'hide-mode-line-mode)
#'hide-mode-line-mode)
;; Better fontification of number literals in code
(use-package! highlight-numbers
@ -495,7 +494,7 @@ treat Emacs as a non-application window."
;; line numbers in most modes
(add-hook! '(prog-mode-hook text-mode-hook conf-mode-hook)
#'display-line-numbers-mode)
#'display-line-numbers-mode)
(defun doom-enable-line-numbers-h () (display-line-numbers-mode +1))
(defun doom-disable-line-numbers-h () (display-line-numbers-mode -1))

View file

@ -7,20 +7,21 @@ It is integrated into Helpful, in Doom.
#+BEGIN_SRC elisp :eval no
;; With only one hook and one function, this is identical to `add-hook'. In that
;; case, use that instead.
(add-hook! 'some-mode-hook 'enable-something)
(add-hook! 'some-mode-hook #'enable-something)
;; Adding many-to-many functions to hooks
(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! some-mode #'enable-something #'and-another)
(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)
;; Appending and local hooks
(add-hook! :append (one-mode second-mode) 'enable-something)
(add-hook! :local (one-mode second-mode) 'enable-something)
(add-hook! (one-mode second-mode) :append #'enable-something)
(add-hook! (one-mode second-mode) :local #'enable-something)
;; With arbitrary forms
(add-hook! (one-mode second-mode) (setq v 5) (setq a 2))
(add-hook! :append :local (one-mode second-mode) (setq v 5) (setq a 2))
(add-hook! (one-mode second-mode) :append :local (setq v 5) (setq a 2))
;; Inline named hook functions
(add-hook! '(one-mode-hook second-mode-hook)
@ -133,16 +134,17 @@ It is integrated into Helpful, in Doom.
#+BEGIN_SRC elisp :eval no
;; With only one hook and one function, this is identical to `add-hook'. In that
;; case, use that instead.
(remove-hook! 'some-mode-hook 'enable-something)
(remove-hook! 'some-mode-hook #'enable-something)
;; Adding many-to-many functions to hooks
(remove-hook! some-mode '(enable-something and-another))
(remove-hook! '(one-mode-hook second-mode-hook) 'enable-something)
(remove-hook! (one-mode second-mode) 'enable-something)
(remove-hook! some-mode #'enable-something #'and-another)
(remove-hook! some-mode #'(enable-something and-another))
(remove-hook! '(one-mode-hook second-mode-hook) #'enable-something)
(remove-hook! (one-mode second-mode) #'enable-something)
;; Appending and local hooks
(remove-hook! :append (one-mode second-mode) 'enable-something)
(remove-hook! :local (one-mode second-mode) 'enable-something)
(remove-hook! (one-mode second-mode) :append #'enable-something)
(remove-hook! (one-mode second-mode) :local #'enable-something)
;; With arbitrary forms
(remove-hook! (one-mode second-mode) (setq v 5) (setq a 2))

View file

@ -97,7 +97,7 @@ playback.")
:after #'circe--irc-conn-disconnected
(run-hooks '+irc-disconnect-hook))
(add-hook 'lui-pre-output-hook
(add-hook! 'lui-pre-output-hook
(defun +irc-circe-truncate-nicks-h ()
"Truncate long nicknames in chat output non-destructively."
(when-let (beg (text-property-any (point-min) (point-max) 'lui-format-argument 'nick))
@ -109,7 +109,7 @@ playback.")
(compose-region (+ beg +irc-left-padding -1) end
+irc-truncate-nick-char))))))
(add-hook 'doom-real-buffer-functions
(add-hook! 'doom-real-buffer-functions
(defun +circe-buffer-p (buf)
"Return non-nil if BUF is a `circe-mode' buffer."
(with-current-buffer buf
@ -117,13 +117,13 @@ playback.")
(eq (safe-persp-name (get-current-persp))
+irc--workspace-name)))))
(add-hook 'circe-message-option-functions
(add-hook! 'circe-message-option-functions
(defun +irc-circe-message-option-bot-h (nick &rest ignored)
"Fontify known bots and mark them to not be tracked."
(when (member nick +irc-bot-list)
'((text-properties . (face circe-fool-face lui-do-not-track t))))))
(add-hook 'circe-mode-hook
(add-hook! 'circe-mode-hook
(defun +irc-add-circe-buffer-to-persp-h ()
(let ((persp (get-current-persp))
(buf (current-buffer)))
@ -202,7 +202,8 @@ after prompt marker."
(goto-char (point-max))))
(add-hook! 'lui-mode-hook
(add-hook 'evil-insert-state-entry-hook #'+irc-evil-insert-h nil t))
(add-hook 'evil-insert-state-entry-hook #'+irc-evil-insert-h
nil 'local))
(mapc (lambda (cmd) (push cmd +irc-scroll-to-bottom-on-commands))
'(evil-paste-after evil-paste-before evil-open-above evil-open-below)))

View file

@ -36,14 +36,14 @@ easier to scroll through.")
(make-directory elfeed-db-directory t)
;; Ensure elfeed buffers are treated as real
(add-hook 'doom-real-buffer-functions
(add-hook! 'doom-real-buffer-functions
(defun +rss-buffer-p (buf)
(string-match-p "^\\*elfeed" (buffer-name buf))))
;; Enhance readability of a post
(add-hook 'elfeed-show-mode-hook #'+rss-elfeed-wrap-h)
(add-hook! 'elfeed-search-mode-hook
(add-hook 'kill-buffer-hook #'+rss-cleanup-h nil t))
(add-hook 'kill-buffer-hook #'+rss-cleanup-h nil 'local))
;; Large images are annoying to scroll through, because scrolling follows the
;; cursor, so we force shr to insert images in slices.

View file

@ -41,7 +41,8 @@
(cl-loop for x in ido-temp-list
if (char-equal (string-to-char x) ?.)
collect x)))
(add-hook! (ido-make-file-list ido-make-dir-list) #'ido-sort-mtime)
(add-hook! '(ido-make-file-list-hook ido-make-dir-list-hook)
#'ido-sort-mtime)
;;
(ido-mode 1)

View file

@ -48,7 +48,7 @@
;; disable evil-escape in evil-mc; causes unwanted text on invocation
(add-to-list 'evil-mc-incompatible-minor-modes 'evil-escape-mode nil #'eq)
(add-hook 'doom-escape-hook
(add-hook! 'doom-escape-hook
(defun +multiple-cursors-escape-multiple-cursors-h ()
"Clear evil-mc cursors and restore state."
(when (evil-mc-has-cursors-p)
@ -80,7 +80,7 @@
(defvar +mc--compat-evil-prev-state nil)
(defvar +mc--compat-mark-was-active nil)
(add-hook 'multiple-cursors-mode-enabled-hook
(add-hook! 'multiple-cursors-mode-enabled-hook
(defun +multiple-cursors-compat-switch-to-emacs-state-h ()
(when (and (bound-and-true-p evil-mode)
(not (memq evil-state '(insert emacs))))
@ -94,7 +94,7 @@
(goto-char point-before)
(set-mark mark-before))))))
(add-hook 'multiple-cursors-mode-disabled-hook
(add-hook! 'multiple-cursors-mode-disabled-hook
(defun +multiple-cursors-compat-back-to-previous-state-h ()
(when +mc--compat-evil-prev-state
(unwind-protect
@ -115,7 +115,7 @@
(goto-char (1- (point)))
(push-mark (1- (mark))))))
(add-hook 'rectangular-region-mode-hook
(add-hook! 'rectangular-region-mode-hook
(defun +multiple-cursors-evil-compat-rect-switch-state-h ()
(if rectangular-region-mode
(+multiple-cursors-compat-switch-to-emacs-state-h)

View file

@ -256,7 +256,7 @@ shadow the default snippet)."
+snippets-dir))))))))
;;;###autoload
(defun +snippets|show-hints-in-header-line ()
(defun +snippets-show-hints-in-header-line-h ()
(setq header-line-format
(substitute-command-keys
(concat "\\[yas-load-snippet-buffer-and-close] to finish, "
@ -268,7 +268,7 @@ shadow the default snippet)."
;;; Hooks
;;;###autoload
(defun +snippets|enable-project-modes (mode &rest _)
(defun +snippets-enable-project-modes-h (mode &rest _)
"Automatically enable snippet libraries for project minor modes defined with
`def-project-mode!'."
(if (symbol-value mode)
@ -276,7 +276,7 @@ shadow the default snippet)."
(yas-deactivate-extra-mode mode)))
;;;###autoload
(defun +snippets|read-only-maybe ()
(defun +snippets-read-only-maybe-h ()
"Enable `read-only-mode' if snippet is built-in."
(when (file-in-directory-p default-directory doom-local-dir)
(read-only-mode 1)
@ -287,7 +287,7 @@ shadow the default snippet)."
;;; Advice
;;;###autoload
(defun +snippets*expand-on-region (orig-fn &optional no-condition)
(defun +snippets-expand-on-region-a (orig-fn &optional no-condition)
"Fix off-by-one issue with expanding snippets on an evil visual region, and
switches to insert mode.

View file

@ -20,8 +20,11 @@
;; have additional configuration for yasnippet. For example, file-templates.
(add-transient-hook! 'yas-minor-mode-hook (yas-reload-all))
(add-hook! (text-mode prog-mode conf-mode snippet-mode)
#'yas-minor-mode-on)
(add-hook! '(text-mode-hook
prog-mode-hook
conf-mode-hook
snippet-mode-hook)
#'yas-minor-mode-on)
:config
(setq yas-verbosity (if doom-debug-mode 3 0)
@ -44,7 +47,7 @@
;; Register `def-project-mode!' modes with yasnippet. This enables project
;; specific snippet libraries (e.g. for Laravel, React or Jekyll projects).
(add-hook 'doom-project-hook #'+snippets|enable-project-modes)
(add-hook 'doom-project-hook #'+snippets-enable-project-modes-h)
;; Exit snippets on ESC from normal mode
(add-hook 'doom-escape-hook #'yas-abort-snippet)
@ -54,16 +57,16 @@
(advice-add #'yas-expand :before #'sp-remove-active-pair-overlay))
;; Enable `read-only-mode' for built-in snippets (in `doom-local-dir')
(add-hook 'snippet-mode-hook #'+snippets|read-only-maybe)
(add-hook 'snippet-mode-hook #'+snippets-read-only-maybe-h)
;; (Evil only) fix off-by-one issue with line-wise visual selections in
;; `yas-insert-snippet', and switches to insert mode afterwards.
(advice-add #'yas-insert-snippet :around #'+snippets*expand-on-region)
(advice-add #'yas-insert-snippet :around #'+snippets-expand-on-region-a)
(define-key! snippet-mode-map
"C-c C-k" #'+snippet--abort
"C-c C-e" #'+snippet--edit)
(add-hook 'snippet-mode-hook #'+snippets|show-hints-in-header-line)
(add-hook 'snippet-mode-hook #'+snippets-show-hints-in-header-line-h)
;; Replace commands with superior alternatives
(define-key! yas-minor-mode-map
@ -75,7 +78,7 @@
:defer t
:init (setq aya-persist-snippets-dir (concat doom-etc-dir "auto-snippets/"))
:config
(defadvice! +snippets--inhibit-yas-global-mode (orig-fn &rest args)
(defadvice! +snippets--inhibit-yas-global-mode-a (orig-fn &rest args)
"auto-yasnippet enables `yas-global-mode'. This is obnoxious for folks like
us who use yas-minor-mode and enable yasnippet more selectively. This advice
swaps `yas-global-mode' with `yas-minor-mode'."

View file

@ -168,7 +168,7 @@
;; Without it, refiling (archiving), trashing, and flagging (starring) email
;; won't properly result in the corresponding gmail action, since the marks
;; are ineffectual otherwise.
(add-hook 'mu4e-mark-execute-pre-hook
(add-hook! 'mu4e-mark-execute-pre-hook
(defun +mu4e-gmail-fix-flags-h (mark msg)
(pcase mark
(`trash (mu4e-action-retag-message msg "-\\Inbox,+\\Trash,-\\Draft"))

View file

@ -89,7 +89,7 @@
;; Advice
;;;###autoload
(defun +notmuch*dont-confirm-on-kill-process (orig-fn &rest args)
(defun +notmuch-dont-confirm-on-kill-process-a (orig-fn &rest args)
"Don't prompt for confirmation when killing notmuch sentinel."
(let (confirm-kill-processes)
(apply orig-fn args)))

View file

@ -42,13 +42,15 @@
;; (setq-hook! 'notmuch-show-mode-hook line-spacing 0)
(add-to-list 'doom-real-buffer-functions #'notmuch-interesting-buffer nil #'eq)
(add-hook 'doom-real-buffer-functions #'notmuch-interesting-buffer)
(advice-add #'notmuch-start-notmuch-sentinel :around #'+notmuch*dont-confirm-on-kill-process)
(advice-add #'notmuch-start-notmuch-sentinel :around #'+notmuch-dont-confirm-on-kill-process-a)
;; modeline doesn't have much use in these modes
(add-hook! (notmuch-show-mode notmuch-tree-mode notmuch-search-mode)
#'hide-mode-line-mode))
(add-hook! '(notmuch-show-mode-hook
notmuch-tree-mode-hook
notmuch-search-mode-hook)
#'hide-mode-line-mode))
(use-package! org-mime

View file

@ -74,6 +74,6 @@
;; Neither wl-folder-mode or wl-summary-mode are correctly defined as major
;; modes, so `evil-set-initial-state' won't work here.
(add-hook! '(wl-folder-mode-hook wl-summary-mode-hook)
#'evil-emacs-state))
#'evil-emacs-state))
(add-hook 'mime-edit-mode-hook #'auto-fill-mode))

View file

@ -169,7 +169,7 @@ compilation dbs."
;; collect (format "-I%s" path))])))))))
;;;###autoload
(defun +cc|init-ffap-integration ()
(defun +cc-init-ffap-integration-h ()
"Takes the local project include paths and registers them with ffap.
This way, `find-file-at-point' (and `+lookup/file') will know where to find most
header files."

View file

@ -50,8 +50,10 @@ This is ignored by ccls.")
;; Ensure find-file-at-point works in C modes, must be added before irony
;; and/or lsp hooks are run.
(add-hook! (c-mode-local-vars c++-mode-local-vars objc-mode-local-vars)
#'+cc|init-ffap-integration)
(add-hook! '(c-mode-local-vars-hook
c++-mode-local-vars-hook
objc-mode-local-vars-hook)
#'+cc-init-ffap-integration-h)
:config
(set-electric! '(c-mode c++-mode objc-mode java-mode) :chars '(?\n ?\} ?\{))
@ -80,7 +82,7 @@ This is ignored by ccls.")
;;; Better fontification (also see `modern-cpp-font-lock')
(add-hook 'c-mode-common-hook #'rainbow-delimiters-mode)
(add-hook! (c-mode c++-mode) #'+cc-fontify-constants-h)
(add-hook! '(c-mode-hook c++-mode-hook) #'+cc-fontify-constants-h)
;; Custom style, based off of linux
(c-add-style
@ -125,7 +127,9 @@ This is ignored by ccls.")
:preface
(setq irony-server-install-prefix (concat doom-etc-dir "irony-server/"))
:init
(add-hook! (c-mode-local-vars c++-mode-local-vars objc-mode-local-vars)
(add-hook! '(c-mode-local-vars-hook
c++-mode-local-vars-hook
objc-mode-local-vars-hook)
(defun +cc-init-irony-mode-h ()
(if (file-directory-p irony-server-install-prefix)
(irony-mode +1)
@ -181,7 +185,9 @@ This is ignored by ccls.")
:preface
(setq rtags-install-path (concat doom-etc-dir "rtags/"))
:init
(add-hook! (c-mode-local-vars c++-mode-local-vars objc-mode-local-vars)
(add-hook! '(c-mode-local-vars-hook
c++-mode-local-vars-hook
objc-mode-local-vars-hook)
(defun +cc-init-rtags-h ()
"Start an rtags server in c-mode and c++-mode buffers."
(when (and (require 'rtags nil t)

View file

@ -19,12 +19,12 @@
(setq omnisharp-auto-complete-want-documentation nil
omnisharp-cache-directory (concat doom-cache-dir "omnisharp"))
:config
(defun +csharp|cleanup-omnisharp-server ()
(defun +csharp-cleanup-omnisharp-server-h ()
"Clean up the omnisharp server once you kill the last csharp-mode buffer."
(unless (doom-buffers-in-mode 'csharp-mode (buffer-list))
(omnisharp-stop-server)))
(add-hook! csharp-mode
(add-hook 'kill-buffer-hook #'+csharp|cleanup-omnisharp-server nil t))
(add-hook! 'csharp-mode-hook
(add-hook 'kill-buffer-hook #'+csharp-cleanup-omnisharp-server-h nil t))
(set-company-backend! 'csharp-mode 'company-omnisharp)
(set-lookup-handlers! 'csharp-mode

View file

@ -47,24 +47,16 @@ This marks a foldable marker for `outline-minor-mode' in elisp buffers.")
;; variable-width indentation is superior in elisp
(add-to-list 'doom-detect-indentation-excluded-modes 'emacs-lisp-mode nil #'eq)
;; Special indentation behavior for `add-hook'; indent like a defun block if
;; it contains `defun' forms and like normal otherwise.
(defun +emacs-lisp-indent-add-hook-fn (indent-point state)
(goto-char indent-point)
(when (looking-at-p "\\s-*(defun ")
(lisp-indent-defform state indent-point)))
(put 'add-hook 'lisp-indent-function #'+emacs-lisp-indent-add-hook-fn)
;; Use helpful instead of describe-* from `company'
(advice-add #'elisp--company-doc-buffer :around #'doom-use-helpful-a)
(add-hook! 'emacs-lisp-mode-hook
#'(outline-minor-mode
;; fontificiation
rainbow-delimiters-mode
highlight-quoted-mode
;; initialization
+emacs-lisp-extend-imenu-h))
#'outline-minor-mode
;; fontificiation
#'rainbow-delimiters-mode
#'highlight-quoted-mode
;; initialization
#'+emacs-lisp-extend-imenu-h)
;; Flycheck's two emacs-lisp checkers produce a *lot* of false positives in
;; emacs configs, so we disable `emacs-lisp-checkdoc' and reduce the

View file

@ -24,8 +24,8 @@
#'+haskell/open-repl)
(add-hook! 'haskell-mode-hook
#'(haskell-collapse-mode ; support folding haskell code blocks
interactive-haskell-mode))
#'haskell-collapse-mode ; support folding haskell code blocks
#'interactive-haskell-mode)
(add-to-list 'completion-ignored-extensions ".hi")

View file

@ -1,7 +1,7 @@
;;; lang/idris/config.el -*- lexical-binding: t; -*-
(after! idris-mode
(add-hook! 'idris-mode-hook 'turn-on-idris-simple-indent)
(add-hook 'idris-mode-hook #'turn-on-idris-simple-indent)
(set-repl-handler! 'idris-mode 'idris-pop-to-repl)
(set-lookup-handlers! 'idris-mode
:documentation #'idris-docs-at-point

View file

@ -23,7 +23,7 @@
(buffer-substring-no-properties beg end))))
;;;###autoload
(defun +java|android-mode-maybe ()
(defun +java-android-mode-maybe-h ()
"Enable `android-mode' if this looks like an android project.
It determines this by the existence of AndroidManifest.xml or

View file

@ -33,7 +33,8 @@ If the depth is 2, the first two directories are removed: net.lissner.game.")
(use-package! android-mode
:commands android-mode
:init
(add-hook! (java-mode groovy-mode nxml-mode) #'+java|android-mode-maybe)
(add-hook! '(java-mode-hook groovy-mode-hook nxml-mode-hook)
#'+java-android-mode-maybe-h)
:config
(set-yas-minor-mode! 'android-mode))

View file

@ -84,7 +84,7 @@ Run this for any buffer you want to skewer."
;; Hooks
;;;###autoload
(defun +javascript|add-node-modules-path ()
(defun +javascript-add-node-modules-path-h ()
"Add current project's `node_modules/.bin` to `exec-path', so js tools
prioritize project-local packages over global ones."
(make-local-variable 'exec-path)
@ -96,7 +96,7 @@ prioritize project-local packages over global ones."
exec-path :test #'string=))
;;;###autoload
(defun +javascript|cleanup-tide-processes ()
(defun +javascript-cleanup-tide-processes-h ()
"Clean up dangling tsserver processes if there are no more buffers with
`tide-mode' active that belong to that server's project."
(when tide-mode
@ -113,7 +113,7 @@ prioritize project-local packages over global ones."
;; Advice
;;;###autoload
(defun +javascript*tide-project-root ()
(defun +javascript-tide-project-root-a ()
"Resolve to `doom-project-root' if `tide-project-root' fails."
(or tide-project-root
(or (locate-dominating-file default-directory "tsconfig.json")

View file

@ -87,10 +87,10 @@
;; a self-closing tag, so that it can insert a matching ending tag at point.
;; However, the parser doesn't run immediately, so a fast typist can outrun
;; it, causing tags to stay unclosed, so we force it to parse.
(defun +javascript|reparse (n)
(defadvice! +javascript-reparse-a (n)
;; if n != 1, rjsx-electric-gt calls rjsx-maybe-reparse itself
(if (= n 1) (rjsx-maybe-reparse)))
(advice-add #'rjsx-electric-gt :before #'+javascript|reparse))
:before #'rjsx-electric-gt
(if (= n 1) (rjsx-maybe-reparse))))
(after! typescript-mode
@ -127,33 +127,32 @@
;;
;;; Tools
(defun +javascript|init-lsp-or-tide-maybe ()
"Start `lsp' or `tide' in the current buffer.
(add-hook! '(js-mode-hook typescript-mode-hook web-mode-hook)
(defun +javascript-init-lsp-or-tide-maybe-h ()
"Start `lsp' or `tide' in the current buffer.
LSP will be used if the +lsp flag is enabled for :lang javascript AND if the
current buffer represents a file in a project.
If LSP fails to start (e.g. no available server or project), then we fall back
to tide."
(let ((buffer-file-name (buffer-file-name (buffer-base-buffer))))
(when (or (derived-mode-p 'js-mode 'typescript-mode)
(and (eq major-mode 'web-mode)
(string= "tsx" (file-name-extension buffer-file-name))))
(if (not buffer-file-name)
;; necessary because `tide-setup' and `lsp' will error if not a
;; file-visiting buffer
(add-hook 'after-save-hook #'+javascript|init-tide-or-lsp-maybe nil 'local)
(or (and (featurep! +lsp)
(progn (lsp!) lsp-mode))
;; fall back to tide
(if (executable-find "node")
(and (require 'tide nil t)
(progn (tide-setup) tide-mode))
(ignore
(doom-log "Couldn't start tide because 'node' is missing"))))
(remove-hook 'after-save-hook #'+javascript|init-tide-or-lsp-maybe 'local)))))
(add-hook! (js-mode typescript-mode web-mode) #'+javascript|init-lsp-or-tide-maybe)
(let ((buffer-file-name (buffer-file-name (buffer-base-buffer))))
(when (or (derived-mode-p 'js-mode 'typescript-mode)
(and (eq major-mode 'web-mode)
(string= "tsx" (file-name-extension buffer-file-name))))
(if (not buffer-file-name)
;; necessary because `tide-setup' and `lsp' will error if not a
;; file-visiting buffer
(add-hook 'after-save-hook #'+javascript-init-tide-or-lsp-maybe-h nil 'local)
(or (and (featurep! +lsp)
(progn (lsp!) lsp-mode))
;; fall back to tide
(if (executable-find "node")
(and (require 'tide nil t)
(progn (tide-setup) tide-mode))
(ignore
(doom-log "Couldn't start tide because 'node' is missing"))))
(remove-hook 'after-save-hook #'+javascript-init-tide-or-lsp-maybe-h 'local))))))
(use-package! tide
@ -172,10 +171,10 @@ to tide."
:definition '(tide-jump-to-definition :async t)
:references '(tide-references :async t))
;; resolve to `doom-project-root' if `tide-project-root' fails
(advice-add #'tide-project-root :override #'+javascript*tide-project-root)
(advice-add #'tide-project-root :override #'+javascript-tide-project-root-a)
;; cleanup tsserver when no tide buffers are left
(add-hook! 'tide-mode-hook
(add-hook 'kill-buffer-hook #'+javascript|cleanup-tide-processes nil t))
(add-hook 'kill-buffer-hook #'+javascript-cleanup-tide-processes-h nil t))
(define-key tide-mode-map [remap +lookup/documentation] #'tide-documentation-at-point)
@ -206,9 +205,8 @@ to tide."
(use-package! eslintd-fix
:commands eslintd-fix
:config
(defun +javascript|set-flycheck-executable-to-eslint ()
(setq flycheck-javascript-eslint-executable eslintd-fix-executable))
(add-hook 'eslintd-fix-mode-hook #'+javascript|set-flycheck-executable-to-eslint))
(setq-hook! 'eslintd-fix-mode-hook
flycheck-javascript-eslint-executable eslintd-fix-executable))
;;;###package skewer-mode
@ -253,7 +251,7 @@ to tide."
(def-project-mode! +javascript-npm-mode
:modes '(html-mode css-mode web-mode typescript-mode js2-mode rjsx-mode json-mode markdown-mode)
:when (locate-dominating-file default-directory "package.json")
:add-hooks '(+javascript|add-node-modules-path npm-mode))
:add-hooks '(+javascript-add-node-modules-path-h npm-mode))
(def-project-mode! +javascript-gulp-mode
:when (locate-dominating-file default-directory "gulpfile.js"))

View file

@ -26,8 +26,8 @@
(setq-hook! 'moonscript-mode-hook
moonscript-indent-offset tab-width)
(add-hook! 'moonscript-mode-hook
#'(+lua|moonscript-fix-single-quotes
+lua|moonscript-fontify-interpolation)))
#'+lua|moonscript-fix-single-quotes
#'+lua|moonscript-fontify-interpolation))
;;

View file

@ -1,8 +1,8 @@
;;; lang/ocaml/config.el -*- lexical-binding: t; -*-
(when (featurep! +lsp)
(add-hook! (tuareg-mode-local-vars reason-mode-local-vars)
#'lsp!))
(add-hook! '(tuareg-mode-local-vars-hook reason-mode-local-vars-hook)
#'lsp!))
(after! tuareg

View file

@ -491,8 +491,12 @@ between the two."
;; insert new headings after current subtree rather than inside it
org-insert-heading-respect-content t)
(add-hook! 'org-tab-first-hook #'(+org-indent-maybe-h +org-yas-expand-maybe-h))
(add-hook 'doom-delete-backward-functions #'+org-delete-backward-char-and-realign-table-maybe-h)
(add-hook! 'org-tab-first-hook
#'+org-indent-maybe-h
#'+org-yas-expand-maybe-h)
(add-hook 'doom-delete-backward-functions
#'+org-delete-backward-char-and-realign-table-maybe-h)
(map! :map org-mode-map
;; textmate-esque newline insertion
@ -803,39 +807,39 @@ compelling reason, so..."
))
(add-hook! 'org-mode-hook
#'(org-bullets-mode ; "prettier" bullets
org-indent-mode ; margin-based indentation
toc-org-enable ; auto-table of contents
auto-fill-mode ; hard line wrapping
;; `show-paren-mode' causes flickering with indentation margins made by
;; `org-indent-mode', so we turn off show-paren-mode altogether
doom-disable-show-paren-mode-h
;; Shows a lot of false positives, so...
doom-disable-show-trailing-whitespace-h
#'org-bullets-mode ; "prettier" bullets
#'org-indent-mode ; margin-based indentation
#'toc-org-enable ; auto-table of contents
#'auto-fill-mode ; hard line wrapping
;; `show-paren-mode' causes flickering with indentation margins made by
;; `org-indent-mode', so we turn off show-paren-mode altogether
#'doom-disable-show-paren-mode-h
;; Shows a lot of false positives, so...
#'doom-disable-show-trailing-whitespace-h
+org-enable-auto-reformat-tables-h
+org-enable-auto-update-cookies-h
+org-unfold-to-2nd-level-or-point-h))
#'+org-enable-auto-reformat-tables-h
#'+org-enable-auto-update-cookies-h
#'+org-unfold-to-2nd-level-or-point-h)
(add-hook! 'org-load-hook
#'(+org-init-appearance-h
+org-init-agenda-h
+org-init-babel-h
+org-init-babel-lazy-loader-h
+org-init-capture-defaults-h
+org-init-capture-frame-h
+org-init-centralized-attachments-h
+org-init-centralized-exports-h
+org-init-custom-links-h
+org-init-export-h
+org-init-habit-h
+org-init-hacks-h
+org-init-keybinds-h
+org-init-keybinds-for-evil-h ; will noop without :editor evil
+org-init-popup-rules-h
+org-init-protocol-h
+org-init-protocol-lazy-loader-h
+org-init-smartparens-h))
#'+org-init-appearance-h
#'+org-init-agenda-h
#'+org-init-babel-h
#'+org-init-babel-lazy-loader-h
#'+org-init-capture-defaults-h
#'+org-init-capture-frame-h
#'+org-init-centralized-attachments-h
#'+org-init-centralized-exports-h
#'+org-init-custom-links-h
#'+org-init-export-h
#'+org-init-habit-h
#'+org-init-hacks-h
#'+org-init-keybinds-h
#'+org-init-keybinds-for-evil-h ; will noop without :editor evil
#'+org-init-popup-rules-h
#'+org-init-protocol-h
#'+org-init-protocol-lazy-loader-h
#'+org-init-smartparens-h)
;; In case the user has eagerly loaded org from their configs
(when (featurep 'org)

View file

@ -36,9 +36,9 @@
:n [left] #'org-tree-slide-move-previous-tree)
(add-hook! 'org-tree-slide-mode-after-narrow-hook
#'(+org-present-detect-slide-h
+org-present-add-overlays-h
org-display-inline-images))
#'+org-present-detect-slide-h
#'+org-present-add-overlays-h
#'org-display-inline-images)
(add-hook 'org-tree-slide-mode-hook #'+org-present-init-org-tree-window-h)
(advice-add #'org-tree-slide--display-tree-with-narrow

View file

@ -2,8 +2,8 @@
(after! purescript-mode
(add-hook! 'purescript-mode-hook
#'(purescript-indentation-mode
rainbow-delimiters-mode))
#'purescript-indentation-mode
#'rainbow-delimiters-mode)
(set-lookup-handlers! 'purescript-mode
:definition #'psc-ide-goto-definition
:documentation #'purescript-pursuit))

View file

@ -84,7 +84,7 @@ called.")
(use-package! anaconda-mode
:hook (python-mode-local-vars . +python|init-anaconda-mode-maybe)
:hook (python-mode-local-vars . +python-init-anaconda-mode-maybe-h)
:init
(setq anaconda-mode-installation-directory (concat doom-etc-dir "anaconda/")
anaconda-mode-eldoc-as-single-line t)
@ -97,18 +97,18 @@ called.")
:documentation #'anaconda-mode-show-doc)
(set-popup-rule! "^\\*anaconda-mode" :select nil)
(defun +python|init-anaconda-mode-maybe ()
(defun +python-init-anaconda-mode-maybe-h ()
(unless (bound-and-true-p lsp-mode)
(anaconda-mode +1)))
(defun +python|auto-kill-anaconda-processes ()
(defun +python-auto-kill-anaconda-processes-h ()
"Kill anaconda processes if this buffer is the last python buffer."
(when (and (eq major-mode 'python-mode)
(not (delq (current-buffer)
(doom-buffers-in-mode 'python-mode (buffer-list)))))
(anaconda-mode-stop)))
(add-hook! 'python-mode-hook
(add-hook 'kill-buffer-hook #'+python|auto-kill-anaconda-processes nil t))
(add-hook 'kill-buffer-hook #'+python-auto-kill-anaconda-processes-h nil t))
(when (featurep 'evil)
(add-hook 'anaconda-mode-hook #'evil-normalize-keymaps))

View file

@ -18,7 +18,9 @@
(setq racket-smart-open-bracket-enable t)
(add-hook! racket-mode #'(rainbow-delimiters-mode highlight-quoted-mode))
(add-hook! 'racket-mode-hook
#'rainbow-delimiters-mode
#'highlight-quoted-mode)
(map! :localleader
:map racket-mode-map

View file

@ -24,7 +24,8 @@
;;
;;; Major modes
(add-hook! (css-mode sass-mode stylus-mode) #'rainbow-mode)
(add-hook! '(css-mode-hook sass-mode-hook stylus-mode-hook)
#'rainbow-mode)
;; built-in, and contains both css-mode & scss-mode
(after! css-mode
@ -47,7 +48,8 @@
;;; Tools
(when (featurep! +lsp)
(add-hook! (css-mode sass-mode less-css-mode) #'lsp!))
(add-hook! '(css-mode-hook sass-mode-hook less-css-mode-hook)
#'lsp!))
(use-package! counsel-css

View file

@ -142,4 +142,4 @@
(when (featurep! +lsp)
(add-hook! (html-mode web-mode) #'lsp!))
(add-hook! '(html-mode-hook web-mode-hook) #'lsp!))

View file

@ -25,7 +25,7 @@
(use-package! lsp-ui
:hook (lsp-mode . lsp-ui-mode)
:init
(add-hook 'lsp-ui-mode-hook
(add-hook! 'lsp-ui-mode-hook
(defun +lsp-init-ui-flycheck-or-flymake-h ()
"Sets up flymake-mode or flycheck-mode, depending on `lsp-prefer-flymake'."
(unless (eq :none lsp-prefer-flymake)
@ -61,7 +61,7 @@
:init
;; Make sure that `company-capf' is disabled since it is incompatible with
;; `company-lsp' (see lsp-mode#884)
(add-hook 'lsp-mode-hook
(add-hook! 'lsp-mode-hook
(defun +lsp-init-company-h ()
(if (not (bound-and-true-p company-mode))
(add-hook 'company-mode-hook #'+lsp-init-company-h t t)

View file

@ -43,7 +43,7 @@
(use-package! solaire-mode
:defer t
:init
(add-hook 'doom-load-theme-hook
(add-hook! 'doom-load-theme-hook
(defun +doom-solaire-mode-swap-bg-maybe-h ()
(pcase-let ((`(,theme . ,swap) (assq doom-theme +doom-solaire-themes)))
(require 'solaire-mode)
@ -53,8 +53,8 @@
;; fringe can become unstyled when deleting or focusing frames
(add-hook 'focus-in-hook #'solaire-mode-reset)
;; Prevent color glitches when reloading either DOOM or loading a new theme
(add-hook! :append '(doom-load-theme-hook doom-reload-hook)
#'solaire-mode-reset)
(add-hook! '(doom-load-theme-hook doom-reload-hook) :append
#'solaire-mode-reset)
;; org-capture takes an org buffer and narrows it. The result is erroneously
;; considered an unreal buffer, so solaire-mode must be restored.
(add-hook 'org-capture-mode-hook #'turn-on-solaire-mode)
@ -78,7 +78,7 @@
;; Because fringes can't be given a buffer-local face, they can look odd, so
;; we remove them in the minibuffer and which-key popups (they serve no
;; purpose there anyway).
(add-hook 'solaire-mode-hook
(add-hook! 'solaire-mode-hook
(defun +doom-disable-fringes-in-minibuffer-h (&rest _)
(set-window-fringes (minibuffer-window) 0 0 nil)))
@ -88,6 +88,6 @@
(set-window-fringes (get-buffer-window which-key--buffer) 0 0 nil))
(add-hook! '(minibuffer-setup-hook window-configuration-change-hook)
#'+doom-disable-fringes-in-minibuffer-h)
#'+doom-disable-fringes-in-minibuffer-h)
(solaire-global-mode +1))

View file

@ -3,4 +3,5 @@
;;;###autoload (autoload 'hl-fill-column-mode "hl-fill-column" nil t)
;;;###autoload
(add-hook! (text-mode prog-mode conf-mode) #'hl-fill-column-mode)
(add-hook! '(text-mode-hook prog-mode-hook conf-mode-hook)
#'hl-fill-column-mode)

View file

@ -10,10 +10,11 @@
:init
;; NOTE In :tools lookup `recenter' is hooked to a bunch of jumping
;; commands, which will trigger nav-flash.
(add-hook!
'(imenu-after-jump-hook better-jumper-post-jump-hook
counsel-grep-post-action-hook dumb-jump-after-jump-hook)
#'+nav-flash-blink-cursor-maybe-h)
(add-hook! '(imenu-after-jump-hook
better-jumper-post-jump-hook
counsel-grep-post-action-hook
dumb-jump-after-jump-hook)
#'+nav-flash-blink-cursor-maybe-h)
(add-hook 'doom-switch-window-hook #'+nav-flash-blink-cursor-maybe-h)

View file

@ -55,7 +55,7 @@ adjustment.")
:global t
:keymap +popup-mode-map
(cond (+popup-mode
(add-hook 'doom-escape-hook #'+popup-close-on-escape-h t)
(add-hook 'doom-escape-hook #'+popup-close-on-escape-h 'append)
(setq +popup--old-display-buffer-alist display-buffer-alist
display-buffer-alist +popup--display-buffer-alist
window--sides-inhibit-check t)
@ -79,7 +79,8 @@ that window has been changed or closed."
:keymap +popup-buffer-mode-map
(if (not +popup-buffer-mode)
(remove-hook 'after-change-major-mode-hook #'+popup-set-modeline-on-enable-h t)
(add-hook 'after-change-major-mode-hook #'+popup-set-modeline-on-enable-h nil t)
(add-hook 'after-change-major-mode-hook #'+popup-set-modeline-on-enable-h
nil 'local)
(when (timerp +popup--timer)
(remove-hook 'kill-buffer-hook #'+popup-kill-buffer-hook-h t)
(cancel-timer +popup--timer)
@ -160,13 +161,13 @@ prevent the popup(s) from messing up the UI (or vice versa)."
("^\\*CPU-Profiler-Report " :side bottom :vslot 100 :slot 1 :height 0.4 :width 0.5 :quit nil)
("^\\*Memory-Profiler-Report " :side bottom :vslot 100 :slot 2 :height 0.4 :width 0.5 :quit nil)))
(add-hook 'doom-init-ui-hook #'+popup-mode :append)
(add-hook 'doom-init-ui-hook #'+popup-mode 'append)
(add-hook! '+popup-buffer-mode-hook
#'(+popup-adjust-fringes-h
+popup-adjust-margins-h
+popup-set-modeline-on-enable-h
+popup-unset-modeline-on-disable-h))
#'+popup-adjust-fringes-h
#'+popup-adjust-margins-h
#'+popup-set-modeline-on-enable-h
#'+popup-unset-modeline-on-disable-h)
;;

View file

@ -22,7 +22,7 @@ to the right fringe.")
(use-package! git-gutter
:commands git-gutter:revert-hunk git-gutter:stage-hunk
:init
(add-hook 'find-file-hook
(add-hook! 'find-file-hook
(defun +vc-gutter-init-maybe-h ()
"Enable `git-gutter-mode' in the current buffer.
@ -67,7 +67,7 @@ is deferred until the file is saved. Respects `git-gutter:disabled-modes'."
;; Update git-gutter on focus (in case I was using git externally)
(add-hook 'focus-in-hook #'git-gutter:update-all-windows)
(add-hook! :append '(doom-escape-hook doom-switch-window-hook)
(add-hook! '(doom-escape-hook doom-switch-window-hook) :append
(defun +vc-gutter-update-h (&rest _)
"Refresh git-gutter on ESC. Return nil to prevent shadowing other
`doom-escape-hook' hooks."

View file

@ -1,4 +1,5 @@
;;; ui/vi-tilde-fringe/autoload.el -*- lexical-binding: t; -*-
;;;###autoload
(add-hook! (prog-mode text-mode conf-mode) #'vi-tilde-fringe-mode)
(add-hook! '(prog-mode-hook text-mode-hook conf-mode-hook)
#'vi-tilde-fringe-mode)

View file

@ -83,7 +83,7 @@ stored in `persp-save-dir'.")
(display-buffer-in-side-window
warnings '((window-height . shrink-window-if-larger-than-buffer)))))))))))
(add-hook 'persp-mode-hook
(add-hook! 'persp-mode-hook
(defun +workspaces-init-persp-mode-h ()
(cond (persp-mode
;; `uniquify' breaks persp-mode. It renames old buffers, which causes
@ -109,7 +109,7 @@ stored in `persp-save-dir'.")
(setq persp-add-buffer-on-find-file nil
persp-add-buffer-on-after-change-major-mode nil)
(add-hook 'doom-switch-buffer-hook
(add-hook! 'doom-switch-buffer-hook
(defun +workspaces-add-current-buffer-h ()
"Add current buffer to focused perspective."
(when persp-mode