aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStefan Monnier2024-12-21 21:45:41 -0500
committerStefan Monnier2024-12-21 21:45:41 -0500
commit961cff855a9eccb9c2de31edc7d90ce697ebb65d (patch)
tree6bb940202724a3e8833dacf2e9c5a0e50a31aaa8
parent86a8b24bdea52a7aab45abcc51db2dd47308c11f (diff)
downloademacs-961cff855a9eccb9c2de31edc7d90ce697ebb65d.tar.gz
emacs-961cff855a9eccb9c2de31edc7d90ce697ebb65d.zip
* lisp/vc/smerge-mode.el (smerge-extend): New command (bug#74509)
-rw-r--r--etc/NEWS3
-rw-r--r--lisp/vc/smerge-mode.el60
2 files changed, 55 insertions, 8 deletions
diff --git a/etc/NEWS b/etc/NEWS
index 12a318f5ed7..847cc39ce96 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -311,6 +311,9 @@ modal editing packages.
311 311
312* Changes in Specialized Modes and Packages in Emacs 31.1 312* Changes in Specialized Modes and Packages in Emacs 31.1
313 313
314** Smerge
315*** New command 'smerge-extend' extends a conflict over surrounding lines.
316
314** Browse URL 317** Browse URL
315 318
316*** New user option 'browse-url-transform-alist'. 319*** New user option 'browse-url-transform-alist'.
diff --git a/lisp/vc/smerge-mode.el b/lisp/vc/smerge-mode.el
index 09d9ebda21b..a64ad2e0ec3 100644
--- a/lisp/vc/smerge-mode.el
+++ b/lisp/vc/smerge-mode.el
@@ -311,7 +311,7 @@ Can be nil if the style is undecided, or else:
311 (let ((ends nil)) 311 (let ((ends nil))
312 (dolist (i '(3 2 1 0)) 312 (dolist (i '(3 2 1 0))
313 (push (if (match-end i) (copy-marker (match-end i) t)) ends)) 313 (push (if (match-end i) (copy-marker (match-end i) t)) ends))
314 (setq ends (apply 'vector ends)) 314 (setq ends (apply #'vector ends))
315 (goto-char (aref ends 0)) 315 (goto-char (aref ends 0))
316 (if (not (re-search-forward smerge-begin-re nil t)) 316 (if (not (re-search-forward smerge-begin-re nil t))
317 (error "No next conflict") 317 (error "No next conflict")
@@ -701,7 +701,7 @@ this keeps \"LLL\"."
701 (smerge-keep-n 3) 701 (smerge-keep-n 3)
702 (smerge-auto-leave)) 702 (smerge-auto-leave))
703 703
704(define-obsolete-function-alias 'smerge-keep-other 'smerge-keep-lower "26.1") 704(define-obsolete-function-alias 'smerge-keep-other #'smerge-keep-lower "26.1")
705 705
706(defun smerge-keep-upper () 706(defun smerge-keep-upper ()
707 "Keep the \"upper\" version of a merge conflict. 707 "Keep the \"upper\" version of a merge conflict.
@@ -718,7 +718,7 @@ this keeps \"UUU\"."
718 (smerge-keep-n 1) 718 (smerge-keep-n 1)
719 (smerge-auto-leave)) 719 (smerge-auto-leave))
720 720
721(define-obsolete-function-alias 'smerge-keep-mine 'smerge-keep-upper "26.1") 721(define-obsolete-function-alias 'smerge-keep-mine #'smerge-keep-upper "26.1")
722 722
723(defun smerge-get-current () 723(defun smerge-get-current ()
724 (let ((i 3)) 724 (let ((i 3))
@@ -759,7 +759,7 @@ this keeps \"UUU\"."
759 (smerge-diff 2 1)) 759 (smerge-diff 2 1))
760 760
761(define-obsolete-function-alias 'smerge-diff-base-mine 761(define-obsolete-function-alias 'smerge-diff-base-mine
762 'smerge-diff-base-upper "26.1") 762 #'smerge-diff-base-upper "26.1")
763 763
764(defun smerge-diff-base-lower () 764(defun smerge-diff-base-lower ()
765 "Diff `base' and `lower' version in current conflict region." 765 "Diff `base' and `lower' version in current conflict region."
@@ -767,7 +767,7 @@ this keeps \"UUU\"."
767 (smerge-diff 2 3)) 767 (smerge-diff 2 3))
768 768
769(define-obsolete-function-alias 'smerge-diff-base-other 769(define-obsolete-function-alias 'smerge-diff-base-other
770 'smerge-diff-base-lower "26.1") 770 #'smerge-diff-base-lower "26.1")
771 771
772(defun smerge-diff-upper-lower () 772(defun smerge-diff-upper-lower ()
773 "Diff `upper' and `lower' version in current conflict region." 773 "Diff `upper' and `lower' version in current conflict region."
@@ -775,7 +775,7 @@ this keeps \"UUU\"."
775 (smerge-diff 1 3)) 775 (smerge-diff 1 3))
776 776
777(define-obsolete-function-alias 'smerge-diff-mine-other 777(define-obsolete-function-alias 'smerge-diff-mine-other
778 'smerge-diff-upper-lower "26.1") 778 #'smerge-diff-upper-lower "26.1")
779 779
780(defun smerge-match-conflict () 780(defun smerge-match-conflict ()
781 "Get info about the conflict. Puts the info in the `match-data'. 781 "Get info about the conflict. Puts the info in the `match-data'.
@@ -1207,6 +1207,7 @@ repeating the command will highlight other two parts."
1207 '((smerge . refine) (font-lock-face . smerge-refined-added)))))) 1207 '((smerge . refine) (font-lock-face . smerge-refined-added))))))
1208 1208
1209(defun smerge-swap () 1209(defun smerge-swap ()
1210 ;; FIXME: Extend for diff3 to allow swapping the middle end as well.
1210 "Swap the \"Upper\" and the \"Lower\" chunks. 1211 "Swap the \"Upper\" and the \"Lower\" chunks.
1211Can be used before things like `smerge-keep-all' or `smerge-resolve' where the 1212Can be used before things like `smerge-keep-all' or `smerge-resolve' where the
1212ordering can have some subtle influence on the result, such as preferring the 1213ordering can have some subtle influence on the result, such as preferring the
@@ -1219,6 +1220,49 @@ spacing of the \"Lower\" chunk."
1219 (goto-char (match-beginning 1)) 1220 (goto-char (match-beginning 1))
1220 (insert txt3))) 1221 (insert txt3)))
1221 1222
1223(defun smerge-extend (otherpos)
1224 "Extend current conflict with some of the surrounding text.
1225Point should be inside a conflict and OTHERPOS should be either a marker
1226indicating the position until which to extend the conflict (either before
1227or after the current conflict),
1228OTHERPOS can also be an integer indicating the number of lines over which
1229to extend the conflict. If positive, it extends over the lines following
1230the conflict and other, it extends over the lines preceding the conflict.
1231When used interactively, you can specify OTHERPOS either using an active
1232region, or with a numeric prefix. By default it uses a numeric prefix of 1."
1233 (interactive
1234 (list (if (use-region-p) (mark-marker)
1235 (prefix-numeric-value current-prefix-arg))))
1236 ;; FIXME: If OTHERPOS is inside (or next to) another conflict
1237 ;; or if there are conflicts between the current conflict and OTHERPOS,
1238 ;; we end up messing up the conflict markers. We should merge the
1239 ;; conflicts instead!
1240 (condition-case err
1241 (smerge-match-conflict)
1242 (error (if (not (markerp otherpos)) (signal (car err) (cdr err))
1243 (goto-char (prog1 otherpos (setq otherpos (point-marker))))
1244 (smerge-match-conflict))))
1245 (let ((beg (match-beginning 0))
1246 (end (copy-marker (match-end 0)))
1247 text)
1248 (when (integerp otherpos)
1249 (goto-char (if (>= otherpos 0) end beg))
1250 (setq otherpos (copy-marker (line-beginning-position (+ otherpos 1)))))
1251 (setq text (cond
1252 ((<= end otherpos)
1253 (buffer-substring end otherpos))
1254 ((<= otherpos beg)
1255 (buffer-substring otherpos beg))
1256 (t (user-error "The other end should be outside the conflict"))))
1257 (dotimes (i 3)
1258 (let* ((mn (- 3 i))
1259 (me (funcall (if (<= end otherpos) #'match-end #'match-beginning)
1260 mn)))
1261 (when me
1262 (goto-char me)
1263 (insert text))))
1264 (delete-region (if (<= end otherpos) end beg) otherpos)))
1265
1222(defun smerge-diff (n1 n2) 1266(defun smerge-diff (n1 n2)
1223 (smerge-match-conflict) 1267 (smerge-match-conflict)
1224 (smerge-ensure-match n1) 1268 (smerge-ensure-match n1)
@@ -1252,7 +1296,7 @@ spacing of the \"Lower\" chunk."
1252 (let ((inhibit-read-only t)) 1296 (let ((inhibit-read-only t))
1253 (erase-buffer) 1297 (erase-buffer)
1254 (let ((status 1298 (let ((status
1255 (apply 'call-process diff-command nil t nil 1299 (apply #'call-process diff-command nil t nil
1256 (append smerge-diff-switches 1300 (append smerge-diff-switches
1257 (and (diff-check-labels) 1301 (and (diff-check-labels)
1258 (list "--label" 1302 (list "--label"
@@ -1394,7 +1438,7 @@ with a \\[universal-argument] prefix, makes up a 3-way conflict."
1394 (when current-prefix-arg (pop-mark) (mark)))) 1438 (when current-prefix-arg (pop-mark) (mark))))
1395 ;; Start from the end so as to avoid problems with pos-changes. 1439 ;; Start from the end so as to avoid problems with pos-changes.
1396 (pcase-let ((`(,pt1 ,pt2 ,pt3 ,pt4) 1440 (pcase-let ((`(,pt1 ,pt2 ,pt3 ,pt4)
1397 (sort `(,pt1 ,pt2 ,pt3 ,@(if pt4 (list pt4))) '>=))) 1441 (sort `(,pt1 ,pt2 ,pt3 ,@(if pt4 (list pt4))) #'>=)))
1398 (goto-char pt1) (beginning-of-line) 1442 (goto-char pt1) (beginning-of-line)
1399 (insert ">>>>>>> LOWER\n") 1443 (insert ">>>>>>> LOWER\n")
1400 (goto-char pt2) (beginning-of-line) 1444 (goto-char pt2) (beginning-of-line)