Add git stash support and make branch status more efficient

This commit is contained in:
Alexander Rosenberg 2024-01-17 21:12:42 -08:00
parent 7b9cc70e7c
commit 47039d4bfe
Signed by: Zander671
GPG Key ID: 5FD0394ADBD72730

View File

@ -5,6 +5,7 @@
(require 'vc) (require 'vc)
(require 'vc-git) (require 'vc-git)
(require 'eshell) (require 'eshell)
(require 'cl-lib)
(defun eshell-starship--git-process-lines (&rest flags) (defun eshell-starship--git-process-lines (&rest flags)
"Run `vc-git-program' and return an array of its output lines. "Run `vc-git-program' and return an array of its output lines.
@ -43,68 +44,56 @@ Example:
(if-let ((worktree (vc-root-dir)) (if-let ((worktree (vc-root-dir))
(parent (file-name-parent-directory worktree))) (parent (file-name-parent-directory worktree)))
(file-relative-name default-directory parent) (file-relative-name default-directory parent)
(eshell-starship--replace-home-with-tilda default-directory)))) (eshell-starship--replace-home-with-tilda
default-directory))))
(defun eshell-starship--prompt-status-char-for-branch (branch remote) (defun eshell-starship--prompt-current-branch-status (status-line)
"Get the status char representing the relation between BRANCH and REMOTE." "Get the status char for the current branch and its remote.
(let ((lines (eshell-starship--git-process-lines STATUS-LINE is the first line of output from \"git status --porcelain=v1 -b\"."
"rev-list" (when (string-match
"--left-right" "\\[\\(?:ahead \\([0-9]+\\)\\)?,? ?\\(?:behind \\([0-9]+\\)\\)?\\]$"
(concat branch "..." remote))) status-line)
(to-remote nil) (let ((ahead (match-string 1 status-line))
(to-local nil)) (behind (match-string 2 status-line)))
(dolist (line lines)
(if-let (((not (string-empty-p line)))
(dir-char (aref line 0)))
(if (= dir-char ?<)
(setq to-remote t)
(setq to-local t))))
(cond (cond
((and to-remote to-local) ?󰹺) ((and ahead behind) ?󰹺)
(to-remote ?󰜷) (ahead ?󰜷)
(to-local ?󰜮)))) (behind ?󰜮)))))
(defun eshell-starship--prompt-git-has-stash ()
(defun eshell-starship--prompt-current-branch-status () "Return t if the current git directory has a stash, nil otherwise."
"Get the status char for the current branch and its remote." (= (process-file vc-git-program nil nil nil
(let ((refs (eshell-starship--git-process-lines "rev-parse" "--verify" "refs/stash") 0))
"for-each-ref"
"--format=%(HEAD)%00%(refname:short)%00%(upstream:short)"
"refs/heads")))
(catch 'break
(dolist (ref refs)
(if-let ((split-ref (split-string ref "\0" nil nil))
((equal (car split-ref) "*")))
(throw 'break (eshell-starship--prompt-status-char-for-branch
(cadr split-ref)
(caddr split-ref))))))))
(defun eshell-starship--prompt-git-state-chars () (defun eshell-starship--prompt-git-state-chars ()
"Get chars, like + and ✘ for `eshell-starship--prompt-function'." "Get chars, like + and ✘ for `eshell-starship--prompt-function'."
(let ((lines (eshell-starship--git-process-lines "status" "--porcelain=v1")) (let* ((lines (eshell-starship--git-process-lines "status" "--porcelain=v1" "-b"))
(branch-status (eshell-starship--prompt-current-branch-status)) (branch-status (eshell-starship--prompt-current-branch-status
(car lines)))
(status-arr)) (status-arr))
(dolist (line lines) (dolist (line (cdr lines))
(cl-loop with fields = (string-split line " " t " *") (cl-loop with fields = (string-split line " " t " *")
with status-str = (car-safe fields) with status-str = (car-safe fields)
for status-char across status-str for status-char across status-str
do do
(cond ((or (= status-char ?M) (= status-char ?T)) (cond ((or (= status-char ?M) (= status-char ?T))
(add-to-list 'status-arr ?!)) (push ?! status-arr))
((= status-char ??) ((= status-char ??)
(add-to-list 'status-arr ??)) (push ?? status-arr))
((or (= status-char ?A) (= status-char ?C)) ((or (= status-char ?A) (= status-char ?C))
(add-to-list 'status-arr ?+)) (push ?+ status-arr))
((= status-char ?D) ((= status-char ?D)
(add-to-list 'status-arr ?)) (push ? status-arr))
((= status-char ?R) ((= status-char ?R)
(add-to-list 'status-arr )) (push status-arr))
((= status-char ?U) ((= status-char ?U)
(add-to-list 'status-arr ?=))))) (push ?= status-arr)))))
(when (eshell-starship--prompt-git-has-stash)
(push ?$ status-arr))
(sort status-arr #'<) (sort status-arr #'<)
(when branch-status (when branch-status
(push branch-status status-arr)) (push branch-status status-arr))
(apply 'string status-arr))) (apply 'string (seq-uniq status-arr))))
(defun eshell-starship--prompt-git-get-operation () (defun eshell-starship--prompt-git-get-operation ()
"Return the current git operation. For example, a revert." "Return the current git operation. For example, a revert."
@ -198,7 +187,7 @@ END-TIME is the time when the command finished executing."
;;;###autoload ;;;###autoload
(define-minor-mode eshell-starship-prompt-mode (define-minor-mode eshell-starship-prompt-mode
"Minor mode to make eshell prompts look like starship (https://starship.rs)" "Minor mode to make eshell prompts look like starship (https://starship.rs)."
:global nil :global nil
:init-value nil :init-value nil
:interactive (eshell-mode) :interactive (eshell-mode)