parent
29ba637959
commit
543c82bb08
217
mood-line.el
217
mood-line.el
@ -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
|
(propertize " "
|
||||||
left
|
'display `((space :align-to (- right ,reserve))))
|
||||||
" "
|
right)))
|
||||||
(propertize " "
|
|
||||||
'display `((space :align-to (- (+ right right-fringe right-margin) ,(+ reserve 0)))))
|
|
||||||
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 ")
|
(cond ((memq (plist-get sys :category) '(coding-category-undecided coding-category-utf-8))
|
||||||
(2 "CR "))
|
"UTF-8")
|
||||||
(let ((sys (coding-system-plist buffer-file-coding-system)))
|
(t (upcase (symbol-name (plist-get sys :name))))))
|
||||||
(cond ((memq (plist-get sys :category) '(coding-category-undecided coding-category-utf-8))
|
" ")))
|
||||||
"UTF-8")
|
|
||||||
(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))))
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user