Skip to content

Bad-ptr/common-header-mode-line.el

Repository files navigation

common-header-mode-line

Copyright

Copyright (C) 2017 Constantin Kulikov

Author: Constantin Kulikov (Bad_ptr) zxnotdead@gmail.com
Date: 2017/02/12 11:14:08
License: GPL either version 3 or any later version
Keywords: emacs, mode-line, header-line, convenience, frames, windows
URL: http://github.com/Bad-ptr/common-header-mode-line.el

Intro

Draws per-frame mode-line and/or header-line and allow to customize per-window header/mode-line.

emacs 24 -Q

Installation

    git clone git@github.com:Bad-ptr/common-header-mode-line.el.git
    cd common-header-mode-line.el
    make package

This will create a tar file in the common-header-mode-line.el/pkg/ directory.
Or you can download a release.

Then start emacs and M-x package-install-file RET path/to/common-header-mode-line-{version}.tar RET.

Put the following into your emacs config:

    (with-eval-after-load "common-header-mode-line-autoloads"
      (common-mode-line-mode 1)
      (common-header-line-mode 1))

How to use

M-x customize-group RET common-header-mode-line RET

M-x customize-group RET common-mode-line RET

M-x customize-group RET common-header-line RET

M-x customize-group RET per-window-header-mode-line RET

M-x customize-group RET per-window-mode-line RET

M-x customize-group RET per-window-header-line RET

M-x customize-group RET per-frame-header-mode-line RET

M-x customize-group RET per-frame-mode-line RET

M-x customize-group RET per-frame-header-line RET

Activating the common-header-mode-line-mode is equivalent to activating common-header-line-mode and common-mode-line-mode which is equivalent to activating per-frame-header-mode-line-mode and per-window-header-mode-line-mode which is equivalent to activating per-frame-header-line-mode, per-frame-mode-line-mode, per-window-header-line-mode and per-window-mode-line-mode.
You can enable/disable any subset of these minor-modes at any time. For example you can enable the common-header-mode-line-mode and then disable the per-frame-header-line-mode:

    (common-header-mode-line-mode 1)
    (per-frame-header-line-mode -1)

Example configuration

    (with-eval-after-load "common-header-mode-line-autoloads"
      (add-hook
       'window-setup-hook
       #'(lambda ()
           (common-header-mode-line-mode 1)

           (dolist (frame (frame-list))
             (set-frame-parameter frame 'bottom-divider-width 1)
             (set-frame-parameter frame 'right-divider-width 1))

           (push (cons 'bottom-divider-width 1) default-frame-alist)
           (push (cons 'right-divider-width 1) default-frame-alist)

           (let ((def-height (face-attribute 'default :height)))
             (set-face-attribute
              'per-window-header-line-active-face nil
              :height (ceiling (max 1 (* 0.9 def-height))))

             (set-face-attribute
              'per-window-header-line-inactive-face nil
              :height (floor (max 1 (* 0.7 def-height)))))

           ;; (set-face-background
           ;;  'per-window-header-line-active-face
           ;;  (face-background 'mode-line))

           ;; (set-face-background
           ;;  'per-frame-header-line-inactive-face
           ;;  (face-background 'mode-line-inactive))

           (setq common-header-mode-line-update-delay 0.1)

           (defvar per-window-header-line-active-format nil)
           (defvar per-window-header-line-inactive-format nil)

           (add-hook 'semantic-stickyfunc-mode-hook
                     #'(lambda ()
                         (if (and semantic-mode semantic-stickyfunc-mode)
                             (push semantic-stickyfunc-header-line-format
                                   per-window-header-line-active-format)
                           (setq per-window-header-line-active-format
                                 (delq semantic-stickyfunc-header-line-format
                                       per-window-header-line-active-format)))))

           (add-hook 'multiple-cursors-mode-hook
                     #'(lambda ()
                         (if multiple-cursors-mode
                             (add-to-list 'per-window-header-line-active-format
                                          mc/mode-line)
                           (setq per-window-header-line-active-format
                                 (delq mc/mode-line
                                       per-window-header-line-active-format)))))

           (setq per-window-header-line-format-function
                 #'(lambda (win)
                     (unless per-window-header-line-active-format
                       (setq per-window-header-line-active-format
                             `("" mode-line-front-space mode-line-mule-info
                               mode-line-modified
                               mode-line-remote " " mode-line-buffer-identification
                               " " mode-line-position (vc-mode vc-mode) " "
                               ;;" " ,(caddr mode-line-modes)
                               mode-line-misc-info mode-line-end-spaces)))
                     (unless per-window-header-line-inactive-format
                       (setq per-window-header-line-inactive-format
                             `("" mode-line-front-space mode-line-mule-info
                               mode-line-modified
                               mode-line-remote " " mode-line-buffer-identification
                               " " ,(caddr mode-line-position) (vc-mode vc-mode) " "
                               mode-line-misc-info mode-line-end-spaces)))
                     ;; (let* ((buf (window-buffer win))
                     ;;        (bfrmt (buffer-local-value 'header-line-format buf))
                     ;;        (cf-sym (if (eq win (selected-window))
                     ;;                    'per-window-header-line-active-format
                     ;;                  'per-window-header-line-inactive-format)))
                     ;;   (with-current-buffer buf
                     ;;     (when (and (not (eq bfrmt per-window-header-line-active-format))
                     ;;                (not (eq bfrmt per-window-header-line-inactive-format))
                     ;;                (not (eq bfrmt tabbar-header-line-format)))
                     ;;       (set (make-local-variable 'per-window-header-line-active-format)
                     ;;            (cons bfrmt (default-value 'per-window-header-line-active-format)))
                     ;;       (set (make-local-variable 'per-window-header-line-inactive-format)
                     ;;            (cons bfrmt (default-value 'per-window-header-line-inactive-format))))
                     ;;     (symbol-value cf-sym)))
                     (let* ((buf (window-buffer win))
                            (frmt (unless (with-current-buffer buf
                                            (derived-mode-p 'magit-mode))
                                    (if (eq (selected-window) win)
                                        per-window-header-line-active-format
                                      per-window-header-line-inactive-format)))
                            ;; (bfrmt (buffer-local-value 'header-line-format (window-buffer win)))
                            )
                       ;; (if (eq frmt (cdr bfrmt))
                       ;;     (setq frmt bfrmt)
                       ;;   (when (and bfrmt (not (eq bfrmt frmt))
                       ;;              (not (eq bfrmt '(:eval (tabbar-line)))))
                       ;;     (setq frmt (cons bfrmt frmt))))
                       (or frmt (buffer-local-value 'header-line-format buf)))))

           (setq per-frame-mode-line-update-display-function
                 #'(lambda (display)
                     (let ((buf (cdr (assq 'buf display))))
                       (with-current-buffer buf
                         (setq-local buffer-read-only nil)
                         (erase-buffer)
                         (let*
                             ((mode-l-str
                               (format-mode-line
                                `("%e" mode-line-front-space
                                  (eldoc-mode-line-string (" " eldoc-mode-line-string " "))
                                  mode-line-modified mode-line-client mode-line-frame-identification
                                  mode-line-modes mode-line-misc-info mode-line-end-spaces)
                                'per-frame-mode-line-face per-frame-header-mode-line--selected-window)))
                           (insert mode-l-str))
                         (setq-local mode-line-format nil)
                         (setq-local header-line-format nil)
                         (goto-char (point-min))
                         (setq-local buffer-read-only t))))))))

Result of the above code:
emacs 26 custom

How to contribute

Edit a *-source.el, then run make package, install package, then start emacs, activate the common-header-mode-line-mode, test how it works, if works well commit and push.

Cryptic writings

When editing *-source.el using $* in symbol or string will cause the current top level form be repeated two times -- first time the $* will be replaced by header, second time by mode.
The $@ in symbol or string will be replaced by header-mode.
$0 -- to header, $1 -- mode.
($eval expr) is replaced by the result of evaluation of the expr.
($subloop expr) limit bounds of the $* expansion.