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)
|
||||||
(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)
|
||||||
|
Loading…
Reference in New Issue
Block a user