emacs-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

face-attribute and face-remapping-alist


From: address@hidden
Subject: face-attribute and face-remapping-alist
Date: Tue, 30 Mar 2021 18:53:28 +0000

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 via email to

[Prev in Thread] Current Thread [Next in Thread]