aboutsummaryrefslogtreecommitdiff
path: root/modules/font-config.el
diff options
context:
space:
mode:
Diffstat (limited to 'modules/font-config.el')
-rw-r--r--modules/font-config.el137
1 files changed, 54 insertions, 83 deletions
diff --git a/modules/font-config.el b/modules/font-config.el
index 39d21364c..2be051ddc 100644
--- a/modules/font-config.el
+++ b/modules/font-config.el
@@ -1,4 +1,4 @@
-;;; font-config --- Font Defaults and Related Functionality -*- lexical-binding: t; coding: utf-8; -*-
+;;; font-config.el --- Font Defaults and Related Functionality -*- lexical-binding: t; coding: utf-8; -*-
;; author: Craig Jennings <c@cjennings.net>
;;; Commentary:
@@ -6,56 +6,26 @@
;; Layer: 2 (Core UX).
;; Category: C/P/S.
;; Load shape: eager.
-;; Eager reason: font setup for the first frame, plus font keybindings.
-;; Top-level side effects: binds five global font keys, runs font-installation
-;; checks, configures packages via use-package.
+;; Eager reason: first-frame font setup and font keybindings.
+;; Top-level side effects: font keys, font checks, package config.
;; Runtime requires: host-environment, keybindings.
;; Direct test load: yes.
;;
-;; This module provides font configuration, including:
-;;
-;; 1. Font Management:
-;; - Dynamic font preset switching via `fontaine' package
-;; - Separate configurations for fixed-pitch and variable-pitch fonts
-;; - Multiple size presets for different viewing contexts
-;; - Per-frame font configuration tracking for daemon mode compatibility
-;;
-;; 2. Icon Support:
-;; - All-the-icons integration with automatic font installation
-;; - Nerd fonts support for enhanced icons in terminals and GUI
-;; - Platform-specific emoji font configuration (Noto, Apple, Segoe)
-;; - Emojify package for emoji rendering and insertion
-;;
-;; 3. Typography Enhancements:
-;; - Programming ligatures via `ligature' package
-;; - Mode-specific ligature rules for markdown and programming
-;; - Text scaling keybindings for quick size adjustments
-;;
-;; 4. Utility Functions:
-;; - `cj/font-installed-p': Check font availability
-;; - `cj/display-available-fonts': Interactive font browser with samples
-;; - Frame-aware font application for client/server setups
-;;
-;; Configuration Notes:
-;; - Default preset: BerkeleyMono Nerd Font; height 120 on laptops, 140 on desktops
-;; - Variable pitch: Lexend in the default preset; Merriweather for fallback presets
-;; - Handles both standalone and daemon mode Emacs instances
-;; - Emoji fonts selected based on OS availability
-;;
-;; Keybindings:
-;; - M-S-f: Select font preset (fontaine-set-preset)
-;; - C-z F: Display available fonts
-;; - C-+/C-=: Increase text scale
-;; - C--/C-_: Decrease text scale
-;; - C-c E i: Insert emoji
-;; - C-c E l: List emojis
-;;
+;; Configures fontaine presets, text scaling keys, icon/emoji fonts, and
+;; programming ligatures. Presets are applied per frame so daemon clients get
+;; the intended fixed/variable pitch sizes.
;;
+;; Also carries font-rendering safeguards for known HarfBuzz/font-cache crashes
+;; triggered by emoji and Arabic shaping in this setup.
+
;;; Code:
(require 'host-environment)
(require 'keybindings) ;; establishes the C-z prefix used for "C-z F" below
+(defvar text-scale-mode-step)
+(declare-function cj/disable-emojify-mode "font-config")
+
;; ---------------------- HarfBuzz Font Cache Crash Fix -----------------------
;; Prevents Emacs from compacting font caches during GC. Without this, GC can
;; free font cache entries that HarfBuzz still references, causing SIGSEGV
@@ -93,7 +63,7 @@
(default
:default-family "BerkeleyMono Nerd Font"
:default-weight regular
- :default-height ,(if (env-laptop-p) 120 140)
+ :default-height ,(if (env-laptop-p) 130 140)
:fixed-pitch-family nil ;; falls back to :default-family
:fixed-pitch-weight nil ;; falls back to :default-weight
:fixed-pitch-height 1.0
@@ -153,36 +123,38 @@
:italic-slant italic
:line-spacing nil))))
-(with-eval-after-load 'fontaine
- ;; Track which frames have had fonts applied
- (defvar cj/fontaine-configured-frames nil
- "List of frames that have had fontaine configuration applied.")
+;; Track which frames have had fonts applied
+(defvar cj/fontaine-configured-frames nil
+ "List of frames that have had fontaine configuration applied.")
- (defun cj/apply-font-settings-to-frame (&optional frame)
- "Apply font settings to FRAME if not already configured.
+(declare-function fontaine-set-preset "fontaine")
+
+(defun cj/apply-font-settings-to-frame (&optional frame)
+ "Apply font settings to FRAME if not already configured.
If FRAME is nil, uses the selected frame."
- (let ((target-frame (or frame (selected-frame))))
- (unless (member target-frame cj/fontaine-configured-frames)
- (with-selected-frame target-frame
- (when (env-gui-p)
- (fontaine-set-preset 'default)
- (push target-frame cj/fontaine-configured-frames))))))
-
- (defun cj/cleanup-frame-list (frame)
- "Remove FRAME from the configured frames list when deleted."
- (setq cj/fontaine-configured-frames
- (delq frame cj/fontaine-configured-frames)))
+ (let ((target-frame (or frame (selected-frame))))
+ (unless (member target-frame cj/fontaine-configured-frames)
+ (with-selected-frame target-frame
+ (when (env-gui-p)
+ (fontaine-set-preset 'default)
+ (push target-frame cj/fontaine-configured-frames))))))
+
+(defun cj/cleanup-frame-list (frame)
+ "Remove FRAME from the configured frames list when deleted."
+ (setq cj/fontaine-configured-frames
+ (delq frame cj/fontaine-configured-frames)))
+(with-eval-after-load 'fontaine
;; Handle daemon mode and regular mode
(if (daemonp)
- (progn
- ;; Apply to each new frame in daemon mode
- (add-hook 'server-after-make-frame-hook #'cj/apply-font-settings-to-frame)
- ;; Clean up deleted frames from tracking list
- (add-hook 'delete-frame-functions #'cj/cleanup-frame-list))
- ;; Apply immediately in non-daemon mode
- (when (env-gui-p)
- (cj/apply-font-settings-to-frame))))
+ (progn
+ ;; Apply to each new frame in daemon mode
+ (add-hook 'server-after-make-frame-hook #'cj/apply-font-settings-to-frame)
+ ;; Clean up deleted frames from tracking list
+ (add-hook 'delete-frame-functions #'cj/cleanup-frame-list))
+ ;; Apply immediately in non-daemon mode
+ (when (env-gui-p)
+ (cj/apply-font-settings-to-frame))))
;; ----------------------------- Font Install Check ----------------------------
;; convenience function to indicate whether a font is available by name.
@@ -196,22 +168,23 @@ If FRAME is nil, uses the selected frame."
;; ------------------------------- All The Icons -------------------------------
;; icons made available through fonts
+(declare-function all-the-icons-install-fonts "all-the-icons")
+
+(defun cj/maybe-install-all-the-icons-fonts (&optional _frame)
+ "Install all-the-icons fonts if needed and we have a GUI."
+ (when (and (env-gui-p)
+ (not (cj/font-installed-p "all-the-icons")))
+ (all-the-icons-install-fonts t)
+ ;; Remove this hook after successful installation
+ (remove-hook 'server-after-make-frame-hook #'cj/maybe-install-all-the-icons-fonts)))
+
(use-package all-the-icons
:demand t
:config
- ;; Check for font installation after frame creation
- (defun cj/maybe-install-all-the-icons-fonts (&optional _frame)
- "Install all-the-icons fonts if needed and we have a GUI."
- (when (and (env-gui-p)
- (not (cj/font-installed-p "all-the-icons")))
- (all-the-icons-install-fonts t)
- ;; Remove this hook after successful installation
- (remove-hook 'server-after-make-frame-hook #'cj/maybe-install-all-the-icons-fonts)))
-
;; Handle both daemon and non-daemon modes
(if (daemonp)
- (add-hook 'server-after-make-frame-hook #'cj/maybe-install-all-the-icons-fonts)
- (cj/maybe-install-all-the-icons-fonts)))
+ (add-hook 'server-after-make-frame-hook #'cj/maybe-install-all-the-icons-fonts)
+ (cj/maybe-install-all-the-icons-fonts)))
(use-package all-the-icons-nerd-fonts
:after all-the-icons
@@ -220,7 +193,6 @@ If FRAME is nil, uses the selected frame."
(all-the-icons-nerd-fonts-prefer))
;; ----------------------------- Emoji Fonts Per OS ----------------------------
-;; Set emoji fonts in priority order (first found wins)
(defun cj/setup-emoji-fontset (&optional _frame)
"Set emoji fonts in priority order (first found wins).
@@ -262,13 +234,12 @@ the fontset repeatedly is harmless, so it can be called from
(setq emojify-display-style (if (env-gui-p) 'image 'unicode))
(setq emojify-emoji-styles '(ascii unicode github))
- ;; Disable emojify in programming and gptel modes
+ ;; Disable emojify in programming modes
(defun cj/disable-emojify-mode ()
"Disable emojify-mode in the current buffer."
(emojify-mode -1))
- (add-hook 'prog-mode-hook #'cj/disable-emojify-mode)
- (add-hook 'gptel-mode-hook #'cj/disable-emojify-mode))
+ (add-hook 'prog-mode-hook #'cj/disable-emojify-mode))
;; -------------------------- Display Available Fonts --------------------------
;; display all available fonts on the system in a side panel