1;;; pcvs-defs.el --- variable definitions for PCL-CVS
2
3;; Copyright (C) 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
4;;   2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
5
6;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
7;; Keywords: pcl-cvs
8
9;; This file is part of GNU Emacs.
10
11;; 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
13;; the Free Software Foundation; either version 2, or (at your option)
14;; any later version.
15
16;; GNU Emacs is distributed in the hope that it will be useful,
17;; but WITHOUT ANY WARRANTY; without even the implied warranty of
18;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19;; GNU General Public License for more details.
20
21;; You should have received a copy of the GNU General Public License
22;; along with GNU Emacs; see the file COPYING.  If not, write to the
23;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
24;; Boston, MA 02110-1301, USA.
25
26;;; Commentary:
27
28
29;;; Code:
30
31(eval-when-compile (require 'cl))
32(require 'pcvs-util)
33
34;;;; -------------------------------------------------------
35;;;;	    START OF THINGS TO CHECK WHEN INSTALLING
36
37(defvar cvs-program "cvs"
38  "*Name or full path of the cvs executable.")
39
40(defvar cvs-version
41  ;; With the divergence of the CVSNT codebase and version numbers, this is
42  ;; not really good any more.
43  (ignore-errors
44    (with-temp-buffer
45      (call-process cvs-program nil t nil "-v")
46      (goto-char (point-min))
47      (when (re-search-forward "(CVS\\(NT\\)?) \\([0-9]+\\)\\.\\([0-9]+\\)"
48                               nil t)
49	(cons (string-to-number (match-string 1))
50	      (string-to-number (match-string 2))))))
51  "*Version of `cvs' installed on your system.
52It must be in the (MAJOR . MINOR) format.")
53
54;; FIXME: this is only used by cvs-mode-diff-backup
55(defvar cvs-diff-program (or (and (boundp 'diff-command) diff-command) "diff")
56  "*Name or full path of the best diff program you've got.
57NOTE:  there are some nasty bugs in the context diff variants of some vendor
58versions, such as the one in SunOS-4.")
59
60;;;;	     END OF THINGS TO CHECK WHEN INSTALLING
61;;;; --------------------------------------------------------
62
63;;;;
64;;;;	User configuration variables:
65;;;;
66;;;; NOTE: these should be set in your ~/.emacs (or site-lisp/default.el) file.
67;;;;
68
69(defgroup pcl-cvs nil
70  "Special support for the CVS versioning system."
71  :version "21.1"
72  :group 'tools
73  :prefix "cvs-")
74
75;;
76;;  cvsrc options
77;;
78
79(defcustom cvs-cvsrc-file "~/.cvsrc"
80  "Path to your cvsrc file."
81  :group 'pcl-cvs
82  :type '(file))
83
84(defvar cvs-shared-start 4
85  "Index of the first shared flag.
86If set to 4, for instance, a numeric argument smaller than 4 will
87select a non-shared flag, while a numeric argument greater than 3
88will select a shared-flag.")
89
90(defvar cvs-shared-flags (make-list cvs-shared-start nil)
91  "List of flags whose settings is shared among several commands.")
92
93(defvar cvs-cvsroot nil
94  "*Specifies where the (current) cvs master repository is.
95Overrides the environment variable $CVSROOT by sending \" -d dir\" to
96all CVS commands. This switch is useful if you have multiple CVS
97repositories. It can be set interactively with \\[cvs-change-cvsroot.]
98There is no need to set this if $CVSROOT is set to a correct value.")
99
100(defcustom cvs-auto-remove-handled nil
101  "If up-to-date files should be acknowledged automatically.
102If T, they will be removed from the *cvs* buffer after every command.
103If DELAYED, they will be removed from the *cvs* buffer before every command.
104If STATUS, they will only be removed after a `cvs-mode-status' command.
105Else, they will never be automatically removed from the *cvs* buffer."
106  :group 'pcl-cvs
107  :type '(choice (const nil) (const status) (const delayed) (const t)))
108
109(defcustom cvs-auto-remove-directories 'handled
110  "If ALL, directory entries will never be shown.
111If HANDLED, only non-handled directories will be shown.
112If EMPTY, only non-empty directories will be shown."
113  :group 'pcl-cvs
114  :type '(choice (const :tag "No" nil) (const all) (const handled) (const empty)))
115
116(defcustom cvs-auto-revert t
117  "Non-nil if changed files should automatically be reverted."
118  :group 'pcl-cvs
119  :type '(boolean))
120
121(defcustom cvs-sort-ignore-file t
122  "Non-nil if `cvs-mode-ignore' should sort the .cvsignore automatically."
123  :group 'pcl-cvs
124  :type '(boolean))
125
126(defcustom cvs-force-dir-tag t
127  "If non-nil, tagging can only be applied to directories.
128Tagging should generally be applied a directory at a time, but sometimes it is
129useful to be able to tag a single file.  The normal way to do that is to use
130`cvs-mode-force-command' so as to temporarily override the restrictions,"
131  :group 'pcl-cvs
132  :type '(boolean))
133
134(defcustom cvs-default-ignore-marks nil
135  "Non-nil if cvs mode commands should ignore any marked files.
136Normally they run on the files that are marked (with `cvs-mode-mark'),
137or the file under the cursor if no files are marked.  If this variable
138is set to a non-nil value they will by default run on the file on the
139current line.  See also `cvs-invert-ignore-marks'"
140  :group 'pcl-cvs
141  :type '(boolean))
142
143(defvar cvs-diff-ignore-marks t)
144(make-obsolete-variable 'cvs-diff-ignore-marks
145                        'cvs-invert-ignore-marks)
146
147(defcustom cvs-invert-ignore-marks
148  (let ((l ()))
149    (unless (equal cvs-diff-ignore-marks cvs-default-ignore-marks)
150      (push "diff" l))
151    (when (and cvs-force-dir-tag (not cvs-default-ignore-marks))
152      (push "tag" l))
153    l)
154  "List of cvs commands that invert the default ignore-mark behavior.
155Commands in this set will use the opposite default from the one set
156in `cvs-default-ignore-marks'."
157  :group 'pcl-cvs
158  :type '(set (const "diff")
159	      (const "tag")
160	      (const "ignore")))
161
162(defcustom cvs-confirm-removals t
163  "Ask for confirmation before removing files.
164Non-nil means that PCL-CVS will ask confirmation before removing files
165except for files whose content can readily be recovered from the repository.
166A value of `list' means that the list of files to be deleted will be
167displayed when asking for confirmation."
168  :group 'pcl-cvs
169  :type '(choice (const list)
170		 (const t)
171		 (const nil)))
172
173(defcustom cvs-add-default-message nil
174  "Default message to use when adding files.
175If set to nil, `cvs-mode-add' will always prompt for a message."
176  :group 'pcl-cvs
177  :type '(choice (const :tag "Prompt" nil)
178		 (string)))
179
180(defvar cvs-diff-buffer-name "*cvs-diff*")
181(make-obsolete-variable 'cvs-diff-buffer-name
182                        'cvs-buffer-name-alist)
183
184(defcustom cvs-find-file-and-jump nil
185  "Jump to the modified area when finding a file.
186If non-nil, `cvs-mode-file-file' will place the cursor at the beginning of
187the modified area.  If the file is not locally modified, this will obviously
188have no effect."
189  :group 'pcl-cvs
190  :type '(boolean))
191
192(defcustom cvs-buffer-name-alist
193  '(("diff" cvs-diff-buffer-name diff-mode)
194    ("status" "*cvs-info*" cvs-status-mode)
195    ("tree" "*cvs-info*" cvs-status-mode)
196    ("message" "*cvs-commit*" nil log-edit)
197    ("log" "*cvs-info*" log-view-mode))
198  "Buffer name and mode to be used for each command.
199This is a list of elements of the form
200
201	(CMD BUFNAME MODE &optional POSTPROC)
202
203CMD is the name of the command.
204BUFNAME is an expression that should evaluate to a string used as
205  a buffer name.  It can use the variable CMD if it wants to.
206MODE is the command to use to setup the buffer.
207POSTPROC is a function that should be executed when the command terminates
208
209The CMD used for `cvs-mode-commit' is \"message\".  For that special
210  case, POSTPROC is called just after MODE with special arguments."
211  :group 'pcl-cvs
212  :type '(repeat
213	  (list (choice (const "diff")
214			(const "status")
215			(const "tree")
216			(const "message")
217			(const "log")
218			(string))
219		(choice (const "*vc-diff*")
220			(const "*cvs-info*")
221			(const "*cvs-commit*")
222			(const (expand-file-name "*cvs-commit*"))
223			(const (format "*cvs-%s*" cmd))
224			(const (expand-file-name (format "*cvs-%s*" cmd)))
225			(sexp :value "my-cvs-info-buffer")
226			(const nil))
227		(choice (function-item diff-mode)
228			(function-item cvs-edit-mode)
229			(function-item cvs-status-mode)
230			function
231			(const nil))
232		(set :inline t
233		     (choice (function-item cvs-status-cvstrees)
234			     (function-item cvs-status-trees)
235			     function)))))
236
237(defvar cvs-buffer-name '(expand-file-name "*cvs*" dir) ;; "*cvs*"
238  "Name of the cvs buffer.
239This expression will be evaluated in an environment where DIR is set to
240the directory name of the cvs buffer.")
241
242(defvar cvs-temp-buffer-name
243  ;; Was '(expand-file-name " *cvs-tmp*" dir), but that causes them to
244  ;; become non-hidden if uniquification is done `forward'.
245  " *cvs-tmp*"
246  "*Name of the cvs temporary buffer.
247Output from cvs is placed here for asynchronous commands.")
248
249(defcustom cvs-idiff-imerge-handlers
250  (if (fboundp 'ediff)
251      '(cvs-ediff-diff . cvs-ediff-merge)
252    '(cvs-emerge-diff . cvs-emerge-merge))
253  "Pair of functions to be used for resp.  diff'ing and merg'ing interactively."
254  :group 'pcl-cvs
255  :type '(choice (const :tag "Ediff" (cvs-ediff-diff . cvs-ediff-merge))
256		 (const :tag "Emerge" (cvs-emerge-diff . cvs-emerge-merge))))
257
258(defvar cvs-mode-hook nil
259  "Run after `cvs-mode' was setup.")
260
261
262;;;;
263;;;; Internal variables, used in the process buffer.
264;;;;
265
266(defvar cvs-postprocess nil
267  "(Buffer local) what to do once the process exits.")
268
269;;;;
270;;;; Internal variables for the *cvs* buffer.
271;;;;
272
273(defcustom cvs-reuse-cvs-buffer 'subdir
274  "When to reuse an existing cvs buffer.
275Alternatives are:
276 CURRENT: just reuse the current buffer if it is a cvs buffer
277 SAMEDIR: reuse any cvs buffer displaying the same directory
278 SUBDIR:  or reuse any cvs buffer displaying any sub- or super- directory
279 ALWAYS:  reuse any cvs buffer."
280  :group 'pcl-cvs
281  :type '(choice (const always) (const subdir) (const samedir) (const current)))
282
283(defvar cvs-temp-buffer nil
284  "(Buffer local) The temporary buffer associated with this *cvs* buffer.")
285
286(defvar cvs-lock-file nil
287  "Full path to a lock file that CVS is waiting for (or was waiting for).
288This variable is buffer local and only used in the *cvs* buffer.")
289
290(defvar cvs-lock-file-regexp "^#cvs\\.\\([trw]fl\\.[-.a-z0-9]+\\|lock\\)\\'"
291  "Regexp matching the possible names of locks in the CVS repository.")
292
293(defconst cvs-cursor-column 22
294  "Column to position cursor in in `cvs-mode'.")
295
296;;;;
297;;;; Global internal variables
298;;;;
299
300(defconst cvs-vendor-branch "1.1.1"
301  "The default branch used by CVS for vendor code.")
302
303(easy-mmode-defmap cvs-mode-diff-map
304  '(("E" "imerge" .	cvs-mode-imerge)
305    ("=" .		cvs-mode-diff)
306    ("e" "idiff" .	cvs-mode-idiff)
307    ("2" "other" .	cvs-mode-idiff-other)
308    ("d" "diff" .	cvs-mode-diff)
309    ("b" "backup" .	cvs-mode-diff-backup)
310    ("h" "head" .	cvs-mode-diff-head)
311    ("r" "repository" .	cvs-mode-diff-repository)
312    ("y" "yesterday" .	cvs-mode-diff-yesterday)
313    ("v" "vendor" .	cvs-mode-diff-vendor))
314  "Keymap for diff-related operations in `cvs-mode'."
315  :name "Diff")
316;; This is necessary to allow correct handling of \\[cvs-mode-diff-map]
317;; in substitute-command-keys.
318(fset 'cvs-mode-diff-map cvs-mode-diff-map)
319
320(easy-mmode-defmap cvs-mode-map
321  ;;(define-prefix-command 'cvs-mode-map-diff-prefix)
322  ;;(define-prefix-command 'cvs-mode-map-control-c-prefix)
323  '(;; simulate `suppress-keymap'
324    (self-insert-command . undefined)
325    (("0" "1" "2" "3" "4" "5" "6" "7" "8" "9") . digit-argument)
326    ("-" .	negative-argument)
327    ;; various
328    ;; (undo .	cvs-mode-undo)
329    ("?" .	cvs-help)
330    ("h" .	cvs-help)
331    ("q" .	cvs-bury-buffer)
332    ("z" .	kill-this-buffer)
333    ("F" .	cvs-mode-set-flags)
334    ;; ("\M-f" .	cvs-mode-force-command)
335    ("!" .	cvs-mode-force-command)
336    ("\C-c\C-c" . cvs-mode-kill-process)
337    ;; marking
338    ("m" .	cvs-mode-mark)
339    ("M" .	cvs-mode-mark-all-files)
340    ("S" .	cvs-mode-mark-on-state)
341    ("u" .	cvs-mode-unmark)
342    ("\C-?".	cvs-mode-unmark-up)
343    ("%" .	cvs-mode-mark-matching-files)
344    ("T" .	cvs-mode-toggle-marks)
345    ("\M-\C-?" .	cvs-mode-unmark-all-files)
346    ;; navigation keys
347    (" " .	cvs-mode-next-line)
348    ("n" .	cvs-mode-next-line)
349    ("p" .	cvs-mode-previous-line)
350    ;; M- keys are usually those that operate on modules
351    ;;("\M-C".	cvs-mode-rcs2log) ; i.e. "Create a ChangeLog"
352    ;;("\M-t".	cvs-rtag)
353    ;;("\M-l".	cvs-rlog)
354    ("\M-c".	cvs-checkout)
355    ("\M-e".	cvs-examine)
356    ("g" .	cvs-mode-revert-buffer)
357    ("\M-u".	cvs-update)
358    ("\M-s".	cvs-status)
359    ;; diff commands
360    ("=" .	cvs-mode-diff)
361    ("d" .	cvs-mode-diff-map)
362    ;; keys that operate on individual files
363    ("\C-k" .	cvs-mode-acknowledge)
364    ("A" .	cvs-mode-add-change-log-entry-other-window)
365    ;;("B" .	cvs-mode-byte-compile-files)
366    ("C" .	cvs-mode-commit-setup)
367    ("O" .	cvs-mode-update)
368    ("U" .	cvs-mode-undo)
369    ("I" .	cvs-mode-insert)
370    ("a" .	cvs-mode-add)
371    ("b" .	cvs-set-branch-prefix)
372    ("B" .	cvs-set-secondary-branch-prefix)
373    ("c" .	cvs-mode-commit)
374    ("e" .	cvs-mode-examine)
375    ("f" .	cvs-mode-find-file)
376    ("\C-m" .	cvs-mode-find-file)
377    ("i" .	cvs-mode-ignore)
378    ("l" .	cvs-mode-log)
379    ("o" .	cvs-mode-find-file-other-window)
380    ("r" .	cvs-mode-remove)
381    ("s" .	cvs-mode-status)
382    ("t" .	cvs-mode-tag)
383    ("v" .	cvs-mode-view-file)
384    ("x" .	cvs-mode-remove-handled)
385    ;; cvstree bindings
386    ("+" .	cvs-mode-tree)
387    ;; mouse bindings
388    ([mouse-2] . cvs-mode-find-file)
389    ([follow-link] . (lambda (pos)
390		       (if (eq (get-char-property pos 'face) 'cvs-filename) t)))
391    ([(down-mouse-3)] . cvs-menu)
392    ;; dired-like bindings
393    ("\C-o" .   cvs-mode-display-file)
394    ;; Emacs-21 toolbar
395    ;;([tool-bar item1] . (menu-item "Examine" cvs-examine :image (image :file "/usr/share/icons/xpaint.xpm" :type xpm)))
396    ;;([tool-bar item2] . (menu-item "Update" cvs-update :image (image :file "/usr/share/icons/mail1.xpm" :type xpm)))
397    )
398  "Keymap for `cvs-mode'."
399  :dense t)
400
401(fset 'cvs-mode-map cvs-mode-map)
402
403(easy-menu-define cvs-menu cvs-mode-map "Menu used in `cvs-mode'."
404  '("CVS"
405    ["Open file.."		cvs-mode-find-file	t]
406    [" ..other window"		cvs-mode-find-file-other-window	t]
407    ["Display in other window"  cvs-mode-display-file   t]
408    ["Interactive merge"	cvs-mode-imerge		t]
409    ("View diff"
410     ["Interactive diff"	cvs-mode-idiff		t]
411     ["Current diff"		cvs-mode-diff		t]
412     ["Diff with head"		cvs-mode-diff-head	t]
413     ["Diff with vendor"	cvs-mode-diff-vendor	t]
414     ["Diff with backup"	cvs-mode-diff-backup	t])
415    ["View log"			cvs-mode-log		t]
416    ["View status"		cvs-mode-status		t]
417    ["View tag tree"		cvs-mode-tree		t]
418    "----"
419    ["Insert"			cvs-mode-insert]
420    ["Update"			cvs-mode-update		(cvs-enabledp 'update)]
421    ["Re-examine"		cvs-mode-examine	t]
422    ["Commit"			cvs-mode-commit-setup	(cvs-enabledp 'commit)]
423    ["Tag"			cvs-mode-tag		(cvs-enabledp (when cvs-force-dir-tag 'tag))]
424    ["Undo changes"		cvs-mode-undo		(cvs-enabledp 'undo)]
425    ["Add"			cvs-mode-add		(cvs-enabledp 'add)]
426    ["Remove"			cvs-mode-remove		(cvs-enabledp 'remove)]
427    ["Ignore"			cvs-mode-ignore		(cvs-enabledp 'ignore)]
428    ["Add ChangeLog"		cvs-mode-add-change-log-entry-other-window t]
429    "----"
430    ["Mark"                     cvs-mode-mark t]
431    ["Mark all"			cvs-mode-mark-all-files	t]
432    ["Mark by regexp..."        cvs-mode-mark-matching-files t]
433    ["Mark by state..."         cvs-mode-mark-on-state t]
434    ["Unmark"                   cvs-mode-unmark	t]
435    ["Unmark all"		cvs-mode-unmark-all-files t]
436    ["Hide handled"		cvs-mode-remove-handled	t]
437    "----"
438    ["Quit"			cvs-mode-quit		t]))
439
440;;;;
441;;;; CVS-Minor mode
442;;;;
443
444(defcustom cvs-minor-mode-prefix "\C-xc"
445  "Prefix key for the `cvs-mode' bindings in `cvs-minor-mode'."
446  :group 'pcl-cvs)
447
448(easy-mmode-defmap cvs-minor-mode-map
449  `((,cvs-minor-mode-prefix . cvs-mode-map)
450    ("e" . (menu-item nil cvs-mode-edit-log
451	    :filter (lambda (x) (if (derived-mode-p 'log-view-mode) x)))))
452  "Keymap for `cvs-minor-mode', used in buffers related to PCL-CVS.")
453
454(defvar cvs-buffer nil
455  "(Buffer local) The *cvs* buffer associated with this buffer.")
456(put 'cvs-buffer 'permanent-local t)
457;;(make-variable-buffer-local 'cvs-buffer)
458
459(defvar cvs-minor-wrap-function nil
460  "Function to call when switching to the *cvs* buffer.
461Takes two arguments:
462- a *cvs* buffer.
463- a zero-arg function which is guaranteed not to switch buffer.
464It is expected to call the function.")
465;;(make-variable-buffer-local 'cvs-minor-wrap-function)
466
467(defvar cvs-minor-current-files)
468;;"Current files in a `cvs-minor-mode' buffer."
469;; This should stay `void' because we want to be able to tell the difference
470;; between an empty list and no list at all.
471
472(defconst cvs-pcl-cvs-dirchange-re "^pcl-cvs: descending directory \\(.*\\)$")
473
474;;;;
475;;;; autoload the global menu
476;;;;
477
478;;;###autoload
479(defvar cvs-global-menu
480  (let ((m (make-sparse-keymap "PCL-CVS")))
481    (define-key m [status]
482      '(menu-item "Directory Status" cvs-status
483		  :help "A more verbose status of a workarea"))
484    (define-key m [checkout]
485      '(menu-item "Checkout Module" cvs-checkout
486		  :help "Check out a module from the repository"))
487    (define-key m [update]
488      '(menu-item "Update Directory" cvs-update
489		  :help "Fetch updates from the repository"))
490    (define-key m [examine]
491      '(menu-item "Examine Directory" cvs-examine
492		  :help "Examine the current state of a workarea"))
493    (fset 'cvs-global-menu m)))
494
495
496;; cvs-1.10 and above can take file arguments in other directories
497;; while others need to be executed once per directory
498(defvar cvs-execute-single-dir
499  (if (or (null cvs-version)
500          (or (>= (cdr cvs-version) 10) (> (car cvs-version) 1)))
501      ;; Supposedly some recent versions of CVS output some directory info
502      ;; as they recurse downthe tree, but it's not good enough in the case
503      ;; where we run "cvs status foo bar/foo".
504      '("status")
505    t)
506  "Whether cvs commands should be executed a directory at a time.
507If a list, specifies for which commands the single-dir mode should be used.
508If T, single-dir mode should be used for all operations.
509
510CVS versions before 1.10 did not allow passing them arguments in different
511directories, so pcl-cvs checks what version you're using to determine
512whether to use the new feature or not.
513Sadly, even with a new cvs executable, if you connect to an older cvs server
514\(typically a cvs-1.9 on the server), the old restriction applies.  In such
515a case the sanity check made by pcl-cvs fails and you will have to manually
516set this variable to t (until the cvs server is upgraded).
517When the above problem occurs, pcl-cvs should (hopefully) catch cvs' error
518message and replace it with a message telling you to change this variable.")
519
520;;
521(provide 'pcvs-defs)
522
523;; arch-tag: c7c701d0-d1d4-4aa9-a302-007bb03aca5e
524;;; pcvs-defs.el ends here
525