diff --git a/elisp/eshell-starship.el b/elisp/eshell-starship.el index 08e2b6e..4ffea7a 100644 --- a/elisp/eshell-starship.el +++ b/elisp/eshell-starship.el @@ -58,6 +58,12 @@ appear at most once to denote \"all remaining modules\"." :tag "Suppress eshell-starship explore refresh messages" :type 'boolean) +(defface eshell-starship-icon-face '((t :inherit default)) + "Face to use when drawing module icons. +Note that the foreground color will be overridden by the module." + :group 'eshell-starship + :tag "Icon face") + ;;; Module API (defvar eshell-starship-modules (make-hash-table :test 'equal) @@ -252,7 +258,7 @@ Example: :doc "The current working directory.") -;;; VC (git) module +;;; Git module (defun eshell-starship--git-parse-status-headers () "Parse the status headers (read from the current buffer). The headers are as described in the porcelain v2 section of the git-status(3) @@ -372,39 +378,51 @@ For example, a revert. If there is no current operation, return nil." (goto-char (point-min)) (cl-destructuring-bind (oid head _upstream ahead behind stash) (eshell-starship--git-parse-status-headers) - (let ((file-status (eshell-starship--git-file-status stash ahead - behind)) - (operation (eshell-starship--git-current-operation))) - (concat - (if (string= "(detached)" head) - (propertize (concat " (" (substring oid 0 7) ")") - 'face '(:foreground "lawn green")) - (propertize (concat "󰊢 " head) - 'face '(:foreground "medium purple"))) - (unless (string-empty-p file-status) - (propertize (concat " [" file-status "]") - 'face '(:foreground "red"))) - (when operation - (concat " (" (propertize - operation 'face - '(:inherit bold :foreground "yellow")) ")")))))))) + (let* ((file-status (eshell-starship--git-file-status stash ahead + behind)) + (operation (eshell-starship--git-current-operation)) + (output + (concat + (if (string= "(detached)" head) + (propertize (concat " (" (substring oid 0 7) ")") + 'face '(:foreground "lawn green")) + (propertize (concat head) + 'face '(:foreground "medium purple"))) + (unless (string-empty-p file-status) + (propertize (concat " [" file-status "]") + 'face '(:foreground "red"))) + (when operation + (concat " (" (propertize + operation 'face + '(:inherit bold :foreground "yellow")) + ")"))))) + (unless (zerop (length output)) + output)))))) +(eshell-starship-defmodule git + :predicate (lambda () + (eq (vc-responsible-backend default-directory t) 'Git)) + :color "medium purple" + :icon "󰊢 " + :reload-on 'always + :action 'eshell-starship--git-status) + + +;;; Non-git VC module (defun eshell-starship--vc-status () "Get vc status for `eshell-starship--prompt-function'." - (if-let (backend (vc-responsible-backend default-directory t)) - (if (eq backend 'Git) - (let ((status (eshell-starship--git-status))) - (and (not (zerop (length status))) status)) - (propertize - (concat " " (downcase (symbol-name backend))) - 'face '(:foreground "purple"))))) + (when-let ((backend (vc-responsible-backend default-directory t)) + ((not (eq backend 'Git)))) + (downcase (symbol-name backend)))) (eshell-starship-defmodule vc :predicate 'always :allow-remote nil :reload-on 'always + :color "purple" + :icon " " :action 'eshell-starship--vc-status - :doc "The working directory's version control status.") + :doc "The working directory's version control status (other than git).") ;;; Timer module @@ -421,7 +439,8 @@ For example, a revert. If there is no current operation, return nil." eshell-starship--last-end-time (eshell-starship-format-span (- eshell-starship--last-end-time eshell-starship--last-start-time))) - (setq eshell-starship--last-start-time nil))) + (setq eshell-starship--last-start-time nil + eshell-starship--last-end-time nil))) (eshell-starship-defmodule cmd-time :prefix "took " @@ -671,6 +690,17 @@ The test is performed relative to `default-directory'." (and extensions (apply' eshell-starship--exts-exist-p extensions)) (and predicate (funcall predicate))))))) +(defun eshell-starship--propertize-face (str append &rest faces) + "Copy STR and add FACES to its text properties. +This uses `add-face-text-property' internally, so it will add to existing `face' +properties. If STR is nil, return an empty string. If APPEND, give priority to +existing faces." + (if (not str) + "" + (let ((copy (copy-sequence str))) + (dolist (face faces copy) + (add-face-text-property 0 (length copy) face append copy))))) + (defun eshell-starship--execute-module (module) "Run the module MODULE and return its output. Also cache the time it took to run it and its output." @@ -681,12 +711,18 @@ Also cache the time it took to run it and its output." result (funcall action) end-time (float-time)) (when-let ((result) - (output (concat prefix - (if color - (propertize (concat icon result) - 'face `(:foreground ,color)) - (concat icon result)) - postfix))) + (output + (concat prefix + (eshell-starship--propertize-face + icon t + (when color + (list (list :foreground color))) + 'eshell-starship-icon-face) + (if color + (eshell-starship--propertize-face + result t (list :foreground color)) + result) + postfix))) (puthash name (list t output (cons (- end-time start-time) (take 9 oldtimes))) eshell-starship--module-cache) diff --git a/init.el b/init.el index 6b84330..219cfbb 100644 --- a/init.el +++ b/init.el @@ -2002,7 +2002,9 @@ If no name is given, list all bookmarks instead." :demand t :hook (eshell-prompt-mode . eshell-starship-prompt-mode) :config - (eshell-starship-setup-evil-keybindings)) + (eshell-starship-setup-evil-keybindings) + (set-face-attribute 'eshell-starship-icon-face nil + :family "FiraCode Nerd Font")) ;; proced (use-package proced