diff --git a/elisp/eshell-starship.el b/elisp/eshell-starship.el index be5ac16..515bc8a 100644 --- a/elisp/eshell-starship.el +++ b/elisp/eshell-starship.el @@ -62,49 +62,83 @@ STATUS-LINE is the first line of output from \"git status --porcelain=v1 -b\"." (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)) + (zerop (process-file vc-git-program nil nil nil + "rev-parse" "--verify" "refs/stash"))) (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" "-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 + (with-temp-buffer + (when (zerop (vc-git-command t nil nil "status" "--porcelain=v1" "-b")) + (goto-char (point-min)) + (cl-loop with command-error-function = nil + with status-arr = nil + with first-line = (buffer-substring-no-properties + (point) (pos-eol)) + ;; account for newline at end + with line-count = (car (buffer-line-statistics)) + with cur-buf = (current-buffer) + do (forward-line) + for x_status = (char-after) + for y_status = (char-after (1+ (point))) + until (> (line-number-at-pos) line-count) do - (cond ((or (= status-char ?M) (= status-char ?T)) - (push ?! status-arr)) - ((= status-char ??) - (push ?? status-arr)) - ((or (= status-char ?A) (= status-char ?C)) - (push ?+ status-arr)) - ((= status-char ?D) - (push ? status-arr)) - ((= status-char ?R) - (push ?» status-arr)) - ((= status-char ?U) - (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 (seq-uniq status-arr)))) + (cond + ((or (= ?D x_status y_status) + (= ?A x_status y_status) + (= ?U x_status y_status) + (and (= ?A x_status) (= ?U y_status)) + (and (= ?U x_status) (= ?D y_status)) + (and (= ?U x_status) (= ?A y_status)) + (and (= ?D x_status) (= ?U y_status))) + (push ?= status-arr)) + ((or (= x_status ?D) (= y_status ?D)) + (push ? status-arr)) + ((or (= x_status ?R) (= y_status ?R)) + (push ?» status-arr)) + ((= y_status ?M) + (push ?! status-arr)) + ((or (= x_status ?A) (= x_status ?M)) + (push ?+ status-arr)) + ((= x_status y_status ??) + (push ?? status-arr))) + finally + (sort status-arr #'(lambda (a b) + (cond + ((= a ?=) + t) + ((= b ?=) + nil) + (t + (< a b))))) + (when (eshell-starship--prompt-git-has-stash) + (if (= (car status-arr) ?=) + (setq status-arr (append '(?= ?$) (cdr status-arr))) + (push ?$ status-arr))) + (when-let (branch-status (eshell-starship--prompt-current-branch-status + first-line)) + (push branch-status status-arr)) + finally return (apply 'string (seq-uniq status-arr)))))) (defun eshell-starship--prompt-git-get-operation () "Return the current git operation. For example, a revert." (let ((git-dir (expand-file-name ".git" (vc-git-root default-directory)))) (cond - ((file-exists-p (expand-file-name "REVERT_HEAD" git-dir)) - "REVERTING") + ((file-exists-p (expand-file-name "rebase-apply/applying" git-dir)) + "AM") + ((file-exists-p (expand-file-name "rebase-apply/rebasing" git-dir)) + "REBASE") + ((file-exists-p (expand-file-name "rebase-apply" git-dir)) + "AM/REBASE") ((file-exists-p (expand-file-name "rebase-merge" git-dir)) "REBASING") + ((file-exists-p (expand-file-name "CHERRY_PICK_HEAD" git-dir)) + "CHERRY-PICKING") ((file-exists-p (expand-file-name "MERGE_HEAD" git-dir)) - "MERGING")))) + "MERGING") + ((file-exists-p (expand-file-name "BISECT_LOG" git-dir)) + "BISECTING") + ((file-exists-p (expand-file-name "REVERT_HEAD" git-dir)) + "REVERTING")))) (defun eshell-starship--prompt-git-status () "Get git status for `eshell-starship--prompt-function'."