Add git stash support and make branch status more efficient
This commit is contained in:
parent
7b9cc70e7c
commit
47039d4bfe
@ -5,6 +5,7 @@
|
||||
(require 'vc)
|
||||
(require 'vc-git)
|
||||
(require 'eshell)
|
||||
(require 'cl-lib)
|
||||
|
||||
(defun eshell-starship--git-process-lines (&rest flags)
|
||||
"Run `vc-git-program' and return an array of its output lines.
|
||||
@ -43,68 +44,56 @@ Example:
|
||||
(if-let ((worktree (vc-root-dir))
|
||||
(parent (file-name-parent-directory worktree)))
|
||||
(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)
|
||||
"Get the status char representing the relation between BRANCH and REMOTE."
|
||||
(let ((lines (eshell-starship--git-process-lines
|
||||
"rev-list"
|
||||
"--left-right"
|
||||
(concat branch "..." remote)))
|
||||
(to-remote nil)
|
||||
(to-local nil))
|
||||
(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
|
||||
((and to-remote to-local) ?)
|
||||
(to-remote ?)
|
||||
(to-local ?))))
|
||||
(defun eshell-starship--prompt-current-branch-status (status-line)
|
||||
"Get the status char for the current branch and its remote.
|
||||
STATUS-LINE is the first line of output from \"git status --porcelain=v1 -b\"."
|
||||
(when (string-match
|
||||
"\\[\\(?:ahead \\([0-9]+\\)\\)?,? ?\\(?:behind \\([0-9]+\\)\\)?\\]$"
|
||||
status-line)
|
||||
(let ((ahead (match-string 1 status-line))
|
||||
(behind (match-string 2 status-line)))
|
||||
(cond
|
||||
((and ahead behind) ?)
|
||||
(ahead ?)
|
||||
(behind ?)))))
|
||||
|
||||
|
||||
(defun eshell-starship--prompt-current-branch-status ()
|
||||
"Get the status char for the current branch and its remote."
|
||||
(let ((refs (eshell-starship--git-process-lines
|
||||
"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-has-stash ()
|
||||
"Return t if the current git directory has a stash, nil otherwise."
|
||||
(= (process-file vc-git-program nil nil nil
|
||||
"rev-parse" "--verify" "refs/stash") 0))
|
||||
|
||||
(defun eshell-starship--prompt-git-state-chars ()
|
||||
"Get chars, like + and ✘ for `eshell-starship--prompt-function'."
|
||||
(let ((lines (eshell-starship--git-process-lines "status" "--porcelain=v1"))
|
||||
(branch-status (eshell-starship--prompt-current-branch-status))
|
||||
(status-arr))
|
||||
(dolist (line lines)
|
||||
(let* ((lines (eshell-starship--git-process-lines "status" "--porcelain=v1" "-b"))
|
||||
(branch-status (eshell-starship--prompt-current-branch-status
|
||||
(car lines)))
|
||||
(status-arr))
|
||||
(dolist (line (cdr lines))
|
||||
(cl-loop with fields = (string-split line " " t " *")
|
||||
with status-str = (car-safe fields)
|
||||
for status-char across status-str
|
||||
do
|
||||
(cond ((or (= status-char ?M) (= status-char ?T))
|
||||
(add-to-list 'status-arr ?!))
|
||||
(push ?! status-arr))
|
||||
((= status-char ??)
|
||||
(add-to-list 'status-arr ??))
|
||||
(push ?? status-arr))
|
||||
((or (= status-char ?A) (= status-char ?C))
|
||||
(add-to-list 'status-arr ?+))
|
||||
(push ?+ status-arr))
|
||||
((= status-char ?D)
|
||||
(add-to-list 'status-arr ?))
|
||||
(push ? status-arr))
|
||||
((= status-char ?R)
|
||||
(add-to-list 'status-arr ?»))
|
||||
(push ?» status-arr))
|
||||
((= status-char ?U)
|
||||
(add-to-list 'status-arr ?=)))))
|
||||
(push ?= status-arr)))))
|
||||
(when (eshell-starship--prompt-git-has-stash)
|
||||
(push ?$ status-arr))
|
||||
(sort status-arr #'<)
|
||||
(when branch-status
|
||||
(push branch-status status-arr))
|
||||
(apply 'string status-arr)))
|
||||
(apply 'string (seq-uniq status-arr))))
|
||||
|
||||
(defun eshell-starship--prompt-git-get-operation ()
|
||||
"Return the current git operation. For example, a revert."
|
||||
@ -198,7 +187,7 @@ END-TIME is the time when the command finished executing."
|
||||
|
||||
;;;###autoload
|
||||
(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
|
||||
:init-value nil
|
||||
:interactive (eshell-mode)
|
||||
|
Loading…
Reference in New Issue
Block a user