;; Most of the code in this file is based on: ;; https://git.sr.ht/~protesilaos/dotfiles/tree/cf26bc34/item/emacs/.emacs.d/prot-lisp/prot-modeline.el ;; ;; All Kudos to Prot. ;;;; Faces (defface rul-modeline-indicator-red '((default :inherit bold) (((class color) (min-colors 88) (background light)) :foreground "#880000") (((class color) (min-colors 88) (background dark)) :foreground "#ff9f9f") (t :foreground "red")) "Face for modeline indicators.") ;;;; Common helper functions (defcustom rul-modeline-string-truncate-length 9 "String length after which truncation should be done in small windows." :type 'natnum) (defun rul-modeline--string-truncate-p (str) "Return non-nil if STR should be truncated." (and (< (window-total-width) split-width-threshold) (> (length str) rul-modeline-string-truncate-length) (not (one-window-p :no-minibuffer)))) (defun rul-modeline-string-truncate (str) "Return truncated STR, if appropriate, else return STR. Truncation is done up to `rul-modeline-string-truncate-length'." (if (rul-modeline--string-truncate-p str) (concat (substring str 0 rul-modeline-string-truncate-length) "...") str)) ;;;; Major mode (defun rul-modeline-major-mode-indicator () "Return appropriate propertized mode line indicator for the major mode." (let ((indicator (cond ((derived-mode-p 'text-mode) "§") ((derived-mode-p 'prog-mode) "λ") ((derived-mode-p 'comint-mode) ">_") (t "◦")))) (propertize indicator 'face 'shadow))) (defun rul-modeline-major-mode-name () "Return capitalized `major-mode' without the -mode suffix." (capitalize (string-replace "-mode" "" (symbol-name major-mode)))) (defun rul-modeline-major-mode-help-echo () "Return `help-echo' value for `rul-modeline-major-mode'." (if-let ((parent (get major-mode 'derived-mode-parent))) (format "Symbol: `%s'. Derived from: `%s'" major-mode parent) (format "Symbol: `%s'." major-mode))) (defvar-local rul-modeline-major-mode (list (propertize "%[" 'face 'rul-modeline-indicator-red) '(:eval (concat (rul-modeline-major-mode-indicator) " " (propertize (rul-modeline-string-truncate (rul-modeline-major-mode-name)) 'mouse-face 'mode-line-highlight 'help-echo (rul-modeline-major-mode-help-echo)))) (propertize "%]" 'face 'rul-modeline-indicator-red)) "Mode line construct for displaying major modes.") (with-eval-after-load 'eglot (setq mode-line-misc-info (delete '(eglot--managed-mode (" [" eglot--mode-line-format "] ")) mode-line-misc-info))) (defvar-local prot-modeline-eglot `(:eval (when (and (featurep 'eglot) (mode-line-window-selected-p)) '(eglot--managed-mode eglot--mode-line-format))) "Mode line construct displaying Eglot information. Specific to the current window's mode line.") ;;;; Miscellaneous (defvar-local rul-modeline-misc-info '(:eval (when (mode-line-window-selected-p) mode-line-misc-info)) "Mode line construct displaying `mode-line-misc-info'. Specific to the current window's mode line.") ;;;; Display current time (setq display-time-format " %a %e %b, %H:%M ") (setq display-time-default-load-average nil) (setq display-time-mail-string "") ;;;; Variables used in the modeline need to be in `risky-local-variable'. (dolist (construct '( rul-modeline-major-mode rul-modeline-misc-info )) (put construct 'risky-local-variable t)) ;;;; Finally, define the modeline format (setq-default mode-line-format '("%e" mode-line-front-space mode-line-buffer-identification mode-line-front-space rul-modeline-major-mode prot-modeline-eglot mode-line-format-right-align rul-modeline-misc-info )) (provide 'rul-modeline)