38 |
;; (goto-char (point-min)) |
;; (goto-char (point-min)) |
39 |
;; (when (re-search-forward "^<<<<<<< " nil t) |
;; (when (re-search-forward "^<<<<<<< " nil t) |
40 |
;; (smerge-mode 1)))) |
;; (smerge-mode 1)))) |
41 |
;; (add-hook 'find-file-hooks 'sm-try-smerge t) |
;; (add-hook 'find-file-hook 'sm-try-smerge t) |
42 |
|
|
43 |
;;; Todo: |
;;; Todo: |
44 |
|
|
54 |
:group 'tools |
:group 'tools |
55 |
:prefix "smerge-") |
:prefix "smerge-") |
56 |
|
|
57 |
(defcustom smerge-diff-buffer-name "*smerge-diff*" |
(defcustom smerge-diff-buffer-name "*vc-diff*" |
58 |
"Buffer name to use for displaying diffs." |
"Buffer name to use for displaying diffs." |
59 |
:group 'smerge |
:group 'smerge |
60 |
:type '(choice |
:type '(choice |
115 |
(easy-mmode-defmap smerge-basic-map |
(easy-mmode-defmap smerge-basic-map |
116 |
`(("n" . smerge-next) |
`(("n" . smerge-next) |
117 |
("p" . smerge-prev) |
("p" . smerge-prev) |
118 |
|
("r" . smerge-resolve) |
119 |
("a" . smerge-keep-all) |
("a" . smerge-keep-all) |
120 |
("b" . smerge-keep-base) |
("b" . smerge-keep-base) |
121 |
("o" . smerge-keep-other) |
("o" . smerge-keep-other) |
184 |
;; Compiler pacifiers |
;; Compiler pacifiers |
185 |
(defvar font-lock-mode) |
(defvar font-lock-mode) |
186 |
(defvar font-lock-keywords) |
(defvar font-lock-keywords) |
|
(eval-when-compile |
|
|
(unless (fboundp 'font-lock-fontify-region) |
|
|
(autoload 'font-lock-fontify-region "font-lock"))) |
|
187 |
|
|
188 |
;;;; |
;;;; |
189 |
;;;; Actual code |
;;;; Actual code |
203 |
(save-excursion (goto-char (point-min)) |
(save-excursion (goto-char (point-min)) |
204 |
(not (re-search-forward smerge-begin-re nil t)))) |
(not (re-search-forward smerge-begin-re nil t)))) |
205 |
(smerge-mode -1))) |
(smerge-mode -1))) |
206 |
|
|
207 |
|
|
208 |
(defun smerge-keep-all () |
(defun smerge-keep-all () |
209 |
"Keep all three versions. |
"Keep all three versions. |
216 |
t t) |
t t) |
217 |
(smerge-auto-leave)) |
(smerge-auto-leave)) |
218 |
|
|
219 |
|
(defun smerge-combine-with-next () |
220 |
|
"Combine the current conflict with the next one." |
221 |
|
(interactive) |
222 |
|
(smerge-match-conflict) |
223 |
|
(let ((ends nil)) |
224 |
|
(dolist (i '(3 2 1 0)) |
225 |
|
(push (if (match-end i) (copy-marker (match-end i) t)) ends)) |
226 |
|
(setq ends (apply 'vector ends)) |
227 |
|
(goto-char (aref ends 0)) |
228 |
|
(if (not (re-search-forward smerge-begin-re nil t)) |
229 |
|
(error "No next conflict") |
230 |
|
(smerge-match-conflict) |
231 |
|
(let ((match-data (mapcar (lambda (m) (if m (copy-marker m))) |
232 |
|
(match-data)))) |
233 |
|
;; First copy the in-between text in each alternative. |
234 |
|
(dolist (i '(1 2 3)) |
235 |
|
(when (aref ends i) |
236 |
|
(goto-char (aref ends i)) |
237 |
|
(insert-buffer-substring (current-buffer) |
238 |
|
(aref ends 0) (car match-data)))) |
239 |
|
(delete-region (aref ends 0) (car match-data)) |
240 |
|
;; Then move the second conflict's alternatives into the first. |
241 |
|
(dolist (i '(1 2 3)) |
242 |
|
(set-match-data match-data) |
243 |
|
(when (and (aref ends i) (match-end i)) |
244 |
|
(goto-char (aref ends i)) |
245 |
|
(insert-buffer-substring (current-buffer) |
246 |
|
(match-beginning i) (match-end i)))) |
247 |
|
(delete-region (car match-data) (cadr match-data)) |
248 |
|
;; Free the markers. |
249 |
|
(dolist (m match-data) (if m (move-marker m nil))) |
250 |
|
(mapc (lambda (m) (if m (move-marker m nil))) ends))))) |
251 |
|
|
252 |
|
(defvar smerge-resolve-function |
253 |
|
(lambda () (error "Don't know how to resolve")) |
254 |
|
"Mode-specific merge function. |
255 |
|
The function is called with no argument and with the match data set |
256 |
|
according to `smerge-match-conflict'.") |
257 |
|
|
258 |
|
(defun smerge-resolve () |
259 |
|
"Resolve the conflict at point intelligently. |
260 |
|
This relies on mode-specific knowledge and thus only works in |
261 |
|
some major modes. Uses `smerge-resolve-function' to do the actual work." |
262 |
|
(interactive) |
263 |
|
(smerge-match-conflict) |
264 |
|
(funcall smerge-resolve-function) |
265 |
|
(smerge-auto-leave)) |
266 |
|
|
267 |
(defun smerge-keep-base () |
(defun smerge-keep-base () |
268 |
"Revert to the base version." |
"Revert to the base version." |
269 |
(interactive) |
(interactive) |
333 |
|
|
334 |
(start (match-beginning 0)) |
(start (match-beginning 0)) |
335 |
(mine-start (match-end 0)) |
(mine-start (match-end 0)) |
336 |
(filename (match-string 1)) |
(filename (or (match-string 1) "")) |
337 |
|
|
338 |
(_ (re-search-forward smerge-end-re)) |
(_ (re-search-forward smerge-end-re)) |
339 |
(_ (assert (< orig-point (match-end 0)))) |
(_ (assert (< orig-point (match-end 0)))) |
340 |
|
|
341 |
(other-end (match-beginning 0)) |
(other-end (match-beginning 0)) |
342 |
(end (match-end 0)) |
(end (match-end 0)) |
343 |
|
|
370 |
(setq base-end mine-end) |
(setq base-end mine-end) |
371 |
(setq mine-start other-start) |
(setq mine-start other-start) |
372 |
(setq mine-end other-end))) |
(setq mine-end other-end))) |
373 |
|
|
374 |
(store-match-data (list start end |
(store-match-data (list start end |
375 |
mine-start mine-end |
mine-start mine-end |
376 |
base-start base-end |
base-start base-end |
406 |
(dir default-directory) |
(dir default-directory) |
407 |
(file (file-relative-name buffer-file-name)) |
(file (file-relative-name buffer-file-name)) |
408 |
(coding-system-for-read buffer-file-coding-system)) |
(coding-system-for-read buffer-file-coding-system)) |
409 |
(write-region beg1 end1 file1) |
(write-region beg1 end1 file1 nil 'nomessage) |
410 |
(write-region beg2 end2 file2) |
(write-region beg2 end2 file2 nil 'nomessage) |
411 |
(unwind-protect |
(unwind-protect |
412 |
(with-current-buffer (get-buffer-create smerge-diff-buffer-name) |
(with-current-buffer (get-buffer-create smerge-diff-buffer-name) |
413 |
(setq default-directory dir) |
(setq default-directory dir) |
414 |
(let ((inhibit-read-only t)) |
(let ((inhibit-read-only t)) |
415 |
(erase-buffer) |
(erase-buffer) |
416 |
(apply 'call-process diff-command nil t nil |
(let ((status |
417 |
(append smerge-diff-switches |
(apply 'call-process diff-command nil t nil |
418 |
(list "-L" (concat name1 "/" file) |
(append smerge-diff-switches |
419 |
"-L" (concat name2 "/" file) |
(list "-L" (concat name1 "/" file) |
420 |
file1 file2)))) |
"-L" (concat name2 "/" file) |
421 |
|
file1 file2))))) |
422 |
|
(if (eq status 0) (insert "No differences found.\n")))) |
423 |
(goto-char (point-min)) |
(goto-char (point-min)) |
424 |
(diff-mode) |
(diff-mode) |
425 |
(display-buffer (current-buffer) t)) |
(display-buffer (current-buffer) t)) |
426 |
(delete-file file1) |
(delete-file file1) |
427 |
(delete-file file2)))) |
(delete-file file2)))) |
428 |
|
|
429 |
(eval-when-compile |
;; compiler pacifiers |
430 |
;; compiler pacifiers |
(defvar smerge-ediff-windows) |
431 |
(defvar smerge-ediff-windows) |
(defvar smerge-ediff-buf) |
432 |
(defvar smerge-ediff-buf) |
(defvar ediff-buffer-A) |
433 |
(defvar ediff-buffer-A) |
(defvar ediff-buffer-B) |
434 |
(defvar ediff-buffer-B) |
(defvar ediff-buffer-C) |
435 |
(defvar ediff-buffer-C) |
|
436 |
(unless (fboundp 'ediff-cleanup-mess) |
;;;###autoload |
437 |
(autoload 'ediff-cleanup-mess "ediff-util"))) |
(defun smerge-ediff (&optional name-mine name-other name-base) |
438 |
|
"Invoke ediff to resolve the conflicts. |
439 |
(defun smerge-ediff () |
NAME-MINE, NAME-OTHER, and NAME-BASE, if non-nil, are used for the |
440 |
"Invoke ediff to resolve the conflicts." |
buffer names." |
441 |
(interactive) |
(interactive) |
442 |
(let* ((buf (current-buffer)) |
(let* ((buf (current-buffer)) |
443 |
(mode major-mode) |
(mode major-mode) |
444 |
;;(ediff-default-variant 'default-B) |
;;(ediff-default-variant 'default-B) |
445 |
(config (current-window-configuration)) |
(config (current-window-configuration)) |
446 |
(filename (file-name-nondirectory buffer-file-name)) |
(filename (file-name-nondirectory buffer-file-name)) |
447 |
(mine (generate-new-buffer (concat "*" filename " MINE*"))) |
(mine (generate-new-buffer |
448 |
(other (generate-new-buffer (concat "*" filename " OTHER*"))) |
(or name-mine (concat "*" filename " MINE*")))) |
449 |
|
(other (generate-new-buffer |
450 |
|
(or name-other (concat "*" filename " OTHER*")))) |
451 |
base) |
base) |
452 |
(with-current-buffer mine |
(with-current-buffer mine |
453 |
(buffer-disable-undo) |
(buffer-disable-undo) |
469 |
(buffer-enable-undo) |
(buffer-enable-undo) |
470 |
(set-buffer-modified-p nil) |
(set-buffer-modified-p nil) |
471 |
(funcall mode)) |
(funcall mode)) |
472 |
|
|
473 |
(when base |
(when base |
474 |
(setq base (generate-new-buffer (concat "*" filename " BASE*"))) |
(setq base (generate-new-buffer |
475 |
|
(or name-base (concat "*" filename " BASE*")))) |
476 |
(with-current-buffer base |
(with-current-buffer base |
477 |
(buffer-disable-undo) |
(buffer-disable-undo) |
478 |
(insert-buffer-substring buf) |
(insert-buffer-substring buf) |
482 |
(buffer-enable-undo) |
(buffer-enable-undo) |
483 |
(set-buffer-modified-p nil) |
(set-buffer-modified-p nil) |
484 |
(funcall mode))) |
(funcall mode))) |
485 |
|
|
486 |
;; the rest of the code is inspired from vc.el |
;; the rest of the code is inspired from vc.el |
487 |
;; Fire up ediff. |
;; Fire up ediff. |
488 |
(set-buffer |
(set-buffer |
491 |
;; nil 'ediff-merge-revisions-with-ancestor buffer-file-name) |
;; nil 'ediff-merge-revisions-with-ancestor buffer-file-name) |
492 |
(ediff-merge-buffers mine other))) |
(ediff-merge-buffers mine other))) |
493 |
;; nil 'ediff-merge-revisions buffer-file-name))) |
;; nil 'ediff-merge-revisions buffer-file-name))) |
494 |
|
|
495 |
;; Ediff is now set up, and we are in the control buffer. |
;; Ediff is now set up, and we are in the control buffer. |
496 |
;; Do a few further adjustments and take precautions for exit. |
;; Do a few further adjustments and take precautions for exit. |
497 |
(set (make-local-variable 'smerge-ediff-windows) config) |
(set (make-local-variable 'smerge-ediff-windows) config) |