This commit is contained in:
Jessie Hildebrandt 2019-09-30 05:34:56 -04:00
parent 29ba637959
commit 543c82bb08

View File

@ -18,6 +18,7 @@
;; * Anzu and multiple-cursors counter ;; * Anzu and multiple-cursors counter
;; * Version control status indicator ;; * Version control status indicator
;; * Flycheck status indicator ;; * Flycheck status indicator
;; * Flymake support
;; * Lightweight with no dependencies ;; * Lightweight with no dependencies
;; ;;
;; To enable mood-line: ;; To enable mood-line:
@ -46,9 +47,13 @@
;; Variable declarations ;; Variable declarations
;; ;;
(defvar mood-line--current-window)
(defvar flycheck-current-errors) (defvar flycheck-current-errors)
(defvar flymake--mode-line-format)
(defvar anzu--state) (defvar anzu--state)
(defvar anzu--cached-count)
(defvar anzu--overflow-p)
(defvar anzu--current-position)
(defvar anzu--total-matched)
(defvar multiple-cursors-mode) (defvar multiple-cursors-mode)
;; ;;
@ -56,7 +61,6 @@
;; ;;
(declare-function flycheck-count-errors "flycheck" (errors)) (declare-function flycheck-count-errors "flycheck" (errors))
(declare-function anzu--update-mode-line "anzu" ())
(declare-function mc/num-cursors "multiple-cursors" ()) (declare-function mc/num-cursors "multiple-cursors" ())
;; ;;
@ -67,13 +71,23 @@
"A minimal mode-line configuration inspired by doom-modeline." "A minimal mode-line configuration inspired by doom-modeline."
:group 'mode-line) :group 'mode-line)
(defcustom mood-line-show-point nil (defcustom mood-line-show-eol-style nil
"If t, the EOL style of the current buffer will be displayed in the mode-line."
:group 'mood-line
:type 'boolean)
(defcustom mood-line-show-encoding-information nil
"If t, the encoding format of the current buffer will be displayed in the mode-line."
:group 'mood-line
:type 'boolean)
(defcustom mood-line-show-cursor-point nil
"If t, the value of `point' will be displayed next to the cursor position in the mode-line." "If t, the value of `point' will be displayed next to the cursor position in the mode-line."
:group 'mood-line :group 'mood-line
:type 'boolean) :type 'boolean)
(defface mood-line-status-grayed-out (defface mood-line-status-neutral
'((t (:inherit (font-lock-doc-face)))) '((t (:inherit (shadow))))
"Face used for neutral or inactive status indicators in the mode-line." "Face used for neutral or inactive status indicators in the mode-line."
:group 'mood-line) :group 'mood-line)
@ -98,11 +112,10 @@
:group 'mood-line) :group 'mood-line)
(defface mood-line-unimportant (defface mood-line-unimportant
'((t (:inherit (font-lock-doc-face)))) '((t (:inherit (shadow))))
"Face used for less important mode-line elements." "Face used for less important mode-line elements."
:group 'mood-line) :group 'mood-line)
(defface mood-line-modified (defface mood-line-modified
'((t (:inherit (error)))) '((t (:inherit (error))))
"Face used for the 'modified' indicator symbol in the mode-line." "Face used for the 'modified' indicator symbol in the mode-line."
@ -112,36 +125,35 @@
;; Helper functions ;; Helper functions
;; ;;
(defun mood-line-format (left right) (defun --string-trim-left (string)
"Remove whitespace at the beginning of STRING."
(if (string-match "\\`[ \t\n\r]+" string)
(replace-match "" t t string)
string))
(defun --string-trim-right (string)
"Remove whitespace at the end of STRING."
(if (string-match "[ \t\n\r]+\\'" string)
(replace-match "" t t string)
string))
(defun --string-trim (string)
"Remove whitespace at the beginning and end of STRING."
(--string-trim-left (--string-trim-right string)))
(defun --format-mood-line (left right)
"Return a string of `window-width' length containing LEFT and RIGHT, aligned respectively." "Return a string of `window-width' length containing LEFT and RIGHT, aligned respectively."
(let ((reserve (length right))) (let ((reserve (length right)))
(when (and (display-graphic-p) (eq 'right (get-scroll-bar-mode))) (concat left
(setq reserve (- reserve 3)))
(concat
left
" " " "
(propertize " " (propertize " "
'display `((space :align-to (- (+ right right-fringe right-margin) ,(+ reserve 0))))) 'display `((space :align-to (- right ,reserve))))
right))) right)))
;; Define a helper function to determine whether or not the current window is active.
(defsubst mood-line-is-active ()
"Return \"t\" if the current window is active, \"nil\" if it is not."
(eq (selected-window) mood-line--current-window))
;; ;;
;; Update functions ;; Update functions
;; ;;
;; Window update function
(defvar-local mood-line--current-window (frame-selected-window))
(defun mood-line--update-selected-window (&rest _)
"Update the `mood-line--current-window' variable."
(when (frame-selected-window)
(let ((win (frame-selected-window)))
(unless (minibuffer-window-active-p win)
(setq mood-line--current-window win)))))
;; VC update function ;; VC update function
(defvar-local mood-line--vc-text nil) (defvar-local mood-line--vc-text nil)
(defun mood-line--update-vc-segment (&rest _) (defun mood-line--update-vc-segment (&rest _)
@ -150,26 +162,25 @@
(when (and vc-mode buffer-file-name) (when (and vc-mode buffer-file-name)
(let ((backend (vc-backend buffer-file-name)) (let ((backend (vc-backend buffer-file-name))
(state (vc-state buffer-file-name (vc-backend buffer-file-name)))) (state (vc-state buffer-file-name (vc-backend buffer-file-name))))
(let ((face 'mode-line-inactive) (let ((face 'mode-line-neutral))
(active (mood-line-is-active)))
(concat (cond ((memq state '(edited added)) (concat (cond ((memq state '(edited added))
(if active (setq face 'mood-line-status-info)) (setq face 'mood-line-status-info)
(propertize "" 'face face)) (propertize "+ " 'face face))
((eq state 'needs-merge) ((eq state 'needs-merge)
(if active (setq face 'mood-line-status-warning)) (setq face 'mood-line-status-warning)
(propertize "" 'face face)) (propertize "" 'face face))
((eq state 'needs-update) ((eq state 'needs-update)
(if active (setq face 'mood-line-status-warning)) (setq face 'mood-line-status-warning)
(propertize "" 'face face)) (propertize "" 'face face))
((memq state '(removed conflict unregistered)) ((memq state '(removed conflict unregistered))
(if active (setq face 'mood-line-status-error)) (setq face 'mood-line-status-error)
(propertize "" 'face face)) (propertize " " 'face face))
(t (t
(if active (setq face 'mood-line-status-grayed-out)) (setq face 'mood-line-status-neutral)
(propertize "" 'face face))) (propertize "" 'face face)))
" "
(propertize (substring vc-mode (+ (if (eq backend 'Hg) 2 3) 2)) (propertize (substring vc-mode (+ (if (eq backend 'Hg) 2 3) 2))
'face (if active face)) 'face face
'mouse-face face)
" ")))))) " "))))))
;; Flycheck update function ;; Flycheck update function
@ -181,73 +192,74 @@
('finished (if flycheck-current-errors ('finished (if flycheck-current-errors
(let-alist (flycheck-count-errors flycheck-current-errors) (let-alist (flycheck-count-errors flycheck-current-errors)
(let ((sum (+ (or .error 0) (or .warning 0)))) (let ((sum (+ (or .error 0) (or .warning 0))))
(propertize (concat " Issues: " (propertize (concat " Issues: "
(number-to-string sum) (number-to-string sum)
" ") " ")
'face (if .error 'face (if .error
'mood-line-status-error 'mood-line-status-error
'mood-line-status-warning)))) 'mood-line-status-warning))))
(propertize "✔ Good " 'face 'mood-line-status-success))) (propertize "✔ Good " 'face 'mood-line-status-success)))
('running (propertize "● Checking " 'face 'mood-line-status-info)) ('running (propertize "𝚫 Checking " 'face 'mood-line-status-info))
('no-checker "")
('errored (propertize "✖ Error " 'face 'mood-line-status-error)) ('errored (propertize "✖ Error " 'face 'mood-line-status-error))
('interrupted (propertize "⏸ Paused " 'face 'mood-line-status-grayed-out))))) ('interrupted (propertize "⏸ Paused " 'face 'mood-line-status-neutral))
('no-checker ""))))
;; ;;
;; Segments ;; Segments
;; ;;
(defun mood-line-segment-modified () (defun mood-line-segment-modified ()
"Displays a color-coded buffer modification indicator in the mode-line." "Displays a color-coded buffer modification/read-only indicator in the mode-line."
(propertize (if (not (string-match-p "\\*.*\\*" (buffer-name)))
(if (and (if (buffer-modified-p)
(buffer-modified-p) (propertize "" 'face 'mood-line-modified)
(not (string-match-p "\\*.*\\*" (buffer-name)))) (if buffer-read-only
"" (propertize "" 'face 'mood-line-unimportant)
" ") " "))
'face 'mood-line-modified)) " "))
(defun mood-line-segment-buffer-name () (defun mood-line-segment-buffer-name ()
"Displays the name of the current buffer in the mode-line." "Displays the name of the current buffer in the mode-line."
(concat (propertize "%b" 'face 'mode-line-buffer-id) " ")) (propertize "%b " 'face 'mode-line-buffer-id))
(defun mood-line-segment-anzu () (defun mood-line-segment-anzu ()
"Displays color-coded anzu status information in the mode-line (if available)." "Displays color-coded anzu status information in the mode-line (if available)."
(when (and (boundp 'anzu--state) anzu--state) (when (and (boundp 'anzu--state) anzu--state)
(concat (anzu--update-mode-line) " "))) (cond ((eq anzu--state 'replace-query)
(format #("Replace: %d " 0 11 (face mood-line-status-warning)) anzu--cached-count))
(anzu--overflow-p
(format #("%d/%d+ " 0 3 (face mood-line-status-info) 3 6 (face mood-line-status-error)) anzu--current-position anzu--total-matched))
(t
(format #("%d/%d " 0 5 (face mood-line-status-info)) anzu--current-position anzu--total-matched)))))
(defun mood-line-segment-multiple-cursors () (defun mood-line-segment-multiple-cursors ()
"Displays the number of active multiple-cursors in the mode-line (if available)." "Displays the number of active multiple-cursors in the mode-line (if available)."
(when (and (boundp 'multiple-cursors-mode) multiple-cursors-mode) (when (and (boundp 'multiple-cursors-mode) multiple-cursors-mode)
(concat "MC:" (concat "MC"
(format #("%d" 0 2 (face font-lock-warning-face)) (mc/num-cursors)) (format #("×%d " 0 3 (face mood-line-status-warning)) (mc/num-cursors)))))
" ")))
(defun mood-line-segment-position () (defun mood-line-segment-position ()
"Displays the current cursor position in the mode-line." "Displays the current cursor position in the mode-line."
(concat "%l:%c" (concat "%l:%c"
(when mood-line-show-point (when mood-line-show-cursor-point (propertize (format ":%d" (point)) 'face))
(concat ":" (propertize " %p%% " 'face 'mood-line-unimportant)))
(propertize (format "%d" (point)) 'face (if (mood-line-is-active)
'mood-line-unimportant (defun mood-line-segment-eol ()
'mode-line-inactive)))) "Displays the EOL style of the current buffer in the mode-line."
" " (when mood-line-show-eol-style
(propertize "%p%%" 'face (if (mood-line-is-active) (pcase (coding-system-eol-type buffer-file-coding-system)
'mood-line-unimportant (0 "LF ")
'mode-line-inactive)) (1 "CRLF ")
" ")) (2 "CR "))))
(defun mood-line-segment-encoding () (defun mood-line-segment-encoding ()
"Displays the encoding and EOL style of the buffer in the mode-line." "Displays the encoding and EOL style of the buffer in the mode-line."
(concat (pcase (coding-system-eol-type buffer-file-coding-system) (when mood-line-show-encoding-information
(0 "LF ") (concat (let ((sys (coding-system-plist buffer-file-coding-system)))
(1 "CRLF ")
(2 "CR "))
(let ((sys (coding-system-plist buffer-file-coding-system)))
(cond ((memq (plist-get sys :category) '(coding-category-undecided coding-category-utf-8)) (cond ((memq (plist-get sys :category) '(coding-category-undecided coding-category-utf-8))
"UTF-8") "UTF-8")
(t (upcase (symbol-name (plist-get sys :name)))))) (t (upcase (symbol-name (plist-get sys :name))))))
" ")) " ")))
(defun mood-line-segment-vc () (defun mood-line-segment-vc ()
"Displays color-coded version control information in the mode-line." "Displays color-coded version control information in the mode-line."
@ -255,25 +267,27 @@
(defun mood-line-segment-major-mode () (defun mood-line-segment-major-mode ()
"Displays the current major mode in the mode-line." "Displays the current major mode in the mode-line."
(propertize "%m " (propertize "%m " 'face 'bold))
'face (if (mood-line-is-active)
'bold
'mood-line-status-grayed-out)))
(defun mood-line-segment-global-mode-string () (defun mood-line-segment-misc-info ()
"Displays the current value of `global-mode-string' in the mode-line." "Displays the current value of `mode-line-misc-info' in the mode-line."
(let ((global (format-mode-line global-mode-string 'mood-line-status-grayed-out))) (let ((misc-info (format-mode-line mode-line-misc-info 'mood-line-unimportant)))
(unless (string-empty-p global) (unless (string= misc-info "")
(concat global " ")))) (concat (--string-trim misc-info) " "))))
(defun mood-line-segment-flycheck () (defun mood-line-segment-flycheck ()
"Displays color-coded flycheck information in the mode-line (if available)." "Displays color-coded flycheck information in the mode-line (if available)."
mood-line--flycheck-text) mood-line--flycheck-text)
(defun mood-line-segment-flymake ()
"Displays information about the current status of flymake in the mode-line (if available)."
(when (and (boundp 'flymake-mode) flymake-mode)
(concat (--string-trim (format-mode-line flymake--mode-line-format)) " ")))
(defun mood-line-segment-process () (defun mood-line-segment-process ()
"Displays the current value of `mode-line-process' in the mode-line." "Displays the current value of `mode-line-process' in the mode-line."
(when mode-line-process (when mode-line-process
(list mode-line-process " "))) (concat (--string-trim (format-mode-line mode-line-process)) " ")))
;; ;;
;; Activation function ;; Activation function
@ -300,19 +314,14 @@
(add-hook 'after-save-hook #'mood-line--update-vc-segment) (add-hook 'after-save-hook #'mood-line--update-vc-segment)
(advice-add #'vc-refresh-state :after #'mood-line--update-vc-segment) (advice-add #'vc-refresh-state :after #'mood-line--update-vc-segment)
;; Setup window update hooks
(add-hook 'window-configuration-change-hook #'mood-line--update-selected-window)
(add-hook 'focus-in-hook #'mood-line--update-selected-window)
(advice-add #'handle-switch-frame :after #'mood-line--update-selected-window)
(advice-add #'select-window :after #'mood-line--update-selected-window)
;; Set the new mode-line-format ;; Set the new mode-line-format
(setq-default mode-line-format (setq-default mode-line-format
'((:eval '((:eval
(mood-line-format (--format-mood-line
;; Left ;; Left
(format-mode-line (format-mode-line
'((:eval (mood-line-segment-modified)) '(" "
(:eval (mood-line-segment-modified))
(:eval (mood-line-segment-buffer-name)) (:eval (mood-line-segment-buffer-name))
(:eval (mood-line-segment-anzu)) (:eval (mood-line-segment-anzu))
(:eval (mood-line-segment-multiple-cursors)) (:eval (mood-line-segment-multiple-cursors))
@ -320,11 +329,13 @@
;; Right ;; Right
(format-mode-line (format-mode-line
'((:eval (mood-line-segment-encoding)) '((:eval (mood-line-segment-eol))
(:eval (mood-line-segment-encoding))
(:eval (mood-line-segment-vc)) (:eval (mood-line-segment-vc))
(:eval (mood-line-segment-major-mode)) (:eval (mood-line-segment-major-mode))
(:eval (mood-line-segment-global-mode-string)) (:eval (mood-line-segment-misc-info))
(:eval (mood-line-segment-flycheck)) (:eval (mood-line-segment-flycheck))
(:eval (mood-line-segment-flymake))
(:eval (mood-line-segment-process)) (:eval (mood-line-segment-process))
" "))))))) " ")))))))
(progn (progn
@ -338,12 +349,6 @@
(remove-hook 'after-save-hook #'mood-line--update-vc-segment) (remove-hook 'after-save-hook #'mood-line--update-vc-segment)
(advice-remove #'vc-refresh-state #'mood-line--update-vc-segment) (advice-remove #'vc-refresh-state #'mood-line--update-vc-segment)
;; Remove window update hooks
(remove-hook 'window-configuration-change-hook #'mood-line--update-selected-window)
(remove-hook 'focus-in-hook #'mood-line--update-selected-window)
(advice-remove #'handle-switch-frame #'mood-line--update-selected-window)
(advice-remove #'select-window #'mood-line--update-selected-window)
;; Restore the original mode-line format ;; Restore the original mode-line format
(setq-default mode-line-format mood-line--default-mode-line)))) (setq-default mode-line-format mood-line--default-mode-line))))