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)