# HG changeset patch # User Stefan Monnier # Date 1124721531 0 # Node ID 52de8046c483f95dc6f457e9f1f02db356fd6cc3 # Parent 67861e2e09d6eebdc3ad83f0b9f3d4983d8dcc42 (smerge-basic-map): Bind smerge-combine-with-next. (smerge-auto-leave): Make undo re-enable the mode. (debug-ignored-errors): Add the user-error of impossible resolution. (smerge-resolve): Move things around a bit, in preparation for later. (smerge-diff): Don't fail if the buffer has no associated file. (ediff-ancestor-buffer, ediff-quit-hook): Quieten byte-compiler. (smerge-conflict-overlay): New function. (smerge-match-conflict): Don't add text properties here. (smerge-find-conflict): Instead, add an overlay here. Also check for the case where we're inside a conflict already, so as to obviate the need for font-lock-multiline, which is unbearably slow with large conflicts and ciomplex font-lock patterns. (smerge-remove-props): Remove overlay rather than text-properties. (smerge-mode): Don't set font-lock-multiline. Remove overlays when turned off. diff -r 67861e2e09d6 -r 52de8046c483 lisp/ChangeLog --- a/lisp/ChangeLog Sun Aug 21 21:48:22 2005 +0000 +++ b/lisp/ChangeLog Mon Aug 22 14:38:51 2005 +0000 @@ -1,3 +1,21 @@ +2005-08-22 Stefan Monnier + + * smerge-mode.el (smerge-basic-map): Bind smerge-combine-with-next. + (smerge-auto-leave): Make undo re-enable the mode. + (debug-ignored-errors): Add the user-error of impossible resolution. + (smerge-resolve): Move things around a bit, in preparation for later. + (smerge-diff): Don't fail if the buffer has no associated file. + (ediff-ancestor-buffer, ediff-quit-hook): Quieten byte-compiler. + (smerge-conflict-overlay): New function. + (smerge-match-conflict): Don't add text properties here. + (smerge-find-conflict): Instead, add an overlay here. + Also check for the case where we're inside a conflict already, so as to + obviate the need for font-lock-multiline, which is unbearably slow with + large conflicts and ciomplex font-lock patterns. + (smerge-remove-props): Remove overlay rather than text-properties. + (smerge-mode): Don't set font-lock-multiline. + Remove overlays when turned off. + 2005-08-21 Kim F. Storm * ido.el (ido-ignore-item-p): Use save-match-data. @@ -123,7 +141,7 @@ (tree-widget-image-properties): Look up in the default theme too. (tree-widget--cursors): Only for images with arrow pointer shape. (tree-widget-lookup-image): Pointer shape is hand by default. - (tree-widget-icon): Generic icon widget renamed from + (tree-widget-icon): Rename generic icon widget from `tree-widget-control'. (tree-widget-*-icon): Rename from `tree-widget-*-control' and derive from `tree-widget-icon'. @@ -147,8 +165,8 @@ 2005-08-15 Richard M. Stallman - * textmodes/flyspell.el (flyspell-large-region): Fix doc and custom type. - (flyspell-mark-duplications-flag): Doc fix. + * textmodes/flyspell.el (flyspell-mark-duplications-flag): Doc fix. + (flyspell-large-region): Fix doc and custom type. 2005-08-14 Richard M. Stallman @@ -158,11 +176,11 @@ (rmail-clear-headers): Use it. (rmail-reply): Better handling of mail-followup-to header. - * progmodes/sh-script.el (sh-font-lock-keywords-var): Variable - renamed from sh-font-lock-keywords. In the `shell' entry, don't - try to refer to executable-font-lock-keywords. - (sh-font-lock-keywords-var-1): Renamed from sh-font-lock-keywords-1. - (sh-font-lock-keywords-var-2): Renamed from sh-font-lock-keywords-2. + * progmodes/sh-script.el (sh-font-lock-keywords-var): + Rename variable from sh-font-lock-keywords. In the `shell' entry, + don't try to refer to executable-font-lock-keywords. + (sh-font-lock-keywords-var-1): Rename from sh-font-lock-keywords-1. + (sh-font-lock-keywords-var-2): Rename from sh-font-lock-keywords-2. (sh-font-lock-keywords): Append executable-font-lock-keywords here. (sh-mode): Set comment-start-skip, local-abbrev-table, imenu-case-fold-search. @@ -178,8 +196,7 @@ 2005-08-15 Andreas Schwab - * desktop.el: Put autoload cookie at risky-local-variable - declarations. + * desktop.el: Put autoload cookie at risky-local-variable declarations. * dired.el, info.el, mail/rmail.el: Revert last change. @@ -217,8 +234,8 @@ 2005-08-12 Eli Zaretskii - * cus-edit.el (custom-save-all, custom-save-delete): Bind - recentf-exclude to exclude custom-file. + * cus-edit.el (custom-save-all, custom-save-delete): + Bind recentf-exclude to exclude custom-file. 2005-08-12 Ehud Karni @@ -227,17 +244,17 @@ `rmail-summary-mode-map' with key "/". (rmail-summary-show-message): New (internal) function for use by both `rmail-summary-beginning/end-of-message'. - (rmail-summary-beginning-of-message): Changed to use + (rmail-summary-beginning-of-message): Change to use rmail-summary-show-message. * mail/rmail.el (rmail-end-of-message): New command to go to the end of the current message. Added to `rmail-mode-map' with key "/". - (rmail-beginning-of-message): Fixed to work as documented. + (rmail-beginning-of-message): Fix to work as documented. (rmail-mode): Change documentation. * progmodes/compile.el (compilation-start): Add the line "Compilation started" with compilation start time. - (compilation-mode-font-lock-keywords): Add `started' to keywords. + (compilation-mode-font-lock-keywords): Add `started' to keywords. 2005-08-11 Luc Teirlinck @@ -275,16 +292,16 @@ * desktop.el (desktop-buffer-mode-handlers): Make non-customizable. Add autoload cookie. Change initial value to - nil; add elements in respective modules instead. Fix doc string. + nil; add elements in respective modules instead. Fix doc string. (desktop-load-file): New function. (desktop-minor-mode-handlers): New autoloaded variable. (desktop-create-buffer): Call minor mode handlers. Use desktop-load-file to load major and minor mode modules prior to checking for a handler. (desktop-save): Don't add nil to desktop-minor-modes for minor - modes with nil function in desktop-minor-mode-table. Don't delete + modes with nil function in desktop-minor-mode-table. Don't delete desktop file before rewriting it. - (desktop-locals-to-save): Add autoload cookie. Don't make + (desktop-locals-to-save): Add autoload cookie. Don't make automatically buffer-local. Add variables column-number-mode, size-indication-mode, indent-tabs-mode, indicate-buffer-boundaries, indicate-empty-lines and @@ -344,15 +361,13 @@ (compilation-info-text-face): Delete face variables. (compilation-text-face): Delete function. - * progmodes/grep.el (grep-regexp-alist): Use `.+?' instead of - `[^:\n]+'. + * progmodes/grep.el (grep-regexp-alist): Use `.+?' instead of `[^:\n]+'. (grep-mode-font-lock-keywords): Use `.+?' instead of `[^\n-]+'. (grep-error-face): Set to `compilation-error' instead of `compilation-error-face' (which is redefined to `grep-hit-face' in grep buffers). (grep-mode-font-lock-keywords): Remove `-text' from face variable - names. Use `grep-error-face' instead of - `compilation-error-text-face'. + names. Use `grep-error-face' instead of `compilation-error-text-face'. * dired-aux.el (dired-do-query-replace-regexp): Use `query-replace-read-args'. @@ -598,9 +613,9 @@ 2005-08-06 Luc Teirlinck - * wid-edit.el (widget-choice-value-create): Unconditionally - respect user choice. Set :explicit-choice back to nil when no - longer needed. + * wid-edit.el (widget-choice-value-create): + Unconditionally respect user choice. Set :explicit-choice back to nil + when no longer needed. (widget-choice-action): Unconditionally respect user choice. Eliminate :explicit-choice-value. @@ -779,6 +794,11 @@ 2005-07-29 Stefan Monnier + * simple.el (next-error-follow-minor-mode): + make-variable-buffer-local -> make-local-variable. + + * emacs-lisp/cl-extra.el: Require CL also when compiling. + * emacs-lisp/bytecomp.el (byte-compile-make-variable-buffer-local) (byte-compile-form-make-variable-buffer-local): New functions to warn about misuses of make-variable-buffer-local where make-local-variable diff -r 67861e2e09d6 -r 52de8046c483 lisp/smerge-mode.el --- a/lisp/smerge-mode.el Sun Aug 21 21:48:22 2005 +0000 +++ b/lisp/smerge-mode.el Mon Aug 22 14:38:51 2005 +0000 @@ -53,7 +53,7 @@ (defvar smerge-mode) (defgroup smerge () - "Minor mode to resolve diff3 conflicts." + "Minor mode to highlight and resolve diff3 conflicts." :group 'tools :prefix "smerge-") @@ -69,13 +69,13 @@ (defcustom smerge-diff-switches (append '("-d" "-b") (if (listp diff-switches) diff-switches (list diff-switches))) - "*A list of strings specifying switches to be passed to diff. + "A list of strings specifying switches to be passed to diff. Used in `smerge-diff-base-mine' and related functions." :group 'smerge :type '(repeat string)) (defcustom smerge-auto-leave t - "*Non-nil means to leave `smerge-mode' when the last conflict is resolved." + "Non-nil means to leave `smerge-mode' when the last conflict is resolved." :group 'smerge :type 'boolean) @@ -138,6 +138,7 @@ ("o" . smerge-keep-other) ("m" . smerge-keep-mine) ("E" . smerge-ediff) + ("C" . smerge-combine-with-next) ("\C-m" . smerge-keep-current) ("=" . ,(make-sparse-keymap "Diff")) ("=<" "base-mine" . smerge-diff-base-mine) @@ -257,6 +258,8 @@ (when (and smerge-auto-leave (save-excursion (goto-char (point-min)) (not (re-search-forward smerge-begin-re nil t)))) + (when (and (listp buffer-undo-list) smerge-mode) + (push (list 'apply 'smerge-mode 1) buffer-undo-list)) (smerge-mode -1))) @@ -316,6 +319,7 @@ "Mode-specific merge function. The function is called with no argument and with the match data set according to `smerge-match-conflict'.") +(add-to-list 'debug-ignored-errors "Don't know how to resolve") (defvar smerge-text-properties `(help-echo "merge conflict: mouse-3 shows a menu" @@ -323,10 +327,7 @@ keymap (keymap (down-mouse-3 . smerge-popup-context-menu)))) (defun smerge-remove-props (&optional beg end) - (remove-text-properties - (or beg (match-beginning 0)) - (or end (match-end 0)) - smerge-text-properties)) + (remove-overlays beg end 'smerge 'conflict)) (defun smerge-popup-context-menu (event) "Pop up the Smerge mode context menu under mouse." @@ -368,8 +369,16 @@ ;; Trivial diff3 -A non-conflicts. ((and (eq (match-end 1) (match-end 3)) (eq (match-beginning 1) (match-beginning 3))) - ;; FIXME: Add "if [ diff -b MINE OTHER ]; then select OTHER; fi" (smerge-keep-n 3)) + ;; Mode-specific conflict resolution. + ((condition-case nil + (atomic-change-group + (funcall smerge-resolve-function) + t) + (error nil)) + ;; Nothing to do: the resolution function has done it already. + nil) + ;; FIXME: Add "if [ diff -b MINE OTHER ]; then select OTHER; fi" ((and (match-end 2) ;; FIXME: Add "diff -b BASE MINE | patch OTHER". ;; FIXME: Add "diff -b BASE OTHER | patch MINE". @@ -380,8 +389,7 @@ nil) ) (t - ;; Mode-specific conflict resolution. - (funcall smerge-resolve-function))) + (error "Don't know how to resolve"))) (smerge-auto-leave)) (defun smerge-keep-base () @@ -500,6 +508,10 @@ (re-search-forward smerge-begin-re end t)) ;; There's a nested conflict and we're after the the beginning ;; of the outer one but before the beginning of the inner one. + ;; Of course, maybe this is not a nested conflict but in that + ;; case it can only be something nastier that we don't know how + ;; to handle, so may as well arbitrarily decide to treat it as + ;; a nested conflict. --Stef (error "There is a nested conflict")) ((re-search-backward smerge-base-re start t) @@ -524,13 +536,6 @@ (setq mine-start other-start) (setq mine-end other-end))) - (let ((inhibit-read-only t) - (inhibit-modification-hooks t) - (m (buffer-modified-p))) - (unwind-protect - (add-text-properties start end smerge-text-properties) - (restore-buffer-modified-p m))) - (store-match-data (list start end mine-start mine-end base-start base-end @@ -540,17 +545,60 @@ t) (search-failed (error "Point not in conflict region"))))) +(defun smerge-conflict-overlay (pos) + "Return the conflict overlay at POS if any." + (let ((ols (overlays-at pos)) + conflict) + (dolist (ol ols) + (if (and (eq (overlay-get ol 'smerge) 'conflict) + (> (overlay-end ol) pos)) + (setq conflict ol))) + conflict)) + (defun smerge-find-conflict (&optional limit) "Find and match a conflict region. Intended as a font-lock MATCHER. The submatches are the same as in `smerge-match-conflict'. -Returns non-nil if a match is found between the point and LIMIT. -The point is moved to the end of the conflict." - (when (re-search-forward smerge-begin-re limit t) - (condition-case err - (progn - (smerge-match-conflict) - (goto-char (match-end 0))) - (error (smerge-find-conflict limit))))) +Returns non-nil if a match is found between point and LIMIT. +Point is moved to the end of the conflict." + (let ((found nil) + (pos (point)) + conflict) + ;; First check to see if point is already inside a conflict, using + ;; the conflict overlays. + (while (and (not found) (setq conflict (smerge-conflict-overlay pos))) + ;; Check the overlay's validity and kill it if it's out of date. + (condition-case nil + (progn + (goto-char (overlay-start conflict)) + (smerge-match-conflict) + (goto-char (match-end 0)) + (if (<= (point) pos) + (error "Matching backward!") + (setq found t))) + (error (smerge-remove-props + (overlay-start conflict) (overlay-end conflict)) + (goto-char pos)))) + ;; If we're not already inside a conflict, look for the next conflict + ;; and add/update its overlay. + (while (and (not found) (re-search-forward smerge-begin-re limit t)) + (condition-case nil + (progn + (smerge-match-conflict) + (goto-char (match-end 0)) + (let ((conflict (smerge-conflict-overlay (1- (point))))) + (if conflict + ;; Update its location, just in case it got messed up. + (move-overlay conflict (match-beginning 0) (match-end 0)) + (setq conflict (make-overlay (match-beginning 0) (match-end 0) + nil 'front-advance nil)) + (overlay-put conflict 'evaporate t) + (overlay-put conflict 'smerge 'conflict) + (let ((props smerge-text-properties)) + (while props + (overlay-put conflict (pop props) (pop props)))))) + (setq found t)) + (error nil))) + found)) (defun smerge-diff (n1 n2) (smerge-match-conflict) @@ -566,7 +614,12 @@ (file1 (make-temp-file "smerge1")) (file2 (make-temp-file "smerge2")) (dir default-directory) - (file (file-relative-name buffer-file-name)) + (file (if buffer-file-name (file-relative-name buffer-file-name))) + ;; We would want to use `emacs-mule-unix' for read&write, but we + ;; bump into problems with the coding-system used by diff to write + ;; the file names and the time stamps in the header. + ;; `buffer-file-coding-system' is not always correct either, but if + ;; the OS/user uses only one coding-system, then it works. (coding-system-for-read buffer-file-coding-system)) (write-region beg1 end1 file1 nil 'nomessage) (write-region beg2 end2 file2 nil 'nomessage) @@ -594,6 +647,8 @@ (defvar ediff-buffer-A) (defvar ediff-buffer-B) (defvar ediff-buffer-C) +(defvar ediff-ancestor-buffer) +(defvar ediff-quit-hook) ;;;###autoload (defun smerge-ediff (&optional name-mine name-other name-base) @@ -687,7 +742,6 @@ \\{smerge-mode-map}" :group 'smerge :lighter " SMerge" (when (and (boundp 'font-lock-mode) font-lock-mode) - (set (make-local-variable 'font-lock-multiline) t) (save-excursion (if smerge-mode (font-lock-add-keywords nil smerge-font-lock-keywords 'append) @@ -695,7 +749,9 @@ (goto-char (point-min)) (while (smerge-find-conflict) (save-excursion - (font-lock-fontify-region (match-beginning 0) (match-end 0) nil)))))) + (font-lock-fontify-region (match-beginning 0) (match-end 0) nil))))) + (unless smerge-mode + (smerge-remove-props (point-min) (point-max)))) (provide 'smerge-mode)