5

By analogy to the mode-line-inactive face, I'd like to dim the header line for inactive windows. But I can't find a "header-line-inactive" face, nor can I find an appropriate hook to modify.

I have the following in my init file, so every window gets a header line.

(setq-default header-line-format 
              '("%e"
                mode-line-front-space
                mode-line-buffer-identification
                (vc-mode vc-mode)
                mode-line-end-spaces))
purple_arrows
  • 2,373
  • 10
  • 19
  • Looks like you would need to set the face each time you switch windows. You could do this by advising `select-window`, or perhaps using a `buffer-list-update-hook`. – glucas Nov 14 '14 at 01:26
  • Could you specify the `header-line-format` you use? (I need to know it to be able to improve my answer.) – Constantine Nov 14 '14 at 06:30
  • I didn't know header lines were supported. There's always something new to discover with Emacs! – glucas Nov 14 '14 at 14:38

2 Answers2

7

You can set the face of the header line by setting properties of the text in header-line-format, but you would need to update header-line-format on every window switch.

As mentioned by @Slomojo, buffer-list-update-hook is the hook to use.

You can start with this draft of a hook and adjust the format string and text properties:

(defun my-update-header ()
  (mapc
   (lambda (window)
     (with-current-buffer (window-buffer window)
       (if (eq window (selected-window))
           (setq header-line-format (propertize "selected" 'face 'mode-line))
         (setq header-line-format (propertize "inactive" 'face 'mode-line-inactive)))))
   (window-list)))

(add-hook 'buffer-list-update-hook #'my-update-header)

Update Nov 14, 2014:

Here's an extension of the idea used above to arbitrary header formats:

(defun my-update-header ()
  (mapc
   (lambda (window)
     (with-current-buffer (window-buffer window)
       ;; don't mess with buffers that don't have a header line
       (when header-line-format
         (let ((original-format (get 'header-line-format 'original))
               (inactive-face 'warning)) ; change this to your favorite inactive header line face
           ;; if we didn't save original format yet, do it now
           (when (not original-format)
             (put 'header-line-format 'original header-line-format)
             (setq original-format header-line-format))
           ;; check if this window is selected, set faces accordingly
           (if (eq window (selected-window))
               (setq header-line-format original-format)
             (setq header-line-format `(:propertize ,original-format face ,inactive-face)))))))
   (window-list)))

I save the original value of header-line-format as a property of header-line-format so it can be restored later. To change the face of inactive header lines I use :propertize.

This breaks if a buffer is displayed by more than one window, and I am convinced that there is no way to do this right: you can't set different buffer-local values of header-line-format in the selected window and the rest of windows displaying the same buffer. (The mode line gets special treatment in the Emacs redisplay code implemented in C.)

Constantine
  • 9,072
  • 1
  • 34
  • 49
  • Whoa. `buffer-list-update-hook` is rocking my world. I want to accept this answer, but first could you please clarify: Is there a way to make this work with arbitrary mode line constructs in `header-line-format`? I've tried and am failing thus far. – purple_arrows Nov 14 '14 at 05:41
  • I think I found it on my own. Instead of changing the string properties, I can use `face-remap-add-relative` / `face-remap-remove-relative` in the hook. I don't have it working yet, but it might do. I'm accepting this one on the assumption that I can come back later and edit it to use those functions – purple_arrows Nov 14 '14 at 06:25
  • Sorry I had a busy day! I was going to suggest keeping a inactive header line alist and copy it to the inactive buffers. And an active header line a list you copy to the active buffer. I'd need to actually try a couple of things to be sure! - nice answer btw – ocodo Nov 14 '14 at 11:46
  • Thank you constantine. I've one question, what are other `inactive-face` colors i can use, can i define myself, or go through the active theme one like modus-vivendi – Rajanboy May 18 '22 at 11:48
  • @Constantine , when i c-x-2, then it highlight both . is it bug? – Rajanboy May 18 '22 at 12:10
1

As a fairly incomplete answer (I'm in the bus so I'll flesh it out in a little while.)

You can use the buffer-list-update-hook This hook runs whenever the buffer list changes.

You can then determine which buffer is now current and update the header-line-format accordingly.

ocodo
  • 1,202
  • 11
  • 20
  • Hello can you please explain it. give example . Thank you – Rajanboy May 18 '22 at 11:40
  • You can see that the first answer does explain it all fully? (I see you commenting on it too, so I guess you decided not to delete the above comment.) – ocodo May 20 '22 at 04:48