(follow-mode): Don't run hooks twice. Use `when'.
[bpt/emacs.git] / lisp / pcvs-defs.el
index 1a7ea9a..5798be4 100644 (file)
@@ -1,17 +1,16 @@
 ;;; pcvs-defs.el --- variable definitions for PCL-CVS
 
-;; Copyright (C) 1991-2000  Free Software Foundation, Inc.
+;; Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
+;;   2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
 
-;; Author: Stefan Monnier <monnier@cs.yale.edu>
+;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
 ;; Keywords: pcl-cvs
-;; Version: $Name:  $
-;; Revision: $Id: pcl-cvs-defs.el,v 1.27 2000/03/03 20:58:09 monnier Exp $
 
 ;; This file is part of GNU Emacs.
 
 ;; GNU Emacs is free software; you can redistribute it and/or modify
 ;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation; either version 2, or (at your option)
+;; the Free Software Foundation; either version 3, or (at your option)
 ;; any later version.
 
 ;; GNU Emacs is distributed in the hope that it will be useful,
 
 ;; You should have received a copy of the GNU General Public License
 ;; along with GNU Emacs; see the file COPYING.  If not, write to the
-;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-;; Boston, MA 02111-1307, USA.
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
 
 ;;; Commentary:
 
 
 ;;; Code:
 
-(defconst pcl-cvs-version "$Name:  $")
-
 (eval-when-compile (require 'cl))
 (require 'pcvs-util)
 
   "*Name or full path of the cvs executable.")
 
 (defvar cvs-version
+  ;; With the divergence of the CVSNT codebase and version numbers, this is
+  ;; not really good any more.
   (ignore-errors
     (with-temp-buffer
-      (call-process "cvs" nil t nil "-v")
+      (call-process cvs-program nil t nil "-v")
       (goto-char (point-min))
-      (when (re-search-forward "(CVS) \\([0-9]+\\)\\.\\([0-9]+\\)" nil t)
+      (when (re-search-forward "(CVS\\(NT\\)?) \\([0-9]+\\)\\.\\([0-9]+\\)"
+                               nil t)
        (cons (string-to-number (match-string 1))
              (string-to-number (match-string 2))))))
   "*Version of `cvs' installed on your system.
@@ -68,6 +68,7 @@ versions, such as the one in SunOS-4.")
 
 (defgroup pcl-cvs nil
   "Special support for the CVS versioning system."
+  :version "21.1"
   :group 'tools
   :prefix "cvs-")
 
@@ -97,7 +98,7 @@ repositories. It can be set interactively with \\[cvs-change-cvsroot.]
 There is no need to set this if $CVSROOT is set to a correct value.")
 
 (defcustom cvs-auto-remove-handled nil
-  "*If up-to-date files should be acknowledged automatically.
+  "If up-to-date files should be acknowledged automatically.
 If T, they will be removed from the *cvs* buffer after every command.
 If DELAYED, they will be removed from the *cvs* buffer before every command.
 If STATUS, they will only be removed after a `cvs-mode-status' command.
@@ -106,24 +107,24 @@ Else, they will never be automatically removed from the *cvs* buffer."
   :type '(choice (const nil) (const status) (const delayed) (const t)))
 
 (defcustom cvs-auto-remove-directories 'handled
-  "*If ALL, directory entries will never be shown.
-If HANLDED, only non-handled directories will be shown.
+  "If ALL, directory entries will never be shown.
+If HANDLED, only non-handled directories will be shown.
 If EMPTY, only non-empty directories will be shown."
   :group 'pcl-cvs
   :type '(choice (const :tag "No" nil) (const all) (const handled) (const empty)))
 
 (defcustom cvs-auto-revert t
-  "*Non-nil if changed files should automatically be reverted."
+  "Non-nil if changed files should automatically be reverted."
   :group 'pcl-cvs
   :type '(boolean))
 
 (defcustom cvs-sort-ignore-file t
-  "*Non-nil if `cvs-mode-ignore' should sort the .cvsignore automatically."
+  "Non-nil if `cvs-mode-ignore' should sort the .cvsignore automatically."
   :group 'pcl-cvs
   :type '(boolean))
 
 (defcustom cvs-force-dir-tag t
-  "*If non-nil, tagging can only be applied to directories.
+  "If non-nil, tagging can only be applied to directories.
 Tagging should generally be applied a directory at a time, but sometimes it is
 useful to be able to tag a single file.  The normal way to do that is to use
 `cvs-mode-force-command' so as to temporarily override the restrictions,"
@@ -131,16 +132,17 @@ useful to be able to tag a single file.  The normal way to do that is to use
   :type '(boolean))
 
 (defcustom cvs-default-ignore-marks nil
-  "*Non-nil if cvs mode commands should ignore any marked files.
+  "Non-nil if cvs mode commands should ignore any marked files.
 Normally they run on the files that are marked (with `cvs-mode-mark'),
 or the file under the cursor if no files are marked.  If this variable
 is set to a non-nil value they will by default run on the file on the
-current line.  See also `cvs-ignore-marks'"
+current line.  See also `cvs-invert-ignore-marks'"
   :group 'pcl-cvs
   :type '(boolean))
 
-(defvar cvs-diff-ignore-marks t
-  "Obsolete variable: use cvs-ignore-marks instead.")
+(defvar cvs-diff-ignore-marks t)
+(make-obsolete-variable 'cvs-diff-ignore-marks
+                        'cvs-invert-ignore-marks)
 
 (defcustom cvs-invert-ignore-marks
   (let ((l ()))
@@ -149,7 +151,7 @@ current line.  See also `cvs-ignore-marks'"
     (when (and cvs-force-dir-tag (not cvs-default-ignore-marks))
       (push "tag" l))
     l)
-  "*List of cvs commands that invert the default ignore-mark behavior.
+  "List of cvs commands that invert the default ignore-mark behavior.
 Commands in this set will use the opposite default from the one set
 in `cvs-default-ignore-marks'."
   :group 'pcl-cvs
@@ -158,10 +160,10 @@ in `cvs-default-ignore-marks'."
              (const "ignore")))
 
 (defcustom cvs-confirm-removals t
-  "*Ask for confirmation before removing files.
+  "Ask for confirmation before removing files.
 Non-nil means that PCL-CVS will ask confirmation before removing files
 except for files whose content can readily be recovered from the repository.
-A value of LIST means that the list of files to be deleted will be
+A value of `list' means that the list of files to be deleted will be
 displayed when asking for confirmation."
   :group 'pcl-cvs
   :type '(choice (const list)
@@ -169,16 +171,17 @@ displayed when asking for confirmation."
                 (const nil)))
 
 (defcustom cvs-add-default-message nil
-  "*Default message to use when adding files.
-If set to NIL, `cvs-mode-add' will always prompt for a message."
+  "Default message to use when adding files.
+If set to nil, `cvs-mode-add' will always prompt for a message."
   :group 'pcl-cvs
   :type '(choice (const :tag "Prompt" nil)
                 (string)))
 
-(defvar cvs-diff-buffer-name "*cvs-diff*"
-  "Obsolete variable: use `cvs-buffer-name-alist' instead.")
+(defvar cvs-diff-buffer-name "*cvs-diff*")
+(make-obsolete-variable 'cvs-diff-buffer-name
+                        'cvs-buffer-name-alist)
 
-(defcustom cvs-find-file-and-jump t
+(defcustom cvs-find-file-and-jump nil
   "Jump to the modified area when finding a file.
 If non-nil, `cvs-mode-file-file' will place the cursor at the beginning of
 the modified area.  If the file is not locally modified, this will obviously
@@ -189,10 +192,10 @@ have no effect."
 (defcustom cvs-buffer-name-alist
   '(("diff" cvs-diff-buffer-name diff-mode)
     ("status" "*cvs-info*" cvs-status-mode)
-    ("tree" (format "*cvs-%s*" cmd) cvs-status-mode)
+    ("tree" "*cvs-info*" cvs-status-mode)
     ("message" "*cvs-commit*" nil log-edit)
     ("log" "*cvs-info*" log-view-mode))
-  "*Buffer name and mode to be used for each command.
+  "Buffer name and mode to be used for each command.
 This is a list of elements of the form
 
        (CMD BUFNAME MODE &optional POSTPROC)
@@ -236,7 +239,10 @@ The CMD used for `cvs-mode-commit' is \"message\".  For that special
 This expression will be evaluated in an environment where DIR is set to
 the directory name of the cvs buffer.")
 
-(defvar cvs-temp-buffer-name '(expand-file-name " *cvs-tmp*" dir)
+(defvar cvs-temp-buffer-name
+  ;; Was '(expand-file-name " *cvs-tmp*" dir), but that causes them to
+  ;; become non-hidden if uniquification is done `forward'.
+  " *cvs-tmp*"
   "*Name of the cvs temporary buffer.
 Output from cvs is placed here for asynchronous commands.")
 
@@ -244,14 +250,11 @@ Output from cvs is placed here for asynchronous commands.")
   (if (fboundp 'ediff)
       '(cvs-ediff-diff . cvs-ediff-merge)
     '(cvs-emerge-diff . cvs-emerge-merge))
-  "*Pair of functions to be used for resp.  diff'ing and merg'ing interactively."
+  "Pair of functions to be used for resp.  diff'ing and merg'ing interactively."
   :group 'pcl-cvs
   :type '(choice (const :tag "Ediff" (cvs-ediff-diff . cvs-ediff-merge))
                 (const :tag "Emerge" (cvs-emerge-diff . cvs-emerge-merge))))
 
-(defvar pcl-cvs-load-hook nil
-  "Run after loading pcl-cvs.")
-
 (defvar cvs-mode-hook nil
   "Run after `cvs-mode' was setup.")
 
@@ -294,76 +297,47 @@ This variable is buffer local and only used in the *cvs* buffer.")
 ;;;; Global internal variables
 ;;;;
 
-(defconst cvs-startup-message
-  (concat "PCL-CVS release " pcl-cvs-version)
-  "*Startup message for CVS.")
-
 (defconst cvs-vendor-branch "1.1.1"
   "The default branch used by CVS for vendor code.")
 
-(defvar cvs-menu
-  '("CVS"
-    ["Open File.."             cvs-mode-find-file      t]
-    [" ..Other Window"         cvs-mode-find-file-other-window t]
-    ["Interactive Merge"       cvs-mode-imerge         t]
-    ["Interactive Diff"                cvs-mode-idiff          t]
-    ["View Diff"               cvs-mode-diff           (cvs-enabledp 'diff)]
-    ["Diff with Vendor"                cvs-mode-diff-vendor    t]
-    ["Diff with Backup"                cvs-mode-diff-backup    t]
-    ["View Log"                        cvs-mode-log            t]
-    ["View Status"             cvs-mode-status         t]
-    "----"
-    ["Update"                  cvs-mode-update         (cvs-enabledp 'update)]
-    ["Re-Examine"              cvs-mode-examine        t]
-    ["Commit"                  cvs-mode-commit-setup   (cvs-enabledp 'commit)]
-    ["Undo Changes"            cvs-mode-undo           (cvs-enabledp 'undo)]
-    ["Add"                     cvs-mode-add            (cvs-enabledp 'add)]
-    ["Remove"                  cvs-mode-remove         (cvs-enabledp 'remove)]
-    ["Ignore"                  cvs-mode-ignore         (cvs-enabledp 'ignore)]
-    ["Add ChangeLog"           cvs-mode-add-change-log-entry-other-window t]
-    "----"
-    ["Mark All"                        cvs-mode-mark-all-files t]
-    ["Unmark All"              cvs-mode-unmark-all-files t]
-    ["Hide Handled"            cvs-mode-remove-handled t]
-    "----"
-    ;; ["Update Directory"             cvs-update              t]
-    ;; ["Examine Directory"    cvs-examine             t]
-    ;; ["Status Directory"             cvs-status              t]
-    ;; ["Checkout Module"              cvs-checkout            t]
-    ;; "----"
-    ["Quit"                    cvs-mode-quit           t]
-    ))
-
 (easy-mmode-defmap cvs-mode-diff-map
-  '(("=" .     cvs-mode-diff)
-    ("b" .     cvs-mode-diff-backup)
-    ("2" .     cvs-mode-idiff-other)
-    ("h" .     cvs-mode-diff-head)
-    ("v" .     cvs-mode-diff-vendor)
-    ("?" .     cvs-mode-diff-help)
-    ("e" .     cvs-mode-idiff)
-    ("E" .     cvs-mode-imerge))
-  "Keymap for diff-related operations in `cvs-mode'.")
+  '(("E" "imerge" .    cvs-mode-imerge)
+    ("=" .             cvs-mode-diff)
+    ("e" "idiff" .     cvs-mode-idiff)
+    ("2" "other" .     cvs-mode-idiff-other)
+    ("d" "diff" .      cvs-mode-diff)
+    ("b" "backup" .    cvs-mode-diff-backup)
+    ("h" "head" .      cvs-mode-diff-head)
+    ("r" "repository" .        cvs-mode-diff-repository)
+    ("y" "yesterday" . cvs-mode-diff-yesterday)
+    ("v" "vendor" .    cvs-mode-diff-vendor))
+  "Keymap for diff-related operations in `cvs-mode'."
+  :name "Diff")
+;; This is necessary to allow correct handling of \\[cvs-mode-diff-map]
+;; in substitute-command-keys.
+(fset 'cvs-mode-diff-map cvs-mode-diff-map)
 
 (easy-mmode-defmap cvs-mode-map
   ;;(define-prefix-command 'cvs-mode-map-diff-prefix)
   ;;(define-prefix-command 'cvs-mode-map-control-c-prefix)
-  `(;; simulate `suppress-keymap'
+  '(;; simulate `suppress-keymap'
     (self-insert-command . undefined)
     (("0" "1" "2" "3" "4" "5" "6" "7" "8" "9") . digit-argument)
     ("-" .     negative-argument)
     ;; various
-    (undo .    cvs-mode-undo)
+    ;; (undo . cvs-mode-undo)
     ("?" .     cvs-help)
     ("h" .     cvs-help)
     ("q" .     cvs-bury-buffer)
-    ;;("Q" .   kill-buffer)
+    ("z" .     kill-this-buffer)
     ("F" .     cvs-mode-set-flags)
-    ("\M-f" .  cvs-mode-force-command)
+    ;; ("\M-f" .       cvs-mode-force-command)
+    ("!" .     cvs-mode-force-command)
     ("\C-c\C-c" . cvs-mode-kill-process)
     ;; marking
     ("m" .     cvs-mode-mark)
     ("M" .     cvs-mode-mark-all-files)
+    ("S" .     cvs-mode-mark-on-state)
     ("u" .     cvs-mode-unmark)
     ("\C-?".   cvs-mode-unmark-up)
     ("%" .     cvs-mode-mark-matching-files)
@@ -384,9 +358,9 @@ This variable is buffer local and only used in the *cvs* buffer.")
     ("\M-s".   cvs-status)
     ;; diff commands
     ("=" .     cvs-mode-diff)
-    ("d" .     ,cvs-mode-diff-map)
+    ("d" .     cvs-mode-diff-map)
     ;; keys that operate on individual files
-    ("\C-k"  cvs-mode-acknowledge)
+    ("\C-k" .  cvs-mode-acknowledge)
     ("A" .     cvs-mode-add-change-log-entry-other-window)
     ;;("B" .   cvs-mode-byte-compile-files)
     ("C" .     cvs-mode-commit-setup)
@@ -399,18 +373,24 @@ This variable is buffer local and only used in the *cvs* buffer.")
     ("c" .     cvs-mode-commit)
     ("e" .     cvs-mode-examine)
     ("f" .     cvs-mode-find-file)
+    ("\C-m" .  cvs-mode-find-file)
     ("i" .     cvs-mode-ignore)
     ("l" .     cvs-mode-log)
     ("o" .     cvs-mode-find-file-other-window)
     ("r" .     cvs-mode-remove)
     ("s" .     cvs-mode-status)
     ("t" .     cvs-mode-tag)
-    ;;("v" .   cvs-mode-diff-vendor)
+    ("v" .     cvs-mode-view-file)
     ("x" .     cvs-mode-remove-handled)
     ;; cvstree bindings
     ("+" .     cvs-mode-tree)
     ;; mouse bindings
+    ([mouse-2] . cvs-mode-find-file)
+    ([follow-link] . (lambda (pos)
+                      (if (eq (get-char-property pos 'face) 'cvs-filename) t)))
     ([(down-mouse-3)] . cvs-menu)
+    ;; dired-like bindings
+    ("\C-o" .   cvs-mode-display-file)
     ;; Emacs-21 toolbar
     ;;([tool-bar item1] . (menu-item "Examine" cvs-examine :image (image :file "/usr/share/icons/xpaint.xpm" :type xpm)))
     ;;([tool-bar item2] . (menu-item "Update" cvs-update :image (image :file "/usr/share/icons/mail1.xpm" :type xpm)))
@@ -420,24 +400,56 @@ This variable is buffer local and only used in the *cvs* buffer.")
 
 (fset 'cvs-mode-map cvs-mode-map)
 
-;; add the cvs-menu to the map so it's added whenever we are in cvs-mode
-(when (ignore-errors (require 'easymenu))
-  (easy-menu-define cvs-menu-map
-                   cvs-mode-map
-                   "Menu used in cvs-mode."
-                   cvs-menu))
+(easy-menu-define cvs-menu cvs-mode-map "Menu used in `cvs-mode'."
+  '("CVS"
+    ["Open file.."             cvs-mode-find-file      t]
+    [" ..other window"         cvs-mode-find-file-other-window t]
+    ["Display in other window"  cvs-mode-display-file   t]
+    ["Interactive merge"       cvs-mode-imerge         t]
+    ("View diff"
+     ["Interactive diff"       cvs-mode-idiff          t]
+     ["Current diff"           cvs-mode-diff           t]
+     ["Diff with head"         cvs-mode-diff-head      t]
+     ["Diff with vendor"       cvs-mode-diff-vendor    t]
+     ["Diff with backup"       cvs-mode-diff-backup    t])
+    ["View log"                        cvs-mode-log            t]
+    ["View status"             cvs-mode-status         t]
+    ["View tag tree"           cvs-mode-tree           t]
+    "----"
+    ["Insert"                  cvs-mode-insert]
+    ["Update"                  cvs-mode-update         (cvs-enabledp 'update)]
+    ["Re-examine"              cvs-mode-examine        t]
+    ["Commit"                  cvs-mode-commit-setup   (cvs-enabledp 'commit)]
+    ["Tag"                     cvs-mode-tag            (cvs-enabledp (when cvs-force-dir-tag 'tag))]
+    ["Undo changes"            cvs-mode-undo           (cvs-enabledp 'undo)]
+    ["Add"                     cvs-mode-add            (cvs-enabledp 'add)]
+    ["Remove"                  cvs-mode-remove         (cvs-enabledp 'remove)]
+    ["Ignore"                  cvs-mode-ignore         (cvs-enabledp 'ignore)]
+    ["Add ChangeLog"           cvs-mode-add-change-log-entry-other-window t]
+    "----"
+    ["Mark"                     cvs-mode-mark t]
+    ["Mark all"                        cvs-mode-mark-all-files t]
+    ["Mark by regexp..."        cvs-mode-mark-matching-files t]
+    ["Mark by state..."         cvs-mode-mark-on-state t]
+    ["Unmark"                   cvs-mode-unmark        t]
+    ["Unmark all"              cvs-mode-unmark-all-files t]
+    ["Hide handled"            cvs-mode-remove-handled t]
+    "----"
+    ["Quit"                    cvs-mode-quit           t]))
 
-;;;; 
+;;;;
 ;;;; CVS-Minor mode
-;;;; 
+;;;;
 
 (defcustom cvs-minor-mode-prefix "\C-xc"
   "Prefix key for the `cvs-mode' bindings in `cvs-minor-mode'."
   :group 'pcl-cvs)
 
 (easy-mmode-defmap cvs-minor-mode-map
-  `((,cvs-minor-mode-prefix . cvs-mode-map))
-  "Keymap for `cvs-minor-mode', used in buffers related to pcl-cvs.")
+  `((,cvs-minor-mode-prefix . cvs-mode-map)
+    ("e" . (menu-item nil cvs-mode-edit-log
+           :filter (lambda (x) (if (derived-mode-p 'log-view-mode) x)))))
+  "Keymap for `cvs-minor-mode', used in buffers related to PCL-CVS.")
 
 (defvar cvs-buffer nil
   "(Buffer local) The *cvs* buffer associated with this buffer.")
@@ -459,26 +471,36 @@ It is expected to call the function.")
 
 (defconst cvs-pcl-cvs-dirchange-re "^pcl-cvs: descending directory \\(.*\\)$")
 
-;;;; 
-;;;; 
-;;;; 
+;;;;
+;;;; autoload the global menu
+;;;;
 
 ;;;###autoload
-(if (progn (condition-case () (require 'easymenu) (error nil))
-          (fboundp 'easy-menu-add-item))
-    (easy-menu-add-item nil '("tools")
-                       '("PCL CVS"
-                         ["Update Directory"    cvs-update    t]
-                         ["Examine Directory"   cvs-examine   t]
-                         ["Status Directory"    cvs-status    t]
-                         ["Checkout Module"     cvs-checkout  t]) "vc"))
+(defvar cvs-global-menu
+  (let ((m (make-sparse-keymap "PCL-CVS")))
+    (define-key m [status]
+      '(menu-item "Directory Status" cvs-status
+                 :help "A more verbose status of a workarea"))
+    (define-key m [checkout]
+      '(menu-item "Checkout Module" cvs-checkout
+                 :help "Check out a module from the repository"))
+    (define-key m [update]
+      '(menu-item "Update Directory" cvs-update
+                 :help "Fetch updates from the repository"))
+    (define-key m [examine]
+      '(menu-item "Examine Directory" cvs-examine
+                 :help "Examine the current state of a workarea"))
+    (fset 'cvs-global-menu m)))
 
 
 ;; cvs-1.10 and above can take file arguments in other directories
 ;; while others need to be executed once per directory
 (defvar cvs-execute-single-dir
-  (if (and (consp cvs-version)
-           (or (>= (cdr cvs-version) 10) (> (car cvs-version) 1)))
+  (if (or (null cvs-version)
+          (or (>= (cdr cvs-version) 10) (> (car cvs-version) 1)))
+      ;; Supposedly some recent versions of CVS output some directory info
+      ;; as they recurse downthe tree, but it's not good enough in the case
+      ;; where we run "cvs status foo bar/foo".
       '("status")
     t)
   "Whether cvs commands should be executed a directory at a time.
@@ -491,11 +513,12 @@ whether to use the new feature or not.
 Sadly, even with a new cvs executable, if you connect to an older cvs server
 \(typically a cvs-1.9 on the server), the old restriction applies.  In such
 a case the sanity check made by pcl-cvs fails and you will have to manually
-set this variable to T (until the cvs server is upgraded).
+set this variable to t (until the cvs server is upgraded).
 When the above problem occurs, pcl-cvs should (hopefully) catch cvs' error
-message and replace it with a message tell you to change this variable.")
+message and replace it with a message telling you to change this variable.")
 
 ;;
 (provide 'pcvs-defs)
 
-;;; pcl-cvs-defs.el ends here
+;; arch-tag: c7c701d0-d1d4-4aa9-a302-007bb03aca5e
+;;; pcvs-defs.el ends here