Restructure project

mood-line has been restructured to improve modularity and configurability
with careful attention paid to performance and overall project complexity.
This commit is contained in:
Jessie Hildebrandt 2023-11-18 20:20:29 -05:00
parent d948ba7a94
commit b41f6ba1dd
5 changed files with 665 additions and 542 deletions

View File

@ -0,0 +1,168 @@
;;; mood-line-segment-checker.el --- A checker status segment for mood-line -*- lexical-binding: t; -*-
;;
;; Author: Jessie Hildebrandt <jessieh.net>
;; Homepage: https://gitlab.com/jessieh/mood-line
;; This file is not part of GNU Emacs.
;;; Commentary:
;;
;; This segment displays the current status of any active checker.
;;; License:
;;
;; This program is free software; you can redistribute it and/or
;; modify it under the terms of the GNU General Public License as
;; published by the Free Software Foundation; either version 2, or
;; (at your option) any later version.
;;
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
;; General Public License for more details.
;;
;; You should have received a copy of the GNU General Public License
;; along with this program; see the file COPYING. If not, write to
;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth
;; Floor, Boston, MA 02110-1301, USA.
;;; Code:
;; -------------------------------------------------------------------------- ;;
;;
;; Byte-compiler declarations
;;
;; -------------------------------------------------------------------------- ;;
;; ---------------------------------- ;;
;; Compile time requirements
;; ---------------------------------- ;;
(eval-when-compile
(require 'flymake))
;; ---------------------------------- ;;
;; External variable defs
;; ---------------------------------- ;;
(defvar flycheck-current-errors)
;; ---------------------------------- ;;
;; External function decls
;; ---------------------------------- ;;
(declare-function mood-line--get-glyph "mood-line")
(declare-function flycheck-count-errors "flycheck")
(declare-function flymake-running-backends "flymake")
(declare-function flymake-reporting-backends "flymake")
(declare-function flymake--lookup-type-property "flymake")
;; -------------------------------------------------------------------------- ;;
;;
;; Helper functions
;;
;; -------------------------------------------------------------------------- ;;
(defun mood-line-segment-checker--format-status (status error warning note)
"Format STATUS into a segment string with ERROR, WARNING, and NOTE counts."
(pcase status
('running
(format #("%s Checking"
0 11 (face mood-line-status-neutral))
(mood-line--get-glyph :checker-checking)))
('errored
(format #("%s Error"
0 2 (face mood-line-status-error))
(mood-line--get-glyph :checker-errored)))
('interrupted
(format #("%s Paused"
0 9 (face mood-line-status-neutral))
(mood-line--get-glyph :checker-interrupted)))
('finished
(cond
((> error 0)
(let ((issues (+ error warning)))
(format #("%s %s Issue%s"
0 2 (face mood-line-status-error))
(mood-line--get-glyph :checker-issues)
issues
(if (> issues 1) "s" ""))))
((> warning 0)
(format #("%s %s Issue%s"
0 2 (face mood-line-status-warning))
(mood-line--get-glyph :checker-issues)
warning
(if (> warning 1) "s" "")))
((> note 0)
(format #("%s %s Note%s"
0 2 (face mood-line-status-info))
(mood-line--get-glyph :checker-info)
note
(if (> note 1) "s" "")))
(t
(format #("%s No Issues"
0 12 (face mood-line-status-neutral))
(mood-line--get-glyph :checker-good)))))))
;; -------------------------------------------------------------------------- ;;
;;
;; Flycheck update handler
;;
;; -------------------------------------------------------------------------- ;;
(defvar-local mood-line-segment-checker--flycheck-text nil
"Mode line segment string indicating the current state of `flycheck-mode'.")
(defun mood-line-segment-checker--flycheck-update (&optional status)
"Update `mood-line-segment-checker--flycheck-text' with flycheck's STATUS."
(setq mood-line-segment-checker--flycheck-text
(let-alist (flycheck-count-errors flycheck-current-errors)
(when-let* ((valid-statuses '(finished running errored interrupted))
(status-valid (member status valid-statuses))
(error (or .error 0))
(warning (or .warning 0))
(note (or .info 0)))
(mood-line-segment-checker--format-status
status error warning note)))))
;; -------------------------------------------------------------------------- ;;
;;
;; Flymake update handler
;;
;; -------------------------------------------------------------------------- ;;
(defvar-local mood-line-segment-checker--flymake-text nil
"Mode line segment string indicating the current state of `flymake-mode'.")
(defun mood-line-segment-checker--flymake-count (type)
"Return count of current flymake reports of TYPE."
(cl-loop for diag in (flymake-diagnostics)
as diag-type = (flymake-diagnostic-type diag)
count (eq (flymake--lookup-type-property diag-type 'severity)
(flymake--lookup-type-property type 'severity))))
(defun mood-line-segment-checker--flymake-update (&rest _args)
"Update `mood-line-segment-checker--flymake-state' with flymake's status."
(setq mood-line-segment-checker--flymake-text
(when-let ((flymake-active (and (fboundp 'flymake-is-running)
(flymake-is-running)))
(status (if (seq-difference (flymake-running-backends)
(flymake-reporting-backends))
'running 'finished))
(error (mood-line-segment-checker--flymake-count :error))
(warning (mood-line-segment-checker--flymake-count :warning))
(note (mood-line-segment-checker--flymake-count :note)))
(mood-line-segment-checker--format-status
status error warning note))))
;; -------------------------------------------------------------------------- ;;
;;
;; Provide package
;;
;; -------------------------------------------------------------------------- ;;
(provide 'mood-line-segment-checker)
;;; mood-line-segment-checker.el ends here

View File

@ -39,7 +39,7 @@
;; External function decls ;; External function decls
;; ---------------------------------- ;; ;; ---------------------------------- ;;
(declare-function mood-line--get-glyph "mood-line" (glyph)) (declare-function mood-line--get-glyph "mood-line")
;; -------------------------------------------------------------------------- ;; ;; -------------------------------------------------------------------------- ;;
;; ;;
@ -47,6 +47,14 @@
;; ;;
;; -------------------------------------------------------------------------- ;; ;; -------------------------------------------------------------------------- ;;
;; ---------------------------------- ;;
;; Group definitions
;; ---------------------------------- ;;
(defgroup mood-line-segment-indentation nil
"An indentation info segment for mood-line."
:group 'mood-line)
;; ---------------------------------- ;; ;; ---------------------------------- ;;
;; Variable definitions ;; Variable definitions
;; ---------------------------------- ;; ;; ---------------------------------- ;;
@ -55,14 +63,14 @@
"When non-nil, always show the indentation offset of the current mode. "When non-nil, always show the indentation offset of the current mode.
Default behavior of the indentation segment is to display the indentation offset Default behavior of the indentation segment is to display the indentation offset
of the current mode when `indent-tabs-mode' is non-nil and an offset value can of the current mode when `indent-tabs-mode' is non-nil and an offset value can
be found for the current mode. Otherwise, `tab-wdith' will be shown. be found for the current mode. Otherwise, `tab-wdith' will be shown.
When `mood-line-segment-indentation-always-show-offset' is set to non-nil, the When `mood-line-segment-indentation-always-show-offset' is set to non-nil, the
indentation offset will always be shown alongside `tab-width'. If an offset indentation offset will always be shown alongside `tab-width'. If an offset
value cannot be found for the current mode, a \"?\" character will be displayed value cannot be found for the current mode, a \"?\" character will be displayed
alongside `tab-width'." alongside `tab-width'."
:group 'mood-line :group 'mood-line-segment-indentation
:type 'boolean) :type 'boolean)
;; Assembled from `editorconfig-indentation-alist' and `doom-modeline-indent-alist': ;; Assembled from `editorconfig-indentation-alist' and `doom-modeline-indent-alist':
@ -173,9 +181,9 @@ alongside `tab-width'."
"Alist mapping major mode names to their respective indent offset variables. "Alist mapping major mode names to their respective indent offset variables.
When multiple variables are specified for a given mode, the offset value will When multiple variables are specified for a given mode, the offset value will
be retrieved from the first variable that resolves to a value (evaluated in the be retrieved from the first variable that resolves to a value, evaluated in the
order provided)." order provided."
:group 'mood-line :group 'mood-line-segment-indentation
:type '(alist :key-type symbol :value-type sexp)) :type '(alist :key-type symbol :value-type sexp))
;; -------------------------------------------------------------------------- ;; ;; -------------------------------------------------------------------------- ;;
@ -188,8 +196,8 @@ order provided)."
;; Segment function ;; Segment function
;; ---------------------------------- ;; ;; ---------------------------------- ;;
(defun mood-line-segment-indentation--segment () (defun mood-line-segment-indentation ()
"Display the indentation style of the current buffer." "Return the indentation style of the current buffer."
(let* ((mode-offset (symbol-value (let* ((mode-offset (symbol-value
(seq-some #'identity (seq-some #'identity
(cdr (assoc major-mode (cdr (assoc major-mode
@ -202,8 +210,7 @@ order provided)."
tab-width) tab-width)
(number-to-string (if indent-tabs-mode (number-to-string (if indent-tabs-mode
tab-width tab-width
(or mode-offset tab-width)))) (or mode-offset tab-width)))))
" ")
'face 'mood-line-encoding))) 'face 'mood-line-encoding)))
;; -------------------------------------------------------------------------- ;; ;; -------------------------------------------------------------------------- ;;

View File

@ -1,4 +1,4 @@
;;; mood-line-segment-modal.el --- A modal editing segment for mood-line -*- lexical-binding: t; -*- ;;; mood-line-segment-modal.el --- A modal editing status segment for mood-line -*- lexical-binding: t; -*-
;; ;;
;; Author: trevDev() <trev@trevdev.ca> ;; Author: trevDev() <trev@trevdev.ca>
;; Jessie Hildebrandt <jessieh.net> ;; Jessie Hildebrandt <jessieh.net>
@ -35,11 +35,19 @@
;; ;;
;; -------------------------------------------------------------------------- ;; ;; -------------------------------------------------------------------------- ;;
;; ---------------------------------- ;;
;; Group definitions
;; ---------------------------------- ;;
(defgroup mood-line-segment-modal nil
"A modal editing status segment for mood-line."
:group 'mood-line)
;; ---------------------------------- ;; ;; ---------------------------------- ;;
;; Variable definitions ;; Variable definitions
;; ---------------------------------- ;; ;; ---------------------------------- ;;
(defcustom mood-line-evil-state-alist (defcustom mood-line-segment-modal-evil-state-alist
'((normal . ("<N>" . font-lock-variable-name-face)) '((normal . ("<N>" . font-lock-variable-name-face))
(insert . ("<I>" . font-lock-string-face)) (insert . ("<I>" . font-lock-string-face))
(visual . ("<V>" . font-lock-keyword-face)) (visual . ("<V>" . font-lock-keyword-face))
@ -47,72 +55,67 @@
(motion . ("<M>" . font-lock-constant-face)) (motion . ("<M>" . font-lock-constant-face))
(operator . ("<O>" . font-lock-function-name-face)) (operator . ("<O>" . font-lock-function-name-face))
(emacs . ("<E>" . font-lock-builtin-face))) (emacs . ("<E>" . font-lock-builtin-face)))
"Set the string and corresponding face for any `evil-mode' state. "Alist specifying indicators and faces for corresponding `evil-mode' states.
The `Face' may be either a face symbol or a property list of key-value pairs The face may be either a face symbol or a property list of key-value pairs;
e.g. (:foreground \"red\")." e.g., (:foreground \"red\")."
:group 'mood-line :group 'mood-line-segment-modal
:type '(alist :type '(alist :key-type symbol
:key-type symbol :value-type (cons (string :tag "Display text")
:value-type (choice :tag "Face" face plist))))
(cons (string :tag "Display Text") (choice :tag "Face" face plist))))
(defcustom mood-line-meow-state-alist (defcustom mood-line-segment-modal-meow-state-alist
'((normal . ("<N>" . font-lock-variable-name-face)) '((normal . ("<N>" . font-lock-variable-name-face))
(insert . ("<I>" . font-lock-string-face)) (insert . ("<I>" . font-lock-string-face))
(keypad . ("<K>" . font-lock-keyword-face)) (keypad . ("<K>" . font-lock-keyword-face))
(beacon . ("<B>" . font-lock-type-face)) (beacon . ("<B>" . font-lock-type-face))
(motion . ("<M>" . font-lock-constant-face))) (motion . ("<M>" . font-lock-constant-face)))
"Set the string and corresponding face for any `meow-mode' state. "Alist specifying indicators and faces corresponding `meow-mode' states.
The `Face' may be either a face symbol or a property list of key-value pairs The face may be either a face symbol or a property list of key-value pairs;
e.g. (:foreground \"red\")." e.g., (:foreground \"red\")."
:group 'mood-line :group 'mood-line-segment-modal
:type '(alist :type '(alist :key-type symbol
:key-type symbol :value-type (cons (string :tag "Display text")
:value-type (choice :tag "Face" face plist))))
(cons (string :tag "Display Text") (choice :tag "Face" face plist))))
;; -------------------------------------------------------------------------- ;; ;; -------------------------------------------------------------------------- ;;
;; ;;
;; Modal editing segment ;; Modal editing segments
;; ;;
;; -------------------------------------------------------------------------- ;; ;; -------------------------------------------------------------------------- ;;
;; ---------------------------------- ;; ;; ---------------------------------- ;;
;; Evil segment function ;; Evil segment
;; ---------------------------------- ;; ;; ---------------------------------- ;;
(defun mood-line-segment-modal--evil () (defun mood-line-segment-modal--evil-fn ()
"Display the current evil-mode state." "Return the current `evil-mode' state."
(when (boundp 'evil-state) (when (boundp 'evil-state)
(let ((mode-cons (alist-get evil-state mood-line-evil-state-alist))) (let ((mode-cons (alist-get evil-state
mood-line-segment-modal-evil-state-alist)))
(concat (propertize (car mode-cons) (concat (propertize (car mode-cons)
'face (cdr mode-cons)) 'face (cdr mode-cons))))))
" "))))
;; ---------------------------------- ;; ;; ---------------------------------- ;;
;; Meow segment function ;; Meow segment
;; ---------------------------------- ;; ;; ---------------------------------- ;;
(defun mood-line-segment-modal--meow () (defun mood-line-segment-modal--meow-fn ()
"Display the current meow-mode state." "Return the current `meow-mode' state."
(when (boundp 'meow--current-state) (when (boundp 'meow--current-state)
(let ((mode-cons (alist-get (let ((mode-cons (alist-get meow--current-state
meow--current-state mood-line-segment-modal-meow-state-alist)))
mood-line-meow-state-alist)))
(concat (propertize (car mode-cons) (concat (propertize (car mode-cons)
'face (cdr mode-cons)) 'face (cdr mode-cons))))))
" "))))
;; ---------------------------------- ;; ;; ---------------------------------- ;;
;; God segment function ;; God segment
;; ---------------------------------- ;; ;; ---------------------------------- ;;
(defun mood-line-segment-modal--god () (defun mood-line-segment-modal--god-fn ()
"Indicate whether or not god-mode is active." "Return an indicator of whether or not `god-mode' is active."
(if (bound-and-true-p god-local-mode) (if (bound-and-true-p god-local-mode)
'(:propertize "<G> " (propertize "<G>" 'face 'mood-line-status-warning)
face (:inherit mood-line-status-warning)) "---"))
"--- "))
;; -------------------------------------------------------------------------- ;; ;; -------------------------------------------------------------------------- ;;
;; ;;

110
mood-line-segment-vc.el Normal file
View File

@ -0,0 +1,110 @@
;;; mood-line-segment-vc.el --- A vc-mode info segment for mood-line -*- lexical-binding: t; -*-
;;
;; Author: Jessie Hildebrandt <jessieh.net>
;; Homepage: https://gitlab.com/jessieh/mood-line
;; This file is not part of GNU Emacs.
;;; Commentary:
;;
;; This segment displays the current status of vc-mode.
;;; License:
;;
;; This program is free software; you can redistribute it and/or
;; modify it under the terms of the GNU General Public License as
;; published by the Free Software Foundation; either version 2, or
;; (at your option) any later version.
;;
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
;; General Public License for more details.
;;
;; You should have received a copy of the GNU General Public License
;; along with this program; see the file COPYING. If not, write to
;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth
;; Floor, Boston, MA 02110-1301, USA.
;;; Code:
;; -------------------------------------------------------------------------- ;;
;;
;; Byte-compiler declarations
;;
;; -------------------------------------------------------------------------- ;;
;; ---------------------------------- ;;
;; External function decls
;; ---------------------------------- ;;
(declare-function mood-line--get-glyph "mood-line")
;; -------------------------------------------------------------------------- ;;
;;
;; Helper functions
;;
;; -------------------------------------------------------------------------- ;;
(defun mood-line-segment-vc--rev (vc-mode-str backend)
"Return name of current file's revision for BACKEND according to `vc-mode'.
VC-MODE-STR is expected to be the value of `vc-mode' in the current buffer."
(or (pcase backend
('Git (substring-no-properties vc-mode-str 5))
('Hg (substring-no-properties vc-mode-str 4)))
(ignore-errors
(substring (vc-working-revision buffer-file-name backend) 0 7))
"???"))
;; -------------------------------------------------------------------------- ;;
;;
;; VC segment
;;
;; -------------------------------------------------------------------------- ;;
(defvar-local mood-line-segment-vc--text nil
"Mode line segment string indicating the current state of `vc-mode'.")
(defun mood-line-segment-vc--update (&rest _args)
"Update `mood-line-segment-vc--text' against the current VCS state."
(setq mood-line-segment-vc--text
(when-let* ((vc-active (and vc-mode buffer-file-name))
(backend (vc-backend buffer-file-name))
(state (vc-state buffer-file-name))
(rev (mood-line-segment-vc--rev vc-mode backend)))
(cond
((memq state '(edited added))
(format #("%s %s"
0 2 (face mood-line-status-info))
(mood-line--get-glyph :vc-added)
rev))
((eq state 'needs-merge)
(format #("%s %s"
0 2 (face mood-line-status-warning))
(mood-line--get-glyph :vc-needs-merge)
rev))
((eq state 'needs-update)
(format #("%s %s"
0 2 (face mood-line-status-warning))
(mood-line--get-glyph :vc-needs-update)
rev))
((memq state '(removed conflict unregistered))
(format #("%s %s"
0 2 (face mood-line-status-error))
(mood-line--get-glyph :vc-conflict)
rev))
(t
(format #("%s %s"
0 5 (face mood-line-status-neutral))
(mood-line--get-glyph :vc-good)
rev))))))
;; -------------------------------------------------------------------------- ;;
;;
;; Provide package
;;
;; -------------------------------------------------------------------------- ;;
(provide 'mood-line-segment-vc)
;;; mood-line-segment-vc.el ends here

File diff suppressed because it is too large Load Diff