(directory-files): Use `static-condition-case' instead of `condition-case'.
[elisp/apel.git] / path-util.el
1 ;;; path-util.el --- Emacs Lisp file detection utility
2
3 ;; Copyright (C) 1996,1997,1999 Free Software Foundation, Inc.
4
5 ;; Author: MORIOKA Tomohiko <tomo@m17n.org>
6 ;; Keywords: file detection, install, module
7
8 ;; This file is part of APEL (A Portable Emacs Library).
9
10 ;; This program is free software; you can redistribute it and/or
11 ;; modify it under the terms of the GNU General Public License as
12 ;; published by the Free Software Foundation; either version 2, or (at
13 ;; your option) any later version.
14
15 ;; This program is distributed in the hope that it will be useful, but
16 ;; WITHOUT ANY WARRANTY; without even the implied warranty of
17 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18 ;; General Public License for more details.
19
20 ;; You should have received a copy of the GNU General Public License
21 ;; along with GNU Emacs; see the file COPYING.  If not, write to the
22 ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
23 ;; Boston, MA 02111-1307, USA.
24
25 ;;; Code:
26
27 (eval-when-compile (require 'static))
28
29 (static-condition-case nil
30     (directory-files "." nil nil t)
31   (file-error nil);; unreadable directory.
32   (wrong-number-of-arguments
33    (or (fboundp 'si:directory-files)
34        (fset 'si:directory-files (symbol-function 'directory-files)))
35    ;; This function is also defined in poe-18, but it is needed here
36    ;; for compiling other packages under old Emacsen.
37    (defun directory-files (directory &optional full match nosort)
38      "Return a list of names of files in DIRECTORY.
39 There are three optional arguments:
40 If FULL is non-nil, return absolute file names.  Otherwise return names
41  that are relative to the specified directory.
42 If MATCH is non-nil, mention only file names that match the regexp MATCH.
43 If NOSORT is dummy for compatibility.
44 \[poe-18.el; EMACS 19 emulating function]"
45      (si:directory-files directory full match))
46    ))
47
48 (defvar default-load-path load-path
49   "*Base of `load-path'.
50 It is used as default value of target path to search file or
51 subdirectory under load-path.")
52
53 ;;;###autoload
54 (defun add-path (path &rest options)
55   "Add PATH to `load-path' if it exists under `default-load-path'
56 directories and it does not exist in `load-path'.
57
58 You can use following PATH styles:
59         load-path relative: \"PATH/\"
60                         (it is searched from `defaul-load-path')
61         home directory relative: \"~/PATH/\" \"~USER/PATH/\"
62         absolute path: \"/HOO/BAR/BAZ/\"
63
64 You can specify following OPTIONS:
65         'all-paths      search from `load-path'
66                         instead of `default-load-path'
67         'append         add PATH to the last of `load-path'"
68   (let ((rest (if (memq 'all-paths options)
69                   load-path
70                 default-load-path))
71         p)
72     (if (and (catch 'tag
73                (while rest
74                  (setq p (expand-file-name path (car rest)))
75                  (if (file-directory-p p)
76                      (throw 'tag p)
77                    )
78                  (setq rest (cdr rest))
79                  ))
80              (not (member p load-path))
81              )
82         (setq load-path
83               (if (memq 'append options)
84                   (append load-path (list p))
85                 (cons p load-path)
86                 ))
87       )))
88
89 ;;;###autoload
90 (defun add-latest-path (pattern &optional all-paths)
91   "Add latest path matched by PATTERN to `load-path'
92 if it exists under `default-load-path' directories
93 and it does not exist in `load-path'.
94
95 If optional argument ALL-PATHS is specified, it is searched from all
96 of load-path instead of default-load-path."
97   (let ((path (get-latest-path pattern all-paths)))
98     (if path
99         (add-to-list 'load-path path)
100       )))
101
102 ;;;###autoload
103 (defun get-latest-path (pattern &optional all-paths)
104   "Return latest directory in default-load-path
105 which is matched to regexp PATTERN.
106 If optional argument ALL-PATHS is specified,
107 it is searched from all of load-path instead of default-load-path."
108   (catch 'tag
109     (let ((paths (if all-paths
110                     load-path
111                   default-load-path))
112           dir)
113       (while (setq dir (car paths))
114         (if (and (file-exists-p dir)
115                  (file-directory-p dir)
116                  )
117             (let ((files (sort (directory-files dir t pattern t)
118                                (function file-newer-than-file-p)))
119                   file)
120               (while (setq file (car files))
121                 (if (file-directory-p file)
122                     (throw 'tag file)
123                   )
124                 (setq files (cdr files))
125                 )))
126         (setq paths (cdr paths))
127         ))))
128
129 ;;;###autoload
130 (defun file-installed-p (file &optional paths)
131   "Return absolute-path of FILE if FILE exists in PATHS.
132 If PATHS is omitted, `load-path' is used."
133   (if (null paths)
134       (setq paths load-path)
135     )
136   (catch 'tag
137     (let (path)
138       (while paths
139         (setq path (expand-file-name file (car paths)))
140         (if (file-exists-p path)
141             (throw 'tag path)
142           )
143         (setq paths (cdr paths))
144         ))))
145
146 ;;;###autoload
147 (defvar exec-suffix-list '("")
148   "*List of suffixes for executable.")
149
150 ;;;###autoload
151 (defun exec-installed-p (file &optional paths suffixes)
152   "Return absolute-path of FILE if FILE exists in PATHS.
153 If PATHS is omitted, `exec-path' is used.
154 If suffixes is omitted, `exec-suffix-list' is used."
155   (or paths
156       (setq paths exec-path)
157       )
158   (or suffixes
159       (setq suffixes exec-suffix-list)
160       )
161   (catch 'tag
162     (while paths
163       (let ((stem (expand-file-name file (car paths)))
164             (sufs suffixes)
165             )
166         (while sufs
167           (let ((file (concat stem (car sufs))))
168             (if (file-exists-p file)
169                 (throw 'tag file)
170               ))
171           (setq sufs (cdr sufs))
172           ))
173       (setq paths (cdr paths))
174       )))
175
176 ;;;###autoload
177 (defun module-installed-p (module &optional paths)
178   "Return t if module is provided or exists in PATHS.
179 If PATHS is omitted, `load-path' is used."
180   (or (featurep module)
181       (exec-installed-p (symbol-name module) load-path '(".elc" ".el"))
182       ))
183
184
185 ;;; @ end
186 ;;;
187
188 (provide 'path-util)
189
190 ;;; path-util.el ends here