3

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))
  • 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 1: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 6: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
5

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.)

  • 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 5: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 6: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
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.

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.