Mercurial > emacs
comparison lisp/smerge-mode.el @ 54402:8bf3846fc7dd
2004-03-15 Masatake YAMATO <jet@gyve.org>
Added context menu support in smerge mode.
Most of the part is written by Stefan Monnier.
* smerge-mode.el (smerge-context-menu-map, smerge-context-menu): New
keyman and menu.
(smerge-text-properties): New function.
(smerge-remove-props): New function.
(smerge-popup-context-menu): New function.
(smerge-resolve): Call `smerge-remove-props'.
(smerge-keep-base, smerge-keep-other, smerge-keep-mine):
Ditto.
(smerge-keep-current): Ditto.
(smerge-kill-current): New function.
(smerge-match-conflict): Detect the file as `a same-diff conflict'
if the filename is "ANCESTOR". Put text properties.
author | Masatake YAMATO <jet@gyve.org> |
---|---|
date | Mon, 15 Mar 2004 11:27:47 +0000 |
parents | 118715eba3b3 |
children | 85cd76b8b78c fac24544c283 |
comparison
equal
deleted
inserted
replaced
54401:7f6dab15e141 | 54402:8bf3846fc7dd |
---|---|
1 ;;; smerge-mode.el --- Minor mode to resolve diff3 conflicts | 1 ;;; smerge-mode.el --- Minor mode to resolve diff3 conflicts |
2 | 2 |
3 ;; Copyright (C) 1999, 2000, 01, 03, 2004 Free Software Foundation, Inc. | 3 ;; Copyright (C) 1999, 2000, 01, 03, 2004 Free Software Foundation, Inc. |
4 | 4 |
5 ;; Author: Stefan Monnier <monnier@cs.yale.edu> | 5 ;; Author: Stefan Monnier <monnier@cs.yale.edu> |
6 ;; Keywords: merge diff3 cvs conflict | 6 ;; Keywords: revision-control merge diff3 cvs conflict |
7 ;; Revision: $Id: smerge-mode.el,v 1.24 2003/10/06 16:34:59 fx Exp $ | |
8 | 7 |
9 ;; This file is part of GNU Emacs. | 8 ;; This file is part of GNU Emacs. |
10 | 9 |
11 ;; GNU Emacs is free software; you can redistribute it and/or modify | 10 ;; GNU Emacs is free software; you can redistribute it and/or modify |
12 ;; it under the terms of the GNU General Public License as published by | 11 ;; it under the terms of the GNU General Public License as published by |
185 ["Combine" smerge-combine-with-next | 184 ["Combine" smerge-combine-with-next |
186 :help "Combine current conflict with next" | 185 :help "Combine current conflict with next" |
187 :active (smerge-check 1)] | 186 :active (smerge-check 1)] |
188 )) | 187 )) |
189 | 188 |
189 (easy-mmode-defmap smerge-context-menu-map | |
190 `(([down-mouse-3] . smerge-activate-context-menu)) | |
191 "Keymap for context menu appeared on conflicts area.") | |
192 (easy-menu-define smerge-context-menu nil | |
193 "Context menu for mine area in `smerge-mode'." | |
194 '(nil | |
195 ["Keep Current" smerge-keep-current :help "Use current (at point) version"] | |
196 ["Kill Current" smerge-kill-current :help "Remove current (at point) version"] | |
197 ["Keep All" smerge-keep-all :help "Keep all three versions"] | |
198 "---" | |
199 ["More..." (popup-menu smerge-mode-menu) :help "Show full SMerge mode menu"] | |
200 )) | |
201 | |
190 (defconst smerge-font-lock-keywords | 202 (defconst smerge-font-lock-keywords |
191 '((smerge-find-conflict | 203 '((smerge-find-conflict |
192 (1 smerge-mine-face prepend t) | 204 (1 smerge-mine-face prepend t) |
193 (2 smerge-base-face prepend t) | 205 (2 smerge-base-face prepend t) |
194 (3 smerge-other-face prepend t) | 206 (3 smerge-other-face prepend t) |
281 (lambda () (error "Don't know how to resolve")) | 293 (lambda () (error "Don't know how to resolve")) |
282 "Mode-specific merge function. | 294 "Mode-specific merge function. |
283 The function is called with no argument and with the match data set | 295 The function is called with no argument and with the match data set |
284 according to `smerge-match-conflict'.") | 296 according to `smerge-match-conflict'.") |
285 | 297 |
298 (defvar smerge-text-properties | |
299 `(help-echo "merge conflict: mouse-3 shows a menu" | |
300 ;; mouse-face highlight | |
301 keymap (keymap (down-mouse-3 . smerge-popup-context-menu)))) | |
302 | |
303 (defun smerge-remove-props (&optional beg end) | |
304 (remove-text-properties | |
305 (or beg (match-beginning 0)) | |
306 (or end (match-end 0)) | |
307 smerge-text-properties)) | |
308 | |
309 (defun smerge-popup-context-menu (event) | |
310 "Pop up the Smerge mode context menu under mouse." | |
311 (interactive "e") | |
312 (if (and smerge-mode | |
313 (save-excursion (mouse-set-point event) (smerge-check 1))) | |
314 (progn | |
315 (mouse-set-point event) | |
316 (smerge-match-conflict) | |
317 (let ((i (smerge-get-current)) | |
318 o) | |
319 (if (<= i 0) | |
320 ;; Out of range | |
321 (popup-menu smerge-mode-menu) | |
322 ;; Install overlay. | |
323 (setq o (make-overlay (match-beginning i) (match-end i))) | |
324 (overlay-put o 'face 'highlight) | |
325 (sit-for 0) | |
326 (popup-menu (if (smerge-check 2) | |
327 smerge-mode-menu | |
328 smerge-context-menu)) | |
329 ;; Delete overlay. | |
330 (delete-overlay o)))) | |
331 ;; There's no conflict at point, the text-props are just obsolete. | |
332 (save-excursion | |
333 (let ((beg (re-search-backward smerge-end-re nil t)) | |
334 (end (re-search-forward smerge-begin-re nil t))) | |
335 (smerge-remove-props (or beg (point-min)) (or end (point-max))) | |
336 (push event unread-command-events))))) | |
337 | |
286 (defun smerge-resolve () | 338 (defun smerge-resolve () |
287 "Resolve the conflict at point intelligently. | 339 "Resolve the conflict at point intelligently. |
288 This relies on mode-specific knowledge and thus only works in | 340 This relies on mode-specific knowledge and thus only works in |
289 some major modes. Uses `smerge-resolve-function' to do the actual work." | 341 some major modes. Uses `smerge-resolve-function' to do the actual work." |
290 (interactive) | 342 (interactive) |
291 (smerge-match-conflict) | 343 (smerge-match-conflict) |
344 (smerge-remove-props) | |
292 (funcall smerge-resolve-function) | 345 (funcall smerge-resolve-function) |
293 (smerge-auto-leave)) | 346 (smerge-auto-leave)) |
294 | 347 |
295 (defun smerge-keep-base () | 348 (defun smerge-keep-base () |
296 "Revert to the base version." | 349 "Revert to the base version." |
297 (interactive) | 350 (interactive) |
298 (smerge-match-conflict) | 351 (smerge-match-conflict) |
299 (smerge-ensure-match 2) | 352 (smerge-ensure-match 2) |
353 (smerge-remove-props) | |
300 (replace-match (match-string 2) t t) | 354 (replace-match (match-string 2) t t) |
301 (smerge-auto-leave)) | 355 (smerge-auto-leave)) |
302 | 356 |
303 (defun smerge-keep-other () | 357 (defun smerge-keep-other () |
304 "Use \"other\" version." | 358 "Use \"other\" version." |
305 (interactive) | 359 (interactive) |
306 (smerge-match-conflict) | 360 (smerge-match-conflict) |
307 ;;(smerge-ensure-match 3) | 361 ;;(smerge-ensure-match 3) |
362 (smerge-remove-props) | |
308 (replace-match (match-string 3) t t) | 363 (replace-match (match-string 3) t t) |
309 (smerge-auto-leave)) | 364 (smerge-auto-leave)) |
310 | 365 |
311 (defun smerge-keep-mine () | 366 (defun smerge-keep-mine () |
312 "Keep your version." | 367 "Keep your version." |
313 (interactive) | 368 (interactive) |
314 (smerge-match-conflict) | 369 (smerge-match-conflict) |
315 ;;(smerge-ensure-match 1) | 370 ;;(smerge-ensure-match 1) |
371 (smerge-remove-props) | |
316 (replace-match (match-string 1) t t) | 372 (replace-match (match-string 1) t t) |
317 (smerge-auto-leave)) | 373 (smerge-auto-leave)) |
318 | 374 |
319 (defun smerge-get-current () | 375 (defun smerge-get-current () |
320 (let ((i 3)) | 376 (let ((i 3)) |
328 "Use the current (under the cursor) version." | 384 "Use the current (under the cursor) version." |
329 (interactive) | 385 (interactive) |
330 (smerge-match-conflict) | 386 (smerge-match-conflict) |
331 (let ((i (smerge-get-current))) | 387 (let ((i (smerge-get-current))) |
332 (if (<= i 0) (error "Not inside a version") | 388 (if (<= i 0) (error "Not inside a version") |
389 (smerge-remove-props) | |
333 (replace-match (match-string i) t t) | 390 (replace-match (match-string i) t t) |
391 (smerge-auto-leave)))) | |
392 | |
393 (defun smerge-kill-current () | |
394 "Remove the current (under the cursor) version." | |
395 (interactive) | |
396 (smerge-match-conflict) | |
397 (let ((i (smerge-get-current))) | |
398 (if (<= i 0) (error "Not inside a version") | |
399 (smerge-remove-props) | |
400 (replace-match (mapconcat | |
401 (lambda (j) | |
402 (match-string j)) | |
403 (remove i '(1 2 3)) "") t t) | |
334 (smerge-auto-leave)))) | 404 (smerge-auto-leave)))) |
335 | 405 |
336 (defun smerge-diff-base-mine () | 406 (defun smerge-diff-base-mine () |
337 "Diff 'base' and 'mine' version in current conflict region." | 407 "Diff 'base' and 'mine' version in current conflict region." |
338 (interactive) | 408 (interactive) |
387 (set (make-local-variable 'smerge-conflict-style) 'diff3-A) | 457 (set (make-local-variable 'smerge-conflict-style) 'diff3-A) |
388 (setq base-end mine-end) | 458 (setq base-end mine-end) |
389 (setq mine-end (match-beginning 0)) | 459 (setq mine-end (match-beginning 0)) |
390 (setq base-start (match-end 0))) | 460 (setq base-start (match-end 0))) |
391 | 461 |
392 ((string= filename (file-name-nondirectory | 462 ((string= filename (file-name-nondirectory |
393 (or buffer-file-name ""))) | 463 (or buffer-file-name ""))) |
394 ;; a 2-parts conflict | 464 ;; a 2-parts conflict |
395 (set (make-local-variable 'smerge-conflict-style) 'diff3-E)) | 465 (set (make-local-variable 'smerge-conflict-style) 'diff3-E)) |
396 | 466 |
397 ((and (not base-start) | 467 ((and (not base-start) |
398 (or (eq smerge-conflict-style 'diff3-A) | 468 (or (eq smerge-conflict-style 'diff3-A) |
399 (string-match "^[.0-9]+\\'" filename))) | 469 (equal filename "ANCESTOR") |
400 ;; a same-diff conflict | 470 (string-match "\\`[.0-9]+\\'" filename))) |
401 (setq base-start mine-start) | 471 ;; a same-diff conflict |
402 (setq base-end mine-end) | 472 (setq base-start mine-start) |
403 (setq mine-start other-start) | 473 (setq base-end mine-end) |
404 (setq mine-end other-end))) | 474 (setq mine-start other-start) |
405 | 475 (setq mine-end other-end))) |
476 | |
477 (let ((inhibit-read-only t) | |
478 (inhibit-modification-hooks t) | |
479 (m (buffer-modified-p))) | |
480 (unwind-protect | |
481 (add-text-properties start end smerge-text-properties) | |
482 (restore-buffer-modified-p m))) | |
483 | |
406 (store-match-data (list start end | 484 (store-match-data (list start end |
407 mine-start mine-end | 485 mine-start mine-end |
408 base-start base-end | 486 base-start base-end |
409 other-start other-end | 487 other-start other-end |
410 (when base-start (1- base-start)) base-start | 488 (when base-start (1- base-start)) base-start |