X-Git-Url: https://git.hcoop.net/bpt/emacs.git/blobdiff_plain/4a6e3980e26fda95587bff36c3a0efc0779f0202..a71eca925b1818ee1509675e49a1c3192004b112:/lisp/emerge.el diff --git a/lisp/emerge.el b/lisp/emerge.el index d84812a203..023727e26b 100644 --- a/lisp/emerge.el +++ b/lisp/emerge.el @@ -2,7 +2,7 @@ ;;; The author has placed this file in the public domain. -;; Author: Dale R. Worley +;; Author: Dale R. Worley ;; Version: 5fsf ;; Keywords: unix, tools @@ -21,6 +21,33 @@ ;;; Code: +;;;###autoload +(defvar menu-bar-emerge-menu (make-sparse-keymap "Emerge")) +;;;###autoload +(fset 'menu-bar-emerge-menu (symbol-value 'menu-bar-emerge-menu)) + +;;;###autoload +(define-key menu-bar-emerge-menu [emerge-merge-directories] + '("Merge Directories..." . emerge-merge-directories)) +;;;###autoload +(define-key menu-bar-emerge-menu [emerge-revisions-with-ancestor] + '("Revisions with Ancestor..." . emerge-revisions-with-ancestor)) +;;;###autoload +(define-key menu-bar-emerge-menu [emerge-revisions] + '("Revisions..." . emerge-revisions)) +;;;###autoload +(define-key menu-bar-emerge-menu [emerge-files-with-ancestor] + '("Files with Ancestor..." . emerge-files-with-ancestor)) +;;;###autoload +(define-key menu-bar-emerge-menu [emerge-files] + '("Files..." . emerge-files)) +;;;###autoload +(define-key menu-bar-emerge-menu [emerge-buffers-with-ancestor] + '("Buffers with Ancestor..." . emerge-buffers-with-ancestor)) +;;;###autoload +(define-key menu-bar-emerge-menu [emerge-buffers] + '("Buffers..." . emerge-buffers)) + ;;; Macros (defmacro emerge-eval-in-buffer (buffer &rest forms) @@ -45,11 +72,12 @@ won't destroy Emerge control variables." (put '(, var) 'preserved t)))) ;; Add entries to minor-mode-alist so that emerge modes show correctly -(setq emerge-minor-modes-list '((emerge-mode " Emerge") - (emerge-fast-mode " F") - (emerge-edit-mode " E") - (emerge-auto-advance " A") - (emerge-skip-prefers " S"))) +(defvar emerge-minor-modes-list + '((emerge-mode " Emerge") + (emerge-fast-mode " F") + (emerge-edit-mode " E") + (emerge-auto-advance " A") + (emerge-skip-prefers " S"))) (if (not (assq 'emerge-mode minor-mode-alist)) (setq minor-mode-alist (append emerge-minor-modes-list minor-mode-alist))) @@ -85,6 +113,10 @@ When called interactively, displays the version." ;;; Emerge configuration variables +(defgroup emerge nil + "Merge diffs under Emacs control." + :group 'tools) + ;; Commands that produce difference files ;; All that can be configured is the name of the programs to execute ;; (emerge-diff-program and emerge-diff3-program) and the options @@ -96,60 +128,102 @@ When called interactively, displays the version." ;; The code which processes the diff/diff3 output depends on all the ;; finicky details of their output, including the somewhat strange ;; way they number lines of a file. -(defvar emerge-diff-program "diff" - "*Name of the program which compares two files.") -(defvar emerge-diff3-program "diff3" +(defcustom emerge-diff-program "diff" + "*Name of the program which compares two files." + :type 'string + :group 'emerge) +(defcustom emerge-diff3-program "diff3" "*Name of the program which compares three files. -Its arguments are the ancestor file and the two variant files.") -(defvar emerge-diff-options "" - "*Options to pass to `emerge-diff-program' and `emerge-diff3-program'.") -(defvar emerge-match-diff-line (let ((x "\\([0-9]+\\)\\(\\|,\\([0-9]+\\)\\)")) - (concat "^" x "\\([acd]\\)" x "$")) +Its arguments are the ancestor file and the two variant files." + :type 'string + :group 'emerge) +(defcustom emerge-diff-options "" + "*Options to pass to `emerge-diff-program' and `emerge-diff3-program'." + :type 'string + :group 'emerge) +(defcustom emerge-match-diff-line + (let ((x "\\([0-9]+\\)\\(\\|,\\([0-9]+\\)\\)")) + (concat "^" x "\\([acd]\\)" x "$")) "*Pattern to match lines produced by diff that describe differences. -This is as opposed to lines from the source files.") -(defvar emerge-diff-ok-lines-regexp +This is as opposed to lines from the source files." + :type 'regexp + :group 'emerge) +(defcustom emerge-diff-ok-lines-regexp "^\\([0-9,]+[acd][0-9,]+$\\|[<>] \\|---\\)" "*Regexp that matches normal output lines from `emerge-diff-program'. -Lines that do not match are assumed to be error messages.") -(defvar emerge-diff3-ok-lines-regexp +Lines that do not match are assumed to be error messages." + :type 'regexp + :group 'emerge) +(defcustom emerge-diff3-ok-lines-regexp "^\\([1-3]:\\|====\\| \\)" "*Regexp that matches normal output lines from `emerge-diff3-program'. -Lines that do not match are assumed to be error messages.") - -(defvar emerge-rcs-ci-program "ci" - "*Name of the program that checks in RCS revisions.") -(defvar emerge-rcs-co-program "co" - "*Name of the program that checks out RCS revisions.") - -(defvar emerge-process-local-variables nil +Lines that do not match are assumed to be error messages." + :type 'regexp + :group 'emerge) + +(defcustom emerge-rcs-ci-program "ci" + "*Name of the program that checks in RCS revisions." + :type 'string + :group 'emerge) +(defcustom emerge-rcs-co-program "co" + "*Name of the program that checks out RCS revisions." + :type 'string + :group 'emerge) + +(defcustom emerge-process-local-variables nil "*Non-nil if Emerge should process local-variables lists in merge buffers. \(You can explicitly request processing the local-variables -by executing `(hack-local-variables)'.)") -(defvar emerge-execute-line-deletions nil +by executing `(hack-local-variables)'.)" + :type 'boolean + :group 'emerge) +(defcustom emerge-execute-line-deletions nil "*If non-nil: `emerge-execute-line' makes no output if an input was deleted. It concludes that an input version has been deleted when an ancestor entry is present, only one A or B entry is present, and an output entry is present. If nil: In such circumstances, the A or B file that is present will be -copied to the designated output file.") +copied to the designated output file." + :type 'boolean + :group 'emerge) + +(defcustom emerge-before-flag "vvvvvvvvvvvvvvvvvvvv\n" + "*Flag placed above the highlighted block of code. Must end with newline. +Must be set before Emerge is loaded, or emerge-new-flags must be run +after setting." + :type 'string + :group 'emerge) +(defcustom emerge-after-flag "^^^^^^^^^^^^^^^^^^^^\n" + "*Flag placed below the highlighted block of code. Must end with newline. +Must be set before Emerge is loaded, or emerge-new-flags must be run +after setting." + :type 'string + :group 'emerge) ;; Hook variables -(defvar emerge-startup-hook nil - "*Hook to run in the merge buffer after the merge has been set up.") -(defvar emerge-select-hook nil +(defcustom emerge-startup-hook nil + "*Hook to run in the merge buffer after the merge has been set up." + :type 'hook + :group 'emerge) +(defcustom emerge-select-hook nil "*Hook to run after a difference has been selected. -The variable `n' holds the (internal) number of the difference.") -(defvar emerge-unselect-hook nil +The variable `n' holds the (internal) number of the difference." + :type 'hook + :group 'emerge) +(defcustom emerge-unselect-hook nil "*Hook to run after a difference has been unselected. -The variable `n' holds the (internal) number of the difference.") +The variable `n' holds the (internal) number of the difference." + :type 'hook + :group 'emerge) ;; Variables to control the default directories of the arguments to ;; Emerge commands. -(defvar emerge-default-last-directories nil +(defcustom emerge-default-last-directories nil "*If nil, default dir for filenames in emerge is `default-directory'. If non-nil, filenames complete in the directory of the last argument of the -same type to an `emerge-files...' command.") +same type to an `emerge-files...' command." + :type 'boolean + :group 'emerge) (defvar emerge-last-dir-A nil "Last directory for the first file of an `emerge-files...' command.") @@ -166,6 +240,20 @@ same type to an `emerge-files...' command.") (defvar emerge-last-revision-ancestor nil "Last RCS revision used for ancestor file of an `emerge-revisions...' command.") +(defvar emerge-before-flag-length) +(defvar emerge-before-flag-lines) +(defvar emerge-before-flag-match) +(defvar emerge-after-flag-length) +(defvar emerge-after-flag-lines) +(defvar emerge-after-flag-match) +(defvar emerge-diff-buffer) +(defvar emerge-diff-error-buffer) +(defvar emerge-prefix-argument) +(defvar emerge-file-out) +(defvar emerge-exit-func) +(defvar emerge-globalized-difference-list) +(defvar emerge-globalized-number-of-differences) + ;; The flags used to mark differences in the buffers. ;; These function definitions need to be up here, because they are used @@ -192,39 +280,29 @@ depend on the flags." (setq i (match-end 0))) count)) -(defvar emerge-before-flag "vvvvvvvvvvvvvvvvvvvv\n" - "*Flag placed above the highlighted block of code. Must end with newline. -Must be set before Emerge is loaded, or emerge-new-flags must be run -after setting.") -(defvar emerge-after-flag "^^^^^^^^^^^^^^^^^^^^\n" - "*Flag placed below the highlighted block of code. Must end with newline. -Must be set before Emerge is loaded, or emerge-new-flags must be run -after setting.") - ;; Calculate dependent variables (emerge-new-flags) -(defvar emerge-min-visible-lines 3 +(defcustom emerge-min-visible-lines 3 "*Number of lines that we want to show above and below the flags when we are -displaying a difference.") - -(defvar emerge-temp-file-prefix - (let ((env (getenv "TMPDIR")) - d) - (setq d (if (and env (> (length env) 0)) - env - "/tmp")) - (if (= (aref d (1- (length d))) ?/) - (setq d (substring d 0 -1))) - (concat d "/emerge")) +displaying a difference." + :type 'integer + :group 'emerge) + +(defcustom emerge-temp-file-prefix + (expand-file-name "emerge" temporary-file-directory) "*Prefix to put on Emerge temporary file names. -Do not start with `~/' or `~user-name/'.") +Do not start with `~/' or `~USERNAME/'." + :type 'string + :group 'emerge) -(defvar emerge-temp-file-mode 384 ; u=rw only - "*Mode for Emerge temporary files.") +(defcustom emerge-temp-file-mode 384 ; u=rw only + "*Mode for Emerge temporary files." + :type 'integer + :group 'emerge) -(defvar emerge-combine-versions-template - "#ifdef NEW\n%b#else /* NEW */\n%a#endif /* NEW */\n" +(defcustom emerge-combine-versions-template + "#ifdef NEW\n%b#else /* not NEW */\n%a#endif /* not NEW */\n" "*Template for `emerge-combine-versions' to combine the two versions. The template is inserted as a string, with the following interpolations: %a the A version of the difference @@ -232,7 +310,9 @@ The template is inserted as a string, with the following interpolations: %% the character `%' Don't forget to end the template with a newline. Note that this variable can be made local to a particular merge buffer by -giving a prefix argument to `emerge-set-combine-versions-template'.") +giving a prefix argument to `emerge-set-combine-versions-template'." + :type 'string + :group 'emerge) ;; Build keymaps @@ -245,9 +325,20 @@ must be prefixed by \\\\[emerge-basic-keymap] in `edit' mode "Local keymap used in Emerge `fast' mode. Makes Emerge commands directly available.") -(defvar emerge-command-prefix "\C-c\C-c" +(defvar emerge-options-menu + (make-sparse-keymap "Options")) + +(defvar emerge-merge-menu + (make-sparse-keymap "Merge")) + +(defvar emerge-move-menu + (make-sparse-keymap "Move")) + +(defcustom emerge-command-prefix "\C-c\C-c" "*Command prefix for Emerge commands in `edit' mode. -Must be set before Emerge is loaded.") +Must be set before Emerge is loaded." + :type 'string + :group 'emerge) ;; This function sets up the fixed keymaps. It is executed when the first ;; Emerge is done to allow the user maximum time to set up the global keymap. @@ -308,7 +399,83 @@ Must be set before Emerge is loaded.") (substitute-key-definition 'write-file 'emerge-query-write-file emerge-fast-keymap (current-global-map)) (substitute-key-definition 'save-buffer 'emerge-query-save-buffer - emerge-fast-keymap (current-global-map))) + emerge-fast-keymap (current-global-map)) + + (define-key emerge-basic-keymap [menu-bar] (make-sparse-keymap)) + + (define-key emerge-fast-keymap [menu-bar options] + (cons "Options" emerge-options-menu)) + (define-key emerge-fast-keymap [menu-bar merge] + (cons "Merge" emerge-merge-menu)) + (define-key emerge-fast-keymap [menu-bar move] + (cons "Move" emerge-move-menu)) + + (define-key emerge-move-menu [emerge-scroll-reset] + '("Scroll Reset" . emerge-scroll-reset)) + (define-key emerge-move-menu [emerge-scroll-right] + '("Scroll Right" . emerge-scroll-right)) + (define-key emerge-move-menu [emerge-scroll-left] + '("Scroll Left" . emerge-scroll-left)) + (define-key emerge-move-menu [emerge-scroll-down] + '("Scroll Down" . emerge-scroll-down)) + (define-key emerge-move-menu [emerge-scroll-up] + '("Scroll Up" . emerge-scroll-up)) + (define-key emerge-move-menu [emerge-recenter] + '("Recenter" . emerge-recenter)) + (define-key emerge-move-menu [emerge-mark-difference] + '("Mark Difference" . emerge-mark-difference)) + (define-key emerge-move-menu [emerge-jump-to-difference] + '("Jump To Difference" . emerge-jump-to-difference)) + (define-key emerge-move-menu [emerge-find-difference] + '("Find Difference" . emerge-find-difference)) + (define-key emerge-move-menu [emerge-previous-difference] + '("Previous Difference" . emerge-previous-difference)) + (define-key emerge-move-menu [emerge-next-difference] + '("Next Difference" . emerge-next-difference)) + + + (define-key emerge-options-menu [emerge-one-line-window] + '("One Line Window" . emerge-one-line-window)) + (define-key emerge-options-menu [emerge-set-merge-mode] + '("Set Merge Mode" . emerge-set-merge-mode)) + (define-key emerge-options-menu [emerge-set-combine-template] + '("Set Combine Template..." . emerge-set-combine-template)) + (define-key emerge-options-menu [emerge-default-B] + '("Default B" . emerge-default-B)) + (define-key emerge-options-menu [emerge-default-A] + '("Default A" . emerge-default-A)) + (define-key emerge-options-menu [emerge-skip-prefers] + '("Skip Prefers" . emerge-skip-prefers)) + (define-key emerge-options-menu [emerge-auto-advance] + '("Auto Advance" . emerge-auto-advance)) + (define-key emerge-options-menu [emerge-edit-mode] + '("Edit Mode" . emerge-edit-mode)) + (define-key emerge-options-menu [emerge-fast-mode] + '("Fast Mode" . emerge-fast-mode)) + + (define-key emerge-merge-menu [emerge-abort] '("Abort" . emerge-abort)) + (define-key emerge-merge-menu [emerge-quit] '("Quit" . emerge-quit)) + (define-key emerge-merge-menu [emerge-split-difference] + '("Split Difference" . emerge-split-difference)) + (define-key emerge-merge-menu [emerge-join-differences] + '("Join Differences" . emerge-join-differences)) + (define-key emerge-merge-menu [emerge-trim-difference] + '("Trim Difference" . emerge-trim-difference)) + (define-key emerge-merge-menu [emerge-combine-versions] + '("Combine Versions" . emerge-combine-versions)) + (define-key emerge-merge-menu [emerge-copy-as-kill-B] + '("Copy B as Kill" . emerge-copy-as-kill-B)) + (define-key emerge-merge-menu [emerge-copy-as-kill-A] + '("Copy A as Kill" . emerge-copy-as-kill-A)) + (define-key emerge-merge-menu [emerge-insert-B] + '("Insert B" . emerge-insert-B)) + (define-key emerge-merge-menu [emerge-insert-A] + '("Insert A" . emerge-insert-A)) + (define-key emerge-merge-menu [emerge-select-B] + '("Select B" . emerge-select-B)) + (define-key emerge-merge-menu [emerge-select-A] + '("Select A" . emerge-select-A))) + ;; Variables which control each merge. They are local to the merge buffer. @@ -724,17 +891,16 @@ This is *not* a user option, since Emerge uses it for its own processing.") (let (f) (list current-prefix-arg (setq f (emerge-read-file-name "File A to merge" emerge-last-dir-A - nil nil)) - (emerge-read-file-name "File B to merge" emerge-last-dir-B nil f) + nil nil t)) + (emerge-read-file-name "File B to merge" emerge-last-dir-B nil f t) (and current-prefix-arg (emerge-read-file-name "Output file" emerge-last-dir-output - f f))))) + f f nil))))) + (if file-out + (add-hook 'quit-hooks (` (lambda () (emerge-files-exit (, file-out)))))) (emerge-files-internal file-A file-B startup-hooks - (if file-out - (cons (` (lambda () (emerge-files-exit (, file-out)))) - quit-hooks) - quit-hooks) + quit-hooks file-out)) ;;;###autoload @@ -745,19 +911,18 @@ This is *not* a user option, since Emerge uses it for its own processing.") (let (f) (list current-prefix-arg (setq f (emerge-read-file-name "File A to merge" emerge-last-dir-A - nil nil)) - (emerge-read-file-name "File B to merge" emerge-last-dir-B nil f) + nil nil t)) + (emerge-read-file-name "File B to merge" emerge-last-dir-B nil f t) (emerge-read-file-name "Ancestor file" emerge-last-dir-ancestor - nil f) + nil f t) (and current-prefix-arg (emerge-read-file-name "Output file" emerge-last-dir-output - f f))))) + f f nil))))) + (if file-out + (add-hook 'quit-hooks (` (lambda () (emerge-files-exit (, file-out)))))) (emerge-files-with-ancestor-internal file-A file-B file-ancestor startup-hooks - (if file-out - (cons (` (lambda () (emerge-files-exit (, file-out)))) - quit-hooks) - quit-hooks) + quit-hooks file-out)) ;; Write the merge buffer out in place of the file the A buffer is visiting. @@ -867,7 +1032,7 @@ This is *not* a user option, since Emerge uses it for its own processing.") (setq emerge-file-out file-out) (emerge-files-internal file-a file-b nil - (list (` (lambda () (emerge-remote-exit (, file-out) '(, exit-func))))) + (list (` (lambda () (emerge-remote-exit (, file-out) '(, emerge-exit-func))))) file-out) (throw 'client-wait nil)) @@ -876,17 +1041,18 @@ This is *not* a user option, since Emerge uses it for its own processing.") (setq emerge-file-out file-out) (emerge-files-with-ancestor-internal file-a file-b file-anc nil - (list (` (lambda () (emerge-remote-exit (, file-out) '(, exit-func))))) + (list (` (lambda () (emerge-remote-exit (, file-out) '(, emerge-exit-func))))) file-out) (throw 'client-wait nil)) -(defun emerge-remote-exit (file-out exit-func) +(defun emerge-remote-exit (file-out emerge-exit-func) (emerge-write-and-delete file-out) (kill-buffer emerge-merge-buffer) - (funcall exit-func (if emerge-prefix-argument 1 0))) + (funcall emerge-exit-func (if emerge-prefix-argument 1 0))) ;;; Functions to start Emerge on RCS versions +;;;###autoload (defun emerge-revisions (arg file revision-A revision-B &optional startup-hooks quit-hooks) "Emerge two RCS revisions of a file." @@ -906,6 +1072,7 @@ This is *not* a user option, since Emerge uses it for its own processing.") quit-hooks) quit-hooks))) +;;;###autoload (defun emerge-revisions-with-ancestor (arg file revision-A revision-B ancestor &optional @@ -1118,9 +1285,12 @@ Otherwise, the A or B file present is copied to the output file." ;;; Sample function for creating information for emerge-execute-line -(defvar emerge-merge-directories-filename-regexp "[^.]" - "Regexp describing files to be processed by `emerge-merge-directories'.") +(defcustom emerge-merge-directories-filename-regexp "[^.]" + "Regexp describing files to be processed by `emerge-merge-directories'." + :type 'regexp + :group 'emerge) +;;;###autoload (defun emerge-merge-directories (a-dir b-dir ancestor-dir output-dir) (interactive (list @@ -1241,6 +1411,16 @@ Otherwise, the A or B file present is copied to the output file." ;; Install the Emerge commands (emerge-force-define-key emerge-edit-keymap emerge-command-prefix 'emerge-basic-keymap) + (define-key emerge-edit-keymap [menu-bar] (make-sparse-keymap)) + + ;; Create the additional menu bar items. + (define-key emerge-edit-keymap [menu-bar options] + (cons "Options" emerge-options-menu)) + (define-key emerge-edit-keymap [menu-bar merge] + (cons "Merge" emerge-merge-menu)) + (define-key emerge-edit-keymap [menu-bar move] + (cons "Move" emerge-move-menu)) + ;; Suppress write-file and save-buffer (substitute-key-definition 'write-file 'emerge-query-write-file @@ -1292,6 +1472,12 @@ These characteristics are restored by `emerge-restore-buffer-characteristics'." (emerge-restore-variables emerge-saved-variables B-values)))) +;; Move to line DESIRED-LINE assuming we are at line CURRENT-LINE. +;; Return DESIRED-LINE. +(defun emerge-goto-line (desired-line current-line) + (forward-line (- desired-line current-line)) + desired-line) + (defun emerge-convert-diffs-to-markers (A-buffer B-buffer merge-buffer @@ -1299,17 +1485,13 @@ These characteristics are restored by `emerge-restore-buffer-characteristics'." (let* (marker-list (A-point-min (emerge-eval-in-buffer A-buffer (point-min))) (offset (1- A-point-min)) - (A-hidden-lines (emerge-eval-in-buffer - A-buffer - (save-restriction - (widen) - (count-lines 1 A-point-min)))) (B-point-min (emerge-eval-in-buffer B-buffer (point-min))) - (B-hidden-lines (emerge-eval-in-buffer - B-buffer - (save-restriction - (widen) - (count-lines 1 B-point-min))))) + ;; Record current line number in each buffer + ;; so we don't have to count from the beginning. + (a-line 1) + (b-line 1)) + (emerge-eval-in-buffer A-buffer (goto-char (point-min))) + (emerge-eval-in-buffer B-buffer (goto-char (point-min))) (while lineno-list (let* ((list-element (car lineno-list)) a-begin-marker @@ -1326,15 +1508,15 @@ These characteristics are restored by `emerge-restore-buffer-characteristics'." ;; place markers at the appropriate places in the buffers (emerge-eval-in-buffer A-buffer - (goto-line (+ a-begin A-hidden-lines)) + (setq a-line (emerge-goto-line a-begin a-line)) (setq a-begin-marker (point-marker)) - (goto-line (+ a-end A-hidden-lines)) + (setq a-line (emerge-goto-line a-end a-line)) (setq a-end-marker (point-marker))) (emerge-eval-in-buffer B-buffer - (goto-line (+ b-begin B-hidden-lines)) + (setq b-line (emerge-goto-line b-begin b-line)) (setq b-begin-marker (point-marker)) - (goto-line (+ b-end B-hidden-lines)) + (setq b-line (emerge-goto-line b-end b-line)) (setq b-end-marker (point-marker))) (setq merge-begin-marker (set-marker (make-marker) @@ -1412,8 +1594,8 @@ With an argument, reestablish the default three-window display." (let* ((merge-buffer emerge-merge-buffer) (buffer-A emerge-A-buffer) (buffer-B emerge-B-buffer) - (window-A (get-buffer-window buffer-A)) - (window-B (get-buffer-window buffer-B)) + (window-A (get-buffer-window buffer-A 'visible)) + (window-B (get-buffer-window buffer-B 'visible)) (merge-window (get-buffer-window merge-buffer)) (diff-vector (aref emerge-difference-list emerge-current-difference))) @@ -1457,8 +1639,8 @@ With an argument, reestablish the default three-window display." (let* ((merge-buffer emerge-merge-buffer) (buffer-A emerge-A-buffer) (buffer-B emerge-B-buffer) - (window-A (get-buffer-window buffer-A)) - (window-B (get-buffer-window buffer-B)) + (window-A (get-buffer-window buffer-A 'visible)) + (window-B (get-buffer-window buffer-B 'visible)) (merge-window (get-buffer-window merge-buffer))) (if window-A (progn (select-window window-A) @@ -1597,7 +1779,7 @@ to the left margin, if they are in windows." ;; If there are min-lines lines above and below the region, then don't do ;; anything. ;; If not, recenter the region to make it so. -;; If that isn't possible, remove context lines balancedly from top and botton +;; If that isn't possible, remove context lines balancedly from top and bottom ;; so the entire region shows. ;; If that isn't possible, show the top of the region. ;; BEG must be at the beginning of a line. @@ -1798,10 +1980,10 @@ which there is no preference." (emerge-select-A) (aset diff-vector 6 'default-A)))) (setq n (1+ n)) - (if (= (* (/ n 10) 10) n) + (if (zerop (% n 10)) (message "Setting default to A...%d" n))) (emerge-unselect-and-select-difference selected-difference))) - (message "Default A set")) + (message "Default choice is now A")) (defun emerge-default-B () "Make the B variant the default from here down. @@ -1820,10 +2002,10 @@ which there is no preference." (emerge-select-B) (aset diff-vector 6 'default-B)))) (setq n (1+ n)) - (if (= (* (/ n 10) 10) n) + (if (zerop (% n 10)) (message "Setting default to B...%d" n))) (emerge-unselect-and-select-difference selected-difference))) - (message "Default B set")) + (message "Default choice is now B")) (defun emerge-fast-mode () "Set fast mode, for Emerge. @@ -1836,8 +2018,7 @@ need not be prefixed with \\\\[emerge-basic-keymap]." (setq emerge-fast-mode t) (setq emerge-edit-mode nil) (message "Fast mode set") - ;; force mode line redisplay - (set-buffer-modified-p (buffer-modified-p))) + (force-mode-line-update)) (defun emerge-edit-mode () "Set edit mode, for Emerge. @@ -1850,8 +2031,7 @@ must be prefixed with \\\\[emerge-basic-keymap]." (setq emerge-fast-mode nil) (setq emerge-edit-mode t) (message "Edit mode set") - ;; force mode line redisplay - (set-buffer-modified-p (buffer-modified-p))) + (force-mode-line-update)) (defun emerge-auto-advance (arg) "Toggle Auto-Advance mode, for Emerge. @@ -1863,11 +2043,10 @@ With a negative argument, turn off Auto-Advance mode." (setq emerge-auto-advance (if (null arg) (not emerge-auto-advance) (> (prefix-numeric-value arg) 0))) - (message (if emerge-skip-prefers + (message (if emerge-auto-advance "Auto-advance set" "Auto-advance cleared")) - ;; force mode line redisplay - (set-buffer-modified-p (buffer-modified-p))) + (force-mode-line-update)) (defun emerge-skip-prefers (arg) "Toggle Skip-Prefers mode, for Emerge. @@ -1882,8 +2061,7 @@ With a negative argument, turn off Skip-Prefers mode." (message (if emerge-skip-prefers "Skip-prefers set" "Skip-prefers cleared")) - ;; force mode line redisplay - (set-buffer-modified-p (buffer-modified-p))) + (force-mode-line-update)) (defun emerge-copy-as-kill-A () "Put the A variant of this difference in the kill ring." @@ -2004,7 +2182,10 @@ Use C-u l to reset the windows afterward." (princ "Ancestor buffer is: ") (princ (buffer-name)))) (princ "\n"))) - (princ emerge-output-description)))) + (princ emerge-output-description) + (save-excursion + (set-buffer standard-output) + (help-mode))))) (defun emerge-join-differences (arg) "Join the selected difference with the following one. @@ -2215,6 +2396,7 @@ ancestor version does not share.)" If there is no containing difference and the prefix argument is positive, it finds the nearest following difference. A negative prefix argument finds the nearest previous difference." + (interactive "P") (cond ((eq (current-buffer) emerge-A-buffer) (emerge-find-difference-A arg)) ((eq (current-buffer) emerge-B-buffer) @@ -2325,10 +2507,24 @@ merge buffers." (setq temp (- temp emerge-after-flag-lines))))) temp)) +(defun emerge-set-combine-template (string &optional localize) + "Set `emerge-combine-versions-template' to STRING. +This value controls how `emerge-combine-versions' combines the two versions. +With prefix argument, `emerge-combine-versions-template' is made local to this +merge buffer. Localization is permanent for any particular merge buffer." + (interactive "s\nP") + (if localize + (make-local-variable 'emerge-combine-versions-template)) + (setq emerge-combine-versions-template string) + (message + (if (assq 'emerge-combine-versions-template (buffer-local-variables)) + "emerge-set-combine-versions-template set locally" + "emerge-set-combine-versions-template set"))) + (defun emerge-set-combine-versions-template (start end &optional localize) "Copy region into `emerge-combine-versions-template'. This controls how `emerge-combine-versions' will combine the two versions. -With prefix argument, `emerge-combine-versions' is made local to this +With prefix argument, `emerge-combine-versions-template' is made local to this merge buffer. Localization is permanent for any particular merge buffer." (interactive "r\nP") (if localize @@ -2575,7 +2771,7 @@ keymap. Leaves merge in fast mode." ;; Read a file name, handling all of the various defaulting rules. (defun emerge-read-file-name (prompt alternative-default-dir default-file - A-file) + A-file must-match) ;; `prompt' should not have trailing ": ", so that it can be modified ;; according to context. ;; If alternative-default-dir is non-nil, it should be used as the default @@ -2603,7 +2799,7 @@ keymap. Leaves merge in fast mode." alternative-default-dir (concat alternative-default-dir (file-name-nondirectory A-file)) - 'confirm)) + (and must-match 'confirm))) ;; If there is a default file, use it. (default-file (read-file-name (format "%s (default %s): " prompt default-file) @@ -2612,7 +2808,7 @@ keymap. Leaves merge in fast mode." ;; Emerge as the default for this argument. (and emerge-default-last-directories alternative-default-dir) - default-file 'confirm)) + default-file (and must-match 'confirm))) (t (read-file-name (concat prompt ": ") ;; If emerge-default-last-directories is set, use the @@ -2620,7 +2816,7 @@ keymap. Leaves merge in fast mode." ;; Emerge as the default for this argument. (and emerge-default-last-directories alternative-default-dir) - nil 'confirm)))) + nil (and must-match 'confirm))))) ;; Revise the mode line to display which difference we have selected @@ -2641,8 +2837,7 @@ keymap. Leaves merge in fast mode." (prefer-B . " - B*") (combined . " - comb")))) "")))) - ;; Force mode-line redisplay - (set-buffer-modified-p (buffer-modified-p))) + (force-mode-line-update)) ;; compare two regions in two buffers for containing the same text (defun emerge-compare-buffers (buffer-x x-begin x-end buffer-y y-begin y-end) @@ -2690,7 +2885,7 @@ keymap. Leaves merge in fast mode." ;; a list of variables. The argument is a list of symbols (the names of ;; the variables). A list element can also be a list of two functions, ;; the first of which (when called with no arguments) gets the value, and -;; the second (when called with a value as an argment) sets the value. +;; the second (when called with a value as an argument) sets the value. ;; A "function" is anything that funcall can handle as an argument. (defun emerge-save-variables (vars) @@ -2830,6 +3025,9 @@ If some prefix of KEY has a non-prefix definition, it is redefined." ;; minor-mode indicator)) ;; (princ (documentation minor-mode))))) ;; (setq minor-modes (cdr minor-modes)))) +;; (save-excursion +;; (set-buffer standard-output) +;; (help-mode)) ;; (print-help-return-message))) ;; This goes with the redefinition of describe-mode. @@ -2996,9 +3194,11 @@ See also `auto-save-file-name-p'." ;; Metacharacters that have to be protected from the shell when executing ;; a diff/diff3 command. -(defvar emerge-metachars "[ \t\n!\"#$&'()*;<=>?[\\^`{|~]" +(defcustom emerge-metachars "[ \t\n!\"#$&'()*;<=>?[\\^`{|~]" "Characters that must be quoted with \\ when used in a shell command line. -More precisely, a [...] regexp to match any one such character.") +More precisely, a [...] regexp to match any one such character." + :type 'regexp + :group 'emerge) ;; Quote metacharacters (using \) when executing a diff/diff3 command. (defun emerge-protect-metachars (s)