Change Emacs Mode-Line color based on major-mode
Asked Answered
S

2

6

I like to see if there is a way to change the mode-link foreground and background color base on the major-mode,

I was thinking to add the logic in the

(add-hook 'after-change-major-mode-hook

But, I do not have all the emacs lisp experience to make such change. Here is the logic:

switch major-mode:
case "emacs-lisp-mode":
  (set-face-foreground 'mode-line "ivory")
  (set-face-background 'mode-line "DarkOrange2")
case "ruby-mode":
  (set-face-foreground 'mode-line "white")
  (set-face-background 'mode-line "red")
...
default:
  (set-face-foreground 'mode-line "black")
  (set-face-background 'mode-line "white")
end switch

Many thanks in advance!.

Sherrisherrie answered 9/4, 2013 at 15:38 Comment(0)
K
10

You probably want something like:

(add-hook 'emacs-lisp-mode-hook
          (lambda ()
            (face-remap-add-relative
             'mode-line '((:foreground "ivory" :background "DarkOrange2") mode-line))))

You might want to use face-remap for the mode-line-inactive face as well.

Karelia answered 10/4, 2013 at 0:55 Comment(3)
THANK YOU VERY MUCH. This works beautifully :) Would you also be kind to help me combine your add-hook by using a predefined list? Similar to "sds" suggestion but add-hook to all the mode in the predefined list with the colors? Thanks!Sherrisherrie
You mean like (dolist (x '((emacs-lisp-mode :foreground "ivory" :background "DarkOrange2") (ruby-mode :foreground "white" :background "red"))) (add-hook (intern (concat (symbol-name (car x)) "-mode")) (lambda () (face-remap-add-relative 'mode-line (cons (cdr x) '(mode-line)))))) tho beware that it will only work in a lexical-binding:t buffer.Karelia
I have tried something like: (add-hook 'shell-mode-hook (lambda () (font-lock-variable-name-face 'mode-line '((:foreground "LightGoldenrod" :weight bold) mode-line)))) which didn't have any affect :-(Cleghorn
P
3

"The logic" you are talking about is something like this:

(add-hook 'after-change-major-mode-hook 'my-set-mode-line-colors)
(defvar my-mode-line-colors
  '((emacs-lisp-mode :foreground "ivory" :background "DarkOrange2")
    (ruby-mode :foreground "white" :background "red")))
(defun my-set-mode-line-colors ()
  (face-remap-add-relative
   'mode-line (list (or (cdr (assq major-mode my-mode-line-colors))
                        '(:foreground "black" :background "white"))
                    'mode-line)))

Alternatively, you can do that from mode-specific hooks, as suggested by Stefan.

Protolanguage answered 9/4, 2013 at 17:21 Comment(4)
I actually had the add-hook to each mode. But when I switch buffer from ruby to lisp, etc., the mode-line did not get update.. Hence I thought about "change-major-mode-hook" and you are right, neither work either... is that a buffer-switch-hook ? I tried to look for something like it but no avail. Thanks!Sherrisherrie
The problem, as I wrote, is that the emacs faces are not buffer-local, so the above set-face-foreground calls will affect all windows and all mode lines. The is no way to make mode-line appearance buffer-specificProtolanguage
the set-face-foreground can be set per frame. even if I have multiple frames up, I can change the mode-line just for that frame... as long as I could tell when a buffer is switched in and out and change the mode-line, it should work..Sherrisherrie
if you have one frame per buffer, yes, you should be fine. I have a single maximized frame, so this is not a method for me.Protolanguage

© 2022 - 2024 — McMap. All rights reserved.