2

I'm seeing rather bizarre behavior. I have the following code:

(defun set-mode-line-face ()
  (let ((color
          (pcase (random 6)
            (`1  '("#586e75" . "#eee8d5"))
            (`2   '("#859900" . "#eee8d5"))
            (`3  '("#93a1a1" . "#073642"))
            (`4  '("#268bd2" . "#eee8d5"))
            (`5 '("#dc322f" . "#eee8d5"))
            (other    '("grey70" . "black")))))

    (set-face-attribute 'mode-line nil
      :background (car color)
      :foreground (cdr color))

    (set-face-foreground 'mode-line-buffer-id (cdr color))))

;; Change modeline color by Evil state
(add-hook 'post-command-hook #'set-mode-line-face)

Strangely enough, this causes emacs to become nearly unusable (~0.2s delays abound). Is the overhead of setting a face really that high? Is there any way I can fix it?

This is Emacs 24.5 on a graphical Linux frame.

  • Try pre-constructing the six faces and rewrite the mode line format variables like mode-line-buffer-identification instead -- it might be faster (I haven't tested it). – Lindydancer Jul 3 '15 at 4:44
  • 2
    If the faces already exist -- e.g., defined with defface, then use those. If you are changing an existing face, then face-remap-add-relative will be much faster than set-face-attribute. See this related thread: stackoverflow.com/a/25150669/2112489 You have already discovered the reason not to use set-face-attribute when adjusting the mode-line colors. The set-face-background likely suffers the same lag. – lawlist Jul 3 '15 at 5:27
  • @lawlist that does the trick! Would you mind posting an answer, so I can accept it? – PythonNut Jul 3 '15 at 14:43
3

Due to the speed at which the mode-line needs to update, it is too costly to use functions like set-face-attribute, set-face-foreground, and set-face-background. The most efficient method of setting mode-line faces will be to use either ones that have already been defined -- e.g., defface -- or, by modifying existing faces with face-remap-add-relative: http://www.gnu.org/software/emacs/manual/html_node/elisp/Face-Remapping.html

The following is a quote from Stefan in the related thread at the following link https://stackoverflow.com/a/25150669/2112489

"Changing faces dynamically is going to be slow because the redisplay code is written under the assumption that faces don't change (if they change, we basically redo a lot of work). Using face-remapping-alist will result in much better performance because the redisplay code does expect it to change and know how to cache the result."

  • face-remap-add-relative works wonderfully! – PythonNut Jul 3 '15 at 20:55

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.