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
;; ---------------------------------- ;;
(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
;; ---------------------------------- ;;
@ -55,14 +63,14 @@
"When non-nil, always show the indentation offset of the current mode.
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
be found for the current mode. Otherwise, `tab-wdith' will be shown.
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.
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
value cannot be found for the current mode, a \"?\" character will be displayed
alongside `tab-width'."
:group 'mood-line
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
alongside `tab-width'."
:group 'mood-line-segment-indentation
:type 'boolean)
;; 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.
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
order provided)."
:group 'mood-line
be retrieved from the first variable that resolves to a value, evaluated in the
order provided."
:group 'mood-line-segment-indentation
:type '(alist :key-type symbol :value-type sexp))
;; -------------------------------------------------------------------------- ;;
@ -188,8 +196,8 @@ order provided)."
;; Segment function
;; ---------------------------------- ;;
(defun mood-line-segment-indentation--segment ()
"Display the indentation style of the current buffer."
(defun mood-line-segment-indentation ()
"Return the indentation style of the current buffer."
(let* ((mode-offset (symbol-value
(seq-some #'identity
(cdr (assoc major-mode
@ -202,8 +210,7 @@ order provided)."
tab-width)
(number-to-string (if indent-tabs-mode
tab-width
(or mode-offset tab-width))))
" ")
(or mode-offset tab-width)))))
'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>
;; 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
;; ---------------------------------- ;;
(defcustom mood-line-evil-state-alist
(defcustom mood-line-segment-modal-evil-state-alist
'((normal . ("<N>" . font-lock-variable-name-face))
(insert . ("<I>" . font-lock-string-face))
(visual . ("<V>" . font-lock-keyword-face))
@ -47,72 +55,67 @@
(motion . ("<M>" . font-lock-constant-face))
(operator . ("<O>" . font-lock-function-name-face))
(emacs . ("<E>" . font-lock-builtin-face)))
"Set the string and corresponding face for any `evil-mode' state.
The `Face' may be either a face symbol or a property list of key-value pairs
e.g. (:foreground \"red\")."
:group 'mood-line
:type '(alist
:key-type symbol
:value-type
(cons (string :tag "Display Text") (choice :tag "Face" face plist))))
"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;
e.g., (:foreground \"red\")."
:group 'mood-line-segment-modal
:type '(alist :key-type symbol
:value-type (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))
(insert . ("<I>" . font-lock-string-face))
(keypad . ("<K>" . font-lock-keyword-face))
(beacon . ("<B>" . font-lock-type-face))
(motion . ("<M>" . font-lock-constant-face)))
"Set the string and corresponding face for any `meow-mode' state.
The `Face' may be either a face symbol or a property list of key-value pairs
e.g. (:foreground \"red\")."
:group 'mood-line
:type '(alist
:key-type symbol
:value-type
(cons (string :tag "Display Text") (choice :tag "Face" face plist))))
"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;
e.g., (:foreground \"red\")."
:group 'mood-line-segment-modal
:type '(alist :key-type symbol
:value-type (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 ()
"Display the current evil-mode state."
(defun mood-line-segment-modal--evil-fn ()
"Return the current `evil-mode' 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)
'face (cdr mode-cons))
" "))))
'face (cdr mode-cons))))))
;; ---------------------------------- ;;
;; Meow segment function
;; Meow segment
;; ---------------------------------- ;;
(defun mood-line-segment-modal--meow ()
"Display the current meow-mode state."
(defun mood-line-segment-modal--meow-fn ()
"Return the current `meow-mode' state."
(when (boundp 'meow--current-state)
(let ((mode-cons (alist-get
meow--current-state
mood-line-meow-state-alist)))
(let ((mode-cons (alist-get meow--current-state
mood-line-segment-modal-meow-state-alist)))
(concat (propertize (car mode-cons)
'face (cdr mode-cons))
" "))))
'face (cdr mode-cons))))))
;; ---------------------------------- ;;
;; God segment function
;; God segment
;; ---------------------------------- ;;
(defun mood-line-segment-modal--god ()
"Indicate whether or not god-mode is active."
(defun mood-line-segment-modal--god-fn ()
"Return an indicator of whether or not `god-mode' is active."
(if (bound-and-true-p god-local-mode)
'(:propertize "<G> "
face (:inherit mood-line-status-warning))
"--- "))
(propertize "<G>" 'face '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