Change how themes, fonts & modelines are loaded

WARNING: THIS IS A BREAKING CHANGE FOR THEME/FONT/NLINUM CUSTOMIZATIONS.

This change was motivated by the need to decouple theme and font loading
from the ui/doom module.

Now, it is doom-core's purview. Theme and fonts are loaded after
initfiles are read (attached to the doom-init-ui-hook hook), giving
other modules (especially private ones) a chance to change the theme or
fonts.

+ Refactor core-ui.el
+ New init hook: doom-init-ui-hook
+ Decouple theme/font loading from ui/doom
+ Load modelines are doom-init-ui-hook
+ New theme/font variables (replaces old ui/doom variables)
  + doom-theme
  + doom-font
  + doom-variable-pitch-font
  + doom-unicode-font
+ Change nlinum variables
  + doom-line-number-lpad
  + doom-line-number-rpad
  + doom-line-number-pad-char

Addresses #117
This commit is contained in:
Henrik Lissner 2017-06-28 16:18:22 +02:00
parent 804fd31aab
commit ecd8ad0f46
No known key found for this signature in database
GPG key ID: 5F6C0EA160557395
8 changed files with 147 additions and 132 deletions

View file

@ -59,3 +59,12 @@ window changes before then, the undo expires."
(when (doom-quit-p "Close frame?") (when (doom-quit-p "Close frame?")
(delete-frame)) (delete-frame))
(save-buffers-kill-emacs))) (save-buffers-kill-emacs)))
;;;###autoload
(defun doom/reload-theme ()
"Reset the color theme currently in use."
(interactive)
(let ((theme (or (car-safe custom-enabled-themes) doom-theme)))
(when theme
(mapc #'disable-theme custom-enabled-themes))
(+doom|init-ui)))

View file

@ -164,7 +164,7 @@ for :align t on every rule."
(t (t
(when doom-popup-no-fringes (when doom-popup-no-fringes
(set-window-fringes window (set-window-fringes window
doom-ui-fringe-size doom-ui-fringe-size doom-fringe-size doom-fringe-size
fringes-outside-margins)) fringes-outside-margins))
;; Ensure window parameters are cleaned up ;; Ensure window parameters are cleaned up
(set-window-parameter window 'popup nil) (set-window-parameter window 'popup nil)

View file

@ -1,6 +1,44 @@
;;; core-ui.el -*- lexical-binding: t; -*- ;;; core-ui.el -*- lexical-binding: t; -*-
(defvar doom-ui-fringe-size '4 "Default fringe width") (defvar doom-fringe-size '4
"Default fringe width.")
(defvar doom-theme nil
"A symbol representing the color theme to load.")
(defvar doom-font (font-spec :family "Fira Mono" :size 12)
"The default font to use. Expects a FONT-SPEC (`font-spec').")
(defvar doom-variable-pitch-font (font-spec :family "Fira Sans" :size 12)
"The default font to use for variable-pitch text. Expects a FONT-SPEC (`font-spec').")
(defvar doom-unicode-font (font-spec :family "DejaVu Sans Mono" :size 12)
"Fallback font for unicode glyphs. Is ignored if :feature unicode is active.")
(defvar doom-major-mode-names
'((sh-mode . "sh")
(emacs-lisp-mode . "Elisp"))
"An alist mapping major modes symbols to strings (or functions that will
return a string). This changes the 'long' name of a major-mode, allowing for
shorter major mode name in the mode-line. See `doom|set-mode-name'.")
;; Line numbers
(defvar doom-line-number-lpad 4
"How much padding to place before line numbers.")
(defvar doom-line-number-rpad 1
"How much padding to place after line numbers.")
(defvar doom-line-number-pad-char ?\u2002
"Character to use for padding line numbers. We use an exotic 'space-looking'
character so that `whitespace-mode' won't replace spaces inside the line number
overlay.")
;; Hook(s)
(defvar doom-init-ui-hook nil
"List of hooks to run when the theme and font is initialized (or reloaded with
`doom/reload-theme').")
(setq-default (setq-default
bidi-display-reordering nil ; disable bidirectional text for tiny performance boost bidi-display-reordering nil ; disable bidirectional text for tiny performance boost
@ -39,8 +77,8 @@
(fset #'yes-or-no-p #'y-or-n-p) ; y/n instead of yes/no (fset #'yes-or-no-p #'y-or-n-p) ; y/n instead of yes/no
(defun doom-quit-p (&optional prompt) (defun doom-quit-p (&optional prompt)
"Return t if this session should be killed, but not before it prompts the user "Return t if this session should be killed. Prompts the user for
for confirmation." confirmation."
(interactive) (interactive)
(if (ignore-errors (doom-real-buffer-list)) (if (ignore-errors (doom-real-buffer-list))
(or (yes-or-no-p (format " %s" (or prompt "Quit Emacs?"))) (or (yes-or-no-p (format " %s" (or prompt "Quit Emacs?")))
@ -108,52 +146,85 @@ local value, whether or not it's permanent-local. Therefore, we cycle
;; The native border "consumes" a pixel of the fringe on righter-most splits, ;; The native border "consumes" a pixel of the fringe on righter-most splits,
;; `window-divider' does not. Available since Emacs 25.1. ;; `window-divider' does not. Available since Emacs 25.1.
(setq-default window-divider-default-places t (setq-default window-divider-default-places t
window-divider-default-bottom-width 1 window-divider-default-bottom-width 0
window-divider-default-right-width 1) window-divider-default-right-width 1)
(add-hook 'doom-init-hook #'window-divider-mode) (add-hook 'doom-init-hook #'window-divider-mode)
;; like diminish, but for major-modes. [pedantry intensifies] ;; like diminish, but for major-modes. [pedantry intensifies]
(defvar doom-ui-mode-names
'((sh-mode . "sh")
(emacs-lisp-mode "Elisp"))
"An alist mapping major modes to alternative names, which will be set when the
mode is detected.")
(defun doom|set-mode-name () (defun doom|set-mode-name ()
"Set the major mode's `mode-name', as dictated by `doom-ui-mode-names'." "Set the major mode's `mode-name', as dictated by `doom-major-mode-names'."
(let ((name (assq major-mode doom-ui-mode-names))) (when-let (name (cdr (assq major-mode doom-major-mode-names)))
(if name (setq mode-name (cdr name))))) (setq mode-name
(cond ((functionp name)
(funcall name))
((stringp name)
name)
(t
(error "'%s' isn't a valid name for %s" name major-mode))))))
(add-hook 'after-change-major-mode-hook #'doom|set-mode-name) (add-hook 'after-change-major-mode-hook #'doom|set-mode-name)
;;
;; Themes & fonts
;;
;; Getting themes to remain consistent across GUI Emacs, terminal Emacs and
;; daemon Emacs is hairy.
;;
;; + Running `+doom|init-ui' directly sorts out the initial GUI frame.
;; + Attaching it to `after-make-frame-functions' sorts out daemon Emacs.
;; + Waiting for 0.1s in `doom|reload-ui-in-daemon' fixes daemon Emacs started
;; with `server-start' in an interactive session of Emacs AND in tty Emacs.
(defun doom|init-ui (&optional frame)
"Set the theme and load the font, in that order."
(when doom-theme
(load-theme doom-theme t))
(with-demoted-errors "FONT ERROR: %s"
(when (fontp doom-font)
(set-frame-font doom-font nil (if frame (list frame) t)))
;; Fallback to `doom-unicode-font' for Unicode characters
(when (fontp doom-unicode-font)
(set-fontset-font t 'unicode doom-unicode-font frame))
;; ...and for variable-pitch-mode:
(when (fontp doom-variable-pitch-font)
(set-face-attribute 'variable-pitch frame :font doom-variable-pitch-font)))
(run-hooks 'doom-init-ui-hook))
(defun doom|reload-ui-in-daemon (frame)
"Reload the theme (and font) in an daemon frame."
(when (or (daemonp) (not (display-graphic-p)))
(with-selected-frame frame
(run-with-timer 0.1 nil #'doom|init-ui))))
;; register UI init hooks
(add-hook 'doom-init-hook #'doom|init-ui)
(add-hook! 'after-make-frame-functions #'(doom|init-ui doom|reload-ui-in-daemon))
;; ;;
;; Bootstrap ;; Bootstrap
;; ;;
;; prompts the user for confirmation when deleting a non-empty frame
;; Prompts the user for confirmation when deleting a non-empty frame
(define-key global-map [remap delete-frame] #'doom/delete-frame) (define-key global-map [remap delete-frame] #'doom/delete-frame)
;; buffer name in frame title
(global-eldoc-mode -1) ; auto-enabled in Emacs 25+; I'll do it myself (setq-default frame-title-format '("DOOM Emacs"))
(blink-cursor-mode +1) ; a good indicator that Emacs isn't frozen ;; auto-enabled in Emacs 25+; I'll do it myself
(global-eldoc-mode -1)
;; a good indicator that Emacs isn't frozen
(add-hook 'doom-post-init-hook #'blink-cursor-mode)
;; standardize default fringe width
(fringe-mode doom-fringe-size)
;; draw me like one of your French editors ;; draw me like one of your French editors
(tooltip-mode -1) ; relegate tooltips to echo area only (tooltip-mode -1) ; relegate tooltips to echo area only
(menu-bar-mode -1) (menu-bar-mode -1)
(if (fboundp 'tool-bar-mode) (tool-bar-mode -1)) (if (fboundp 'tool-bar-mode) (tool-bar-mode -1))
(if (fboundp 'scroll-bar-mode) (scroll-bar-mode -1)) (if (fboundp 'scroll-bar-mode) (scroll-bar-mode -1))
;; buffer name in frame title
(setq-default frame-title-format '("DOOM Emacs"))
;; standardize fringe width
(push (cons 'left-fringe doom-ui-fringe-size) default-frame-alist)
(push (cons 'right-fringe doom-ui-fringe-size) default-frame-alist)
;; no fringe in the minibuffer
(defun doom|no-fringes-in-minibuffer () (defun doom|no-fringes-in-minibuffer ()
"Disable fringes in the minibuffer window."
(set-window-fringes (minibuffer-window) 0 0 nil)) (set-window-fringes (minibuffer-window) 0 0 nil))
(add-hook! '(doom-init-hook minibuffer-setup-hook) (add-hook! '(doom-post-init-hook minibuffer-setup-hook)
#'doom|no-fringes-in-minibuffer) #'doom|no-fringes-in-minibuffer)
@ -182,7 +253,7 @@ mode is detected.")
:commands (fringe-helper-define fringe-helper-convert) :commands (fringe-helper-define fringe-helper-convert)
:init :init
(unless (fboundp 'define-fringe-bitmap) (unless (fboundp 'define-fringe-bitmap)
(fset 'define-fringe-bitmap (lambda (&rest _))))) (defun define-fringe-bitmap (&rest _))))
(def-package! hideshow ; built-in (def-package! hideshow ; built-in
:commands (hs-minor-mode hs-toggle-hiding hs-already-hidden-p) :commands (hs-minor-mode hs-toggle-hiding hs-already-hidden-p)
@ -198,8 +269,7 @@ mode is detected.")
;; Line highlighting ;; Line highlighting
(def-package! hl-line ; built-in (def-package! hl-line ; built-in
:init :init (add-hook! (linum-mode nlinum-mode) #'hl-line-mode)
(add-hook! (linum-mode nlinum-mode) #'hl-line-mode)
:config :config
;; I don't need hl-line showing in other windows. This also offers a small ;; I don't need hl-line showing in other windows. This also offers a small
;; speed boost when buffer is displayed in multiple windows. ;; speed boost when buffer is displayed in multiple windows.
@ -222,12 +292,9 @@ mode is detected.")
;; plugin than the built-in `linum'. ;; plugin than the built-in `linum'.
(def-package! nlinum (def-package! nlinum
:commands nlinum-mode :commands nlinum-mode
:preface
(defvar doom-ui-nlinum-lpad 4)
(defvar doom-ui-nlinum-rpad 1)
(defvar doom-ui-nlinum-spacer ?\u2002)
:init :init
(defun doom|init-nlinum-mode () (defun doom|init-nlinum-mode ()
"Turn on `nlinum-mode', except in org-mode"
(unless (eq major-mode 'org-mode) (unless (eq major-mode 'org-mode)
(nlinum-mode +1))) (nlinum-mode +1)))
(add-hook! (prog-mode text-mode) #'doom|init-nlinum-mode) (add-hook! (prog-mode text-mode) #'doom|init-nlinum-mode)
@ -235,14 +302,14 @@ mode is detected.")
(setq nlinum-highlight-current-line t) (setq nlinum-highlight-current-line t)
(defun doom-nlinum-format-fn (line _width) (defun doom-nlinum-format-fn (line _width)
"A more customizable `nlinum-format-function'. See `doom-ui-nlinum-lpad', "A more customizable `nlinum-format-function'. See `doom-line-number-lpad',
`doom-ui-nlinum-rpad' and `doom-ui-nlinum-spacer'. Allows a fix for `doom-line-number-rpad' and `doom-line-number-pad-char'. Allows a fix for
`whitespace-mode' space-marks appearing inside the line number." `whitespace-mode' space-marks appearing inside the line number."
(let ((str (number-to-string line))) (let ((str (number-to-string line)))
(setq str (concat (make-string (max 0 (- doom-ui-nlinum-lpad (length str))) (setq str (concat (make-string (max 0 (- doom-line-number-lpad (length str)))
doom-ui-nlinum-spacer) doom-line-number-pad-char)
str str
(make-string doom-ui-nlinum-rpad doom-ui-nlinum-spacer))) (make-string doom-line-number-rpad doom-line-number-pad-char)))
(put-text-property 0 (length str) 'face (put-text-property 0 (length str) 'face
(if (and nlinum-highlight-current-line (if (and nlinum-highlight-current-line
(= line nlinum--current-line)) (= line nlinum--current-line))
@ -252,8 +319,8 @@ mode is detected.")
str)) str))
(setq nlinum-format-function #'doom-nlinum-format-fn) (setq nlinum-format-function #'doom-nlinum-format-fn)
;; Optimization: calculate line number column width beforehand
(defun doom|init-nlinum-width () (defun doom|init-nlinum-width ()
"Calculate line number column width beforehand (optimization)."
(setq nlinum--width (setq nlinum--width
(length (save-excursion (goto-char (point-max)) (length (save-excursion (goto-char (point-max))
(format-mode-line "%l"))))) (format-mode-line "%l")))))

View file

@ -14,7 +14,7 @@
+doom-font (font-spec :family "Fira Mono" :size 10) +doom-font (font-spec :family "Fira Mono" :size 10)
+doom-variable-pitch-font (font-spec :family "Fira Sans" :size 10) +doom-variable-pitch-font (font-spec :family "Fira Sans" :size 10)
+doom-unicode-font (font-spec :family "DejaVu Sans Mono" :size 10) +doom-unicode-font (font-spec :family "DejaVu Sans Mono" :size 10)
doom-ui-nlinum-lpad 3)) doom-line-number-lpad 3))
("halimede" ("halimede"
(setq +doom-modeline-height 27)) (setq +doom-modeline-height 27))
;; ("nereid") ;; ("nereid")

View file

@ -563,25 +563,33 @@ with `evil-ex-substitute', and/or 4. The number of active `iedit' regions."
(bar " %b ") (bar " %b ")
(media-info major-mode)) (media-info major-mode))
;;
(doom-set-modeline 'main t)
;; This scratch buffer is already created, and doesn't get a modeline. For the
;; love of Emacs, someone give the man a modeline!
(with-current-buffer "*scratch*"
(doom-set-modeline 'main))
;; ;;
;; Hooks ;; Hooks
;; ;;
(defun +doom-modeline|init ()
"Set the default modeline."
(doom-set-modeline 'main t)
;; This scratch buffer is already created and doesn't get a modeline. For the
;; love of Emacs, someone give the man a modeline!
(with-current-buffer "*scratch*"
(doom-set-modeline 'main)))
(defun +doom-modeline|set-special-modeline () (defun +doom-modeline|set-special-modeline ()
(doom-set-modeline 'special)) (doom-set-modeline 'special))
(defun +doom-modeline|set-media-modeline () (defun +doom-modeline|set-media-modeline ()
(doom-set-modeline 'media)) (doom-set-modeline 'media))
;;
;; Bootstrap
;;
(add-hook 'doom-init-ui-hook #'+doom-modeline|init)
(add-hook 'org-src-mode-hook #'+doom-modeline|set-special-modeline) (add-hook 'org-src-mode-hook #'+doom-modeline|set-special-modeline)
(add-hook 'image-mode-hook #'+doom-modeline|set-media-modeline) (add-hook 'image-mode-hook #'+doom-modeline|set-media-modeline)
(add-hook 'circe-mode-hook #'+doom-modeline|set-special-modeline) (add-hook 'circe-mode-hook #'+doom-modeline|set-special-modeline)

View file

@ -1,28 +0,0 @@
;;; ui/doom/autoload/doom.el -*- lexical-binding: t; -*-
;;;###autoload
(defun +doom/reset-theme ()
"Reset the color theme currently in use."
(interactive)
(let ((theme (or (car-safe custom-enabled-themes) +doom-theme)))
(when theme
(mapc #'disable-theme custom-enabled-themes))
(load "doom-themes-common.el" nil t)
(+doom|init)
(+doom|refresh-bright-buffers)))
;;;###autoload
(defun +doom|restore-bright-buffers (&rest _)
"Restore `doom-buffer-mode' in buffers when `persp-mode' loads a session."
(dolist (buf (persp-buffer-list))
(with-current-buffer buf
(+doom|buffer-mode-on))))
;;;###autoload
(defun +doom|refresh-bright-buffers ()
"Refresh `doom-buffer-mode', in case of graphical glitches."
(dolist (win (window-list))
(when (buffer-local-value 'doom-buffer-mode (window-buffer win))
(with-selected-window win
(doom-buffer-mode -1)
(doom-buffer-mode +1)))))

View file

@ -1,58 +1,15 @@
;;; ui/doom/config.el -*- lexical-binding: t; -*- ;;; ui/doom/config.el -*- lexical-binding: t; -*-
(defvar +doom-theme 'doom-one
"The color theme to use.")
(defvar +doom-font
(font-spec :family "Fira Mono" :size 12)
"The font currently in use.")
(defvar +doom-variable-pitch-font
(font-spec :family "Fira Sans" :size 12)
"The font currently in use.")
(defvar +doom-unicode-font
(font-spec :family "DejaVu Sans Mono" :size 12)
"Fallback font for unicode glyphs. Is ignored if :feature unicode is active.")
;; Getting themes to remain consistent across GUI Emacs, terminal Emacs and
;; daemon Emacs is hairy.
;;
;; + Running `+doom|init' directly sorts out the initial GUI frame.
;; + Attaching it to `after-make-frame-functions' sorts out daemon Emacs.
;; + Terminal Emacs is a bit of a wildcard.
(defun +doom|init (&optional frame)
"Set the theme and load the font, in that order."
(load-theme +doom-theme t)
(with-demoted-errors "FONT ERROR: %s"
(set-frame-font +doom-font nil (if frame (list frame) t))
;; Fallback to `doom-unicode-font' for Unicode characters
(unless (featurep! :ui unicode)
(when +doom-unicode-font
(set-fontset-font t 'unicode +doom-unicode-font frame)))
;; ...and for variable-pitch mode
(when +doom-variable-pitch-font
(set-face-attribute 'variable-pitch frame :font +doom-variable-pitch-font))))
(defun +doom|init-daemon (frame)
(when (or (daemonp) (not (display-graphic-p)))
(with-selected-frame frame
(run-with-timer 0 nil #'+doom|init))))
(add-hook 'after-make-frame-functions #'+doom|init)
(add-hook 'after-make-frame-functions #'+doom|init-daemon)
;; doom-one: gives Emacs a look inspired by Dark One in Atom.
;; <https://github.com/hlissner/emacs-doom-theme> ;; <https://github.com/hlissner/emacs-doom-theme>
(def-package! doom-themes (def-package! doom-themes
:demand t :demand t
:config :config
(+doom|init) (unless doom-theme
(setq doom-theme 'doom-one))
;; blink mode-line on errors ;; blink mode-line on errors
(add-hook 'doom-post-init-hook #'doom-themes-visual-bell-config) (add-hook 'doom-post-init-hook #'doom-themes-visual-bell-config)
;; Add file icons to doom-neotree ;; Add file icons to doom-neotree
(add-hook 'doom-post-init-hook #'doom-themes-neotree-config) (add-hook 'doom-post-init-hook #'doom-themes-neotree-config)
(setq doom-neotree-enable-variable-pitch t (setq doom-neotree-enable-variable-pitch t
@ -63,7 +20,7 @@
(defun +doom|neotree-fix-popup () (defun +doom|neotree-fix-popup ()
"Ensure the fringe settings are maintained on popup restore." "Ensure the fringe settings are maintained on popup restore."
(neo-global--when-window (neo-global--when-window
(doom--neotree-no-fringes))) (doom--neotree-no-fringes)))
(add-hook 'doom-popup-mode-hook #'+doom|neotree-fix-popup))) (add-hook 'doom-popup-mode-hook #'+doom|neotree-fix-popup)))
@ -79,6 +36,7 @@
(defun +doom|reset-solaire-mode (&rest _) (solaire-mode-reset)) (defun +doom|reset-solaire-mode (&rest _) (solaire-mode-reset))
(advice-add #'load-theme :after #'+doom|reset-solaire-mode) (advice-add #'load-theme :after #'+doom|reset-solaire-mode)
(add-hook 'doom-reload-hook #'solaire-mode-reset) (add-hook 'doom-reload-hook #'solaire-mode-reset)
(add-hook 'doom-init-ui-hook #'solaire-mode-reset)
;; Extra modes to activate doom-buffer-mode in ;; Extra modes to activate doom-buffer-mode in
(add-hook! (gist-mode (add-hook! (gist-mode
@ -113,7 +71,7 @@
ov 'display (propertize " [...] " 'face '+doom-folded-face)))))) ov 'display (propertize " [...] " 'face '+doom-folded-face))))))
;; NOTE Adjust these bitmaps if you change `doom-ui-fringe-size' ;; NOTE Adjust these bitmaps if you change `doom-fringe-size'
(after! flycheck (after! flycheck
;; because git-gutter is in the left fringe ;; because git-gutter is in the left fringe
(setq flycheck-indication-mode 'right-fringe) (setq flycheck-indication-mode 'right-fringe)

View file

@ -1,9 +1,10 @@
;;; ui/unicode/config.el -*- lexical-binding: t; -*- ;;; ui/unicode/config.el -*- lexical-binding: t; -*-
(setq-default bidi-display-reordering t)
(def-package! unicode-fonts (def-package! unicode-fonts
:demand t :demand t
:init
(setq-default bidi-display-reordering t
doom-unicode-font nil)
:config :config
;; NOTE will impact startup time on first run ;; NOTE will impact startup time on first run
(unicode-fonts-setup)) (unicode-fonts-setup))