1;; find-recursive.el -- Find files recursively into a directory
3;; Copyright (C) 2001 Ovidiu Predescu
5;; Author: Ovidiu Predescu <ovidiu@cup.hp.com>
8;; This program is free software; you can redistribute it and/or
9;; modify it under the terms of the GNU General Public License
10;; as published by the Free Software Foundation; either version 2
11;; of the License, or (at your option) any later version.
13;; This program is distributed in the hope that it will be useful,
14;; but WITHOUT ANY WARRANTY; without even the implied warranty of
15;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16;; GNU General Public License for more details.
18;; You should have received a copy of the GNU General Public License
19;; along with this program; if not, write to the Free Software
20;; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23;; Setup: put this file in your Lisp path and add the following line in
26;; (require 'find-recursive)
31(defcustom find-recursive-exclude-files '(".*.class$" ".*~$" ".*.elc$")
32 "List of regular expressions of files to be excluded when recursively searching for files."
33 :type '(repeat (string :tag "File regexp")))
35(defun find-file-recursively (file-regexp directory)
36 (interactive "sFile name to search for recursively: \nDIn directory: ")
37 (let ((directory (if (equal (substring directory -1) "/")
39 (concat directory "/")))
41 (find-recursive-filter-out
42 find-recursive-exclude-files
43 (find-recursive-directory-relative-files directory "" file-regexp))))
44 (cond ((eq (length matches) 0) (message "No file(s) found!"))
45 ((eq (length matches) 1)
46 (find-file (concat directory (car matches))))
48 (run-with-timer 0.001 nil
51 (make-event 'key-press '(key tab)))))
52 (let ((file (completing-read "Choose file: "
53 (mapcar 'list matches)
55 (if (or (eq file nil) (equal file ""))
56 (message "No file selected.")
57 (find-file (concat directory file))))))))
59(defun find-recursive-directory-relative-files (directory
62 (let* ((full-dir (concat directory "/" relative-directory))
66 (concat relative-directory x)))
67 (find-recursive-filter-out '(nil)
68 (directory-files full-dir nil
74 (find-recursive-directory-relative-files directory
75 (concat relative-directory
78 (find-recursive-filter-out '(nil "\\." "\\.\\.")
79 (directory-files full-dir nil ".*"
81 (mapcar (function (lambda (dir) (setq matches (append matches dir))))
85(defun find-recursive-filter-out (remove-list list)
86 "Remove all the elements in *remove-list* from *list*"
89 (let ((elem (car list))
93 (if (or (eq elem nil) (eq regexp nil))
95 (not (eq (string-match regexp elem) nil))))
97 (find-recursive-filter-out remove-list rest)
98 (cons elem (find-recursive-filter-out remove-list rest))))))
100(defvar find-recursive-running-xemacs (string-match "XEmacs\\|Lucid" emacs-version))
102(if find-recursive-running-xemacs
104 (defadvice directory-files (after
105 directory-files-xemacs
106 (dirname &optional full match nosort files-only)
108 "Add an additional argument, FILES-ONLY to the list of arguments
109for GNU Emacs. If the symbol is t, then only the files in the
110directory will be returned. If FILES-ONLY is nil, then both files and
111directories are selected. If FILES-ONLY is not nil and not t, then
112only sundirectories are returned."
113 (setq ad-return-value
114 (cond ((null files-only) ad-return-value)
116 (find-recursive-remove-if (lambda (f)
118 (concat dirname "/" f)))
121 (find-recursive-remove-if (lambda (f)
122 (not (file-directory-p
123 (concat dirname "/" f))))
126 (defun find-recursive-remove-if (func list)
127 "Removes all elements satisfying FUNC from LIST."
130 (if (not (funcall func (car list)))
131 (setq result (cons (car list) result)))
132 (setq list (cdr list)))
135(global-set-key [(control x) (meta f)] 'find-file-recursively)
137(provide 'find-recursive)