comparison lisp/pcvs-info.el @ 29576:961f303cda37

(cvs-fi-up-to-date-face, cvs-fi-unknown-face): New vars. (cvs-status-map): Don't inherit from cvs-mode-map anymore. (cvs-filename-map, cvs-dirname-map): Remove. (cvs-default-action): Remove. (cvs-add-face): Use `keymap' rather than `local-map' property, and only if the arg is really a keymap. (cvs-fileinfo-pp): Don't use any special map for file and dir names. Don't hardcode the mapping from state (aka type) to face, but check the var cvs-fi-<type>-face instead. (cvs-fileinfo-from-entries): New function.
author Stefan Monnier <monnier@iro.umontreal.ca>
date Mon, 12 Jun 2000 04:37:50 +0000
parents 06cfa273543d
children 5ca411467bf3
comparison
equal deleted inserted replaced
29575:ab979e3b519a 29576:961f303cda37
3 ;; Copyright (C) 1991-2000 Free Software Foundation, Inc. 3 ;; Copyright (C) 1991-2000 Free Software Foundation, Inc.
4 4
5 ;; Author: Stefan Monnier <monnier@cs.yale.edu> 5 ;; Author: Stefan Monnier <monnier@cs.yale.edu>
6 ;; Keywords: pcl-cvs 6 ;; Keywords: pcl-cvs
7 ;; Version: $Name: $ 7 ;; Version: $Name: $
8 ;; Revision: $Id: pcvs-info.el,v 1.1 2000/03/11 03:42:29 monnier Exp $ 8 ;; Revision: $Id: pcvs-info.el,v 1.2 2000/03/22 02:56:52 monnier Exp $
9 9
10 ;; This file is part of GNU Emacs. 10 ;; This file is part of GNU Emacs.
11 11
12 ;; GNU Emacs is free software; you can redistribute it and/or modify 12 ;; GNU Emacs is free software; you can redistribute it and/or modify
13 ;; it under the terms of the GNU General Public License as published by 13 ;; it under the terms of the GNU General Public License as published by
63 on a directory entry, cvs would commit the whole directory. This seems 63 on a directory entry, cvs would commit the whole directory. This seems
64 to confuse some users sometimes." 64 to confuse some users sometimes."
65 :group 'pcl-cvs 65 :group 'pcl-cvs
66 :type '(boolean)) 66 :type '(boolean))
67 67
68
69 ;;;; 68 ;;;;
70 ;;;; Faces for fontification 69 ;;;; Faces for fontification
71 ;;;; 70 ;;;;
72 71
73 (defface cvs-header-face 72 (defface cvs-header-face
127 (defface cvs-msg-face 126 (defface cvs-msg-face
128 '((t (:italic t))) 127 '((t (:italic t)))
129 "PCL-CVS face used to highlight CVS messages." 128 "PCL-CVS face used to highlight CVS messages."
130 :group 'pcl-cvs) 129 :group 'pcl-cvs)
131 130
131 (defvar cvs-fi-up-to-date-face 'cvs-handled-face)
132 (defvar cvs-fi-unknown-face 'cvs-unknown-face)
132 133
133 ;; There is normally no need to alter the following variable, but if 134 ;; There is normally no need to alter the following variable, but if
134 ;; your site has installed CVS in a non-standard way you might have 135 ;; your site has installed CVS in a non-standard way you might have
135 ;; to change it. 136 ;; to change it.
136 137
137 (defvar cvs-bakprefix ".#" 138 (defvar cvs-bakprefix ".#"
138 "The prefix that CVS prepends to files when rcsmerge'ing.") 139 "The prefix that CVS prepends to files when rcsmerge'ing.")
139 140
140 (easy-mmode-defmap cvs-filename-map
141 '(([(mouse-2)] . cvs-mode-find-file))
142 "Local keymap for text properties of file names"
143 :inherit 'cvs-mode-map)
144
145 (easy-mmode-defmap cvs-status-map 141 (easy-mmode-defmap cvs-status-map
146 '(([(mouse-2)] . cvs-mouse-toggle-mark)) 142 '(([(mouse-2)] . cvs-mouse-toggle-mark))
147 "Local keymap for text properties of status" 143 "Local keymap for text properties of status")
148 :inherit 'cvs-mode-map)
149
150 (easy-mmode-defmap cvs-dirname-map
151 '(([(mouse-2)] . cvs-mode-find-file))
152 "Local keymap for text properties of directory names"
153 :inherit 'cvs-mode-map)
154 144
155 ;; Constructor: 145 ;; Constructor:
156 146
157 (defstruct (cvs-fileinfo 147 (defstruct (cvs-fileinfo
158 (:constructor nil) 148 (:constructor nil)
223 (let ((dir (cvs-fileinfo->dir fileinfo))) 213 (let ((dir (cvs-fileinfo->dir fileinfo)))
224 (if (eq (cvs-fileinfo->type fileinfo) 'DIRCHANGE) 214 (if (eq (cvs-fileinfo->type fileinfo) 'DIRCHANGE)
225 (if (string= dir "") "." (directory-file-name dir)) 215 (if (string= dir "") "." (directory-file-name dir))
226 ;; Here, I use `concat' rather than `expand-file-name' because I want 216 ;; Here, I use `concat' rather than `expand-file-name' because I want
227 ;; the resulting path to stay relative if `dir' is relative. 217 ;; the resulting path to stay relative if `dir' is relative.
228 ;; I could also use `expand-file-name' with `default-directory = ""'
229 (concat dir (cvs-fileinfo->file fileinfo))))) 218 (concat dir (cvs-fileinfo->file fileinfo)))))
230 219
231 (defun cvs-fileinfo->pp-name (fi) 220 (defun cvs-fileinfo->pp-name (fi)
232 "Return the filename of FI as it should be displayed." 221 "Return the filename of FI as it should be displayed."
233 (if cvs-display-full-path 222 (if cvs-display-full-path
318 307
319 ;;;; 308 ;;;;
320 ;;;; Utility functions 309 ;;;; Utility functions
321 ;;;; 310 ;;;;
322 311
323 ;;----------
324 (defun cvs-applicable-p (fi-or-type func) 312 (defun cvs-applicable-p (fi-or-type func)
325 "Check if FUNC is applicable to FI-OR-TYPE. 313 "Check if FUNC is applicable to FI-OR-TYPE.
326 If FUNC is nil, always return t. 314 If FUNC is nil, always return t.
327 FI-OR-TYPE can either be a symbol (a fileinfo-type) or a fileinfo." 315 FI-OR-TYPE can either be a symbol (a fileinfo-type) or a fileinfo."
328 (let ((type (if (symbolp fi-or-type) fi-or-type 316 (let ((type (if (symbolp fi-or-type) fi-or-type
329 (cvs-fileinfo->type fi-or-type)))) 317 (cvs-fileinfo->type fi-or-type))))
330 (and (not (eq type 'MESSAGE)) 318 (and (not (eq type 'MESSAGE))
331 (eq (car (memq func (cdr (assq type cvs-states)))) func)))) 319 (eq (car (memq func (cdr (assq type cvs-states)))) func))))
332 320
333 ;; (defun cvs-default-action (fileinfo)
334 ;; "Return some kind of \"default\" action to be performed."
335 ;; (second (assq (cvs-fileinfo->type fileinfo) cvs-states)))
336
337 ;; fileinfo pretty-printers:
338
339 (defun cvs-add-face (str face &optional keymap) 321 (defun cvs-add-face (str face &optional keymap)
340 (when cvs-highlight 322 (when cvs-highlight
341 (add-text-properties 0 (length str) 323 (add-text-properties 0 (length str)
342 (list* 'face face 324 (list* 'face face
343 (when keymap 325 (when keymap
344 (list 'mouse-face 'highlight 326 (list* 'mouse-face 'highlight
345 'local-map keymap))) 327 (when (keymapp keymap)
328 (list 'keymap keymap)))))
346 str)) 329 str))
347 str) 330 str)
348 331
349 ;;----------
350 (defun cvs-fileinfo-pp (fileinfo) 332 (defun cvs-fileinfo-pp (fileinfo)
351 "Pretty print FILEINFO. Insert a printed representation in current buffer. 333 "Pretty print FILEINFO. Insert a printed representation in current buffer.
352 For use by the cookie package." 334 For use by the cookie package."
353 (cvs-check-fileinfo fileinfo) 335 (cvs-check-fileinfo fileinfo)
354 (let ((type (cvs-fileinfo->type fileinfo)) 336 (let ((type (cvs-fileinfo->type fileinfo))
355 (subtype (cvs-fileinfo->subtype fileinfo))) 337 (subtype (cvs-fileinfo->subtype fileinfo)))
356 (insert 338 (insert
357 (case type 339 (case type
358 (DIRCHANGE (concat "In directory " 340 (DIRCHANGE (concat "In directory "
359 (cvs-add-face (cvs-fileinfo->full-path fileinfo) 341 (cvs-add-face (cvs-fileinfo->full-path fileinfo)
360 'cvs-header-face cvs-dirname-map) 342 'cvs-header-face t)
361 ":")) 343 ":"))
362 (MESSAGE 344 (MESSAGE
363 (cvs-add-face (format "Message: %s" (cvs-fileinfo->full-log fileinfo)) 345 (cvs-add-face (format "Message: %s" (cvs-fileinfo->full-log fileinfo))
364 'cvs-msg-face)) 346 'cvs-msg-face))
365 (t 347 (t
366 (let* ((status (if (cvs-fileinfo->marked fileinfo) 348 (let* ((status (if (cvs-fileinfo->marked fileinfo)
367 (cvs-add-face "*" 'cvs-marked-face) 349 (cvs-add-face "*" 'cvs-marked-face)
368 " ")) 350 " "))
369 (file (cvs-add-face (cvs-fileinfo->pp-name fileinfo) 351 (file (cvs-add-face (cvs-fileinfo->pp-name fileinfo)
370 'cvs-filename-face cvs-filename-map)) 352 'cvs-filename-face t))
371 (base (or (cvs-fileinfo->base-rev fileinfo) "")) 353 (base (or (cvs-fileinfo->base-rev fileinfo) ""))
372 (head (cvs-fileinfo->head-rev fileinfo)) 354 (head (cvs-fileinfo->head-rev fileinfo))
373 (type 355 (type
374 (let ((str (case type 356 (let ((str (case type
375 ;;(MOD-CONFLICT "Not Removed") 357 ;;(MOD-CONFLICT "Not Removed")
376 (DEAD "") 358 (DEAD "")
377 (t (capitalize (symbol-name type))))) 359 (t (capitalize (symbol-name type)))))
378 (face (case type 360 (face (let ((sym (intern
379 (UP-TO-DATE 'cvs-handled-face) 361 (concat "cvs-fi-"
380 (UNKNOWN 'cvs-unknown-face) 362 (downcase (symbol-name type))
381 (t 'cvs-need-action-face)))) 363 "-face"))))
364 (or (and (boundp sym) (symbol-value sym))
365 'cvs-need-action-face))))
382 (cvs-add-face str face cvs-status-map))) 366 (cvs-add-face str face cvs-status-map)))
383 (side (or 367 (side (or
384 ;; maybe a subtype 368 ;; maybe a subtype
385 (when subtype (downcase (symbol-name subtype))) 369 (when subtype (downcase (symbol-name subtype)))
386 ;; or the head-rev 370 ;; or the head-rev
403 (cond 387 (cond
404 (merge (setf (cvs-fileinfo->merge fi) merge)) 388 (merge (setf (cvs-fileinfo->merge fi) merge))
405 ((memq type '(UP-TO-DATE NEED-UPDATE)) 389 ((memq type '(UP-TO-DATE NEED-UPDATE))
406 (setf (cvs-fileinfo->merge fi) nil))))) 390 (setf (cvs-fileinfo->merge fi) nil)))))
407 391
408 ;;----------
409 (defun cvs-fileinfo< (a b) 392 (defun cvs-fileinfo< (a b)
410 "Compare fileinfo A with fileinfo B and return t if A is `less'. 393 "Compare fileinfo A with fileinfo B and return t if A is `less'.
411 The ordering defined by this function is such that directories are 394 The ordering defined by this function is such that directories are
412 sorted alphabetically, and inside every directory the DIRCHANGE 395 sorted alphabetically, and inside every directory the DIRCHANGE
413 fileinfo will appear first, followed by all files (alphabetically)." 396 fileinfo will appear first, followed by all files (alphabetically)."
423 ((eq (cvs-fileinfo->type a) 'DIRCHANGE) t) 406 ((eq (cvs-fileinfo->type a) 'DIRCHANGE) t)
424 407
425 ;; All files are sorted by file name. 408 ;; All files are sorted by file name.
426 ((string< (cvs-fileinfo->file a) (cvs-fileinfo->file b)))))) 409 ((string< (cvs-fileinfo->file a) (cvs-fileinfo->file b))))))
427 410
411 ;;;
412 ;;; Look at CVS/Entries to quickly find a first approximation of the status
413 ;;;
414
415 (defun cvs-fileinfo-from-entries (dir &optional all)
416 "List of fileinfos for DIR, extracted from CVS/Entries.
417 Unless ALL is optional, returns only the files that are not up-to-date.
418 DIR can also be a file."
419 (let* ((singlefile
420 (cond
421 ((equal dir "") nil)
422 ((file-directory-p dir) (setq dir (file-name-as-directory dir)) nil)
423 (t (prog1 (file-name-nondirectory dir)
424 (setq dir (or (file-name-directory dir) ""))))))
425 (file (expand-file-name "CVS/Entries" dir))
426 (fis nil))
427 (if (not (file-readable-p file))
428 (push (cvs-create-fileinfo (if singlefile 'UNKNOWN 'DIRCHANGE)
429 dir (or singlefile ".") "") fis)
430 (with-temp-buffer
431 (insert-file-contents file)
432 (goto-char (point-min))
433 ;; Select the single file entry in case we're only interested in a file.
434 (cond
435 ((not singlefile)
436 (push (cvs-create-fileinfo 'DIRCHANGE dir "." "") fis))
437 ((re-search-forward
438 (concat "^[^/]*/" (regexp-quote singlefile) "/.*") nil t)
439 (setq all t)
440 (goto-char (match-beginning 0))
441 (narrow-to-region (point) (match-end 0)))
442 (t
443 (push (cvs-create-fileinfo 'UNKNOWN dir singlefile "") fis)
444 (narrow-to-region (point-min) (point-min))))
445 (while (looking-at "\\([^/]*\\)/\\([^/]*\\)/\\([^/]*\\)/\\([^/]*\\)/")
446 (if (/= (match-beginning 1) (match-end 1))
447 (setq fis (append (cvs-fileinfo-from-entries
448 (concat dir (file-name-as-directory
449 (match-string 2)))
450 all)
451 fis))
452 (let ((f (match-string 2))
453 (rev (match-string 3))
454 (date (match-string 4))
455 timestamp
456 (type 'MODIFIED)
457 (subtype nil))
458 (cond
459 ((equal (substring rev 0 1) "-")
460 (setq type 'REMOVED rev (substring rev 1)))
461 ((not (file-exists-p (concat dir f))) (setq type 'MISSING))
462 ((equal rev "0") (setq type 'ADDED rev nil))
463 ((equal date "Result of merge") (setq subtype 'MERGED))
464 ((let ((mtime (nth 5 (file-attributes (concat dir f))))
465 (system-time-locale "C"))
466 (equal (setq timestamp (format-time-string "%c" mtime 'utc))
467 date))
468 (setq type (if all 'UP-TO-DATE)))
469 ((equal date (concat "Result of merge+" timestamp))
470 (setq type 'CONFLICT)))
471 (when type
472 (push (cvs-create-fileinfo type dir f ""
473 :base-rev rev :subtype subtype)
474 fis))))
475 (forward-line 1))))
476 fis))
477
428 (provide 'pcvs-info) 478 (provide 'pcvs-info)
429 479
430 ;;; pcl-cvs-info.el ends here 480 ;;; pcl-cvs-info.el ends here