diff options
Diffstat (limited to 'modally.el')
| -rw-r--r-- | modally.el | 241 |
1 files changed, 241 insertions, 0 deletions
diff --git a/modally.el b/modally.el new file mode 100644 index 0000000..d029ee7 --- /dev/null +++ b/modally.el @@ -0,0 +1,241 @@ +;;; modally.el --- An Emacs mode-line -*- lexical-binding: t; -*- + +;; Copyright (C) 2024 Blake Romero + +;; Author: Blake Romero <codeblake@outlook.com> +;; Keywords: extensions + +;; 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 3 of the License, 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. If not, see <https://www.gnu.org/licenses/>. + +;;; Commentary: +;; + +;;; Code: +(require 'subr-x) +(require 'cl-lib) +(require 'vc-git) +(require 'flymake) +(require 'org-timer) + +(require 'modally-faces) + +;; FUNCTIONS +(defun modally--buffer-name () + "Return a propertized buffer name string." + (let* ((buffer-face (cond + ((buffer-modified-p) 'modally-buffer-modified) + (buffer-read-only 'modally-buffer-readonly) + ('modally-buffer))) + (buffer-name (if buffer-file-name + (if (string-match "^\\(/home/[^/]+\\)\\(.+\\)" + buffer-file-name) + (concat "~" (match-string 2 buffer-file-name)) + buffer-file-name) + (buffer-name (current-buffer)))) + (spath (string-split buffer-name "/"))) + + ;; Format + (if (> (length spath) 1) + ;; if buffer has a path + (let ((path (string-join (butlast spath) "/")) + (filename (car (last spath)))) + (format "\s%s/%s" + (propertize path 'face 'modally-buffer-path) + (propertize filename 'face buffer-face))) + ;; if a buffer + (format "\s%s" (propertize buffer-name 'face buffer-face)) + ))) + +(defun modally--major-mode () + "Return a propertized major mode string." + (let ((mode (string-remove-suffix "-mode" (symbol-name major-mode)))) + (format-mode-line (format "\s%s" mode) 'modally-major-mode))) + +(defun modally--line-column () + "Return a propertized line column position." + (format-mode-line + "\sC%C" + `(,(let ((column (current-column))) + (cond + ((and (>= column (- fill-column 10)) + (< column fill-column)) + 'warning) + ((>= column fill-column) + 'modally-column-error)))))) + +(defun modally--git-branch () + "Return a propertized Git branch string." + (when-let* ((buffer (buffer-file-name)) + (branch (vc-git--symbolic-ref buffer))) + (format "\s%s |" (propertize branch 'face 'modally-git-branch)))) + +(defun modally--flymake-diagnostics () + "Return `flymake-mode' alert counts." + (let ((errors 0) (warnings 0) (notes 0) (alerts)) + (dolist (d (flymake-diagnostics)) + (pcase (flymake-diagnostic-type d) + (':error (cl-incf errors)) + (':warning (cl-incf warnings)) + (':note (cl-incf notes)))) + (when (or (> errors 0) (> warnings 0) (> notes 0)) + (when (> notes 0) + (cl-pushnew + (propertize (format "i%s" notes) 'face 'modus-themes-fg-blue) alerts)) + (when (> warnings 0) + (cl-pushnew + (propertize (format "w%s" warnings) 'face 'warning) alerts)) + (when (> errors 0) + (cl-pushnew + (propertize (format "e%s" errors) 'face 'error) alerts)) + (format "\s%s |" (string-join alerts "\s"))))) + +(defun modally--approx-time (time) + "Return an approximation of TIME." + (let ((time (replace-regexp-in-string "<\\|>" "" time)) + (h (string-to-number + (nth 0 (string-split time ":")))) + (m (string-to-number + (nth 1 (string-split time ":")))) + (s (string-to-number + (nth 2 (string-split time ":"))))) + (cond + ((and (eq h 0) (eq m 0)) + (format "%ds" s)) + ((and (eq h 0) (> m 0)) + (format "~%dm" m)) + ((and (> h 0) (> m 0)) + (format "~%dh:%dm" h m))))) + +(defun modally--org-timer () + "Return a timer from `org-timer'." + (when (or org-timer-mode-line-timer + org-timer-pause-time) + (let ((face (if org-timer-pause-time + 'modally-org-timer-pause + 'modally-org-timer))) + (format "\s%s |" + (propertize + (modally--approx-time org-timer-mode-line-string) + 'face face))))) + +;; VARIABLES +(defvar modally-display-buffer-name + '(:eval (modally--buffer-name)) + "Modeline construct to display the buffer name.") + +(defvar modally-display-major-mode + '(:eval (modally--major-mode)) + "Modeline construct to display the major mode.") + +(defvar modally-display-git-branch + '(:eval (modally--git-branch)) + "Modeline construct to display the Git branch name.") + +(defvar modally-display-line-column + '(:eval (modally--line-column)) + "Modeline construct to display line & column position.") + +(defvar modally-display-line-row + '(:eval (format-mode-line "\sL%l")) + "Modeline construct to display line & column position.") + +(defvar modally-display-file-size + '(:eval (format-mode-line "\s%I")) + "Modeline construct to display file size of buffer.") + +(defvar modally-display-flymake + '(:eval (modally--flymake-diagnostics)) + "Modeline construct to display flymake info.") + +(defvar modally-display-org-timer + '(:eval (modally--org-timer)) + "Modeline construct to display `org-timer' info.") + +;; set as risky local variable +(dolist (construct '(modally-display-buffer-name + modally-display-major-mode + modally-display-git-branch + modally-display-line-row + modally-display-line-column + modally-display-file-size + modally-display-flymake + modally-display-org-timer)) + (put construct 'risky-local-variable #'stringp)) + +;; FORMATS +(defvar modally-format-default + `("%e" + modally-display-buffer-name + + mode-line-format-right-align + modally-display-org-timer + modally-display-line-row + modally-display-line-column + " |" + modally-display-git-branch + modally-display-file-size + " |" + modally-display-flymake + modally-display-major-mode + ) + "Default modally format for the mode-line.") + +;; HELPERS +(defun modally--set-face () + "Set mode-line face." + (set-face-attribute + 'mode-line-active nil + :background "black" + :foreground "white" + :box '(:line-width (20 . 2) :color "#444444")) + (set-face-attribute + 'mode-line-inactive nil + :background "black" + :foreground "grey" + :box '(:line-width (20 . 2) :color "#222222"))) + +(defun modally--reset-face() + "Reset mode-line face." + (set-face-attribute + 'mode-line nil + :background "black" + :foreground "white" + :box t)) + +(defun modally--reset-mode-line () + "Reset mode-line." + (setq-default mode-line-format (car (get 'mode-line-format 'standard-value))) + (modally--reset-face)) + +(defun modally--set-mode-line () + "Set modally mode-line." + (setq-default mode-line-format modally-format-default) + (with-eval-after-load 'keycast + (setq-default keycast-mode-line-insert-after 'modally-display-git-branch)) + (modally--set-face)) + +;; MODE +;;;###autoload +(define-minor-mode modally-mode + "An Emacs mode-line." + :group 'modally + :global t + :require '(subr-x vc-git flymake cl-lib) + :lighter " MDL" + (if modally-mode + (modally--set-mode-line) + (modally--reset-mode-line))) + +(provide 'modally) +;;; modally.el ends here |
