Re: [Perlunit-devel] PDC_REFACTOR merged back
Status: Beta
Brought to you by:
mca1001
From: Adam S. <ad...@sp...> - 2001-11-15 13:27:13
|
Piers Cawley (pdc...@bo...) wrote: > Adam Spiers <ad...@sp...> writes: > > I use PCL-CVS under emacs (highly recommended), which amongst other > > things makes it trivial to keep an eye out for files which should be > > checked in but aren't. However for our peace of mind I've just done > > a fresh checkout and it's all good. > > I really must learn PCL-CVS properly. I use it but in a desultory > fashion. I recently submitted a patch against emacs 21.1 to the maintainer, which makes it quite a lot nicer (IMHO ;-) A copy follows below, in case you're interested. Here is a breakdown of what it does: - Adds a custom variable `cvs-buffer-switch-list' controlling whether or not to switch to the new buffer created by a diff/status/log operation. - Adds bindings for C-up and C-down to move the point between directory fileinfos. - Adds a binding for M-t to move the point to the top directory fileinfo (i.e., the first node after the header). - Adds a binding for `.' to move to the containing (i.e. parent) directory. If `.' is hit on the top-level directory, opens a new buffer for the parent directory. - Adds a binding for `v' to visit an arbitrary directory. Defaults to the directory under the point. - Fixes the binding for RET to cvs-mode-find-file. - Allows the user to control whether "New directory `foo' -- ignored" messages appear or not, via cvs-parse-ignored-messages. (The default is to display them, as before.) And la piece de resistance ... ;-) - Adds the option of caching fileinfos on a per-buffer basis, for unbelievably quick start-up via cvs-quickdir on even huge CVS trees. Index: pcvs-defs.el =================================================================== RCS file: /share/cvsroot/adams/pcl-cvs/pcvs-defs.el,v retrieving revision 1.1.1.3 diff -u -r1.1.1.3 pcvs-defs.el --- pcvs-defs.el 2001/10/22 16:11:28 1.1.1.3 +++ pcvs-defs.el 2001/10/24 16:57:16 @@ -229,6 +229,14 @@ (function-item cvs-status-trees) function))))) +(defcustom cvs-buffer-switch-list nil + "*For each operation, decides whether or not to switch to the +new buffer created when the operation is performed." + :group 'pcl-cvs + :type '(set (const "diff") + (const "status") + (const "log"))) + (defvar cvs-buffer-name '(expand-file-name "*cvs*" dir) ;; "*cvs*" "Name of the cvs buffer. This expression will be evaluated in an environment where DIR is set to @@ -253,6 +261,22 @@ (defvar cvs-mode-hook nil "Run after `cvs-mode' was setup.") +(defcustom cvs-use-fileinfo-caches nil + "Non-nil means cache a buffer's fileinfos when it's killed, so that +`cvs-quickdir' can retrieve them from the cache rather than from CVS/Entries +when populating a new buffer. + +If you enable this, it is recommended that you add the value of +`cvs-cache-filename' to your global .cvsignore file." + :group 'pcl-cvs + :type '(boolean)) + +(defcustom cvs-cache-filename ".pcl-cvs-cache" + "The name for fileinfo cache files." + :group 'pcl-cvs + :type '(file)) + + ;;;; ;;;; Internal variables, used in the process buffer. @@ -339,6 +363,8 @@ (" " . cvs-mode-next-line) ("n" . cvs-mode-next-line) ("p" . cvs-mode-previous-line) + ([C-down] . cvs-mode-next-dir) + ([C-up] . cvs-mode-previous-dir) ;; M- keys are usually those that operate on modules ;;("\M-C". cvs-mode-rcs2log) ; i.e. "Create a ChangeLog" ;;("\M-t". cvs-rtag) @@ -348,6 +374,7 @@ ("g" . cvs-mode-revert-buffer) ("\M-u". cvs-update) ("\M-s". cvs-status) + ("\M-t". cvs-mode-top-dir) ;; diff commands ("=" . cvs-mode-diff) ("d" . cvs-mode-diff-map) @@ -365,19 +392,22 @@ ("c" . cvs-mode-commit) ("e" . cvs-mode-examine) ("f" . cvs-mode-find-file) - ([RET] . 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-examine-directory) + ("^" . cvs-mode-examine-parent-directory) + ("." . cvs-mode-up-level) ;;("v" . cvs-mode-diff-vendor) ("x" . cvs-mode-remove-handled) ;; cvstree bindings ("+" . cvs-mode-tree) ;; mouse bindings - ([mouse-2] . cvs-mode-find-file) + ([(mouse-2)] . cvs-mode-find-file) ([(down-mouse-3)] . cvs-menu) ;; dired-like bindings ("\C-o" . cvs-mode-display-file) Index: pcvs-parse.el =================================================================== RCS file: /share/cvsroot/adams/pcl-cvs/pcvs-parse.el,v retrieving revision 1.1.1.2 retrieving revision 1.2 diff -u -r1.1.1.2 -r1.2 --- pcvs-parse.el 2001/10/22 16:11:28 1.1.1.2 +++ pcvs-parse.el 2001/10/03 15:45:47 1.2 @@ -4,7 +4,7 @@ ;; Author: Stefan Monnier <mo...@cs...> ;; Keywords: pcl-cvs -;; Revision: $Id: pcvs-parse.el,v 1.10 2001/09/24 16:39:23 monnier Exp $ +;; Revision: $Id: pcvs-parse.el,v 1.1 2001/10/03 13:35:56 adams Exp $ ;; This file is part of GNU Emacs. @@ -260,11 +260,6 @@ (cvs-match "\\(Examining\\|Updating\\) \\(.*\\)$" (dir 2)) (let ((dir (if (string= "." dir) "" (file-name-as-directory dir)))) (cvs-parsed-fileinfo 'DIRCHANGE "." dir))) - - ;; [-n update] A new (or pruned) directory appeared but isn't traversed - (and - (cvs-match "New directory `\\(.*\\)' -- ignored$" (dir 1)) - (cvs-parsed-fileinfo 'MESSAGE " " (file-name-as-directory dir))) ;; File removed, since it is removed (by third party) in repository. (and Index: pcvs.el =================================================================== RCS file: /share/cvsroot/adams/pcl-cvs/pcvs.el,v retrieving revision 1.1.1.2 retrieving revision 1.12 diff -u -r1.1.1.2 -r1.12 --- pcvs.el 2001/10/22 16:11:28 1.1.1.2 +++ pcvs.el 2001/10/24 16:58:07 1.12 @@ -873,6 +873,24 @@ (interactive) (cvs-examine default-directory t)) +(defun cvs-mode-examine-directory (dir) + "Run `cvs-examine' on a specified directory with the default flags." + (interactive (list (cvs-query-directory-prompt "CVS Examine (directory): "))) + (cvs-examine dir t)) + +(defun cvs-mode-examine-parent-directory () + "Run `cvs-examine' on a specified directory with the default flags." + (interactive) + (cvs-examine ".." t)) + +(defun cvs-query-directory-prompt (msg) + (let* ((cur-fi (ewoc-data (ewoc-locate cvs-cookies))) + (default-dir (if (cvs-fileinfo-p cur-fi) + (expand-file-name (cvs-fileinfo->dir cur-fi) + default-directory) + default-directory))) + (read-file-name msg default-dir default-dir nil))) + (defun cvs-query-directory (msg) ;; last-command-char = ?\r hints that the command was run via M-x (if (and (cvs-buffer-p) @@ -881,6 +899,17 @@ default-directory (read-file-name msg nil default-directory nil))) +(defun cvs-cache-buffer-fileinfos () + "Cache the buffer of fileinfos representing a directory's CVS status +into a file whose name is defined by `cvs-cache-filename'." + (when (eq major-mode 'cvs-mode) + (let ((cookies cvs-cookies)) + (with-temp-file (expand-file-name cvs-cache-filename) + (prin1 (ewoc-map 'identity cookies) (current-buffer)))))) + +(add-hook 'kill-buffer-hook 'cvs-cache-buffer-fileinfos) +(add-hook 'kill-emacs-hook 'cvs-cache-buffer-fileinfos) + ;;;###autoload (defun cvs-quickdir (dir &optional flags noshow) "Open a *cvs* buffer on DIR without running cvs. @@ -902,15 +931,28 @@ (unless (file-directory-p (expand-file-name "CVS" dir)) (error "%s does not contain CVS controlled files" dir)) (set-buffer cvsbuf) - (dolist (fi (cvs-fileinfo-from-entries "")) + (dolist (fi (or (cvs-fileinfo-from-cache "") + (cvs-fileinfo-from-entries ""))) (setq last (cvs-addto-collection cvs-cookies fi last))) (cvs-cleanup-collection cvs-cookies - (eq cvs-auto-remove-handled t) - cvs-auto-remove-directories - nil) + (eq cvs-auto-remove-handled t) + cvs-auto-remove-directories + nil) (if noshow cvsbuf (let ((pop-up-windows nil)) (pop-to-buffer cvsbuf))))) +(defun cvs-fileinfo-from-cache (dir) + "If caching is enabled and a cache file exists for the given +directory DIR, reads fileinfos from it, and returns them. Otherwise +returns nil." + (and cvs-use-fileinfo-caches + (let ((cache (expand-file-name cvs-cache-filename dir))) + (and (file-readable-p cache) + (with-temp-buffer + (insert-file-contents cache) + (message (format "Reading fileinfos from %s" cache)) + (read (buffer-substring 1 (point-max)))))))) + ;;;###autoload (defun cvs-examine (directory flags &optional noshow) "Run a `cvs -n update' in the specified DIRECTORY. @@ -1093,6 +1135,64 @@ (interactive "p") (ewoc-goto-next cvs-cookies arg)) +(defun cvs-mode-previous-dir () + "Go to the previous directory. Returns the destination node." + (interactive) + (catch 'end + (do* ((cur-node (ewoc-goto-prev cvs-cookies 1)) + (cur-fi (ewoc-data cur-node))) + ((and (cvs-fileinfo-p cur-fi) + (eq (cvs-fileinfo->type cur-fi) 'DIRCHANGE)) + cur-node) + (setq cur-node (ewoc-goto-prev cvs-cookies 1)) + (setq cur-fi (ewoc-data cur-node)) + (or (cvs-fileinfo-p cur-fi) (throw 'end cur-node))))) + +(defun cvs-mode-next-dir () + "Go to the next directory. Returns the destination node." + (interactive) + (catch 'end + ;; ewoc considers being in the header equivalent to being in + ;; the first node (doh), so we have to compare the point's + ;; position with the beginning of the first node + (let ((first-node (ewoc-nth cvs-cookies 0))) + (cond ((< (point) (marker-position (ewoc-location first-node))) + (ewoc-goto-node cvs-cookies first-node)) + (t + (do* ((cur-node (ewoc-goto-next cvs-cookies 1)) + (cur-fi (ewoc-data cur-node))) + ((and (cvs-fileinfo-p cur-fi) + (eq (cvs-fileinfo->type cur-fi) 'DIRCHANGE)) + cur-node) + (setq cur-node (ewoc-goto-next cvs-cookies 1)) + (setq cur-fi (ewoc-data cur-node)) + (or (cvs-fileinfo-p cur-fi) (throw 'end cur-node)))))))) + +(defun cvs-mode-up-level () + "Go to the containing directory. Returns the new node." + (interactive) + (let* ((orig-node (ewoc-locate cvs-cookies)) + (orig-fi (ewoc-data (or orig-node (error "Not on a fileinfo")))) + (orig-dir (cvs-fileinfo->dir orig-fi))) + (if (and (eq (cvs-fileinfo->type orig-fi) 'DIRCHANGE) + (equal orig-dir "")) + (cvs-mode-examine-parent-directory) + (do* ((current-node (cvs-mode-previous-dir)) + (current-fi (ewoc-data current-node)) + (current-dir (cvs-fileinfo->dir current-fi))) + ((string-match (concat "^" (regexp-quote current-dir)) orig-dir) + current-node) + (setq current-node (cvs-mode-previous-dir)) + (setq current-fi (ewoc-data current-node)) + (setq current-dir (cvs-fileinfo->dir current-fi)))))) + +(defun cvs-mode-top-dir () + "Go to the top-level directory in the current buffer." + (interactive) + (goto-char 0) + (ewoc-goto-next cvs-cookies 1) + (forward-line -1)) + ;;;; ;;;; Mark handling ;;;; @@ -1661,7 +1761,10 @@ ;;(set (make-local-variable 'cvs-buffer) cvs-buf) (let ((inhibit-read-only t)) (erase-buffer)) (message "Running cvs %s ..." cmd) - (cvs-run-process args fis postproc single-dir)))) + (cvs-run-process args fis postproc single-dir)) + (and (member cmd cvs-buffer-switch-list) + (let ((w (get-buffer-window buf))) + (and w (select-window (get-buffer-window buf))))))) (defun* cvs-mode-do (cmd flags filter cvs diff: Diffing emacs-lisp Index: emacs-lisp/ewoc.el =================================================================== RCS file: /share/cvsroot/adams/pcl-cvs/emacs-lisp/ewoc.el,v retrieving revision 1.1.1.2 retrieving revision 1.3 diff -u -r1.1.1.2 -r1.3 --- emacs-lisp/ewoc.el 2001/10/22 16:16:23 1.1.1.2 +++ emacs-lisp/ewoc.el 2001/10/24 16:33:45 1.3 @@ -396,14 +396,19 @@ it returns, if it changes it. If more than two arguments are given, the remaining -arguments will be passed to MAP-FUNCTION." +arguments will be passed to MAP-FUNCTION. + +Returns a list of all the results from all the calls to MAP-FUNCTION." (ewoc--set-buffer-bind-dll-let* ewoc ((footer (ewoc--footer ewoc)) - (node (ewoc--node-nth dll 1))) + (node (ewoc--node-nth dll 1)) + (result nil)) (while (not (eq node footer)) - (if (apply map-function (ewoc--node-data node) args) - (ewoc--refresh-node (ewoc--pretty-printer ewoc) node)) - (setq node (ewoc--node-next dll node))))) + (let ((mapped (apply map-function (ewoc--node-data node) args))) + (setq result (append result (list mapped))) + (if mapped (ewoc--refresh-node (ewoc--pretty-printer ewoc) node))) + (setq node (ewoc--node-next dll node))) + result)) (defun ewoc-filter (ewoc predicate &rest args) "Remove all elements in EWOC for which PREDICATE returns nil. |