;;; Find global Lisp definitions ;;; Author: Jerry James ;;; ;;; Copyright (C) 2008 by Jeremiah W. James ;;; FIXME: Choose a license (defconst directory-sep-string (char-to-string directory-sep-char) "The directory separating character, as a one-character string.") ;;; FIXME: More defining forms that we may want to track some day: ;;; defact, defface, defgroup, define-behavior, define-behavior-group, ;;; define-error, define-setf-method, and defsetf. (defconst analyze-defs-symbols (concat "^" (regexp-opt '("def-gdb-var" "def-gdb-variable" "defalias" "defalias-compat" "defalias-maybe" "defclass" "defconst" "defconst-maybe" "defcustom" "defezimage" "deffoo" "defgeneric" "defimage" "define-compatible-function-alias" "define-compatible-variable-alias" "define-compiler-macro" "define-function" "define-hmac-function" "define-obsolete-function-alias" "define-obsolete-variable-alias" "define-overload" "define-skeleton" "define-structure" "define-victim-slot" "define-victim-slots" "deflocal" "defmacro" "defmacro*" "defmacro-maybe" "defmacro-maybe-cond" "defmath" "defstruct" "defsubst" "defsubst-maybe" "defsubst-maybe-cond" "defun" "defun*" "defun-bbdb-raw-notes-accessor" "defun-compat" "defun-cvs-mode" "defun-maybe" "defun-maybe-cond" "defun-when-void" "defunx" "defvar" "defvar-mabye" "defvaralias" "defvoo" "skk-deflocalvar" "viper-deflocalvar"))) "Regexp matching definitions to store.") ;;; FIXME: How do we handle defalias and defvaralias: (quote foo)? ;;; WARNING: This function uses the variable "filename" as a special variable. (defun analyze-defs-extract (form) "Extract definition characteristics from a Lisp form. All definitions in the form are returned in a list. Each list element is a 3-element vector of the form [NAME TYPE FILENAME], where NAME is the defined symbol, TYPE is one of the symbols defun, defmacro, defsubst, etc., and FILENAME is a string giving the absolute pathname of the defining file." (when (consp form) (let ((type (car form))) (when (symbolp type) (let ((name (symbol-name type))) (if (string-match analyze-defs-symbols name) (list (vector (cadr form) type filename)) (unless (eq type 'quote) (mapcan #'analyze-defs-extract (rest form))))))))) (defun analyze-defs-file (filename) "Find all global definitions in the file named FILENAME. The definitions are returned in a list with the same structure as that returned by `analyze-defs-extract'." (when (string-match "\\.el$" filename) (with-temp-buffer (insert-file-contents filename) (let ((buf (current-buffer)) defs) (condition-case nil (while t (setq defs (nconc defs (analyze-defs-extract (read buf))))) (end-of-file defs)))))) (defun analyze-defs-dir (dirname) "Find all global definitions in the directory DIRNAME and it subdirectories. The definitions are returned in a list with the same structure as that returned by `analyze-defs-extract'." (if (file-directory-p dirname) (mapcan #'analyze-defs-dir (mapcar #'(lambda (filename) (concat dirname directory-sep-string filename)) (delete ".." (delete "." (directory-files dirname))))) (analyze-defs-file dirname)))