doomemacs/core/core-ui.el
Henrik Lissner 33e7f081a7 Restore hl-line-sticky-flag defaults
There are some modes that expect he highlight to be visible across
windows (like treemacs or mu4e). The performance benefit is negligible
anyhow.
2021-05-09 20:50:23 -04:00

721 lines
28 KiB
EmacsLisp
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

;;; core-ui.el -*- lexical-binding: t; -*-
;;
;;; Variables
(defvar doom-theme nil
"A symbol representing the Emacs theme to load at startup.
Set to `default' to load no theme at all. This is changed by `load-theme'.")
(defvar doom-font nil
"The default font to use.
Must be a `font-spec', a font object, an XFT font string, or an XLFD string.
This affects the `default' and `fixed-pitch' faces.
Examples:
(setq doom-font (font-spec :family \"Fira Mono\" :size 12))
(setq doom-font \"Terminus (TTF):pixelsize=12:antialias=off\")")
(defvar doom-variable-pitch-font nil
"The default font to use for variable-pitch text.
Must be a `font-spec', a font object, an XFT font string, or an XLFD string. See
`doom-font' for examples.
An omitted font size means to inherit `doom-font''s size.")
(defvar doom-serif-font nil
"The default font to use for the `fixed-pitch-serif' face.
Must be a `font-spec', a font object, an XFT font string, or an XLFD string. See
`doom-font' for examples.
An omitted font size means to inherit `doom-font''s size.")
(defvar doom-unicode-font nil
"Fallback font for Unicode glyphs.
Must be a `font-spec', a font object, an XFT font string, or an XLFD string. See
`doom-font' for examples.
The defaults on macOS and Linux are Apple Color Emoji and Symbola, respectively.
An omitted font size means to inherit `doom-font''s size.")
(defvar doom-emoji-fallback-font-families
'("Apple Color Emoji"
"Segoe UI Emoji"
"Noto Color Emoji"
"Noto Emoji")
"A list of fallback font families to use for emojis.")
(defvar doom-symbol-fallback-font-families
'("Segoe UI Symbol"
"Apple Symbols")
"A list of fallback font families for general symbol glyphs.")
;;
;;; Custom hooks
(defvar doom-init-ui-hook nil
"List of hooks to run when the UI has been initialized.")
(defvar doom-load-theme-hook nil
"Hook run after the theme is loaded with `load-theme' or reloaded with
`doom/reload-theme'.")
(defvar doom-switch-buffer-hook nil
"A list of hooks run after changing the current buffer.")
(defvar doom-switch-window-hook nil
"A list of hooks run after changing the focused windows.")
(defvar doom-switch-frame-hook nil
"A list of hooks run after changing the focused frame.")
(defvar doom-inhibit-switch-buffer-hooks nil
"Letvar for inhibiting `doom-switch-buffer-hook'. Do not set this directly.")
(defvar doom-inhibit-switch-window-hooks nil
"Letvar for inhibiting `doom-switch-window-hook'. Do not set this directly.")
(defvar doom-inhibit-switch-frame-hooks nil
"Letvar for inhibiting `doom-switch-frame-hook'. Do not set this directly.")
(defvar doom--last-window nil)
(defvar doom--last-frame nil)
(defun doom-run-switch-window-hooks-h ()
(unless (or doom-inhibit-switch-window-hooks
(eq doom--last-window (selected-window))
(minibufferp))
(let ((gc-cons-threshold most-positive-fixnum)
(doom-inhibit-switch-window-hooks t)
(inhibit-redisplay t))
(run-hooks 'doom-switch-window-hook)
(setq doom--last-window (selected-window)))))
(defun doom-run-switch-frame-hooks-h (&rest _)
(unless (or doom-inhibit-switch-frame-hooks
(eq doom--last-frame (selected-frame))
(frame-parameter nil 'parent-frame))
(let ((gc-cons-threshold most-positive-fixnum)
(doom-inhibit-switch-frame-hooks t))
(run-hooks 'doom-switch-frame-hook)
(setq doom--last-frame (selected-frame)))))
(defun doom-run-switch-buffer-hooks-a (orig-fn buffer-or-name &rest args)
(if (or doom-inhibit-switch-buffer-hooks
(and buffer-or-name
(eq (current-buffer)
(get-buffer buffer-or-name)))
(and (eq orig-fn #'switch-to-buffer) (car args)))
(apply orig-fn buffer-or-name args)
(let ((gc-cons-threshold most-positive-fixnum)
(doom-inhibit-switch-buffer-hooks t)
(inhibit-redisplay t))
(when-let (buffer (apply orig-fn buffer-or-name args))
(with-current-buffer (if (windowp buffer)
(window-buffer buffer)
buffer)
(run-hooks 'doom-switch-buffer-hook))
buffer))))
(defun doom-run-switch-to-next-prev-buffer-hooks-a (orig-fn &rest args)
(if doom-inhibit-switch-buffer-hooks
(apply orig-fn args)
(let ((gc-cons-threshold most-positive-fixnum)
(doom-inhibit-switch-buffer-hooks t)
(inhibit-redisplay t))
(when-let (buffer (apply orig-fn args))
(with-current-buffer buffer
(run-hooks 'doom-switch-buffer-hook))
buffer))))
(defun doom-protect-fallback-buffer-h ()
"Don't kill the scratch buffer. Meant for `kill-buffer-query-functions'."
(not (eq (current-buffer) (doom-fallback-buffer))))
(defun doom-highlight-non-default-indentation-h ()
"Highlight whitespace at odds with `indent-tabs-mode'.
That is, highlight tabs if `indent-tabs-mode' is `nil', and highlight spaces at
the beginnings of lines if `indent-tabs-mode' is `t'. The purpose is to make
incorrect indentation in the current buffer obvious to you.
Does nothing if `whitespace-mode' or `global-whitespace-mode' is already active
or if the current buffer is read-only or not file-visiting."
(unless (or (eq major-mode 'fundamental-mode)
(bound-and-true-p global-whitespace-mode)
(null buffer-file-name))
(require 'whitespace)
(set (make-local-variable 'whitespace-style)
(cl-union (if indent-tabs-mode
'(indentation)
'(tabs tab-mark))
(when whitespace-mode
(remq 'face whitespace-active-style))))
(cl-pushnew 'face whitespace-style) ; must be first
(whitespace-mode +1)))
;;
;;; General UX
;; A simple confirmation prompt when killing Emacs. But only prompt when there
;; are real buffers open.
(setq confirm-kill-emacs #'doom-quit-p)
;; Prompt for confirmation when deleting a non-empty frame; a last line of
;; defense against accidental loss of work.
(global-set-key [remap delete-frame] #'doom/delete-frame-with-prompt)
;; Don't prompt for confirmation when we create a new file or buffer (assume the
;; user knows what they're doing).
(setq confirm-nonexistent-file-or-buffer nil)
(setq uniquify-buffer-name-style 'forward
;; no beeping or blinking please
ring-bell-function #'ignore
visible-bell nil)
;; middle-click paste at point, not at click
(setq mouse-yank-at-point t)
;; Larger column width for function name in profiler reports
(after! profiler
(setf (caar profiler-report-cpu-line-format) 80
(caar profiler-report-memory-line-format) 80))
;;
;;; Scrolling
(setq hscroll-margin 2
hscroll-step 1
;; Emacs spends too much effort recentering the screen if you scroll the
;; cursor more than N lines past window edges (where N is the settings of
;; `scroll-conservatively'). This is especially slow in larger files
;; during large-scale scrolling commands. If kept over 100, the window is
;; never automatically recentered.
scroll-conservatively 101
scroll-margin 0
scroll-preserve-screen-position t
;; Reduce cursor lag by a tiny bit by not auto-adjusting `window-vscroll'
;; for tall lines.
auto-window-vscroll nil
;; mouse
mouse-wheel-scroll-amount '(2 ((shift) . hscroll))
mouse-wheel-scroll-amount-horizontal 2)
;; Remove hscroll-margin in shells, otherwise it causes jumpiness
(setq-hook! '(eshell-mode-hook term-mode-hook) hscroll-margin 0)
;;
;;; Cursor
;; The blinking cursor is distracting, but also interferes with cursor settings
;; in some minor modes that try to change it buffer-locally (like treemacs) and
;; can cause freezing for folks (esp on macOS) with customized & color cursors.
(blink-cursor-mode -1)
;; Don't blink the paren matching the one at point, it's too distracting.
(setq blink-matching-paren nil)
;; Don't stretch the cursor to fit wide characters, it is disorienting,
;; especially for tabs.
(setq x-stretch-cursor nil)
;;
;;; Buffers
;; Make `next-buffer', `other-buffer', etc. ignore unreal buffers.
(push '(buffer-predicate . doom-buffer-frame-predicate) default-frame-alist)
(defadvice! doom--switch-to-fallback-buffer-maybe-a (&rest _)
"Switch to `doom-fallback-buffer' if on last real buffer.
Advice for `kill-current-buffer'. If in a dedicated window, delete it. If there
are no real buffers left OR if all remaining buffers are visible in other
windows, switch to `doom-fallback-buffer'. Otherwise, delegate to original
`kill-current-buffer'."
:before-until #'kill-current-buffer
(let ((buf (current-buffer)))
(cond ((window-dedicated-p)
(delete-window)
t)
((eq buf (doom-fallback-buffer))
(message "Can't kill the fallback buffer.")
t)
((doom-real-buffer-p buf)
(let ((visible-p (delq (selected-window) (get-buffer-window-list buf nil t)))
(doom-inhibit-switch-buffer-hooks t)
(inhibit-redisplay t)
buffer-list-update-hook)
(unless visible-p
(when (and (buffer-modified-p buf)
(not (y-or-n-p
(format "Buffer %s is modified; kill anyway?"
buf))))
(user-error "Aborted")))
(when (or ;; if there aren't more real buffers than visible buffers,
;; then there are no real, non-visible buffers left.
(not (cl-set-difference (doom-real-buffer-list)
(doom-visible-buffers)))
;; if we end up back where we start (or previous-buffer
;; returns nil), we have nowhere left to go
(memq (switch-to-prev-buffer nil t) (list buf 'nil)))
(switch-to-buffer (doom-fallback-buffer)))
(unless visible-p
(with-current-buffer buf
(restore-buffer-modified-p nil))
(kill-buffer buf))
(run-hooks 'buffer-list-update-hook)
t)))))
;;
;;; Fringes
;; Reduce the clutter in the fringes; we'd like to reserve that space for more
;; useful information, like git-gutter and flycheck.
(setq indicate-buffer-boundaries nil
indicate-empty-lines nil)
;;
;;; Windows/frames
;; A simple frame title
(setq frame-title-format '("%b Doom Emacs")
icon-title-format frame-title-format)
;; Don't resize the frames in steps; it looks weird, especially in tiling window
;; managers, where it can leave unseemly gaps.
(setq frame-resize-pixelwise t)
;; But do not resize windows pixelwise, this can cause crashes in some cases
;; when resizing too many windows at once or rapidly.
(setq window-resize-pixelwise nil)
;; Disable tool, menu, and scrollbars. Doom is designed to be keyboard-centric,
;; so these are just clutter (the scrollbar also impacts performance). Whats
;; more, the menu bar exposes functionality that Doom doesn't endorse.
;;
;; I am intentionally avoid using `menu-bar-mode', `tool-bar-mode', and
;; `scroll-bar-mode' because they do extra and unnecessary work that can be more
;; concisely, and efficiently, expressed with these six lines:
(push '(menu-bar-lines . 0) default-frame-alist)
(push '(tool-bar-lines . 0) default-frame-alist)
(push '(vertical-scroll-bars) default-frame-alist)
;; These are disabled directly through their frame parameters to avoid the extra
;; work their minor modes do, but their variables must be unset too, otherwise
;; users will have to cycle them twice to re-enable them.
(setq menu-bar-mode nil
tool-bar-mode nil
scroll-bar-mode nil)
;; The native border "consumes" a pixel of the fringe on righter-most splits,
;; `window-divider' does not. Available since Emacs 25.1.
(setq window-divider-default-places t
window-divider-default-bottom-width 1
window-divider-default-right-width 1)
(add-hook 'doom-init-ui-hook #'window-divider-mode)
;; GUIs are inconsistent across systems and themes (and will rarely match our
;; active Emacs theme). They impose inconsistent shortcut key paradigms too.
;; It's best to avoid GUIs altogether and have Emacs handle the prompting, since
;; its promtps are governed by the same rules and keybinds as the rest of Emacs.
(setq use-dialog-box nil)
(when (bound-and-true-p tooltip-mode)
(tooltip-mode -1))
(when IS-LINUX
(setq x-gtk-use-system-tooltips nil))
;; Favor vertical splits over horizontal ones. Monitors are trending toward
;; wide, rather than tall.
(setq split-width-threshold 160
split-height-threshold nil)
;;
;;; Minibuffer
;; Allow for minibuffer-ception. Sometimes we need another minibuffer command
;; while we're in the minibuffer.
(setq enable-recursive-minibuffers t)
;; Show current key-sequence in minibuffer ala 'set showcmd' in vim. Any
;; feedback after typing is better UX than no feedback at all.
(setq echo-keystrokes 0.02)
;; Expand the minibuffer to fit multi-line text displayed in the echo-area. This
;; doesn't look too great with direnv, however...
(setq resize-mini-windows 'grow-only)
;; Typing yes/no is obnoxious when y/n will do
(fset #'yes-or-no-p #'y-or-n-p)
;; Try to keep the cursor out of the read-only portions of the minibuffer.
(setq minibuffer-prompt-properties '(read-only t intangible t cursor-intangible t face minibuffer-prompt))
(add-hook 'minibuffer-setup-hook #'cursor-intangible-mode)
;;
;;; Built-in packages
;;;###package ansi-color
(setq ansi-color-for-comint-mode t)
(after! comint
(setq comint-prompt-read-only t
comint-buffer-maximum-size 2048)) ; double the default
(after! compile
(setq compilation-always-kill t ; kill compilation process before starting another
compilation-ask-about-save nil ; save all buffers on `compile'
compilation-scroll-output 'first-error)
;; Handle ansi codes in compilation buffer
(add-hook 'compilation-filter-hook #'doom-apply-ansi-color-to-compilation-buffer-h)
;; Automatically truncate compilation buffers so they don't accumulate too
;; much data and bog down the rest of Emacs.
(autoload 'comint-truncate-buffer "comint" nil t)
(add-hook 'compilation-filter-hook #'comint-truncate-buffer))
(after! ediff
(setq ediff-diff-options "-w" ; turn off whitespace checking
ediff-split-window-function #'split-window-horizontally
ediff-window-setup-function #'ediff-setup-windows-plain)
(defvar doom--ediff-saved-wconf nil)
;; Restore window config after quitting ediff
(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) :append
(defun doom-ediff-restore-wconf-h ()
(when (window-configuration-p doom--ediff-saved-wconf)
(set-window-configuration doom--ediff-saved-wconf)))))
(use-package! hl-line
;; Highlights the current line
:hook (doom-first-buffer . global-hl-line-mode)
:init
(defvar global-hl-line-modes
'(prog-mode text-mode conf-mode special-mode
org-agenda-mode)
"What modes to enable `hl-line-mode' in.")
:config
;; HACK I reimplement `global-hl-line-mode' so we can white/blacklist modes in
;; `global-hl-line-modes' _and_ so we can use `global-hl-line-mode',
;; which users expect to control hl-line in Emacs.
(define-globalized-minor-mode global-hl-line-mode hl-line-mode
(lambda ()
(and (not hl-line-mode)
(cond ((null global-hl-line-modes) nil)
((eq global-hl-line-modes t))
((eq (car global-hl-line-modes) 'not)
(not (derived-mode-p global-hl-line-modes)))
((apply #'derived-mode-p global-hl-line-modes)))
(hl-line-mode +1))))
;; Temporarily disable `hl-line' when selection is active, since it doesn't
;; serve much purpose when the selection is so much more visible.
(defvar doom--hl-line-mode nil)
(add-hook! 'hl-line-mode-hook
(defun doom-truly-disable-hl-line-h ()
(unless hl-line-mode
(setq-local doom--hl-line-mode nil))))
(add-hook! '(evil-visual-state-entry-hook activate-mark-hook)
(defun doom-disable-hl-line-h ()
(when hl-line-mode
(hl-line-mode -1)
(setq-local doom--hl-line-mode t))))
(add-hook! '(evil-visual-state-exit-hook deactivate-mark-hook)
(defun doom-enable-hl-line-maybe-h ()
(when doom--hl-line-mode
(hl-line-mode +1)))))
(use-package! winner
;; undo/redo changes to Emacs' window layout
:preface (defvar winner-dont-bind-my-keys t) ; I'll bind keys myself
:hook (doom-first-buffer . winner-mode)
:config
(appendq! winner-boring-buffers
'("*Compile-Log*" "*inferior-lisp*" "*Fuzzy Completions*"
"*Apropos*" "*Help*" "*cvs*" "*Buffer List*" "*Ibuffer*"
"*esh command on file*")))
(use-package! paren
;; highlight matching delimiters
:hook (doom-first-buffer . show-paren-mode)
:config
(setq show-paren-delay 0.1
show-paren-highlight-openparen t
show-paren-when-point-inside-paren t
show-paren-when-point-in-periphery t))
;;;###package whitespace
(setq whitespace-line-column nil
whitespace-style
'(face indentation tabs tab-mark spaces space-mark newline newline-mark
trailing lines-tail)
whitespace-display-mappings
'((tab-mark ?\t [? ?\t])
(newline-mark ?\n [ ?\n])
(space-mark ?\ [] [?.])))
;;
;;; Third party packages
(use-package! all-the-icons
:commands (all-the-icons-octicon
all-the-icons-faicon
all-the-icons-fileicon
all-the-icons-wicon
all-the-icons-material
all-the-icons-alltheicon)
:preface
(add-hook! 'after-setting-font-hook
(defun doom-init-all-the-icons-fonts-h ()
(when (fboundp 'set-fontset-font)
(dolist (font (list "Weather Icons"
"github-octicons"
"FontAwesome"
"all-the-icons"
"file-icons"
"Material Icons"))
(set-fontset-font t 'unicode font nil 'append)))))
:config
(cond ((daemonp)
(defadvice! doom--disable-all-the-icons-in-tty-a (orig-fn &rest args)
"Return a blank string in tty Emacs, which doesn't support multiple fonts."
:around '(all-the-icons-octicon all-the-icons-material
all-the-icons-faicon all-the-icons-fileicon
all-the-icons-wicon all-the-icons-alltheicon)
(if (or (not after-init-time) (display-multi-font-p))
(apply orig-fn args)
"")))
((not (display-graphic-p))
(defadvice! doom--disable-all-the-icons-in-tty-a (&rest _)
"Return a blank string for tty users."
:override '(all-the-icons-octicon all-the-icons-material
all-the-icons-faicon all-the-icons-fileicon
all-the-icons-wicon all-the-icons-alltheicon)
""))))
;; Hide the mode line in completion popups and MAN pages because they serve
;; little purpose there, and is better hidden.
;;;###package hide-mode-line-mode
(add-hook! '(completion-list-mode-hook Man-mode-hook)
#'hide-mode-line-mode)
;; Many major modes do no highlighting of number literals, so we do it for them
(use-package! highlight-numbers
:hook ((prog-mode conf-mode) . highlight-numbers-mode)
:config (setq highlight-numbers-generic-regexp "\\_<[[:digit:]]+\\(?:\\.[0-9]*\\)?\\_>"))
;;;###package image
(setq image-animate-loop t)
;;;###package rainbow-delimiters
;; Helps us distinguish stacked delimiter pairs, especially in parentheses-drunk
;; languages like Lisp. I reduce it from it's default of 9 to reduce the
;; complexity of the font-lock keyword and hopefully buy us a few ms of
;; performance.
(setq rainbow-delimiters-max-face-count 3)
;;
;;; Line numbers
;; Explicitly define a width to reduce the cost of on-the-fly computation
(setq-default display-line-numbers-width 3)
;; Show absolute line numbers for narrowed regions to make it easier to tell the
;; buffer is narrowed, and where you are, exactly.
(setq-default display-line-numbers-widen t)
;; Enable line numbers in most text-editing modes. We avoid
;; `global-display-line-numbers-mode' because there are many special and
;; temporary modes where we don't need/want them.
(add-hook! '(prog-mode-hook text-mode-hook conf-mode-hook)
#'display-line-numbers-mode)
;; Fix #2742: cursor is off by 4 characters in `artist-mode'
;; REVIEW Reported upstream https://debbugs.gnu.org/cgi/bugreport.cgi?bug=43811
;; DEPRECATED Fixed in Emacs 28; remove when we drop 27 support
(unless EMACS28+
(add-hook 'artist-mode-hook #'doom-disable-line-numbers-h))
;;
;;; Theme & font
;; User themes should live in ~/.doom.d/themes, not ~/.emacs.d
(setq custom-theme-directory (concat doom-private-dir "themes/"))
;; Always prioritize the user's themes above the built-in/packaged ones.
(setq custom-theme-load-path
(cons 'custom-theme-directory
(delq 'custom-theme-directory custom-theme-load-path)))
;; Underline looks a bit better when drawn lower
(setq x-underline-at-descent-line t)
(defun doom-init-fonts-h (&optional reload)
"Loads `doom-font'."
(when (fboundp 'set-fontset-font)
(let ((fn (doom-rpartial #'member (font-family-list))))
(when-let (font (cl-find-if fn doom-symbol-fallback-font-families))
(set-fontset-font t 'symbol font))
(when-let (font (cl-find-if fn doom-emoji-fallback-font-families))
(set-fontset-font t 'unicode font))
(when doom-unicode-font
(set-fontset-font t 'unicode doom-unicode-font))))
(apply #'custom-set-faces
(append (when doom-font
`((fixed-pitch ((t (:font ,doom-font))))))
(when doom-serif-font
`((fixed-pitch-serif ((t (:font ,doom-serif-font))))))
(when doom-variable-pitch-font
`((variable-pitch ((t (:font ,doom-variable-pitch-font))))))))
(cond
(doom-font
;; I avoid `set-frame-font' at startup because it is expensive; doing extra,
;; unnecessary work we can avoid by setting the frame parameter directly.
(setf (alist-get 'font default-frame-alist)
(cond ((stringp doom-font) doom-font)
((fontp doom-font) (font-xlfd-name doom-font))
((signal 'wrong-type-argument
(list '(fontp stringp) doom-font)))))
(when reload
(set-frame-font doom-font t)))
((display-graphic-p)
(setq font-use-system-font t)))
;; Give users a chance to inject their own font logic.
(run-hooks 'after-setting-font-hook))
(defun doom-init-theme-h (&optional frame)
"Load the theme specified by `doom-theme' in FRAME."
(when (and doom-theme (not (custom-theme-enabled-p doom-theme)))
;; Fix #1397: if `doom-init-theme-h' is used on `after-make-frame-functions'
;; (for daemon sessions), the new frame must be focused to ensure the theme
;; loads correctly.
(with-selected-frame (or frame (selected-frame))
(load-theme doom-theme t))))
(defadvice! doom--load-theme-a (orig-fn theme &optional no-confirm no-enable)
"Record `doom-theme', disable old themes, and trigger `doom-load-theme-hook'."
:around #'load-theme
;; Run `load-theme' from an estranged buffer, where we can ensure that
;; buffer-local face remaps (by `mixed-pitch-mode', for instance) won't
;; interfere with recalculating faces in new themes.
(with-temp-buffer
(let ((last-themes (copy-sequence custom-enabled-themes)))
;; Disable previous themes so there are no conflicts. If you truly want
;; multiple themes enabled, then use `enable-theme' instead.
(mapc #'disable-theme custom-enabled-themes)
(prog1 (funcall orig-fn theme no-confirm no-enable)
(when (and (not no-enable) (custom-theme-enabled-p theme))
(setq doom-theme theme)
(put 'doom-theme 'previous-themes last-themes)
(doom-run-hooks 'doom-load-theme-hook))))))
;;
;;; Bootstrap
(defun doom-init-ui-h ()
"Initialize Doom's user interface by applying all its advice and hooks."
;; Produce more helpful (and visible) error messages from errors emitted from
;; hooks (particularly mode hooks, that usually go unnoticed otherwise.
(advice-add #'run-hooks :override #'doom-run-hooks)
(doom-run-hooks 'doom-init-ui-hook)
(add-hook 'kill-buffer-query-functions #'doom-protect-fallback-buffer-h)
(add-hook 'after-change-major-mode-hook #'doom-highlight-non-default-indentation-h 'append)
;; Initialize custom switch-{buffer,window,frame} hooks:
;;
;; + `doom-switch-buffer-hook'
;; + `doom-switch-window-hook'
;; + `doom-switch-frame-hook'
;;
;; These should be done as late as possible, as not to prematurely trigger
;; hooks during startup.
(add-hook 'buffer-list-update-hook #'doom-run-switch-window-hooks-h)
(add-hook 'focus-in-hook #'doom-run-switch-frame-hooks-h)
(dolist (fn '(switch-to-next-buffer switch-to-prev-buffer))
(advice-add fn :around #'doom-run-switch-to-next-prev-buffer-hooks-a))
(dolist (fn '(switch-to-buffer display-buffer))
(advice-add fn :around #'doom-run-switch-buffer-hooks-a)))
;; Apply `doom-theme'
(add-hook (if (daemonp)
'after-make-frame-functions
'doom-after-init-modules-hook)
#'doom-init-theme-h)
;; Apply `doom-font' et co
(add-hook 'doom-after-init-modules-hook #'doom-init-fonts-h)
(add-hook 'window-setup-hook #'doom-init-ui-h 'append)
;;
;;; Fixes/hacks
;; Doom doesn't support `customize' and it never will. It's a clumsy interface
;; that sets variables at a time where it can be easily and unpredictably
;; overwritten. Configure things from your $DOOMDIR instead.
(dolist (sym '(customize-option customize-browse customize-group customize-face
customize-rogue customize-saved customize-apropos
customize-changed customize-unsaved customize-variable
customize-set-value customize-customized customize-set-variable
customize-apropos-faces customize-save-variable
customize-apropos-groups customize-apropos-options
customize-changed-options customize-save-customized))
(put sym 'disabled "Doom doesn't support `customize', configure Emacs from $DOOMDIR/config.el instead"))
(put 'customize-themes 'disabled "Set `doom-theme' or use `load-theme' in $DOOMDIR/config.el instead")
;; Doesn't exist in terminal Emacs, but some Emacs packages (internal and
;; external) use it anyway, leading to a void-function error, so define a no-op
;; substitute to suppress them.
(unless (fboundp 'define-fringe-bitmap)
(fset 'define-fringe-bitmap #'ignore))
(after! whitespace
(defun doom-disable-whitespace-mode-in-childframes-a (orig-fn)
"`whitespace-mode' inundates child frames with whitespace markers, so
disable it to fix all that visual noise."
(unless (frame-parameter nil 'parent-frame)
(funcall orig-fn)))
(add-function :around whitespace-enable-predicate #'doom-disable-whitespace-mode-in-childframes-a))
;; Don't display messages in the minibuffer when using the minibuffer
;; DEPRECATED Remove when Emacs 26.x support is dropped.
(eval-when! (not EMACS27+)
(defmacro doom-silence-motion-key (command key)
(let ((key-command (intern (format "doom/silent-%s" command))))
`(progn
(defun ,key-command ()
(interactive)
(ignore-errors (call-interactively ',command)))
(define-key minibuffer-local-map (kbd ,key) #',key-command))))
(doom-silence-motion-key backward-delete-char "<backspace>")
(doom-silence-motion-key delete-char "<delete>"))
(provide 'core-ui)
;;; core-ui.el ends here