Compare commits

..

No commits in common. "main" and "2.3.0" have entirely different histories.
main ... 2.3.0

13 changed files with 576 additions and 1109 deletions

View File

@ -1,20 +0,0 @@
```lisp
;; Emacs 29 with native compilation, default GC threshold
;; Run in a lisp-interaction-mode buffer with Flymake
(defun time-mode-line (num &optional and-mem)
(let ((gc-cons-threshold (if and-mem gc-cons-threshold most-positive-fixnum))
(start-time (current-time)))
(cl-loop for i to num
do (format-mode-line mode-line-format))
(format-time-string "%s.%3N seconds" (time-since start-time))))
;; Default mode line:
(time-mode-line 10000) ;; "0.440 seconds"
(time-mode-line 10000 :and-mem) ;; "2.402 seconds"
;; mood-line (default settings):
(mood-line-mode t)
(time-mode-line 10000) ;; "0.309 seconds"
(time-mode-line 10000 :and-mem) ;; "1.286 seconds"
```

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 65 KiB

View File

@ -1,25 +1,32 @@
# <img src=".repo-assets/icon.png" width=50> mood-line # mood-line
A lightweight, drop-in replacement for the default Emacs mode line configuration.
[![MELPA](https://melpa.org/packages/mood-line-badge.svg)](https://melpa.org/#/mood-line) [![MELPA](https://melpa.org/packages/mood-line-badge.svg)](https://melpa.org/#/mood-line)
[![MELPA Stable](https://stable.melpa.org/packages/mood-line-badge.svg)](https://stable.melpa.org/#/mood-line) [![MELPA Stable](https://stable.melpa.org/packages/mood-line-badge.svg)](https://stable.melpa.org/#/mood-line)
## About
mood-line is a minimal mode line configuration that aims to replicate some of the features of the
more advanced [doom-modeline](https://github.com/seagle0128/doom-modeline) package.
## Features ## Features
* Clean, informative design * Clean, minimal design
* Customizable, modular segment format
* Customizable glyph sets * Customizable glyph sets
* Lazy-loaded extensions * Anzu and multiple-cursors counters
* [Lightweight](.repo-assets/benchmark.md), no dependencies * Encoding and EOL style indicator
* Version control status indicator
* Custom Flycheck/Flymake indicator
* Lightweight with no dependencies
## Preview ## Preview
![Preview Image](.repo-assets/preview.webp "Preview Image") ![Preview Image](https://gitlab.com/jessieh/mood-line/raw/assets/mood-line.png "Preview Image")
## Configuration ## Configuration
@ -38,49 +45,15 @@ If you are a user of `use-package`, it is easy to configure mood-line directly i
;; Use pretty Fira Code-compatible glyphs ;; Use pretty Fira Code-compatible glyphs
:custom :custom
(mood-line-glyph-alist mood-line-glyphs-fira-code)) (mood-line-glyph-alist . mood-line-glyphs-fira-code))
``` ```
### Format
mood-line uses a modular segment format, and it is easy to reconfigure:
```elisp
;; Default format:
;; * init.el 4:32 Top ELisp ! Issues: 2
(setq mood-line-format mood-line-format-default)
;; Extended format:
;; * init.el 4:32:52 Top SPCx2 LF UTF-8 ELisp ! Issues: 2
(setq mood-line-format mood-line-format-default-extended)
;; Custom format:
;; * init.el : ELisp Top 4:32 | ! Issues: 2
(setq mood-line-format
(mood-line-defformat
:left
(((mood-line-segment-buffer-status) . " ")
((mood-line-segment-buffer-name) . " : ")
(mood-line-segment-major-mode))
:right
(((mood-line-segment-scroll) . " ")
((mood-line-segment-cursor-position) . " ")
((when (mood-line-segment-checker) "|") . " ")
((mood-line-segment-checker) . " "))))
```
More information on the format specification is available in the documentation:\
`M-x describe-variable mood-line-format`\
`M-x describe-function mood-line-defformat`
### Glyphs
By default, mood-line will use basic ASCII character glyphs to decorate mode line segments. By default, mood-line will use basic ASCII character glyphs to decorate mode line segments.
If you'd like to see prettier Unicode glyphs, you can change the value of `mood-line-glyph-alist`: If you'd like to see prettier Unicode glyphs, you can change the value of `mood-line-glyph-alist`:
```elisp ```elisp
;; The default set of glyphs: ;; The default set of glyphs:
;; * myModifiedFile.js Replace*3 + main JavaScript ! Issues: 2 ;; * myModifiedFile.js Replace*3 + main Javascript ! Issues: 2
(setq mood-line-glyph-alist mood-line-glyphs-ascii) (setq mood-line-glyph-alist mood-line-glyphs-ascii)
;; A set of Fira Code-compatible Unicode glyphs: ;; A set of Fira Code-compatible Unicode glyphs:
@ -99,18 +72,10 @@ If you'd like to supply your own glyphs, you can use the customization interface
You can further tweak the behavior and appearance of mood-line by viewing the customizable variables You can further tweak the behavior and appearance of mood-line by viewing the customizable variables
and faces in the `mood-line` and `mood-line-faces` customization groups. (`M-x customize-group mood-line`) and faces in the `mood-line` and `mood-line-faces` customization groups. (`M-x customize-group mood-line`)
## Testing
To run the included tests:
```bash
./ert-test.sh
```
## Feedback ## Feedback
If you experience any issues with this package, please If you experience any issues with this package, please
[open an issue](https://git.tty.dog/jessieh/mood-line/issues/new) [open an issue](https://gitlab.com/jessieh/mood-line/issues/new)
on the issue tracker. on the issue tracker.
Suggestions for improvements and feature requests are always appreciated, as well! Suggestions for improvements and feature requests are always appreciated, as well!

View File

@ -1,5 +0,0 @@
#!/bin/bash
emacs --quick --batch --load=ert \
--load=test/mood-line-test.el \
--load=test/mood-line-segment-vc-test.el \
--funcall=ert-run-tests-batch-and-exit

View File

@ -1,168 +0,0 @@
;;; 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
;;
;; -------------------------------------------------------------------------- ;;
;; ---------------------------------- ;;
;; Required features
;; ---------------------------------- ;;
(eval-when-compile
(require 'flymake))
;; ---------------------------------- ;;
;; External variable defs
;; ---------------------------------- ;;
(eval-when-compile
(defvar flycheck-current-errors))
;; ---------------------------------- ;;
;; External function decls
;; ---------------------------------- ;;
(eval-when-compile
(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

@ -3,7 +3,7 @@
;; Author: Alynx Zhou <alynx.zhou@gmail.com> ;; Author: Alynx Zhou <alynx.zhou@gmail.com>
;; Jessie Hildebrandt <jessieh.net> ;; Jessie Hildebrandt <jessieh.net>
;; Homepage: https://gitlab.com/jessieh/mood-line ;; Homepage: https://gitlab.com/jessieh/mood-line
;;
;; This file is not part of GNU Emacs. ;; This file is not part of GNU Emacs.
;;; Commentary: ;;; Commentary:
@ -39,8 +39,7 @@
;; External function decls ;; External function decls
;; ---------------------------------- ;; ;; ---------------------------------- ;;
(eval-when-compile (declare-function mood-line--get-glyph "mood-line" (glyph))
(declare-function mood-line--get-glyph "mood-line"))
;; -------------------------------------------------------------------------- ;; ;; -------------------------------------------------------------------------- ;;
;; ;;
@ -48,14 +47,6 @@
;; ;;
;; -------------------------------------------------------------------------- ;; ;; -------------------------------------------------------------------------- ;;
;; ---------------------------------- ;;
;; Group definitions
;; ---------------------------------- ;;
(defgroup mood-line-segment-indentation nil
"An indentation info segment for mood-line."
:group 'mood-line)
;; ---------------------------------- ;; ;; ---------------------------------- ;;
;; Variable definitions ;; Variable definitions
;; ---------------------------------- ;; ;; ---------------------------------- ;;
@ -64,14 +55,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-segment-indentation :group 'mood-line
:type 'boolean) :type 'boolean)
;; Assembled from `editorconfig-indentation-alist' and `doom-modeline-indent-alist': ;; Assembled from `editorconfig-indentation-alist' and `doom-modeline-indent-alist':
@ -182,9 +173,9 @@ When `mood-line-segment-indentation-always-show-offset' is set to non-nil, the
"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-segment-indentation :group 'mood-line
:type '(alist :key-type symbol :value-type sexp)) :type '(alist :key-type symbol :value-type sexp))
;; -------------------------------------------------------------------------- ;; ;; -------------------------------------------------------------------------- ;;
@ -197,8 +188,8 @@ When multiple variables are specified for a given mode, the offset value will
;; Segment function ;; Segment function
;; ---------------------------------- ;; ;; ---------------------------------- ;;
(defun mood-line-segment-indentation () (defun mood-line-segment-indentation--segment ()
"Return the indentation style of the current buffer." "Display 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
@ -211,7 +202,8 @@ When multiple variables are specified for a given mode, the offset value will
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,9 +1,9 @@
;;; mood-line-segment-modal.el --- A modal editing status segment for mood-line -*- lexical-binding: t; -*- ;;; mood-line-segment-modal.el --- A modal editing 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>
;; Homepage: https://gitlab.com/jessieh/mood-line ;; Homepage: https://gitlab.com/jessieh/mood-line
;;
;; This file is not part of GNU Emacs. ;; This file is not part of GNU Emacs.
;;; Commentary: ;;; Commentary:
@ -35,19 +35,11 @@
;; ;;
;; -------------------------------------------------------------------------- ;; ;; -------------------------------------------------------------------------- ;;
;; ---------------------------------- ;;
;; 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-segment-modal-evil-state-alist (defcustom mood-line-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))
@ -55,77 +47,72 @@
(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)))
"Alist specifying indicators and faces for corresponding `evil-mode' states. "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; 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-segment-modal :group 'mood-line
:type '(alist :key-type symbol :type '(alist
:value-type (cons (string :tag "Display text") :key-type symbol
(choice :tag "Face" face plist)))) :value-type
(cons (string :tag "Display Text") (choice :tag "Face" face plist))))
(defcustom mood-line-segment-modal-meow-state-alist (defcustom mood-line-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)))
"Alist specifying indicators and faces corresponding `meow-mode' states. "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; 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-segment-modal :group 'mood-line
:type '(alist :key-type symbol :type '(alist
:value-type (cons (string :tag "Display text") :key-type symbol
(choice :tag "Face" face plist)))) :value-type
(cons (string :tag "Display Text") (choice :tag "Face" face plist))))
;; -------------------------------------------------------------------------- ;; ;; -------------------------------------------------------------------------- ;;
;; ;;
;; Modal editing segments ;; Modal editing segment
;; ;;
;; -------------------------------------------------------------------------- ;; ;; -------------------------------------------------------------------------- ;;
;; ---------------------------------- ;; ;; ---------------------------------- ;;
;; Evil segment ;; Evil segment function
;; ---------------------------------- ;; ;; ---------------------------------- ;;
(defun mood-line-segment-modal--evil-fn () (defun mood-line-segment-modal--evil ()
"Return the current `evil-mode' state." "Display the current evil-mode state."
(when (boundp 'evil-state) (when (boundp 'evil-state)
(let ((mode-cons (alist-get evil-state (let ((mode-cons (alist-get evil-state mood-line-evil-state-alist)))
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 ;; Meow segment function
;; ---------------------------------- ;; ;; ---------------------------------- ;;
(defun mood-line-segment-modal--meow-fn () (defun mood-line-segment-modal--meow ()
"Return the current `meow-mode' state." "Display the current meow-mode state."
(when (boundp 'meow--current-state) (when (boundp 'meow--current-state)
(let ((mode-cons (alist-get meow--current-state (let ((mode-cons (alist-get
mood-line-segment-modal-meow-state-alist))) meow--current-state
mood-line-meow-state-alist)))
(concat (propertize (car mode-cons) (concat (propertize (car mode-cons)
'face (cdr mode-cons)))))) 'face (cdr mode-cons))
" "))))
;; ---------------------------------- ;; ;; ---------------------------------- ;;
;; Xah segment ;; God segment function
;; ---------------------------------- ;; ;; ---------------------------------- ;;
(defun mood-line-segment-modal--xah-fn () (defun mood-line-segment-modal--god ()
"Display the current xah-fly-keys state." "Indicate whether or not god-mode is active."
(if (bound-and-true-p xah-fly-insert-state-p)
"<I>"
"<C>"))
;; ---------------------------------- ;;
;; God segment
;; ---------------------------------- ;;
(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) (if (bound-and-true-p god-local-mode)
(propertize "<G>" 'face 'mood-line-status-warning) '(:propertize "<G> "
"---")) face (:inherit mood-line-status-warning))
"--- "))
;; -------------------------------------------------------------------------- ;; ;; -------------------------------------------------------------------------- ;;
;; ;;

View File

@ -1,114 +0,0 @@
;;; 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
;; ---------------------------------- ;;
(eval-when-compile
(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.
If `vc-display-status' is nil, return the name of BACKEND."
(or (unless vc-display-status
(symbol-name backend))
(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

View File

@ -1,45 +0,0 @@
;;; mood-line-segment-vc-test.el --- Test specifications for mood-line-segment-vc.el -*- lexical-binding: t; -*-
(add-to-list 'load-path ".")
(require 'ert)
(require 'mood-line)
(require 'mood-line-segment-vc)
;;; Code:
;; -------------------------------------------------------------------------- ;;
;;
;; Helper functions
;;
;; -------------------------------------------------------------------------- ;;
;; ---------------------------------- ;;
;; mood-line-segment-vc--rev
;; ---------------------------------- ;;
(ert-deftest --rev/git ()
"Current rev should be cleanly extracted from git `vc-mode' status string."
(should (string= (mood-line-segment-vc--rev " Git:main" 'Git)
"main")))
(ert-deftest --rev/hg ()
"Current rev should be cleanly extracted from hg `vc-mode' status string."
(should (string= (mood-line-segment-vc--rev " Hg:main" 'Hg)
"main")))
(ert-deftest --rev/unknown ()
"Current rev should be reported as \"???\" when backend is unsupported."
(let ((buffer-file-name ""))
(should (string= (mood-line-segment-vc--rev "" 'SVN)
"???"))))
(ert-deftest --rev/vc-display-status-nil ()
"Name of the VCS backend should be reported when `vc-display-status' is nil."
(let ((vc-display-status nil))
(should (string= (mood-line-segment-vc--rev " Git:main" 'Git)
"Git"))
(should (string= (mood-line-segment-vc--rev " Hg:main" 'Hg)
"Hg"))))
;;; mood-line-segment-vc-test.el ends here

View File

@ -1,206 +0,0 @@
;;; mood-line-test.el --- Test specifications for mood-line.el -*- lexical-binding: t; -*-
(add-to-list 'load-path ".")
(require 'ert)
(require 'mood-line)
;;; Code:
;; -------------------------------------------------------------------------- ;;
;;
;; Macros
;;
;; -------------------------------------------------------------------------- ;;
;; ---------------------------------- ;;
;; mood-line-defformat
;; ---------------------------------- ;;
(ert-deftest -defformat/padding ()
"The expanded sequence should include the provided (or default) padding."
(should (equal (mood-line-defformat)
(list
;; Left
'(" ")
;; Right
'(" "))))
(should (equal (mood-line-defformat
:padding
"---")
(list
;; Left
'("---")
;; Right
'("---")))))
(ert-deftest -defformat/left-right-nil ()
"The format sequence should expand if the left or right segment list is nil."
(should (equal (mood-line-defformat
:left
("XYZ"))
(list
;; Left
'(" " "XYZ")
;; Right
'(" "))))
(should (equal (mood-line-defformat
:right
("XYZ"))
(list
;; Left
'(" ")
;; Right
'("XYZ" " ")))))
(ert-deftest -defformat/left-right ()
"The expanded sequence should include left and right segments lists."
(should (equal (mood-line-defformat
:left
("ABC")
:right
("XYZ"))
(list
;; Left
'(" " "ABC")
;; Right
'("XYZ" " ")))))
(ert-deftest -defformat/cons-cells ()
"Cons cell segments should expand into their `car' and `cdr' values."
(should (equal (mood-line-defformat
:left
("ABC" ("ABC" . "XYZ") "XYZ")
:right
("..." ((some-fn) . " ") "..."))
(list
;; Left
'(" " "ABC" "ABC" "XYZ" "XYZ")
;; Right
'("..." (some-fn) " " "..." " ")))))
(ert-deftest -defformat/exp-separators ()
"Non-string, non-cons expressions should expand followed by a blank string."
(should (equal (mood-line-defformat
:left
("ABC" ("ABC" . "XYZ") some-exp "XYZ" (some-fn))
:right
("..." ((some-fn) . " ") (another-fn) "..."))
(list
;; Left
'(" " "ABC" "ABC" "XYZ" some-exp "" "XYZ" (some-fn) "")
;; Right
'("..." (some-fn) " " (another-fn) "" "..." " ")))))
;; -------------------------------------------------------------------------- ;;
;;
;; Helper functions
;;
;; -------------------------------------------------------------------------- ;;
;; ---------------------------------- ;;
;; mood-line--get-glyph
;; ---------------------------------- ;;
(ert-deftest --get-glyph/unicode ()
"Glyphs should be fethed from `mood-line-glyph-alist'."
(let ((mood-line-glyph-alist '((:checker-info . ?🛈))))
(should (string= (mood-line--get-glyph :checker-info) "🛈"))))
(ert-deftest --get-glyph/fallback-ascii ()
"Glyphs should be fetched from `mood-line-glyphs-ascii' as a fallback."
(let ((mood-line-glyph-alist nil))
(should (string= (mood-line--get-glyph :checker-info) "i"))))
;; ---------------------------------- ;;
;; mood-line--process-segments
;; ---------------------------------- ;;
(ert-deftest --process-segments/default ()
"`mood-line-format-default' should be processed without error."
(let* ((left (car mood-line-format-default))
(right (cadr mood-line-format-default))
(left-str (mood-line--process-segments left))
(right-str (mood-line--process-segments right)))
(should (> (length left-str) 0))
(should (> (length right-str) 0))))
(ert-deftest --process-segments/strings ()
"Literal strings should be concatenated."
(let* ((segments '("ABC" " " "123" " " "XYZ"))
(segments-str (mood-line--process-segments segments)))
(should (string= segments-str "ABC 123 XYZ"))))
(ert-deftest --process-segments/nil-neighbor-exclusion ()
"A nil value should mean skipping evaluation of the following segment."
(let* ((segments '("ABC" nil " " "123" nil " " "XYZ" nil))
(segments-str (mood-line--process-segments segments)))
(should (string= segments-str "ABC123XYZ"))))
(ert-deftest --process-segments/functions ()
"Functions should be evaluated, and their return values concatenated."
(let* ((segments '((string ?A ?B ?C)
(numberp nil) " "
(number-to-string (+ 100 20 3))
(identity nil) " "
(concat "X" "Y" "Z")))
(segments-str (mood-line--process-segments segments)))
(should (string= segments-str "ABC123XYZ"))))
;; ---------------------------------- ;;
;; mood-line--process-format
;; ---------------------------------- ;;
(ert-deftest --process-format/default ()
"`mood-line-format-default' should be processed without error."
(let* ((format-str (mood-line--process-format mood-line-format-default)))
(should (> (length format-str) 0))))
(ert-deftest --process-format/nil-okay ()
"Either segment list should process without error if the other list is nil."
(let* ((format-l-nil '(nil ("ABC" nil " " "123" nil " " "XYZ")))
(format-r-nil '(("ABC" nil " " "123" nil " " "XYZ") nil))
(format-l-nil-str (mood-line--process-format format-l-nil))
(format-r-nil-str (mood-line--process-format format-r-nil)))
(should (string-suffix-p "ABC123XYZ" format-l-nil-str))
(should (string-prefix-p "ABC123XYZ" format-r-nil-str))))
;; -------------------------------------------------------------------------- ;;
;;
;; mood-line-mode
;;
;; -------------------------------------------------------------------------- ;;
;; ---------------------------------- ;;
;; mood-line--activate
;; ---------------------------------- ;;
(ert-deftest --activate/mode-line-format ()
"`mode-line-format' should be set by `mood-line--activate'."
(let* ((setting-val (alist-get 'mode-line-format
mood-line--settings-alist))
(mood-line--settings-alist `((mode-line-format . ,setting-val)))
(mood-line-format mood-line-format-default)
(mode-line-format '("ABC 123 XYZ"))
(format-str (mood-line--process-format mood-line-format)))
(mood-line--activate)
(should (string= (format-mode-line mode-line-format)
(format-mode-line format-str)))))
;; ---------------------------------- ;;
;; mood-line--deactivate
;; ---------------------------------- ;;
(ert-deftest --deactivate/mode-line-format ()
"`mode-line-format' should be restored by `mood-line--deactivate'."
(let* ((setting-val (alist-get 'mode-line-format
mood-line--settings-alist))
(mood-line--settings-alist `((mode-line-format . ,setting-val)))
(mood-line--settings-backup-alist nil)
(mood-line-format mood-line-format-default)
(mode-line-format "ABC 123 XYZ"))
(mood-line--activate)
(mood-line--deactivate)
(should (string= mode-line-format "ABC 123 XYZ"))))
;;; mood-line-test.el ends here