summaryrefslogtreecommitdiffstats
path: root/emacs.d/nxhtml/alts/find-recursive-orig.el
blob: 509a0382bcba1b23be78fd59fd087a4cd3ad7cbf (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
;; find-recursive.el -- Find files recursively into a directory
;;
;; Copyright (C) 2001 Ovidiu Predescu
;;
;; Author: Ovidiu Predescu <ovidiu@cup.hp.com>
;; Date: March 26, 2001
;;
;; This program is free software; you can redistribute it and/or
;; modify it under the terms of the GNU General Public License
;; as published by the Free Software Foundation; either version 2
;; of the License, or (at your option) any later version.
;;
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;; GNU General Public License for more details.
;;
;; You should have received a copy of the GNU General Public License
;; along with this program; if not, write to the Free Software
;; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

;;
;; Setup: put this file in your Lisp path and add the following line in
;; your .emacs:
;;
;; (require 'find-recursive)
;;

(require 'cl)

(defcustom find-recursive-exclude-files '(".*.class$" ".*~$" ".*.elc$")
  "List of regular expressions of files to be excluded when recursively searching for files."
  :type '(repeat (string :tag "File regexp")))

(defun find-file-recursively (file-regexp directory)
  (interactive "sFile name to search for recursively: \nDIn directory: ")
  (let ((directory (if (equal (substring directory -1) "/")
                       directory
                     (concat directory "/")))
        (matches
         (find-recursive-filter-out
          find-recursive-exclude-files
          (find-recursive-directory-relative-files directory "" file-regexp))))
    (cond ((eq (length matches) 0) (message "No file(s) found!"))
           ((eq (length matches) 1)
            (find-file (concat directory (car matches))))
           (t
            (run-with-timer 0.001 nil
                            (lambda ()
                              (dispatch-event
                               (make-event 'key-press '(key tab)))))
            (let ((file (completing-read "Choose file: "
                                           (mapcar 'list matches)
                                           nil t)))
                (if (or (eq file nil) (equal file ""))
                    (message "No file selected.")
                  (find-file (concat directory file))))))))

(defun find-recursive-directory-relative-files (directory
                                          relative-directory
                                          file-regexp)
  (let* ((full-dir (concat directory "/" relative-directory))
         (matches
          (mapcar
           (function (lambda (x)
                       (concat relative-directory x)))
           (find-recursive-filter-out '(nil)
                                (directory-files full-dir nil
                                                 file-regexp nil t))))
         (inner
          (mapcar
           (function
            (lambda (dir)
              (find-recursive-directory-relative-files directory
                                                 (concat relative-directory
                                                         dir "/")
                                                 file-regexp)))
           (find-recursive-filter-out '(nil "\\." "\\.\\.")
                                (directory-files full-dir nil ".*"
                                                 nil 'directories)))))
    (mapcar (function (lambda (dir) (setq matches (append matches dir))))
            inner)
    matches))

(defun find-recursive-filter-out (remove-list list)
  "Remove all the elements in *remove-list* from *list*"
  (if (eq list nil)
      nil
    (let ((elem (car list))
          (rest (cdr list)))
      (if (some
           (lambda (regexp)
             (if (or (eq elem nil) (eq regexp nil))
                 nil
               (not (eq (string-match regexp elem) nil))))
           remove-list)
          (find-recursive-filter-out remove-list rest)
        (cons elem (find-recursive-filter-out remove-list rest))))))

(defvar find-recursive-running-xemacs (string-match "XEmacs\\|Lucid" emacs-version))

(if find-recursive-running-xemacs
    nil
  (defadvice directory-files (after
                              directory-files-xemacs
                              (dirname &optional full match nosort files-only)
                              activate)
    "Add an additional argument, FILES-ONLY to the list of arguments
for GNU Emacs. If the symbol is t, then only the files in the
directory will be returned. If FILES-ONLY is nil, then both files and
directories are selected. If FILES-ONLY is not nil and not t, then
only sundirectories are returned."
    (setq ad-return-value
          (cond ((null files-only) ad-return-value)
                ((eq files-only t)
                 (find-recursive-remove-if (lambda (f)
                                             (file-directory-p
                                              (concat dirname "/" f)))
                                           ad-return-value))
                (t
                 (find-recursive-remove-if (lambda (f)
                                             (not (file-directory-p
                                                   (concat dirname "/" f))))
                                           ad-return-value)))))

  (defun find-recursive-remove-if (func list)
    "Removes all elements satisfying FUNC from LIST."
    (let ((result nil))
      (while list
        (if (not (funcall func (car list)))
            (setq result (cons (car list) result)))
        (setq list (cdr list)))
      (nreverse result))))

(global-set-key [(control x) (meta f)] 'find-file-recursively)

(provide 'find-recursive)