aboutsummaryrefslogtreecommitdiffstats
path: root/admin/admin.el
diff options
context:
space:
mode:
Diffstat (limited to 'admin/admin.el')
-rw-r--r--admin/admin.el131
1 files changed, 127 insertions, 4 deletions
diff --git a/admin/admin.el b/admin/admin.el
index 70958ce1a76..27b2b3ab648 100644
--- a/admin/admin.el
+++ b/admin/admin.el
@@ -1,6 +1,6 @@
1;;; admin.el --- utilities for Emacs administration 1;;; admin.el --- utilities for Emacs administration
2 2
3;; Copyright (C) 2001-2011 Free Software Foundation, Inc. 3;; Copyright (C) 2001-2012 Free Software Foundation, Inc.
4 4
5;; This file is part of GNU Emacs. 5;; This file is part of GNU Emacs.
6 6
@@ -75,11 +75,11 @@ Root must be the root of an Emacs source tree."
75 (submatch (1+ (in "0-9.")))))) 75 (submatch (1+ (in "0-9."))))))
76 (set-version-in-file root "nt/config.nt" version 76 (set-version-in-file root "nt/config.nt" version
77 (rx (and bol "#" (0+ blank) "define" (1+ blank) 77 (rx (and bol "#" (0+ blank) "define" (1+ blank)
78 "VERSION" (1+ blank) 78 "VERSION" (1+ blank) "\""
79 (submatch (1+ (in "0-9.")))))) 79 (submatch (1+ (in "0-9."))))))
80 (set-version-in-file root "msdos/sed2v2.inp" version 80 (set-version-in-file root "msdos/sed2v2.inp" version
81 (rx (and bol "/^#undef " (1+ not-newline) 81 (rx (and bol "/^#undef " (1+ not-newline)
82 "define VERSION" (1+ space) 82 "define VERSION" (1+ space) "\""
83 (submatch (1+ (in "0-9.")))))) 83 (submatch (1+ (in "0-9."))))))
84 (set-version-in-file root "nt/makefile.w32-in" version 84 (set-version-in-file root "nt/makefile.w32-in" version
85 (rx (and "VERSION" (0+ space) "=" (0+ space) 85 (rx (and "VERSION" (0+ space) "=" (0+ space)
@@ -330,7 +330,7 @@ the @import directive."
330 330
331(defun manual-dvi (texi-file dest ps-dest) 331(defun manual-dvi (texi-file dest ps-dest)
332 "Run texi2dvi on TEXI-FILE, emitting dvi output to DEST. 332 "Run texi2dvi on TEXI-FILE, emitting dvi output to DEST.
333Also generate postscript output in PS-DEST." 333Also generate PostScript output in PS-DEST."
334 (call-process "texi2dvi" nil nil nil texi-file "-o" dest) 334 (call-process "texi2dvi" nil nil nil texi-file "-o" dest)
335 (call-process "dvips" nil nil nil dest "-o" ps-dest) 335 (call-process "dvips" nil nil nil dest "-o" ps-dest)
336 (call-process "gzip" nil nil nil dest) 336 (call-process "gzip" nil nil nil dest)
@@ -442,6 +442,129 @@ Also generate postscript output in PS-DEST."
442 (setq done t)))) 442 (setq done t))))
443 (forward-line 1)))) 443 (forward-line 1))))
444 444
445
446;; Stuff to check new defcustoms got :version tags.
447;; Adapted from check-declare.el.
448
449(defun cusver-find-files (root &optional old)
450 "Find .el files beneath directory ROOT that contain defcustoms.
451If optional OLD is non-nil, also include defvars."
452 (process-lines find-program root
453 "-name" "*.el"
454 "-exec" grep-program
455 "-l" "-E" (format "^[ \\t]*\\(def%s"
456 (if old "(custom|var)"
457 "custom"
458 ))
459 "{}" "+"))
460
461;; TODO if a defgroup with a version tag, apply to all customs in that
462;; group (eg for new files).
463(defun cusver-scan (file &optional old)
464 "Scan FILE for `defcustom' calls.
465Return a list with elements of the form (VAR . VER),
466This means that FILE contains a defcustom for variable VAR, with
467a :version tag having value VER (may be nil).
468If optional argument OLD is non-nil, also scan for defvars."
469 (let ((m (format "Scanning %s..." file))
470 (re (format "^[ \t]*\\((def%s\\)[ \t\n]"
471 (if old "\\(?:custom\\|var\\)" "custom")))
472 alist var ver)
473 (message "%s" m)
474 (with-temp-buffer
475 (insert-file-contents file)
476 ;; FIXME we could theoretically be inside a string.
477 (while (re-search-forward re nil t)
478 (goto-char (match-beginning 1))
479 (if (and (setq form (ignore-errors (read (current-buffer))))
480 (setq var (car-safe (cdr-safe form)))
481 ;; Exclude macros, eg (defcustom ,varname ...).
482 (symbolp var))
483 (setq ver (car (cdr-safe (memq :version form)))
484 alist (cons (cons var ver) alist))
485 (if form (message "Malformed defcustom: `%s'" form)))))
486 (message "%sdone" m)
487 alist))
488
489(define-button-type 'cusver-xref 'action #'cusver-goto-xref)
490
491(defun cusver-goto-xref (button)
492 "Jump to a lisp file for the BUTTON at point."
493 (let ((file (button-get button 'file))
494 (var (button-get button 'var)))
495 (if (not (file-readable-p file))
496 (message "Cannot read `%s'" file)
497 (with-current-buffer (find-file-noselect file)
498 (goto-char (point-min))
499 (or (re-search-forward (format "^[ \t]*(defcustom[ \t]*%s" var) nil t)
500 (message "Unable to locate defcustom"))
501 (pop-to-buffer (current-buffer))))))
502
503;; You should probably at least do a grep over the old directory
504;; to check the results of this look sensible. Eg cus-start if
505;; something moved from C to Lisp.
506;; TODO handle renamed things with aliases to the old names.
507;; What to do about new files? Does everything in there need a :version,
508;; or eg just the defgroup?
509(defun cusver-check (newdir olddir)
510 "Check that defcustoms have :version tags where needed.
511NEWDIR is the current lisp/ directory, OLDDIR is that from the previous
512release. A defcustom that is only in NEWDIR should have a :version
513tag. We exclude cases where a defvar exists in OLDDIR, since
514just converting a defvar to a defcustom does not require a :version bump.
515
516Note that a :version tag should also be added if the value of a defcustom
517changes (in a non-trivial way). This function does not check for that."
518 (interactive "DNew Lisp directory: \nDOld Lisp directory: ")
519 (or (file-directory-p (setq newdir (expand-file-name newdir)))
520 (error "Directory `%s' not found" newdir))
521 (or (file-directory-p (setq olddir (expand-file-name olddir)))
522 (error "Directory `%s' not found" olddir))
523 (let* ((newfiles (progn (message "Finding new files with defcustoms...")
524 (cusver-find-files newdir)))
525 (oldfiles (progn (message "Finding old files with defcustoms...")
526 (cusver-find-files olddir t)))
527 (newcus (progn (message "Reading new defcustoms...")
528 (mapcar
529 (lambda (file)
530 (cons file (cusver-scan file))) newfiles)))
531 oldcus result thisfile)
532 (message "Reading old defcustoms...")
533 (dolist (file oldfiles)
534 (setq oldcus (append oldcus (cusver-scan file t))))
535 ;; newcus has elements (FILE (VAR VER) ... ).
536 ;; oldcus just (VAR . VER).
537 (message "Checking for version tags...")
538 (dolist (new newcus)
539 (setq file (car new)
540 thisfile
541 (let (missing var)
542 (dolist (cons (cdr new))
543 (or (cdr cons)
544 (assq (setq var (car cons)) oldcus)
545 (push var missing)))
546 (if missing
547 (cons file missing))))
548 (if thisfile
549 (setq result (cons thisfile result))))
550 (message "Checking for version tags... done")
551 (if (not result)
552 (message "No missing :version tags")
553 (pop-to-buffer "*cusver*")
554 (erase-buffer)
555 (insert "These defcustoms might be missing :version tags:\n\n")
556 (dolist (elem result)
557 (let* ((str (file-relative-name (car elem) newdir))
558 (strlen (length str)))
559 (dolist (var (cdr elem))
560 (insert (format "%s: %s\n" str var))
561 (make-text-button (+ (line-beginning-position 0) strlen 2)
562 (line-end-position 0)
563 'file (car elem)
564 'var var
565 'help-echo "Mouse-2: visit this definition"
566 :type 'cusver-xref)))))))
567
445(provide 'admin) 568(provide 'admin)
446 569
447;;; admin.el ends here 570;;; admin.el ends here