unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
From: "gliao.tw@pm.me" <gliao.tw@pm.me>
To: "emacs-devel@gnu.org" <emacs-devel@gnu.org>
Subject: face-attribute and face-remapping-alist
Date: Tue, 30 Mar 2021 18:53:28 +0000	[thread overview]
Message-ID: <EwbVM_pbf-MZVIrsnzMaJga8Jw9ZBHk4407RMezVzCzUSvML33SPOR7kEW1fTJU6MUvMW7saMCmRwGKAiNUEciI7sxWrtZoZdUwtzXEB60M=@pm.me> (raw)

The `face-attribute' function defined in `faces.el' is the foundation of many face property inquiry functions such as `face-background'. However, `face-attribute' is not aware of buffer-local variable 'face-remapping-alist' which is used for buffer-specific theming.

Since there are many modes, such as `term-mode', rely on `face-attribute' to obtain face information while `face-attribute' is only capabale of obtaining frame-specific, rather than buffer-specific face infomation, these modes cannot display faces sufficiently well while a buffer-local theme is applied via `face-remap-add-relative' or `face-remap-set-base' (both functions, defined in `face-remap.el', add items to buffer-specific variable `face-remapping-alist').

Therefore, I propose the following prototype of an enhanced version of `face-attribute' function that is aware of the existence of `face-remapping-alist' in current buffer and return face property from `face-remapping-alist' instead of  frame-specific (single frame also means global) face property.

Any comments are greatly appreciated, thanks.

Kiong-Gē.

---------------------------


;;
(defun face-attribute (face attribute &optional frame inherit)
  "Return the value of FACE's ATTRIBUTE on FRAME or current buffer.
If the optional argument FRAME is given, report on face FACE in that frame.
If FRAME is t, report on the defaults for face FACE (for new frames).
If FRAME is omitted or nil, use the selected frame.

If INHERIT is nil, only attributes directly defined by FACE are considered,
  so the return value may be `unspecified', or a relative value.
If INHERIT is non-nil, FACE's definition of ATTRIBUTE is merged with the
  faces specified by its `:inherit' attribute; however the return value
  may still be `unspecified' or relative.
If INHERIT is a face or a list of faces, then the result is further merged
  with that face (or faces), until it becomes specified and absolute.

To ensure that the return value is always specified and absolute, use a
value of `default' for INHERIT; this will resolve any unspecified or
relative values by merging with the `default' face (which is always
completely specified)."
  ;; check if `face-remapping-alist' exist as a buffer-local variable
  ;; in current buffer
  (let* ((local-faces (if (local-variable-p 'face-remapping-alist
					    (current-buffer))
			  ;; if so, take faces information from it
			  (buffer-local-value 'face-remapping-alist
					      (current-buffer))))
	 ;; try to fetch buffer-local face proprety from face-remapping-alist
	 (local-face-prop (if local-faces
			      (plist-get (car (alist-get face local-faces))
					 attribute))))
    ;; if there is no inquired face informatio available in
    ;; face-remapping-alist, fallback to frame-specific values
    (or local-face-prop
	(let ((value (internal-get-lisp-face-attribute face attribute frame)))
	  (when (and inherit (face-attribute-relative-p attribute value))
	    ;; VALUE is relative, so merge with inherited faces
	    (let ((inh-from (face-attribute face :inherit frame)))
	      (unless (or (null inh-from) (eq inh-from 'unspecified))
		(condition-case nil
		    (setq value
			  (face-attribute-merged-with attribute value inh-from frame))
		  ;; The `inherit' attribute may point to non existent faces.
		  (error nil)))))
	  (when (and inherit
		     (not (eq inherit t))
		     (face-attribute-relative-p attribute value))
	    ;; We should merge with INHERIT as well
	    (setq value (face-attribute-merged-with attribute value inherit frame)))
	  value))))


----------------------------------------







             reply	other threads:[~2021-03-30 18:53 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-03-30 18:53 gliao.tw [this message]
2021-03-30 19:05 ` face-attribute and face-remapping-alist Eli Zaretskii
2021-03-30 19:13   ` Eli Zaretskii
2021-03-31  3:05     ` gliao.tw
2021-03-31  3:34       ` gliao.tw
2021-03-31  6:58       ` Eli Zaretskii
2021-03-31 13:00         ` Clément Pit-Claudel
2021-03-31 13:27           ` Eli Zaretskii
2021-03-31 22:41         ` gliao.tw
2021-04-01  7:08           ` Eli Zaretskii

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.gnu.org/software/emacs/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to='EwbVM_pbf-MZVIrsnzMaJga8Jw9ZBHk4407RMezVzCzUSvML33SPOR7kEW1fTJU6MUvMW7saMCmRwGKAiNUEciI7sxWrtZoZdUwtzXEB60M=@pm.me' \
    --to=gliao.tw@pm.me \
    --cc=emacs-devel@gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).