diff options
| -rw-r--r-- | lisp/ChangeLog | 12 | ||||
| -rw-r--r-- | lisp/smerge-mode.el | 92 |
2 files changed, 98 insertions, 6 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog index 586500e7b30..ce08638a6be 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog | |||
| @@ -1,3 +1,15 @@ | |||
| 1 | 2005-08-25 Stefan Monnier <monnier@iro.umontreal.ca> | ||
| 2 | |||
| 3 | * smerge-mode.el (smerge-remove-props): Make the args non-optional. | ||
| 4 | (smerge-keep-n): Remove props. | ||
| 5 | (smerge-keep-base, smerge-keep-other, smerge-keep-mine) | ||
| 6 | (smerge-keep-current, smerge-kill-current): Don't remove props anymore | ||
| 7 | now that it's done in smerge-keep-n. | ||
| 8 | (smerge-refined-change): New face. | ||
| 9 | (smerge-refine-chopup-region, smerge-refine-highlight-change) | ||
| 10 | (smerge-refine): New funs. | ||
| 11 | (smerge-basic-map): Bind smerge-refine. | ||
| 12 | |||
| 1 | 2005-08-25 Juri Linkov <juri@jurta.org> | 13 | 2005-08-25 Juri Linkov <juri@jurta.org> |
| 2 | 14 | ||
| 3 | * progmodes/grep.el (grep, grep-mode): Make buffer-local variables | 15 | * progmodes/grep.el (grep, grep-mode): Make buffer-local variables |
diff --git a/lisp/smerge-mode.el b/lisp/smerge-mode.el index 912f3289158..71fb650da7d 100644 --- a/lisp/smerge-mode.el +++ b/lisp/smerge-mode.el | |||
| @@ -129,6 +129,10 @@ Used in `smerge-diff-base-mine' and related functions." | |||
| 129 | (put 'smerge-markers-face 'face-alias 'smerge-markers) | 129 | (put 'smerge-markers-face 'face-alias 'smerge-markers) |
| 130 | (defvar smerge-markers-face 'smerge-markers) | 130 | (defvar smerge-markers-face 'smerge-markers) |
| 131 | 131 | ||
| 132 | (defface smerge-refined-change | ||
| 133 | '((t :background "yellow")) | ||
| 134 | "Face used for char-based changes shown by `smerge-refine'.") | ||
| 135 | |||
| 132 | (easy-mmode-defmap smerge-basic-map | 136 | (easy-mmode-defmap smerge-basic-map |
| 133 | `(("n" . smerge-next) | 137 | `(("n" . smerge-next) |
| 134 | ("p" . smerge-prev) | 138 | ("p" . smerge-prev) |
| @@ -139,6 +143,7 @@ Used in `smerge-diff-base-mine' and related functions." | |||
| 139 | ("m" . smerge-keep-mine) | 143 | ("m" . smerge-keep-mine) |
| 140 | ("E" . smerge-ediff) | 144 | ("E" . smerge-ediff) |
| 141 | ("C" . smerge-combine-with-next) | 145 | ("C" . smerge-combine-with-next) |
| 146 | ("R" . smerge-refine) | ||
| 142 | ("\C-m" . smerge-keep-current) | 147 | ("\C-m" . smerge-keep-current) |
| 143 | ("=" . ,(make-sparse-keymap "Diff")) | 148 | ("=" . ,(make-sparse-keymap "Diff")) |
| 144 | ("=<" "base-mine" . smerge-diff-base-mine) | 149 | ("=<" "base-mine" . smerge-diff-base-mine) |
| @@ -277,6 +282,7 @@ Can be nil if the style is undecided, or else: | |||
| 277 | (smerge-auto-leave))) | 282 | (smerge-auto-leave))) |
| 278 | 283 | ||
| 279 | (defun smerge-keep-n (n) | 284 | (defun smerge-keep-n (n) |
| 285 | (smerge-remove-props (match-beginning 0) (match-end 0)) | ||
| 280 | ;; We used to use replace-match, but that did not preserve markers so well. | 286 | ;; We used to use replace-match, but that did not preserve markers so well. |
| 281 | (delete-region (match-end n) (match-end 0)) | 287 | (delete-region (match-end n) (match-end 0)) |
| 282 | (delete-region (match-beginning 0) (match-beginning n))) | 288 | (delete-region (match-beginning 0) (match-beginning n))) |
| @@ -326,7 +332,8 @@ according to `smerge-match-conflict'.") | |||
| 326 | ;; mouse-face highlight | 332 | ;; mouse-face highlight |
| 327 | keymap (keymap (down-mouse-3 . smerge-popup-context-menu)))) | 333 | keymap (keymap (down-mouse-3 . smerge-popup-context-menu)))) |
| 328 | 334 | ||
| 329 | (defun smerge-remove-props (&optional beg end) | 335 | (defun smerge-remove-props (beg end) |
| 336 | (remove-overlays beg end 'smerge 'refine) | ||
| 330 | (remove-overlays beg end 'smerge 'conflict)) | 337 | (remove-overlays beg end 'smerge 'conflict)) |
| 331 | 338 | ||
| 332 | (defun smerge-popup-context-menu (event) | 339 | (defun smerge-popup-context-menu (event) |
| @@ -397,7 +404,6 @@ some major modes. Uses `smerge-resolve-function' to do the actual work." | |||
| 397 | (interactive) | 404 | (interactive) |
| 398 | (smerge-match-conflict) | 405 | (smerge-match-conflict) |
| 399 | (smerge-ensure-match 2) | 406 | (smerge-ensure-match 2) |
| 400 | (smerge-remove-props) | ||
| 401 | (smerge-keep-n 2) | 407 | (smerge-keep-n 2) |
| 402 | (smerge-auto-leave)) | 408 | (smerge-auto-leave)) |
| 403 | 409 | ||
| @@ -406,7 +412,6 @@ some major modes. Uses `smerge-resolve-function' to do the actual work." | |||
| 406 | (interactive) | 412 | (interactive) |
| 407 | (smerge-match-conflict) | 413 | (smerge-match-conflict) |
| 408 | ;;(smerge-ensure-match 3) | 414 | ;;(smerge-ensure-match 3) |
| 409 | (smerge-remove-props) | ||
| 410 | (smerge-keep-n 3) | 415 | (smerge-keep-n 3) |
| 411 | (smerge-auto-leave)) | 416 | (smerge-auto-leave)) |
| 412 | 417 | ||
| @@ -415,7 +420,6 @@ some major modes. Uses `smerge-resolve-function' to do the actual work." | |||
| 415 | (interactive) | 420 | (interactive) |
| 416 | (smerge-match-conflict) | 421 | (smerge-match-conflict) |
| 417 | ;;(smerge-ensure-match 1) | 422 | ;;(smerge-ensure-match 1) |
| 418 | (smerge-remove-props) | ||
| 419 | (smerge-keep-n 1) | 423 | (smerge-keep-n 1) |
| 420 | (smerge-auto-leave)) | 424 | (smerge-auto-leave)) |
| 421 | 425 | ||
| @@ -433,7 +437,6 @@ some major modes. Uses `smerge-resolve-function' to do the actual work." | |||
| 433 | (smerge-match-conflict) | 437 | (smerge-match-conflict) |
| 434 | (let ((i (smerge-get-current))) | 438 | (let ((i (smerge-get-current))) |
| 435 | (if (<= i 0) (error "Not inside a version") | 439 | (if (<= i 0) (error "Not inside a version") |
| 436 | (smerge-remove-props) | ||
| 437 | (smerge-keep-n i) | 440 | (smerge-keep-n i) |
| 438 | (smerge-auto-leave)))) | 441 | (smerge-auto-leave)))) |
| 439 | 442 | ||
| @@ -443,7 +446,6 @@ some major modes. Uses `smerge-resolve-function' to do the actual work." | |||
| 443 | (smerge-match-conflict) | 446 | (smerge-match-conflict) |
| 444 | (let ((i (smerge-get-current))) | 447 | (let ((i (smerge-get-current))) |
| 445 | (if (<= i 0) (error "Not inside a version") | 448 | (if (<= i 0) (error "Not inside a version") |
| 446 | (smerge-remove-props) | ||
| 447 | (let ((left nil)) | 449 | (let ((left nil)) |
| 448 | (dolist (n '(3 2 1)) | 450 | (dolist (n '(3 2 1)) |
| 449 | (if (and (match-end n) (/= (match-end n) (match-end i))) | 451 | (if (and (match-end n) (/= (match-end n) (match-end i))) |
| @@ -600,6 +602,84 @@ Point is moved to the end of the conflict." | |||
| 600 | (error nil))) | 602 | (error nil))) |
| 601 | found)) | 603 | found)) |
| 602 | 604 | ||
| 605 | (defun smerge-refine-chopup-region (beg end file) | ||
| 606 | "Chopup the region into small elements, one per line." | ||
| 607 | ;; ediff chops up into words, where the definition of a word is | ||
| 608 | ;; customizable. Instead we here keep only one char per line. | ||
| 609 | ;; The advantages are that there's nothing to configure, that we get very | ||
| 610 | ;; fine results, and that it's trivial to map the line numbers in the | ||
| 611 | ;; output of diff back into buffer positions. The disadvantage is that it | ||
| 612 | ;; can take more time to compute the diff and that the result is sometimes | ||
| 613 | ;; too fine. I'm not too concerned about the slowdown because conflicts | ||
| 614 | ;; are usually significantly smaller than the whole file. As for the | ||
| 615 | ;; problem of too-fine-refinement, I have found it to be unimportant | ||
| 616 | ;; especially when you consider the cases where the fine-grain is just | ||
| 617 | ;; what you want. | ||
| 618 | (let ((buf (current-buffer))) | ||
| 619 | (with-temp-buffer | ||
| 620 | (insert-buffer-substring buf beg end) | ||
| 621 | (goto-char (point-min)) | ||
| 622 | (while (not (eobp)) | ||
| 623 | (forward-char 1) | ||
| 624 | (unless (eq (char-before) ?\n) (insert ?\n))) | ||
| 625 | (let ((coding-system-for-write 'emacs-mule)) | ||
| 626 | (write-region (point-min) (point-max) file nil 'nomessage))))) | ||
| 627 | |||
| 628 | (defun smerge-refine-highlight-change (buf beg match-num1 match-num2) | ||
| 629 | (let* ((startline (string-to-number (match-string match-num1))) | ||
| 630 | (ol (make-overlay | ||
| 631 | (+ beg startline -1) | ||
| 632 | (+ beg (if (match-end match-num2) | ||
| 633 | (string-to-number (match-string match-num2)) | ||
| 634 | startline)) | ||
| 635 | buf | ||
| 636 | 'front-advance nil))) | ||
| 637 | (overlay-put ol 'smerge 'refine) | ||
| 638 | (overlay-put ol 'evaporate t) | ||
| 639 | (overlay-put ol 'face 'smerge-refined-change))) | ||
| 640 | |||
| 641 | |||
| 642 | (defun smerge-refine () | ||
| 643 | "Highlight the parts of the conflict that are different." | ||
| 644 | (interactive) | ||
| 645 | ;; FIXME: make it work with 3-way conflicts. | ||
| 646 | (smerge-match-conflict) | ||
| 647 | (remove-overlays (match-beginning 0) (match-end 0) 'smerge 'refine) | ||
| 648 | (smerge-ensure-match 1) | ||
| 649 | (smerge-ensure-match 3) | ||
| 650 | (let ((buf (current-buffer)) | ||
| 651 | ;; Read them before the match-data gets clobbered. | ||
| 652 | (beg1 (match-beginning 1)) (end1 (match-end 1)) | ||
| 653 | (beg2 (match-beginning 3)) (end2 (match-end 3)) | ||
| 654 | (file1 (make-temp-file "smerge1")) | ||
| 655 | (file2 (make-temp-file "smerge2"))) | ||
| 656 | |||
| 657 | ;; Chop up regions into smaller elements and save into files. | ||
| 658 | (smerge-refine-chopup-region beg1 end1 file1) | ||
| 659 | (smerge-refine-chopup-region beg2 end2 file2) | ||
| 660 | |||
| 661 | ;; Call diff on those files. | ||
| 662 | (unwind-protect | ||
| 663 | (with-temp-buffer | ||
| 664 | (let ((coding-system-for-read 'emacs-mule)) | ||
| 665 | (call-process diff-command nil t nil file1 file2)) | ||
| 666 | ;; Process diff's output. | ||
| 667 | (goto-char (point-min)) | ||
| 668 | (while (not (eobp)) | ||
| 669 | (if (not (looking-at "\\([0-9]+\\)\\(?:,\\([0-9]+\\)\\)?\\([acd]\\)\\([0-9]+\\)\\(?:,\\([0-9]+\\)\\)?$")) | ||
| 670 | (error "Unexpected patch hunk header: %s" | ||
| 671 | (buffer-substring (point) (line-end-position))) | ||
| 672 | (let ((op (char-after (match-beginning 3)))) | ||
| 673 | (when (memq op '(?d ?c)) | ||
| 674 | (smerge-refine-highlight-change buf beg1 1 2)) | ||
| 675 | (when (memq op '(?a ?c)) | ||
| 676 | (smerge-refine-highlight-change buf beg2 4 5))) | ||
| 677 | (forward-line 1) ;Skip hunk header. | ||
| 678 | (and (re-search-forward "^[0-9]" nil 'move) ;Skip hunk body. | ||
| 679 | (goto-char (match-beginning 0)))))) | ||
| 680 | (delete-file file1) | ||
| 681 | (delete-file file2)))) | ||
| 682 | |||
| 603 | (defun smerge-diff (n1 n2) | 683 | (defun smerge-diff (n1 n2) |
| 604 | (smerge-match-conflict) | 684 | (smerge-match-conflict) |
| 605 | (smerge-ensure-match n1) | 685 | (smerge-ensure-match n1) |