branch: elpa/magit
commit 9674c4755a9871568c780beb53bde9ad472db067
Author: Jonas Bernoulli <jo...@bernoul.li>
Commit: Jonas Bernoulli <jo...@bernoul.li>

    git-rebase-{alter,squish}: New commands
---
 docs/magit.org     | 31 +++++++++++++++--
 docs/magit.texi    | 33 +++++++++++++++++--
 lisp/git-rebase.el | 97 ++++++++++++++++++++++++++++++++++++++----------------
 3 files changed, 127 insertions(+), 34 deletions(-)

diff --git a/docs/magit.org b/docs/magit.org
index 4a9d4cd625..31ed501d3f 100644
--- a/docs/magit.org
+++ b/docs/magit.org
@@ -6112,12 +6112,37 @@ the following suffix commands.
 
 - Key: s (git-rebase-squash) ::
 
-  Meld commit on current line into previous commit, and edit message.
+  This command folds the commit on the current line into the previous
+  commit, giving the user a change to manually merge the two messages.
+
+- Key: S (git-rebase-squish) ::
+
+  This command folds the commit on the current line into the previous
+  commit, discarding the message of the previous commit but giving the
+  user a change to edit the final message, based on the message of the
+  current commit.
+
+  This action's indicator, shown in the list of commits, is ~fixup -c~
+  (with a lower-case c).
 
 - Key: f (git-rebase-fixup) ::
 
-  Meld commit on current line into previous commit, discarding the
-  current commit's message.
+  This command folds the commit on the current line into the previous
+  commit, using only the message of the previous commit as-is and
+  discarding the message of the current commit.
+
+- Key: F (git-rebase-alter) ::
+
+  This command folds the commit on the current into the previous
+  commit, discarding the message of the previous commit and instead
+  using the message of the current commit as-is.
+
+  This is like ~git-rebase-alter~, except that it uses the other
+  message.  This is also like ~git-rebase-squish~, except that it lets
+  the user edit the message.
+
+  This action's indicator, shown in the list of commits, is ~fixup -C~
+  (with a upper-case C).
 
 - Key: k (git-rebase-kill-line) ::
 
diff --git a/docs/magit.texi b/docs/magit.texi
index 3e36f80cb7..ef1e9fd663 100644
--- a/docs/magit.texi
+++ b/docs/magit.texi
@@ -7220,13 +7220,40 @@ Stop at the commit on the current line.
 @item @kbd{s} (@code{git-rebase-squash})
 @kindex s
 @findex git-rebase-squash
-Meld commit on current line into previous commit, and edit message.
+This command folds the commit on the current line into the previous
+commit, giving the user a change to manually merge the two messages.
+
+@item @kbd{S} (@code{git-rebase-squish})
+@kindex S
+@findex git-rebase-squish
+This command folds the commit on the current line into the previous
+commit, discarding the message of the previous commit but giving the
+user a change to edit the final message, based on the message of the
+current commit.
+
+This action's indicator, shown in the list of commits, is @code{fixup -c}
+(with a lower-case c).
 
 @item @kbd{f} (@code{git-rebase-fixup})
 @kindex f
 @findex git-rebase-fixup
-Meld commit on current line into previous commit, discarding the
-current commit's message.
+This command folds the commit on the current line into the previous
+commit, using only the message of the previous commit as-is and
+discarding the message of the current commit.
+
+@item @kbd{F} (@code{git-rebase-alter})
+@kindex F
+@findex git-rebase-alter
+This command folds the commit on the current into the previous
+commit, discarding the message of the previous commit and instead
+using the message of the current commit as-is.
+
+This is like @code{git-rebase-alter}, except that it uses the other
+message.  This is also like @code{git-rebase-squish}, except that it lets
+the user edit the message.
+
+This action's indicator, shown in the list of commits, is @code{fixup -C}
+(with a upper-case C).
 
 @item @kbd{k} (@code{git-rebase-kill-line})
 @kindex k
diff --git a/lisp/git-rebase.el b/lisp/git-rebase.el
index 984d810b64..64a46d3e32 100644
--- a/lisp/git-rebase.el
+++ b/lisp/git-rebase.el
@@ -162,11 +162,14 @@
   "M M" #'git-rebase-merge
   "M t" #'git-rebase-merge-toggle-editmsg
   "m"   #'git-rebase-edit
+  "s"   #'git-rebase-squash
+  "S"   #'git-rebase-squish
   "f"   #'git-rebase-fixup
+  "F"   #'git-rebase-alter
+  "A"   #'git-rebase-alter
   "q"   #'undefined
   "r"   #'git-rebase-reword
   "w"   #'git-rebase-reword
-  "s"   #'git-rebase-squash
   "t"   #'git-rebase-reset
   "u"   #'git-rebase-update-ref
   "x"   #'git-rebase-exec
@@ -178,6 +181,7 @@
   "M-<up>"         #'git-rebase-move-line-up
   "M-<down>"       #'git-rebase-move-line-down
   "<remap> <undo>" #'git-rebase-undo)
+(put 'git-rebase-alter        :advertised-binding (kbd "F"))
 (put 'git-rebase-reword       :advertised-binding (kbd "r"))
 (put 'git-rebase-move-line-up :advertised-binding (kbd "M-p"))
 (put 'git-rebase-kill-line    :advertised-binding (kbd "k"))
@@ -216,6 +220,17 @@
     (git-rebase-insert            . "insert a line for an arbitrary commit")
     (git-rebase-noop              . "add noop action at point")))
 
+(defvar git-rebase-fixup-descriptions
+  '((git-rebase-squish
+     . "fixup -c <commit> = use commit, but meld into previous commit,\n#\
+          dropping previous commit's message, and open the editor")
+    (git-rebase-fixup
+     . "fixup <commit> = use commit, but meld into previous commit,\n#\
+          dropping <commit>'s message")
+    (git-rebase-alter
+     . "fixup -C <commit> = use commit, but meld into previous commit,\n#\
+          dropping previous commit's message")))
+
 ;;; Commands
 
 (defun git-rebase-pick ()
@@ -243,17 +258,33 @@ If the region is active, act on all lines touched by the 
region."
   (git-rebase-set-action "edit"))
 
 (defun git-rebase-squash ()
-  "Meld commit on current line into previous commit, edit message.
+  "Fold commit on current line into previous commit, edit combined message.
 If the region is active, act on all lines touched by the region."
   (interactive)
   (git-rebase-set-action "squash"))
 
+(defun git-rebase-squish ()
+  "Fold current into previous commit, discard previous message and edit 
current.
+This is like `git-rebase-squash', except that the other message is kept.
+The action indicatore shown in the list commits is \"fixup -c\".  If the
+region is active, act on all lines touched by the region."
+  (interactive)
+  (git-rebase-set-action "fixup -c"))
+
 (defun git-rebase-fixup ()
-  "Meld commit on current line into previous commit, discard its message.
+  "Fold commit on current line into previous commit, discard current message.
 If the region is active, act on all lines touched by the region."
   (interactive)
   (git-rebase-set-action "fixup"))
 
+(defun git-rebase-alter ()
+  "Meld current into previous commit, discard previous message and use current.
+This is like `git-rebase-fixup', except that the other message is kept.
+The action indicatore shown in the list commits is \"fixup -C\".  If the
+region is active, act on all lines touched by the region."
+  (interactive)
+  (git-rebase-set-action "fixup -C"))
+
 (defvar-local git-rebase-comment-re nil)
 
 (defvar git-rebase-short-options
@@ -291,12 +322,14 @@ If the region is active, act on all lines touched by the 
region."
 
 (defvar git-rebase-line-regexps
   `((commit . ,(concat
-                (regexp-opt '("e" "edit"
-                              "d" "drop"
-                              "f" "fixup"
-                              "p" "pick"
-                              "r" "reword"
-                              "s" "squash")
+                (regexp-opt '("d"    "drop"
+                              "e"    "edit"
+                              "f"    "fixup"
+                              "f -C" "fixup -C"
+                              "f -c" "fixup -c"
+                              "p"    "pick"
+                              "r"    "reword"
+                              "s"    "squash")
                             "\\(?1:")
                 " \\(?3:[^ \n]+\\) ?\\(?4:.*\\)"))
     (exec . "\\(?1:x\\|exec\\) \\(?3:.*\\)")
@@ -815,24 +848,23 @@ except for the \"pick\" command."
                   (concat git-rebase-comment-re "\\s-+p, pick")
                   nil t))
         (goto-char (line-beginning-position))
-        (pcase-dolist (`(,cmd . ,desc) git-rebase-command-descriptions)
-          (insert (format (propertize "%s %s %s\n"
-                                      'font-lock-face 'font-lock-comment-face)
-                          comment-start
-                          (string-pad
-                           (substitute-command-keys (format "\\[%s]" cmd)) 8)
-                          desc)))
-        (while (re-search-forward
-                (concat git-rebase-comment-re "\\(?:"
-                        "\\( \\.?     *\\)\\|"
-                        "\\( +\\)\\([^\n,],\\) \\([^\n ]+\\) \\)")
-                nil t)
-          (if (match-string 1)
-              (replace-match (make-string 10 ?\s) t t nil 1)
-            (let ((cmd (intern (concat "git-rebase-" (match-string 4)))))
-              (if (not (fboundp cmd))
-                  (delete-region (line-beginning-position)
-                                 (1+ (line-end-position)))
+        (git-rebase--insert-descriptions git-rebase-command-descriptions)
+        (let ((cmd nil)
+              (line (concat git-rebase-comment-re "\\(?:\\( \\.?     *\\)\\|"
+                            "\\( +\\)\\([^\n,],\\) \\([^\n ]+\\) \\)")))
+          (while (re-search-forward line nil t)
+            (if (match-string 1)
+                (if (assq cmd git-rebase-fixup-descriptions)
+                    (delete-line)
+                  (replace-match (make-string 10 ?\s) t t nil 1))
+              (setq cmd (intern (concat "git-rebase-" (match-string 4))))
+              (cond
+               ((not (fboundp cmd))
+                (delete-line))
+               ((eq cmd 'git-rebase-fixup)
+                (delete-line)
+                (git-rebase--insert-descriptions 
git-rebase-fixup-descriptions))
+               (t
                 (add-text-properties (line-beginning-position)
                                      (1+ (line-end-position))
                                      '(font-lock-face font-lock-comment-face))
@@ -842,7 +874,16 @@ except for the \"pick\" command."
                   (save-match-data
                     (substitute-command-keys (format "\\[%s]" cmd)))
                   8)
-                 t t nil 3)))))))))
+                 t t nil 3))))))))))
+
+(defun git-rebase--insert-descriptions (alist)
+  (pcase-dolist (`(,cmd . ,desc) alist)
+    (insert (format (propertize "%s %s %s\n"
+                                'font-lock-face 'font-lock-comment-face)
+                    comment-start
+                    (string-pad
+                     (substitute-command-keys (format "\\[%s]" cmd)) 8)
+                    desc))))
 
 (add-hook 'git-rebase-mode-hook #'git-rebase-mode-show-keybindings t)
 

Reply via email to