emacs-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: popup menu support for smerge-mode


From: Masatake YAMATO
Subject: Re: popup menu support for smerge-mode
Date: Fri, 26 Sep 2003 16:58:08 +0900 (JST)

> >>>> It's simpler to just place a single overlay over
> >>>> the whole conflict (including markers).
> >> 
> >>> I have not done as you wrote.
> >>> I expect "Keep Current" works on the region which is highlighted.
> >> 
> >> The highlight does not have to apply to the same region as the
> >> `keymap' overlay.
> 
> > I think applying highlight and keymap to the same region is not so
> > complex....probably I have not understood the intent of your
> > suggestions.
> 
> You justified using 2 or 3 overlays over each alternative rather than
> a single one over the whole conflict by saying that "keep current"
> should work on the region which is highlighted.
> 
> What I meant to reply is that you could place a single overlay over the
> whole conflict with a `keymap' property and then when mouse-3 is pressed
> and you add the highlight, you can create a new overlay that covers only
> the relevant alternative and place the highlight there: the highlight
> and the keymap do not have to apply to the same region.
> 
> If you place the overlay over the whole conflict, then the "current"
> alternative can be empty without any problem (other than the fact
> that the highlighting will not aplly to any character) so you
> don't need smerge-delete-current.
> 
> BTW, I don't understand this `smerge-delete-current'.  It seems to take
> a conflict with a non-empty current alternative and replaces it with
> a conflict with an empty current alternative, is that right ?  What I said
> I need is to take a conflict where the current alternative is empty and
> select that alternative (i.e. just delete the whole conflict).

I see. Now overlays for highlighting and a overlays for keymap are used.
Each overlays for highlighting have a property named owner.
Owner property could take a value; whole, mine, other, base...
The popup menu is switched by the property value.

mine and other uses special menus. I added "Keep alternative" to the
menus.  Other including whole uses the smerge menu appeared on the
menu bar.

smerge-delete-current is gone.

> > I've removed smerge-reset-all-overlays. Instead I use evaporate property
> > of overlays. When an overlay is created, I put t to evaporate property of 
> > the overlay. The overlay will be deleted when its region becomes empty.
> 
> I was thinking of suggesting that but wasn't sure whether it'd work.
> Does it ?  If it does, it's probably the simplest alternative, indeed.

`evaporate' doesn't work I expect. So I introduced suboverlays property to
manage overlay deletion.

Masatake YAMATO

Index: lisp/smerge-mode.el
===================================================================
RCS file: /cvsroot/emacs/emacs/lisp/smerge-mode.el,v
retrieving revision 1.22
diff -u -r1.22 smerge-mode.el
--- lisp/smerge-mode.el 1 Sep 2003 15:45:14 -0000       1.22
+++ lisp/smerge-mode.el 26 Sep 2003 07:45:14 -0000
@@ -159,6 +159,31 @@
      :help "Use Ediff to resolve the conflicts"]
     ))
 
+(defvar smerge-overlays nil "Overlays managed by smerge-mode")
+(easy-mmode-defmap smerge-popup-menu-map
+  `(([down-mouse-3] . smerge-activate-popup-menu))
+  "Keymap for popup menu appeared on conflicts area.")
+(easy-menu-define smerge-mode-mine-popup-menu nil
+  "Popup menu for mine area in `smerge-mode'."
+  '(nil
+    ["Keep This" smerge-keep-current :help "Use current (at point) version"]
+    ;; mine <-> other
+    ["Keep Alternative" smerge-keep-other :help "Use alternative version"] 
+    ["Keep All" smerge-keep-all :help "Keep all three versions"]
+    "---"
+    ["More..." (popup-menu smerge-mode-menu) :help "Show full SMerge mode 
menu"]
+    ))
+(easy-menu-define smerge-mode-other-popup-menu nil
+  "Popup menu for other area in `smerge-mode'."
+  '(nil
+    ["Keep This"   smerge-keep-current :help "Use current (at point) version"]
+    ;; other <-> mine
+    ["Keep Alternative" smerge-keep-mine :help "Use alternative version"]
+    ["Keep All"    smerge-keep-all :help "Keep all three versions"]
+    "---"
+    ["More..." (popup-menu smerge-mode-menu) :help "Show full SMerge mode 
menu"]
+    ))
+
 (defconst smerge-font-lock-keywords
   '((smerge-find-conflict
      (1 smerge-mine-face prepend t)
@@ -199,11 +224,13 @@
     (error (format "No `%s'" (aref smerge-match-names n)))))
 
 (defun smerge-auto-leave ()
+  "If no conflict left, turn off Smerge mode.
+Return non-nil if the mode was indeed turned off."
   (when (and smerge-auto-leave
             (save-excursion (goto-char (point-min))
                             (not (re-search-forward smerge-begin-re nil t))))
-    (smerge-mode -1)))
-
+    (smerge-mode -1)
+    t))
 
 (defun smerge-keep-all ()
   "Keep all three versions.
@@ -316,6 +343,92 @@
   (interactive)
   (smerge-diff 1 3))
 
+(defun smerge-put-overlays (match-data)
+  "Put overlays of smerge-mode on the place specified by MATCH-DATA."
+  (let ((m (cddr match-data))
+       (owners '(mine base other base-start other-start))
+       (b-whole (car match-data))
+       (e-whole (cadr match-data))
+       b e o os)
+    (while m
+      (setq b (car m)
+           e (cadr m)
+           m (cddr m)
+           o (car owners)
+           owners (cdr owners))
+      (when (and b e (not (= b e)))
+       (push (smerge-put-highlight-overlay b e o)
+             os)))
+    ;; highlight overlays are managed by keymap overlay.
+    ;; When keymap overlay is shrinked or removed, 
+    ;; highlight overlays are removed.
+    (smerge-put-keymap-overlay b-whole e-whole os)))
+    
+(defun smerge-put-highlight-overlay (start end owner)
+  "Put overlay of smerge-mode between START and END.
+The overlay is highlight when it is pressed.
+OWNER is stored to `owner' property of the new overlay."
+  (let ((overlay (make-overlay start end)))
+    (overlay-put overlay 'evaporate t)
+    (overlay-put overlay 'owner owner)
+    (push overlay smerge-overlays)
+    overlay))
+
+(defun smerge-put-keymap-overlay (start end suboverlays)
+  "Put overlay of smerge-mode between START and END.
+The overlay has its own keymap to show popup menu.
+SUBOVERLAYS are overlays managed by this overlay."
+  (let ((overlay (make-overlay start end)))
+    (overlay-put overlay 'evaporate t)
+    (overlay-put overlay 'help-echo "down-mouse-3: Show popup menu")
+    (overlay-put overlay 'local-map smerge-popup-menu-map)
+    (overlay-put overlay 'owner 'whole)
+    (overlay-put overlay 'suboverlays suboverlays)
+    (push overlay smerge-overlays)
+    overlay))
+
+(defun smerge-activate-popup-menu (event)
+  "Show a popup menu for smerge-mode."
+  (interactive "e")
+  (with-current-buffer (window-buffer 
+                       (posn-window (event-end event)))
+    (save-excursion
+      (goto-char (posn-point (event-end event)))
+      (let* ((os-at (overlays-at (point)))
+            (o-whole (car os-at))
+            (region-whole (- (overlay-end o-whole) (overlay-start o-whole)))
+            (os-sub  (overlay-get o-whole 'suboverlays))
+            (o (if (= 1 (length os-at)) o-whole (cadr os-at)))
+            (owner (overlay-get o 'owner))
+            (face 'highlight)
+            (menu smerge-mode-menu))
+       ;; Set face and menu
+       (cond
+        ((eq 'mine owner)
+         (setq menu smerge-mode-mine-popup-menu
+               face 'region))
+        ((eq 'other owner)
+         (setq menu smerge-mode-other-popup-menu
+               face 'region)))
+       ;; Highlight and show popup menu
+       (unwind-protect
+           (progn
+             (overlay-put o 'face face)
+             (sit-for 0)                     ;; redisplay
+             (popup-menu menu))
+         (overlay-put o 'face nil))
+       ;; Delete overlays
+       (when (or 
+              (not (overlay-buffer o-whole)) ;; dead
+              (< (- (overlay-end o-whole) (overlay-start o-whole))
+                 region-whole))              ;; shrinked up
+         (mapc 'delete-overlay (cons o-whole os-sub)))))))
+
+(defun smerge-delete-overlays ()
+  "Delete all overlays made by  `smerge-put-overlay'."
+  (mapc 'delete-overlay smerge-overlays)
+  (setq smerge-overlays nil))
+
 (defun smerge-match-conflict ()
   "Get info about the conflict.  Puts the info in the `match-data'.
 The submatches contain:
@@ -522,6 +635,12 @@
   "Minor mode to simplify editing output from the diff3 program.
 \\{smerge-mode-map}"
   nil " SMerge" nil
+  ;; overlays management
+  (if smerge-mode
+      ;; entering smerge-mode
+      (make-variable-buffer-local 'smerge-overlays)
+    ;; leaving smerge-mode
+    (smerge-delete-overlays)) 
   (when (and (boundp 'font-lock-mode) font-lock-mode)
     (set (make-local-variable 'font-lock-multiline) t)
     (save-excursion
@@ -531,8 +650,8 @@
       (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)
+         (smerge-put-overlays (match-data)))))))
 
 (provide 'smerge-mode)
 




reply via email to

[Prev in Thread] Current Thread [Next in Thread]