Mercurial > emacs
comparison lisp/smerge-mode.el @ 85099:ccdbfad065e3
(smerge-refine-chopup-region): Add `preproc' argument.
(smerge-refine-highlight-change): Add `props' argument.
(smerge-refine-subst): New function holding most of smerge-refine.
(smerge-refine): Use it.
author | Stefan Monnier <monnier@iro.umontreal.ca> |
---|---|
date | Tue, 09 Oct 2007 03:38:57 +0000 |
parents | 5b92bb6e6570 |
children | 13cb05eb9f29 14c4a6aac623 |
comparison
equal
deleted
inserted
replaced
85098:95e84b39542b | 85099:ccdbfad065e3 |
---|---|
643 (overlay-put conflict (pop props) (pop props)))))) | 643 (overlay-put conflict (pop props) (pop props)))))) |
644 (setq found t)) | 644 (setq found t)) |
645 (error nil))) | 645 (error nil))) |
646 found)) | 646 found)) |
647 | 647 |
648 (defun smerge-refine-chopup-region (beg end file) | 648 (defun smerge-refine-chopup-region (beg end file &optional preproc) |
649 "Chopup the region into small elements, one per line." | 649 "Chopup the region into small elements, one per line. |
650 Save the result into FILE. | |
651 If non-nil, PREPROC is called with no argument in a buffer that contains | |
652 a copy of the text, just before chopping it up. It can be used to replace | |
653 chars to try and eliminate some spurious differences." | |
650 ;; ediff chops up into words, where the definition of a word is | 654 ;; ediff chops up into words, where the definition of a word is |
651 ;; customizable. Instead we here keep only one char per line. | 655 ;; customizable. Instead we here keep only one char per line. |
652 ;; The advantages are that there's nothing to configure, that we get very | 656 ;; The advantages are that there's nothing to configure, that we get very |
653 ;; fine results, and that it's trivial to map the line numbers in the | 657 ;; fine results, and that it's trivial to map the line numbers in the |
654 ;; output of diff back into buffer positions. The disadvantage is that it | 658 ;; output of diff back into buffer positions. The disadvantage is that it |
659 ;; especially when you consider the cases where the fine-grain is just | 663 ;; especially when you consider the cases where the fine-grain is just |
660 ;; what you want. | 664 ;; what you want. |
661 (let ((buf (current-buffer))) | 665 (let ((buf (current-buffer))) |
662 (with-temp-buffer | 666 (with-temp-buffer |
663 (insert-buffer-substring buf beg end) | 667 (insert-buffer-substring buf beg end) |
668 (when preproc (goto-char (point-min)) (funcall preproc)) | |
664 (goto-char (point-min)) | 669 (goto-char (point-min)) |
665 (while (not (eobp)) | 670 (while (not (eobp)) |
666 (forward-char 1) | 671 (forward-char 1) |
672 ;; We add \n after each char except after \n, so we get one line per | |
673 ;; text char, where each line contains just one char, except for \n | |
674 ;; chars which are represented by the empty line. | |
667 (unless (eq (char-before) ?\n) (insert ?\n))) | 675 (unless (eq (char-before) ?\n) (insert ?\n))) |
668 (let ((coding-system-for-write 'emacs-mule)) | 676 (let ((coding-system-for-write 'emacs-mule)) |
669 (write-region (point-min) (point-max) file nil 'nomessage))))) | 677 (write-region (point-min) (point-max) file nil 'nomessage))))) |
670 | 678 |
671 (defun smerge-refine-highlight-change (buf beg match-num1 match-num2) | 679 (defun smerge-refine-highlight-change (buf beg match-num1 match-num2 props) |
672 (let* ((startline (string-to-number (match-string match-num1))) | 680 (let* ((startline (string-to-number (match-string match-num1))) |
673 (ol (make-overlay | 681 (ol (make-overlay |
674 (+ beg startline -1) | 682 (+ beg startline -1) |
675 (+ beg (if (match-end match-num2) | 683 (+ beg (if (match-end match-num2) |
676 (string-to-number (match-string match-num2)) | 684 (string-to-number (match-string match-num2)) |
677 startline)) | 685 startline)) |
678 buf | 686 buf |
687 ;; Make them tend to shrink rather than spread when editing. | |
679 'front-advance nil))) | 688 'front-advance nil))) |
680 (overlay-put ol 'smerge 'refine) | |
681 (overlay-put ol 'evaporate t) | 689 (overlay-put ol 'evaporate t) |
682 (overlay-put ol 'face 'smerge-refined-change))) | 690 (dolist (x props) |
683 | 691 (overlay-put ol (car x) (cdr x))))) |
684 | 692 |
685 (defun smerge-refine () | 693 (defun smerge-refine-subst (beg1 end1 beg2 end2 props &optional preproc) |
686 "Highlight the parts of the conflict that are different." | 694 "Show fine differences in the two regions BEG1..END1 and BEG2..END2. |
687 (interactive) | 695 PROPS is an alist of properties to put (via overlays) on the changes. |
688 ;; FIXME: make it work with 3-way conflicts. | 696 If non-nil, PREPROC is called with no argument in a buffer that contains |
689 (smerge-match-conflict) | 697 a copy of a region, just before preparing it to for `diff'. It can be used to |
690 (remove-overlays (match-beginning 0) (match-end 0) 'smerge 'refine) | 698 replace chars to try and eliminate some spurious differences." |
691 (smerge-ensure-match 1) | 699 (let* ((buf (current-buffer)) |
692 (smerge-ensure-match 3) | 700 (file1 (make-temp-file "diff1")) |
693 (let ((buf (current-buffer)) | 701 (file2 (make-temp-file "diff2"))) |
694 ;; Read them before the match-data gets clobbered. | |
695 (beg1 (match-beginning 1)) (end1 (match-end 1)) | |
696 (beg2 (match-beginning 3)) (end2 (match-end 3)) | |
697 (file1 (make-temp-file "smerge1")) | |
698 (file2 (make-temp-file "smerge2"))) | |
699 | 702 |
700 ;; Chop up regions into smaller elements and save into files. | 703 ;; Chop up regions into smaller elements and save into files. |
701 (smerge-refine-chopup-region beg1 end1 file1) | 704 (smerge-refine-chopup-region beg1 end1 file1 preproc) |
702 (smerge-refine-chopup-region beg2 end2 file2) | 705 (smerge-refine-chopup-region beg2 end2 file2 preproc) |
703 | 706 |
704 ;; Call diff on those files. | 707 ;; Call diff on those files. |
705 (unwind-protect | 708 (unwind-protect |
706 (with-temp-buffer | 709 (with-temp-buffer |
707 (let ((coding-system-for-read 'emacs-mule)) | 710 (let ((coding-system-for-read 'emacs-mule)) |
714 (if (not (looking-at "\\([0-9]+\\)\\(?:,\\([0-9]+\\)\\)?\\([acd]\\)\\([0-9]+\\)\\(?:,\\([0-9]+\\)\\)?$")) | 717 (if (not (looking-at "\\([0-9]+\\)\\(?:,\\([0-9]+\\)\\)?\\([acd]\\)\\([0-9]+\\)\\(?:,\\([0-9]+\\)\\)?$")) |
715 (error "Unexpected patch hunk header: %s" | 718 (error "Unexpected patch hunk header: %s" |
716 (buffer-substring (point) (line-end-position))) | 719 (buffer-substring (point) (line-end-position))) |
717 (let ((op (char-after (match-beginning 3)))) | 720 (let ((op (char-after (match-beginning 3)))) |
718 (when (memq op '(?d ?c)) | 721 (when (memq op '(?d ?c)) |
719 (smerge-refine-highlight-change buf beg1 1 2)) | 722 (smerge-refine-highlight-change buf beg1 1 2 props)) |
720 (when (memq op '(?a ?c)) | 723 (when (memq op '(?a ?c)) |
721 (smerge-refine-highlight-change buf beg2 4 5))) | 724 (smerge-refine-highlight-change buf beg2 4 5 props))) |
722 (forward-line 1) ;Skip hunk header. | 725 (forward-line 1) ;Skip hunk header. |
723 (and (re-search-forward "^[0-9]" nil 'move) ;Skip hunk body. | 726 (and (re-search-forward "^[0-9]" nil 'move) ;Skip hunk body. |
724 (goto-char (match-beginning 0)))))) | 727 (goto-char (match-beginning 0)))))) |
725 (delete-file file1) | 728 (delete-file file1) |
726 (delete-file file2)))) | 729 (delete-file file2)))) |
730 | |
731 (defun smerge-refine () | |
732 "Highlight the parts of the conflict that are different." | |
733 (interactive) | |
734 ;; FIXME: make it work with 3-way conflicts. | |
735 (smerge-match-conflict) | |
736 (remove-overlays (match-beginning 0) (match-end 0) 'smerge 'refine) | |
737 (smerge-ensure-match 1) | |
738 (smerge-ensure-match 3) | |
739 (smerge-refine-subst (match-beginning 1) (match-end 1) | |
740 (match-beginning 3) (match-end 3) | |
741 '((smerge . refine) | |
742 (face . smerge-refined-change)))) | |
727 | 743 |
728 (defun smerge-diff (n1 n2) | 744 (defun smerge-diff (n1 n2) |
729 (smerge-match-conflict) | 745 (smerge-match-conflict) |
730 (smerge-ensure-match n1) | 746 (smerge-ensure-match n1) |
731 (smerge-ensure-match n2) | 747 (smerge-ensure-match n2) |