For better experience color-identifiers-mode recommends turning off colors for everything. The example in README does it by setting :foreground of faces to nil, which kinda works.

However doing it globally is unwanted for unsupported modes, e.g. for Markdown. So faces have to be set locally, which is the problem: setting :foreground to nil triggers an error:

(face-remap-add-relative 'font-lock-keyword-face '((:foreground nil)))
[*Messages* buffer ↓]
Invalid face attribute :foreground nil
Invalid face reference: font-lock-keyword-face

Setting to 'unspecified triggers:

(face-remap-add-relative 'font-lock-keyword-face '((:foreground 'unspecified)))
[*Messages* buffer ↓]
Invalid face attribute :foreground (quote unspecified)
Invalid face reference: font-lock-keyword-face

Using unspecified without ' changes nothing.

And, finally, using an empty string does work, but triggers a warning:

(face-remap-add-relative 'font-lock-keyword-face '((:foreground "")))
[*Messages* buffer ↓]
Unable to load color ""

I personally could settle down with an empty string, but I'm going to change the README recommendation about setting faces, and triggering warnings for users not a good user experience.

So, what is the correct way of unsetting the :foreground color?

  • 1
    I have been admonished by experienced Emacs users that the manual recommends using face-remap-add-relative, so that is what I have tried to use in some of my on-line answers. However, in my own setup I set the face-remapping-alist directly as either global with setq-default or local with setq-local. It is something you may wish to consider, even though people will tell that the manual recommends using face-remap-add-relative. I change my modeline background this way, and also the faces in the minibuffer depending upon whether my cursor is in the minibuffer when open or elsewhere.
    – lawlist
    Sep 8 '17 at 0:15
  • 1
    @lawlist ok, given nobody answered, I decided to give it a try. If I understand correctly, you were meaning that manually setting :foreground to nil should work. Unfortunately it doesn't. Minimal steps are: 1) split Emacs window to buffers *Messages* and a C++ with a function declaration 2) in C++ buffer execute M-: (add-to-list 'face-remapping-alist (cons 'font-lock-function-name-face '((:foreground nil)))). 3) move around a little, and see how *Messages* got spammed with errors.
    – Hi-Angel
    Sep 18 '17 at 20:48

nil is not a valid attribute value for :foreground, which can be a string or unspecified*, see (elisp) Face Attributes:

   Apart from the values given below, each face attribute can have the
value `unspecified'. [...]

     Foreground color, a string.  The value can be a system-defined
     color name, or a hexadecimal color specification.  *Note Color
     Names::.  On black-and-white displays, certain shades of gray are
     implemented by stipple p9atterns.

I think the only options are to inherit from the default face (which overrides also non-colour attributes), or set the foreground to the default's face current one (which means it won't update if you change the default face colour):

(face-remap-add-relative 'font-lock-keyword-face '(:inherit default))
(face-remap-add-relative 'font-lock-keyword-face `(:foreground ,(face-foreground 'default)))

* Your attempt to use unspecified caused errors because you had an extra quote, but even fixing that, it will only tell Emacs to take the foreground from the non-remapped face, i.e., do absolutely nothing.


C-h f face-remap-add-relative tells you:

face-remap-add-relative is an autoloaded compiled Lisp function in face-remap.el.

(face-remap-add-relative FACE &rest SPECS)

Add a face remapping entry of FACE to SPECS in the current buffer. Return a cookie which can be used to delete this remapping with face-remap-remove-relative.

The remaining arguments, SPECS, should form a list of faces. Each list element should be either a face name or a property list of face attribute/value pairs. If more than one face is listed, that specifies an aggregate face, in the same way as in a `face' text property, except for possible priority changes noted below.

The face remapping specified by SPECS takes effect alongside the remappings from other calls to face-remap-add-relative for the same FACE, as well as the normal definition of FACE (at lowest priority). This function tries to sort multiple remappings for the same face, so that remappings specifying relative face attributes are applied after remappings specifying absolute face attributes.

The base (lowest priority) remapping may be set to something other than the normal definition of FACE via face-remap-set-base.

The &rest in the lambda list tells you that the SPECS are not passed as a single list argument but are instead passed as individual args.

Try this:

(face-remap-add-relative 'font-lock-keyword-face '(:foreground nil))

not this:

(face-remap-add-relative 'font-lock-keyword-face '((:foreground nil)))

That will pass ((:foreground nil)) as argument SPECS to the function.

  • It behaves the same as with double parentheses. For the record, I don't know why the double parentheses, but it's the way from the answer here. Anyway, the syntax is definitely not a problem because if you replace nil with a color, e.g. "blue", it works just fine.
    – Hi-Angel
    Sep 7 '17 at 20:32

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.