From ebcde0f90f67852d485a36941b0661cfd1b892eb Mon Sep 17 00:00:00 2001 From: Michael Shields Date: Sat, 19 Apr 2025 12:58:26 -0700 Subject: [PATCH] Fix use-package :custom-face to set face-defface-spec (bug#77928) By default, `face-set-spec' sets the override face spec, so face attributes are combined with defaults rather than replacing them. This was a behavior change that was an apparently unintended consequence of commit 6b344a9. Also set the `face-modified' property, which causes Customize to flag the face as changed outside Customize. * doc/misc/use-package.texi (Faces): Document the behavior. * lisp/use-package/use-package-core.el (use-package-handler/:custom-face): (use-package): Improve docstring to reflect implementation. * test/lisp/use-package/use-package-tests.el (use-package-test/:custom-face-1): (use-package-test/:custom-face-2): (use-package-test/:custom-face-3): (use-package-test/:custom-face-4): Add tests. --- doc/misc/use-package.texi | 7 +++- lisp/use-package/use-package-core.el | 8 +++-- test/lisp/use-package/use-package-tests.el | 40 ++++++++++++++++++---- 3 files changed, 46 insertions(+), 9 deletions(-) diff --git a/doc/misc/use-package.texi b/doc/misc/use-package.texi index c8630cee1c9..2f980df9f45 100644 --- a/doc/misc/use-package.texi +++ b/doc/misc/use-package.texi @@ -1471,7 +1471,7 @@ faces. Example: (use-package example :custom-face (example-1-face ((t (:foreground "LightPink")))) - (example-2-face ((t (:foreground "LightGreen"))) face-defspec-spec)) + (example-2-face ((t (:foreground "LightGreen"))))) @end group @group @@ -1486,6 +1486,11 @@ faces. Example: @end group @end lisp +Similarly to @code{:custom} (@pxref{User options}), this allows +configuring customizable faces outside of Customize (@pxref{Saving +Customizations,,, emacs, GNU Emacs Manual}). Using both systems to +configure the same face can lead to confusing results. + @node Hiding minor modes @section Hiding minor modes with diminish and delight @cindex hiding minor modes diff --git a/lisp/use-package/use-package-core.el b/lisp/use-package/use-package-core.el index 630ee83601c..65b9485b4e3 100644 --- a/lisp/use-package/use-package-core.el +++ b/lisp/use-package/use-package-core.el @@ -1623,7 +1623,11 @@ no keyword implies `:all'." (defun use-package-handler/:custom-face (name _keyword args rest state) "Generate use-package custom-face keyword code." (use-package-concat - (mapcar #'(lambda (def) `(apply #'face-spec-set (backquote ,def))) args) + (mapcar #'(lambda (def) + `(progn + (apply #'face-spec-set (append (backquote ,def) '(face-defface-spec))) + (put ',(car def) 'face-modified t))) + args) (use-package-process-keywords name rest state))) ;;;; :init @@ -1887,7 +1891,7 @@ Usage: :custom Call `Custom-set' or `set-default' with each variable definition without modifying the Emacs `custom-file'. (compare with `custom-set-variables'). -:custom-face Call `custom-set-faces' with each face definition. +:custom-face Call `face-spec-set' with each face definition. :ensure Loads the package using package.el if necessary. :pin Pin the package to an archive. :vc Install the package directly from a version control system diff --git a/test/lisp/use-package/use-package-tests.el b/test/lisp/use-package/use-package-tests.el index 8554b37d5b8..b221c5de5c1 100644 --- a/test/lisp/use-package/use-package-tests.el +++ b/test/lisp/use-package/use-package-tests.el @@ -1153,7 +1153,12 @@ (match-expansion (use-package foo :custom-face (foo ((t (:background "#e4edfc"))))) `(progn - (apply #'face-spec-set (backquote (foo ((t (:background "#e4edfc")))))) + (progn + (apply #'face-spec-set + (append (backquote (foo ((t (:background "#e4edfc"))))) + '(face-defface-spec)) + ) + (put 'foo 'face-modified t)) (require 'foo nil nil)))) (ert-deftest use-package-test/:custom-face-2 () @@ -1163,19 +1168,42 @@ (example-1-face ((t (:foreground "LightPink")))) (example-2-face ((t (:foreground "LightGreen"))))) `(progn - (apply #'face-spec-set - (backquote (example-1-face ((t (:foreground "LightPink")))))) - (apply #'face-spec-set - (backquote (example-2-face ((t (:foreground "LightGreen")))))) + (progn + (apply #'face-spec-set + (append (backquote (example-1-face ((t (:foreground "LightPink"))))) + '(face-defface-spec))) + (put 'example-1-face 'face-modified t)) + (progn + (apply #'face-spec-set + (append (backquote (example-2-face ((t (:foreground "LightGreen"))))) + '(face-defface-spec))) + (put 'example-2-face 'face-modified t)) (require 'example nil nil)))) (ert-deftest use-package-test/:custom-face-3 () (match-expansion (use-package foo :custom-face (foo ((t (:background "#e4edfc"))) face-defspec-spec)) `(progn - (apply #'face-spec-set (backquote (foo ((t (:background "#e4edfc"))) face-defspec-spec))) + (progn + (apply #'face-spec-set + (append (backquote (foo ((t (:background "#e4edfc"))) face-defspec-spec)) + '(face-defface-spec))) + (put 'foo 'face-modified t)) (require 'foo nil nil)))) +(ert-deftest use-package-test/:custom-face-4 () + (defface use-package-test/base-face '((t (:background "green"))) "") + (defface use-package-test/face '((t (:inherit use-package-test/base-face))) "") + (use-package emacs + :custom-face + (use-package-test/face ((t (:foreground "blue"))))) + (should (equal (face-foreground 'use-package-test/face nil t) + "blue")) + (should (equal (face-background 'use-package-test/face nil t) + nil)) + (should (equal (get 'use-package-test/face 'face-modified) + t))) + (ert-deftest use-package-test/:init-1 () (match-expansion (use-package foo :init (init))