From ecd8ad0f46643e946f8ca2b0b3a04765fcfb2193 Mon Sep 17 00:00:00 2001 From: Henrik Lissner Date: Wed, 28 Jun 2017 16:18:22 +0200 Subject: [PATCH] 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 --- core/autoload/ui.el | 9 ++ core/core-popups.el | 2 +- core/core-ui.el | 149 +++++++++++++++++++++-------- modules/private/hlissner/init.el | 2 +- modules/ui/doom-modeline/config.el | 28 ++++-- modules/ui/doom/autoload/doom.el | 28 ------ modules/ui/doom/config.el | 56 ++--------- modules/ui/unicode/config.el | 5 +- 8 files changed, 147 insertions(+), 132 deletions(-) delete mode 100644 modules/ui/doom/autoload/doom.el diff --git a/core/autoload/ui.el b/core/autoload/ui.el index 222e80dab..5d02978f7 100644 --- a/core/autoload/ui.el +++ b/core/autoload/ui.el @@ -59,3 +59,12 @@ window changes before then, the undo expires." (when (doom-quit-p "Close frame?") (delete-frame)) (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))) diff --git a/core/core-popups.el b/core/core-popups.el index 02cdc0396..f3c6cb855 100644 --- a/core/core-popups.el +++ b/core/core-popups.el @@ -164,7 +164,7 @@ for :align t on every rule." (t (when doom-popup-no-fringes (set-window-fringes window - doom-ui-fringe-size doom-ui-fringe-size + doom-fringe-size doom-fringe-size fringes-outside-margins)) ;; Ensure window parameters are cleaned up (set-window-parameter window 'popup nil) diff --git a/core/core-ui.el b/core/core-ui.el index 69919c1f3..11c290628 100644 --- a/core/core-ui.el +++ b/core/core-ui.el @@ -1,6 +1,44 @@ ;;; 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 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 (defun doom-quit-p (&optional prompt) - "Return t if this session should be killed, but not before it prompts the user -for confirmation." + "Return t if this session should be killed. Prompts the user for +confirmation." (interactive) (if (ignore-errors (doom-real-buffer-list)) (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, ;; `window-divider' does not. Available since Emacs 25.1. (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) (add-hook 'doom-init-hook #'window-divider-mode) ;; 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 () - "Set the major mode's `mode-name', as dictated by `doom-ui-mode-names'." - (let ((name (assq major-mode doom-ui-mode-names))) - (if name (setq mode-name (cdr name))))) + "Set the major mode's `mode-name', as dictated by `doom-major-mode-names'." + (when-let (name (cdr (assq major-mode doom-major-mode-names))) + (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) +;; +;; 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 ;; - -;; 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) - -(global-eldoc-mode -1) ; auto-enabled in Emacs 25+; I'll do it myself -(blink-cursor-mode +1) ; a good indicator that Emacs isn't frozen - +;; buffer name in frame title +(setq-default frame-title-format '("DOOM Emacs")) +;; 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 (tooltip-mode -1) ; relegate tooltips to echo area only (menu-bar-mode -1) (if (fboundp 'tool-bar-mode) (tool-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 () + "Disable fringes in the minibuffer window." (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) @@ -182,7 +253,7 @@ mode is detected.") :commands (fringe-helper-define fringe-helper-convert) :init (unless (fboundp 'define-fringe-bitmap) - (fset 'define-fringe-bitmap (lambda (&rest _))))) + (defun define-fringe-bitmap (&rest _)))) (def-package! hideshow ; built-in :commands (hs-minor-mode hs-toggle-hiding hs-already-hidden-p) @@ -198,8 +269,7 @@ mode is detected.") ;; Line highlighting (def-package! hl-line ; built-in - :init - (add-hook! (linum-mode nlinum-mode) #'hl-line-mode) + :init (add-hook! (linum-mode nlinum-mode) #'hl-line-mode) :config ;; I don't need hl-line showing in other windows. This also offers a small ;; speed boost when buffer is displayed in multiple windows. @@ -222,12 +292,9 @@ mode is detected.") ;; plugin than the built-in `linum'. (def-package! nlinum :commands nlinum-mode - :preface - (defvar doom-ui-nlinum-lpad 4) - (defvar doom-ui-nlinum-rpad 1) - (defvar doom-ui-nlinum-spacer ?\u2002) :init (defun doom|init-nlinum-mode () + "Turn on `nlinum-mode', except in org-mode" (unless (eq major-mode 'org-mode) (nlinum-mode +1))) (add-hook! (prog-mode text-mode) #'doom|init-nlinum-mode) @@ -235,14 +302,14 @@ mode is detected.") (setq nlinum-highlight-current-line t) (defun doom-nlinum-format-fn (line _width) - "A more customizable `nlinum-format-function'. See `doom-ui-nlinum-lpad', -`doom-ui-nlinum-rpad' and `doom-ui-nlinum-spacer'. Allows a fix for + "A more customizable `nlinum-format-function'. See `doom-line-number-lpad', +`doom-line-number-rpad' and `doom-line-number-pad-char'. Allows a fix for `whitespace-mode' space-marks appearing inside the line number." (let ((str (number-to-string line))) - (setq str (concat (make-string (max 0 (- doom-ui-nlinum-lpad (length str))) - doom-ui-nlinum-spacer) + (setq str (concat (make-string (max 0 (- doom-line-number-lpad (length str))) + doom-line-number-pad-char) 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 (if (and nlinum-highlight-current-line (= line nlinum--current-line)) @@ -252,8 +319,8 @@ mode is detected.") str)) (setq nlinum-format-function #'doom-nlinum-format-fn) - ;; Optimization: calculate line number column width beforehand (defun doom|init-nlinum-width () + "Calculate line number column width beforehand (optimization)." (setq nlinum--width (length (save-excursion (goto-char (point-max)) (format-mode-line "%l"))))) diff --git a/modules/private/hlissner/init.el b/modules/private/hlissner/init.el index 9bba487c9..9048608ca 100644 --- a/modules/private/hlissner/init.el +++ b/modules/private/hlissner/init.el @@ -14,7 +14,7 @@ +doom-font (font-spec :family "Fira Mono" :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-ui-nlinum-lpad 3)) + doom-line-number-lpad 3)) ("halimede" (setq +doom-modeline-height 27)) ;; ("nereid") diff --git a/modules/ui/doom-modeline/config.el b/modules/ui/doom-modeline/config.el index 681e158a1..de0cb1bf5 100644 --- a/modules/ui/doom-modeline/config.el +++ b/modules/ui/doom-modeline/config.el @@ -563,25 +563,33 @@ with `evil-ex-substitute', and/or 4. The number of active `iedit' regions." (bar " %b ") (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 ;; +(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 () (doom-set-modeline 'special)) (defun +doom-modeline|set-media-modeline () (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 'image-mode-hook #'+doom-modeline|set-media-modeline) -(add-hook 'circe-mode-hook #'+doom-modeline|set-special-modeline) +(add-hook 'image-mode-hook #'+doom-modeline|set-media-modeline) +(add-hook 'circe-mode-hook #'+doom-modeline|set-special-modeline) diff --git a/modules/ui/doom/autoload/doom.el b/modules/ui/doom/autoload/doom.el deleted file mode 100644 index 5cefe3ab4..000000000 --- a/modules/ui/doom/autoload/doom.el +++ /dev/null @@ -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))))) diff --git a/modules/ui/doom/config.el b/modules/ui/doom/config.el index 6e56ae5d0..c1f571bf6 100644 --- a/modules/ui/doom/config.el +++ b/modules/ui/doom/config.el @@ -1,58 +1,15 @@ ;;; 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. ;; (def-package! doom-themes :demand t :config - (+doom|init) + (unless doom-theme + (setq doom-theme 'doom-one)) + ;; blink mode-line on errors (add-hook 'doom-post-init-hook #'doom-themes-visual-bell-config) + ;; Add file icons to doom-neotree (add-hook 'doom-post-init-hook #'doom-themes-neotree-config) (setq doom-neotree-enable-variable-pitch t @@ -63,7 +20,7 @@ (defun +doom|neotree-fix-popup () "Ensure the fringe settings are maintained on popup restore." (neo-global--when-window - (doom--neotree-no-fringes))) + (doom--neotree-no-fringes))) (add-hook 'doom-popup-mode-hook #'+doom|neotree-fix-popup))) @@ -79,6 +36,7 @@ (defun +doom|reset-solaire-mode (&rest _) (solaire-mode-reset)) (advice-add #'load-theme :after #'+doom|reset-solaire-mode) (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 (add-hook! (gist-mode @@ -113,7 +71,7 @@ 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 ;; because git-gutter is in the left fringe (setq flycheck-indication-mode 'right-fringe) diff --git a/modules/ui/unicode/config.el b/modules/ui/unicode/config.el index a9b0e14db..bf9704c64 100644 --- a/modules/ui/unicode/config.el +++ b/modules/ui/unicode/config.el @@ -1,9 +1,10 @@ ;;; ui/unicode/config.el -*- lexical-binding: t; -*- -(setq-default bidi-display-reordering t) - (def-package! unicode-fonts :demand t + :init + (setq-default bidi-display-reordering t + doom-unicode-font nil) :config ;; NOTE will impact startup time on first run (unicode-fonts-setup))