comparison lisp/find-paths.el @ 276:6330739388db r21-0b36

Import from CVS: tag r21-0b36
author cvs
date Mon, 13 Aug 2007 10:30:37 +0200
parents ca9a9ec9c1c1
children 90d73dddcdc4
comparison
equal deleted inserted replaced
275:a68ae4439f57 276:6330739388db
37 ;;; Code: 37 ;;; Code:
38 38
39 (defvar paths-version-control-bases '("RCS" "CVS" "SCCS") 39 (defvar paths-version-control-bases '("RCS" "CVS" "SCCS")
40 "File bases associated with version control.") 40 "File bases associated with version control.")
41 41
42 (defun paths-find-recursive-path (directories &optional exclude) 42 (defun paths-find-recursive-path (directories &optional max-depth exclude)
43 "Return a list of the directory hierarchy underneath DIRECTORIES. 43 "Return a list of the directory hierarchy underneath DIRECTORIES.
44 The returned list is sorted by pre-order and lexicographically." 44 The returned list is sorted by pre-order and lexicographically.
45 MAX-DEPTH limits the depth of the search to MAX-DEPTH level,
46 if it is a number. If MAX-DEPTH is NIL, the search depth is unlimited.
47 EXCLUDE is a list of directory names to exclude from the search."
45 (let ((path '())) 48 (let ((path '()))
46 (while directories 49 (while directories
47 (let ((directory (file-name-as-directory 50 (let ((directory (file-name-as-directory
48 (expand-file-name 51 (expand-file-name
49 (car directories))))) 52 (car directories)))))
50 (if (file-directory-p directory) 53 (if (file-directory-p directory)
51 (let ((raw-dirs (directory-files directory nil "^[^-.]" nil 'dirs-only)) 54 (let ((raw-dirs
55 (if (equal 0 max-depth)
56 '()
57 (directory-files directory nil "^[^-.]" nil 'dirs-only)))
52 (reverse-dirs '())) 58 (reverse-dirs '()))
53 59
54 (while raw-dirs 60 (while raw-dirs
55 (if (null (member (car raw-dirs) exclude)) 61 (if (null (member (car raw-dirs) exclude))
56 (setq reverse-dirs 62 (setq reverse-dirs
57 (cons (expand-file-name (car raw-dirs) directory) 63 (cons (expand-file-name (car raw-dirs) directory)
58 reverse-dirs))) 64 reverse-dirs)))
59 (setq raw-dirs (cdr raw-dirs))) 65 (setq raw-dirs (cdr raw-dirs)))
60 66
61 (let ((sub-path 67 (let ((sub-path
62 (paths-find-recursive-path (reverse reverse-dirs) exclude))) 68 (paths-find-recursive-path (reverse reverse-dirs)
69 (if (numberp max-depth)
70 (- max-depth 1)
71 max-depth)
72 exclude)))
63 (setq path (nconc path 73 (setq path (nconc path
64 (list directory) 74 (list directory)
65 sub-path)))))) 75 sub-path))))))
66 (setq directories (cdr directories))) 76 (setq directories (cdr directories)))
67 path)) 77 path))
68 78
69 (defun paths-find-recursive-load-path (directories) 79 (defun paths-find-recursive-load-path (directories &optional max-depth)
70 "Construct a recursive load path underneath DIRECTORIES." 80 "Construct a recursive load path underneath DIRECTORIES."
71 (paths-find-recursive-path directories paths-version-control-bases)) 81 (paths-find-recursive-path directories
82 max-depth paths-version-control-bases))
72 83
73 (defun paths-emacs-root-p (directory) 84 (defun paths-emacs-root-p (directory)
74 "Check if DIRECTORY is a plausible installation root for XEmacs." 85 "Check if DIRECTORY is a plausible installation root for XEmacs."
75 (or 86 (or
76 ;; installed 87 ;; installed
77 (file-directory-p (concat directory "lib/xemacs")) 88 (file-directory-p (paths-construct-path (list directory "lib" "xemacs")))
78 ;; in-place 89 ;; in-place
79 (and 90 (and
80 (file-directory-p (concat directory "lib-src")) 91 (file-directory-p (paths-construct-path (list directory "lib-src")))
81 (file-directory-p (concat directory "lisp")) 92 (file-directory-p (paths-construct-path (list directory "lisp")))
82 (file-directory-p (concat directory "src"))))) 93 (file-directory-p (paths-construct-path (list directory "src"))))))
83 94
84 (defun paths-chase-symlink (file-name) 95 (defun paths-chase-symlink (file-name)
85 "Chase a symlink until the bitter end." 96 "Chase a symlink until the bitter end."
86 (let ((maybe-symlink (file-symlink-p file-name))) 97 (let ((maybe-symlink (file-symlink-p file-name)))
87 (if maybe-symlink 98 (if maybe-symlink
96 (let* ((executable-file-name (paths-chase-symlink 107 (let* ((executable-file-name (paths-chase-symlink
97 (concat invocation-directory 108 (concat invocation-directory
98 invocation-name))) 109 invocation-name)))
99 (executable-directory (file-name-directory executable-file-name)) 110 (executable-directory (file-name-directory executable-file-name))
100 (maybe-root-1 (file-name-as-directory 111 (maybe-root-1 (file-name-as-directory
101 (expand-file-name ".." executable-directory))) 112 (paths-construct-path '("..") executable-directory)))
102 (maybe-root-2 (file-name-as-directory 113 (maybe-root-2 (file-name-as-directory
103 (expand-file-name "../.." executable-directory)))) 114 (paths-construct-path '(".." "..") executable-directory))))
104 (or (and (paths-emacs-root-p maybe-root-1) 115 (or (and (paths-emacs-root-p maybe-root-1)
105 maybe-root-1) 116 maybe-root-1)
106 (and (paths-emacs-root-p maybe-root-2) 117 (and (paths-emacs-root-p maybe-root-2)
107 maybe-root-2)))) 118 maybe-root-2))))
119
120 (defun paths-construct-path (components &optional expand-directory)
121 "Convert list of path components COMPONENTS into a path.
122 If EXPAND-DIRECTORY is non-NIL, use it as a directory to feed
123 to EXPAND-FILE-NAME."
124 (let* ((reverse-components (reverse components))
125 (last-component (car reverse-components))
126 (first-components (reverse (cdr reverse-components)))
127 (path
128 (apply #'concat
129 (append (mapcar #'file-name-as-directory first-components)
130 (list last-component)))))
131 (if expand-directory
132 (expand-file-name path expand-directory)
133 path)))
108 134
109 (defun paths-construct-emacs-directory (root suffix base) 135 (defun paths-construct-emacs-directory (root suffix base)
110 "Construct a directory name within the XEmacs hierarchy." 136 "Construct a directory name within the XEmacs hierarchy."
111 (file-name-as-directory 137 (file-name-as-directory
112 (expand-file-name 138 (expand-file-name
120 ROOTS must be a list of installation roots. 146 ROOTS must be a list of installation roots.
121 SUFFIX is the subdirectory from there. 147 SUFFIX is the subdirectory from there.
122 BASE is the base to look for. 148 BASE is the base to look for.
123 ENVVAR is the name of the environment variable that might also 149 ENVVAR is the name of the environment variable that might also
124 specify the directory. 150 specify the directory.
125 DEFAULT is a fall-back value." 151 DEFAULT is the preferred value."
126 (let ((envvar-value (and envvar (getenv envvar)))) 152 (let ((preferred-value (or (and envvar (getenv envvar))
127 (if (and envvar-value 153 default)))
128 (file-directory-p envvar-value)) 154 (if (and preferred-value
129 (file-name-as-directory envvar-value) 155 (file-directory-p preferred-value))
156 (file-name-as-directory preferred-value)
130 (catch 'gotcha 157 (catch 'gotcha
131 (while roots 158 (while roots
132 (let* ((root (car roots)) 159 (let* ((root (car roots))
133 (path (paths-construct-emacs-directory root suffix base))) 160 (path (paths-construct-emacs-directory root suffix base)))
134 ;; installed 161 ;; installed
137 (let ((path (paths-construct-emacs-directory root "" base))) 164 (let ((path (paths-construct-emacs-directory root "" base)))
138 ;; in-place 165 ;; in-place
139 (if (file-directory-p path) 166 (if (file-directory-p path)
140 (throw 'gotcha path))))) 167 (throw 'gotcha path)))))
141 (setq roots (cdr roots))) 168 (setq roots (cdr roots)))
142 (if (and default 169 nil))))
143 (file-directory-p default))
144 (file-name-as-directory default)
145 nil)))))
146 170
147 (defun paths-find-site-directory (roots base &optional envvar default) 171 (defun paths-find-site-directory (roots base &optional envvar default)
148 "Find a site-specific directory in the XEmacs hierarchy." 172 "Find a site-specific directory in the XEmacs hierarchy."
149 (paths-find-emacs-directory roots "lib/xemacs/" base envvar default)) 173 (paths-find-emacs-directory roots
174 (file-name-as-directory
175 (paths-construct-path '("lib" "xemacs")))
176 base
177 envvar default))
150 178
151 (defun paths-find-version-directory (roots base &optional envvar default) 179 (defun paths-find-version-directory (roots base &optional envvar default)
152 "Find a version-specific directory in the XEmacs hierarchy." 180 "Find a version-specific directory in the XEmacs hierarchy."
153 (paths-find-emacs-directory roots 181 (paths-find-emacs-directory roots
154 (concat "lib/xemacs-" (construct-emacs-version) "/") 182 (file-name-as-directory
183 (paths-construct-path
184 (list "lib"
185 (concat "xemacs-"
186 (construct-emacs-version)))))
155 base 187 base
156 envvar default)) 188 envvar default))
157 189
158 (defun paths-find-architecture-directory (roots base &optional envvar default) 190 (defun paths-find-architecture-directory (roots base &optional envvar default)
159 "Find an architecture-specific directory in the XEmacs hierarchy." 191 "Find an architecture-specific directory in the XEmacs hierarchy."
187 "-b" 219 "-b"
188 (substring emacs-version 220 (substring emacs-version
189 (match-beginning 1) (match-end 1))))) 221 (match-beginning 1) (match-end 1)))))
190 (setq paths-path-emacs-version version) 222 (setq paths-path-emacs-version version)
191 version))))) 223 version)))))
192
193 (defun paths-find-emacs-path (roots suffix base &optional envvar default)
194 "Find a path in the XEmacs hierarchy.
195 ROOTS must be a list of installation roots.
196 SUFFIX is the subdirectory from there.
197 BASE is the base to look for.
198 ENVVAR is the name of the environment variable that might also
199 specify the path.
200 DEFAULT is a fall-back value."
201 (let ((envvar-value (and envvar (getenv envvar))))
202 (if envvar-value
203 (decode-path-internal envvar-value)
204 (let ((directory (paths-find-emacs-directory roots base suffix)))
205 (if (and directory (file-directory-p directory))
206 (list directory)
207 (paths-directories-which-exist default))))))
208 224
209 (defun paths-directories-which-exist (directories) 225 (defun paths-directories-which-exist (directories)
210 "Return the directories among DIRECTORIES." 226 "Return the directories among DIRECTORIES."
211 (let ((reverse-directories '())) 227 (let ((reverse-directories '()))
212 (while directories 228 (while directories
225 (setq reverse-survivors (cons (car list-2) reverse-survivors))) 241 (setq reverse-survivors (cons (car list-2) reverse-survivors)))
226 (setq list-2 (cdr list-2))) 242 (setq list-2 (cdr list-2)))
227 (append list-1 243 (append list-1
228 (reverse reverse-survivors)))) 244 (reverse reverse-survivors))))
229 245
230 (defun paths-find-site-path (roots base &optional envvar default) 246 (defun paths-delete (predicate list)
231 "Find a path underneath the site hierarchy." 247 "Delete all matches of PREDICATE from LIST."
232 (paths-find-emacs-path roots "lib/xemacs/" base envvar default)) 248 (let ((reverse-result '()))
233 249 (while list
234 (defun paths-find-version-path (roots base &optional envvar default) 250 (if (not (funcall predicate (car list)))
235 "Find a path underneath the site hierarchy." 251 (setq reverse-result (cons (car list) reverse-result)))
236 (paths-find-emacs-path roots 252 (setq list (cdr list)))
237 (concat "lib/xemacs-" (construct-emacs-version) "/") 253 (nreverse reverse-result)))
238 base 254
239 envvar default)) 255 (defun paths-decode-directory-path (string &optional drop-empties)
240 256 "Split STRING at path separators into a directory list.
257 Non-\"\" comonents are converted into directory form.
258 If DROP-EMPTIES is non-NIL, \"\" components are dropped from the output.
259 Otherwise, they are left alone."
260 (let* ((components (decode-path-internal string))
261 (directories
262 (mapcar #'(lambda (component)
263 (if (string-equal "" component)
264 component
265 (file-name-as-directory component)))
266 components)))
267 (if drop-empties
268 (paths-delete #'(lambda (component)
269 (string-equal "" component))
270 directories)
271 directories)))
272
241 (defun paths-find-emacs-roots (invocation-directory 273 (defun paths-find-emacs-roots (invocation-directory
242 invocation-name) 274 invocation-name)
243 "Find all plausible installation roots for XEmacs." 275 "Find all plausible installation roots for XEmacs."
244 (let ((invocation-root 276 (let ((invocation-root
245 (paths-find-emacs-root invocation-directory invocation-name)) 277 (paths-find-emacs-root invocation-directory invocation-name))