From a60d8b3da4324170e3bdcb7e73a5e35e0d828a4f Mon Sep 17 00:00:00 2001 From: Gerry Agbobada Date: Sun, 17 Sep 2023 09:59:09 +0200 Subject: [PATCH] fix(ligatures): proper resetting of font-ligatures resetting font-ligatures means passing `nil` as the second argument of `(set-font-ligatures!)` Using `ligatures-ignored-major-modes` to cancel ligatures is too brittle, because "resetting ligatures for `prog-mode`" would have bad semantics with all its derived modes. The user probably just wants to remove the default ligatures and then configure `foo-mode`, but pushing `prog-mode` to `ignored-major-modes` might just disable ligatures across all modes _derived from_ `prog-mode`. This commit changes things in 2 ways: - resetting ligatures now directly manipulates ligature.el internal state (the `ligature-composition-table` alist) - in order to work, Doom must maintain an extra invariant on that alist, multi-modes keys (`'(foo-mode bar-mode)`), cannot be used, only single modes. That mostly means that users should _not_ use `ligature-set-ligatures` themselves in private config, but instead always rely on `set-font-ligatures!` which does splicing behind curtains. Failing to do so would be mostly harmless though (it would just make "resetting ligatures" only partially remove set ligatures). Fix: #7433 --- modules/ui/ligatures/autoload/ligatures.el | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/modules/ui/ligatures/autoload/ligatures.el b/modules/ui/ligatures/autoload/ligatures.el index 25d71dfb8..b44cc9599 100644 --- a/modules/ui/ligatures/autoload/ligatures.el +++ b/modules/ui/ligatures/autoload/ligatures.el @@ -67,10 +67,15 @@ Font ligatures can be unset for emacs-lisp-mode with: Note that this will keep all ligatures in `+ligatures-prog-mode-list' active, as `emacs-lisp-mode' is derived from `prog-mode'." (declare (indent defun)) + ;; NOTE: Doom enforces `ligature-composition-table' to have a single mode per key in the alist. + ;; This is less efficient than what ligature.el can do (i.e. use a list of modes, or `t' as a key), + ;; but holding this invariant allows resetting with `(set-font-ligatures! 'mode nil)` to work reliably. (if (null ligatures) (dolist (mode (ensure-list modes)) - (add-to-list 'ligature-ignored-major-modes mode)) + (delq! mode ligature-composition-table 'assq)) (after! ligature (dolist (mode (ensure-list modes)) - (setq ligature-ignored-major-modes (delq mode ligature-ignored-major-modes))) - (ligature-set-ligatures (ensure-list modes) ligatures)))) + (setq ligature-ignored-major-modes (delq mode ligature-ignored-major-modes)) + (ligature-set-ligatures mode ligatures))))) + +