[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: popup menu support for smerge-mode
Re: popup menu support for smerge-mode
Sun, 24 Aug 2003 15:03:34 +0900 (JST)
Several month ago, I wrote:
> I've added popup menu support in smerge-mode.
> Could you evaluate my patch? and if you prefer, please
> add the patch to official source tree.
Stefan Monnier wrote:
> Looks like a good idea. The patch has some problems (the menu and mouse-face
> stays after the conflict is resolved and even after smerge-mode is turned
> but I'll take care of it.
I've rewritten the patch using overlays. Overlays are removed after smerge-mode
turned off. Please, review.
2003-08-24 Masatake YAMATO <address@hidden>
* smerge-mode.el (smerge-overlays): New variable.
(smerge-mode-popup-menu): New menu.
(smerge-auto-leave): Call `smerge-find-conflict' to put overlays.
(smerge-keep-current-by-mouse): New function.
(smerge-put-overlay): New function.
(smerge-delete-overlays): New function.
(smerge-match-conflict): Put overlay here.
(smerge-find-conflict): Add new argument `put-overlay'.
(smerge-mode): Add code to manage overlays.
RCS file: /cvsroot/emacs/emacs/lisp/smerge-mode.el,v
retrieving revision 1.21
diff -u -r1.21 smerge-mode.el
--- lisp/smerge-mode.el 4 Feb 2003 12:05:02 -0000 1.21
+++ lisp/smerge-mode.el 24 Aug 2003 05:50:28 -0000
@@ -137,6 +137,8 @@
`((,smerge-command-prefix . ,smerge-basic-map))
"Keymap for `smerge-mode'.")
+(defvar smerge-overlays nil "Overlays managed by smerge-mode")
(easy-menu-define smerge-mode-menu smerge-mode-map
"Menu for `smerge-mode'."
@@ -159,6 +161,13 @@
:help "Use Ediff to resolve the conflicts"]
+(easy-menu-define smerge-mode-popup-menu smerge-mode-map
+ "Popup menu for `smerge-mode'."
+ ["Keep Current" smerge-keep-current-by-mouse :help "Use current (at point)
+ ["Keep All" smerge-keep-all :help "Keep all three versions"]
(1 smerge-mine-face prepend t)
@@ -199,9 +208,18 @@
(error (format "No `%s'" (aref smerge-match-names n)))))
(defun smerge-auto-leave ()
- (when (and smerge-auto-leave
- (save-excursion (goto-char (point-min))
- (not (re-search-forward smerge-begin-re nil t))))
+ (when (and
+ ;; 1. Are conflict existed?
+ ;; As the side effect, overlays are put.
+ (not (save-excursion
+ (goto-char (point-min))
+ (let (matched)
+ (while (smerge-find-conflict nil t)
+ (setq matched t))
+ ;; 2. Check customize option.
@@ -301,6 +319,15 @@
(replace-match (match-string i) t t)
+(defun smerge-keep-current-by-mouse (event)
+ "Call `smerge-keep-current'at the place where you clicked by a mouse."
+ (interactive "e")
+ (set-buffer (window-buffer (posn-window (event-end event))))
+ (goto-char (posn-point (event-end event)))
(defun smerge-diff-base-mine ()
"Diff 'base' and 'mine' version in current conflict region."
@@ -316,14 +343,33 @@
(smerge-diff 1 3))
-(defun smerge-match-conflict ()
+(defun smerge-put-overlay (start end)
+ "Put overlay of smerge-mode between START and END.
+The overlay has its own keymap to show popup menu."
+ (setq overlay (make-overlay start end))
+ (overlay-put overlay 'mouse-face 'highlight)
+ (overlay-put overlay 'keymap (let ((km (make-sparse-keymap)))
+ (define-key km [down-mouse-3]
+ (lambda () (interactive)
+ (popup-menu smerge-mode-popup-menu)))
+ (overlay-put overlay 'help-echo "down-mouse-3: Use current (at point)
+ (push overlay smerge-overlays))
+(defun smerge-remove-overlays ()
+ "Delete all overlays made by `smerge-put-overlay'."
+ (mapcar (lambda (o) (delete-overlay o)) smerge-overlays)
+ (setq smerge-overlays nil))
+(defun smerge-match-conflict (&optional put-overlay)
"Get info about the conflict. Puts the info in the `match-data'.
The submatches contain:
0: the whole conflict.
1: your code.
2: the base code.
3: other code.
-An error is raised if not inside a conflict."
+An error is raised if not inside a conflict.
+Overlays for smerge popup menu are put if PUT-OVERLAY is non-nil."
(let* ((orig-point (point))
@@ -370,7 +416,13 @@
(setq base-end mine-end)
(setq mine-start other-start)
(setq mine-end other-end)))
+ (when put-overlay
+ (if (and base-start base-end)
+ (smerge-put-overlay base-start base-end))
+ (if (and mine-start mine-end)
+ (smerge-put-overlay mine-start mine-end))
+ (if (and other-start other-end)
+ (smerge-put-overlay other-start other-end)))
(store-match-data (list start end
@@ -380,14 +432,16 @@
(search-failed (error "Point not in conflict region")))))
-(defun smerge-find-conflict (&optional limit)
+(defun smerge-find-conflict (&optional limit put-overlay)
"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."
+The point is moved to the end of the conflict.
+If PUT-OVERLAY is non-nil, overlays for smerge popup menu are put
+as side effect."
(when (re-search-forward smerge-begin-re limit t)
+ (smerge-match-conflict put-overlay)
(goto-char (match-end 0)))))
(defun smerge-diff (n1 n2)
@@ -522,6 +576,12 @@
"Minor mode to simplify editing output from the diff3 program.
nil " SMerge" nil
+ ;; overlays management
+ (if smerge-mode
+ ;; entering smerge-mode
+ (set (make-variable-buffer-local 'smerge-overlays) nil)
+ ;; leaving smerge-mode
(when (and (boundp 'font-lock-mode) font-lock-mode)
(set (make-local-variable 'font-lock-multiline) t)
@@ -529,7 +589,7 @@
(font-lock-add-keywords nil smerge-font-lock-keywords 'append)
(font-lock-remove-keywords nil smerge-font-lock-keywords))
- (while (smerge-find-conflict)
+ (while (smerge-find-conflict nil smerge-mode)
(font-lock-fontify-region (match-beginning 0) (match-end 0) nil))))))
- Re: popup menu support for smerge-mode,
Masatake YAMATO <=