[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[elpa] externals/diff-hl b68fc2f8e6 1/5: New commands: diff-hl-stage-som
|
From: |
ELPA Syncer |
|
Subject: |
[elpa] externals/diff-hl b68fc2f8e6 1/5: New commands: diff-hl-stage-some and diff-hl-stage-dwim |
|
Date: |
Sun, 21 Jan 2024 00:57:43 -0500 (EST) |
branch: externals/diff-hl
commit b68fc2f8e68132187d1799d0295aecadddd350bf
Author: Dmitry Gutov <dmitry@gutov.dev>
Commit: Dmitry Gutov <dmitry@gutov.dev>
New commands: diff-hl-stage-some and diff-hl-stage-dwim
#195
---
diff-hl.el | 98 ++++++++++++++++++++++++++++++++++++++++++++++++++++++--------
1 file changed, 86 insertions(+), 12 deletions(-)
diff --git a/diff-hl.el b/diff-hl.el
index e302523a42..56255232c1 100644
--- a/diff-hl.el
+++ b/diff-hl.el
@@ -708,6 +708,21 @@ its end position."
(unless (eq backend 'Git)
(user-error "Only Git supports staging; this file is controlled by %s"
backend))))
+(defun diff-hl-stage-diff (orig-buffer)
+ (let ((patchfile (make-temp-file "diff-hl-stage-patch"))
+ success)
+ (write-region (point-min) (point-max) patchfile
+ nil 'silent)
+ (unwind-protect
+ (with-current-buffer orig-buffer
+ (with-output-to-string
+ (vc-git-command standard-output 0
+ patchfile
+ "apply" "--cached" )
+ (setq success t)))
+ (delete-file patchfile))
+ success))
+
(defun diff-hl-stage-current-hunk ()
"Stage the hunk at or near point.
@@ -741,17 +756,7 @@ Only supported with Git."
(insert (format "diff a/%s b/%s\n" file-base file-base))
(insert (format "--- a/%s\n" file-base))
(insert (format "+++ b/%s\n" file-base)))
- (let ((patchfile (make-temp-file "diff-hl-stage-patch")))
- (write-region (point-min) (point-max) patchfile
- nil 'silent)
- (unwind-protect
- (with-current-buffer orig-buffer
- (with-output-to-string
- (vc-git-command standard-output 0
- patchfile
- "apply" "--cached" ))
- (setq success t))
- (delete-file patchfile))))
+ (setq success (diff-hl-stage-diff orig-buffer)))
(when success
(if diff-hl-show-staged-changes
(message (concat "Hunk staged; customize
`diff-hl-show-staged-changes'"
@@ -773,6 +778,75 @@ Only supported with Git."
(unless diff-hl-show-staged-changes
(diff-hl-update)))
+(defun diff-hl-stage-dwim (&optional with-edit)
+ "Stage the current hunk or choose the hunks to stage.
+When called with the prefix argument, invokes `diff-hl-stage-some'."
+ (interactive "p")
+ (if with-edit
+ (call-interactively #'diff-hl-stage-some)
+ (call-interactively #'diff-hl-stage-current-hunk)))
+
+(defvar diff-hl-stage--orig nil)
+
+(define-derived-mode diff-hl-stage-diff-mode diff-mode "Stage Diff"
+ "Major mode for editing a diff buffer before staging.
+
+\\[diff-hl-stage-commit]"
+ (setq revert-buffer-function #'ignore))
+
+(define-key diff-hl-stage-diff-mode-map (kbd "C-c C-c") #'diff-hl-stage-finish)
+
+(defun diff-hl-stage-some ()
+ "Stage some or all of the current changes, interactively.
+Pops up a diff buffer that can be edited to choose the changes to stage."
+ (interactive)
+ (diff-hl--ensure-staging-supported)
+ (diff-hl-find-current-hunk)
+ (let* ((line (line-number-at-pos))
+ (file buffer-file-name)
+ (dest-buffer (get-buffer-create "*diff-hl-stage-some*"))
+ (orig-buffer (current-buffer))
+ ;; FIXME: If the file name has double quotes, these need to be quoted.
+ (file-base (file-name-nondirectory file)))
+ (with-current-buffer dest-buffer
+ (let ((inhibit-read-only t))
+ (erase-buffer)))
+ (diff-hl-diff-buffer-with-reference file dest-buffer nil 3)
+ (with-current-buffer dest-buffer
+ (with-no-warnings
+ (let (diff-auto-refine-mode)
+ (diff-hl-diff-skip-to line)))
+ (let ((inhibit-read-only t))
+ (goto-char (point-min))
+ (forward-line 3)
+ (delete-region (point-min) (point))
+ ;; diff-no-select creates a very ugly header; Git rejects it
+ (insert (format "diff a/%s b/%s\n" file-base file-base))
+ (insert (format "--- a/%s\n" file-base))
+ (insert (format "+++ b/%s\n" file-base)))
+ (let ((diff-default-read-only t))
+ (diff-hl-stage-diff-mode))
+ (setq-local diff-hl-stage--orig orig-buffer))
+ (pop-to-buffer dest-buffer)
+ (message "Press %s and %s to navigate, %s to split, %s to kill hunk, %s to
undo, and %s to stage the diff after editing"
+ (substitute-command-keys "\\`n'")
+ (substitute-command-keys "\\`p'")
+ (substitute-command-keys "\\[diff-split-hunk]")
+ (substitute-command-keys "\\[diff-hunk-kill]")
+ (substitute-command-keys "\\[diff-undo]")
+ (substitute-command-keys "\\[diff-hl-stage-finish]"))))
+
+(defun diff-hl-stage-finish ()
+ (interactive)
+ (let ((count 0))
+ (when (diff-hl-stage-diff diff-hl-stage--orig)
+ (save-excursion
+ (goto-char (point-min))
+ (while (re-search-forward diff-hunk-header-re-unified nil t)
+ (cl-incf count)))
+ (message "Staged %d hunks" count)
+ (bury-buffer))))
+
(defvar diff-hl-command-map
(let ((map (make-sparse-keymap)))
(define-key map "n" 'diff-hl-revert-hunk)
@@ -781,7 +855,7 @@ Only supported with Git."
(define-key map "*" 'diff-hl-show-hunk)
(define-key map "{" 'diff-hl-show-hunk-previous)
(define-key map "}" 'diff-hl-show-hunk-next)
- (define-key map "S" 'diff-hl-stage-current-hunk)
+ (define-key map "S" 'diff-hl-stage-dwim)
map))
(fset 'diff-hl-command-map diff-hl-command-map)