forked from emacsattic/ilocate-library
-
Notifications
You must be signed in to change notification settings - Fork 0
/
ilocate-library.el
308 lines (271 loc) · 11.2 KB
/
ilocate-library.el
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
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
;;; ilocate-library.el --- Interactive replacement for locate-library with completion.
;; ilocate-library.el
;; add minibuffer name completion to locate library
;;
;;
;; Copyright (C) 2001 Michael Slass
;; 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., 59 Temple Place, Suite 330, Boston,
;; MA 02111-1307 USA
;;
;;; Commentary:
;;
;; This package consists of functions to replace
;; `locate-library' and `load-library' with interactive
;; versions that do minibuffer completion.
;;
;; entry points:
;; ilocate-library :
;; locate library in load-path
;; ilocate-library-find-source :
;; locate library, and read the source (.el),
;; if it's available, into a new buffer in
;; the other window
;; ilocate-load-library :
;; interactive load-library with completion
;;
;; All functions use a cached table of libraries found in the
;; `load-path'. The table, `ilocate-library-cache', is
;; generated the first time any of these functions are
;; called, or if the `load-path' has changed since the last
;; invocation of the function. You may force the refreshing
;; of the cache by calling any of the functions with a
;; prefix arg.
;;
;;
;;; History:
;;
;; created by Mike Slass <[email protected]>
;; version 0.6 9/12/2001
;; - fix completing-read-library to handle non-existant directories
;; in the load-path
;;
;; modified by Klaus Berndl <[email protected]>
;; version 0.7 30/07/2002
;; - added a library cache with lazy instantiation. See
;; `ilocate-library-cache'.
;;
;;
;; version 0.8 July 30, 2002 - Mike Slass
;; - incorporated Klaus Berndl's changes (see above)
;; - modified all the ilocate-... interactive functions
;; to accept only one (optional) argument, a prefix arg.
;; With prefix arg, all now force a refresh of
;; `ilocate-library-cache'
;; - modified completing-read-library to accept an
;; optional third argument, reload-cache, to force the
;; refresh
;; - added "Building libraries list ..." message to
;; `ilocate-get-all-libs'
;; - clean up the doc strings
;;
;;
;; version 0.9 31/07/2002
;; modified by Klaus Berndl <[email protected]>
;;
;; - added a mechanism which detects changes of last
;; library-search-path (so also for `load-path' for
;; example) and then rebuilds auto. the
;; `ilocate-library-cache'. See
;; `ilocate-last-search-path-cache'.
;;
;; modified by Mike Slass
;; - incorporated changes and suggestions from
;; Jens Schmidt <[email protected]>:
;; * clean up docs
;; * fix a bug in ilocate-library-find-souce
;; * renamed symbols to all have ilocate prefix:
;; completing-read-library ==>
;; ilocate-completing-read-library
;; iload-library ==>
;; ilocate-load-library
;; - deleted iupdate-library-cache
;;
;;
;; version 0.9.1 09/03/2002 - update maintainer address
;;
;;
;; version 0.9.2 01/14/2012
;; modified by John Yates <[email protected]>
;;
;; - support gzipped files (adjust regexps and doc strings)
;; - visit files in view mode
;;
;; version 0.9.3 01/08/2021
;; modified by John Yates <[email protected]>
;;
;; - add autoload cookies
;; - replace copy-list with cl-copy-list
;;; Code:
(defun ilocate-get-all-libs (&optional search-path)
"Return a table of all Lisp files \(.el[c] or .el[c].gz) in `load-path'.
Optional argument SEARCH-PATH is a list of directory names
to search instead of those listed in `load-path'.
The return value is a table suitable for use as the second
argument to `completing-read'.
See also `ilocate-completing-read-library' and `ilocate-library-cache'."
(message "Building libraries list...")
(mapcar
'list
(let ((lp (or search-path load-path))
(liblist ()))
(progn
(while (car lp)
;; iterate over each directory in the search path
;; skip any directories that don't exist, or the user
;; can't read
(let* ((dir (car lp))
(dirfiles
(and
(file-accessible-directory-p dir)
(directory-files dir nil "\\.elc?\\(\\.gz\\)?$" t))))
(while (car dirfiles)
;; iterate over this directory's files
(let* ((file (car dirfiles))
;; change file name to package name
(package (if (string-match "\\.elc?\\(\\.gz\\)?$" file)
(replace-match "" t nil file)
file)))
;; add the package to the liblist if it's not already there
(if (not (member package liblist))
(setq liblist (cons package liblist))))
(setq dirfiles (cdr dirfiles))))
(setq lp (cdr lp)))
(message "Building libraries list...done")
liblist))))
(defvar ilocate-library-cache nil
"Cached table of Lisp libraries.
Set only by `ilocate-get-all-libs' from `ilocate-completing-read-library'.")
(defvar ilocate-last-search-path-cache nil
"The search path from which `ilocate-library-cache' was built.")
(defun ilocate-completing-read-library (&optional prompt search-path reload-cache)
"Read Lisp library name from minibuffer with completion.
Allows minibuffer completion to the name of any Lisp file
\(.el[c] or .el[c].gz) in the `load-path'.
Optional first argument PROMPT is a prompt string. If nil,
use a default prompt: \"Enter library name: \".
Optional second argument SEARCH-PATH is a list of directory
names to search instead of those listed in `load-path'.
The list of libraries is cached in `ilocate-library-cache',
which is created by `ilocate-get-all-libs' the first time
`ilocate-completing-read-library' is called. The cache is also
rebuilt if the `search-path' has changed since the last
invocation of `ilocate-completing-read-library'
Optional third argument RELOAD-CACHE will force a call to
`ilocate-get-all-libs' to re-scan the `load-path' and
rebuild the cache."
(completing-read-default
(or prompt "Enter library name: " )
;; this argument to completing-read is a table of all
;; the names of packages found in all the directories in
;; the search-path
;; - 7/30/2002
;; - the search of the load-path which was originally
;; here was packaged into ilocate-get-all-libs \(to enable
;; caching of the list ) by Klaus Berndl
;; rebuild the `ilocate-library-cache' if
;; - that's requested by arg 3
;; - it's nil
;; - the `load-path' has changed
(if (or reload-cache
(not ilocate-library-cache)
(not (equal (or search-path load-path)
ilocate-last-search-path-cache)))
(progn
(setq ilocate-last-search-path-cache
(cl-copy-list (or search-path
load-path)))
(setq ilocate-library-cache
(ilocate-get-all-libs search-path)))
ilocate-library-cache)
nil t))
;;;###autoload
(defun ilocate-library (&optional reload-cache)
"Interactive-only version of `locate-library' with name completion.
This function is intended to be a replacement for the
interactive functionality of `locate-library'. It makes a
completion list from all .el, .elc, .el.gz and .elc.gz
files in all the directories in your `load-path'.
The list of libraries is cached in `ilocate-library-cache',
which is generated the first time one of the `ilocate-library'
functions is invoked.
With optional prefix arg, RELOAD-CACHE, force refreshing of
the cache before running this function.
Since the value-add of `ilocate-library' makes sense only as
an interactive feature, this function should not be used in
Lisp programs unless you always want user interaction at
this step. Use `locate-library' otherwise.
See also `ilocate-completing-read-library'."
(interactive "P")
(locate-library
(ilocate-completing-read-library "ilocate library: " nil reload-cache)
nil nil t))
;;;###autoload
(defun ilocate-load-library (&optional reload-cache)
"Interactive-only version of `load-library' with name completion.
This function is intended to be a replacement for the
interactive functionality of `load-library'. It makes a
completion list from all .el, .elc, .el.gz and .elc.gz
files in all the directories in your `load-path'.
The list of libraries is cached in `ilocate-library-cache',
which is generated the first time one of the `ilocate-library'
functions is invoked.
With optional prefix arg, RELOAD-CACHE, force refreshing of
the cache before running this function.
Since the value-add of `ilocate-load-library' makes sense only as an
interactive feature, this function should not be used in
Lisp programs unless you always want user interaction at
this step. Use `load-library' otherwise.
See also `ilocate-completing-read-library'"
(interactive "P")
(load-library
(ilocate-completing-read-library "iload library: " nil reload-cache)))
;;;###autoload
(defun ilocate-library-find-source (&optional reload-cache)
"Prompt with completion for name of a Lisp library, and visit the source.
This function uses list of all .el, .elc, .el.gz and .elc.gz
files in the `load-path', to allow minibuffer completion of
the library name.
The list of libraries is cached in `ilocate-library-cache',
which is generated the first time one of the `ilocate-library'
functions is invoked.
With optional prefix arg, RELOAD-CACHE, force refreshing of
the cache before running this function.
Once the library is located, if it is a compiled Lisp file
\(.elc or .elc.gz), this function looks for the corresponding
.el or .el.gz file in the same directory. If found, it visits
it with `view-file-other-window'. If no .el nor .el.gz file
is not found, an error is returned.
Since the value-add of `ilocate-library-find-source' makes
sense only as an interactive feature, this function should
not be used in Lisp programs unless you always want user
interaction at this step.
See also `ilocate-completing-read-library'"
(interactive "P")
(let* ((library-name (ilocate-completing-read-library
"Find source for library: " nil reload-cache))
;; use locate-library to change the library name
;; into a full path to the library file
(library-file (locate-library library-name))
(source-file (if (string-match "elc?\\(\\.gz\\)?$" library-file)
(replace-match "el" t t library-file)
library-file))
(source-file-gz (concat source-file ".gz")))
(cond
((file-exists-p source-file)
(view-file-other-window (file-truename source-file)))
((file-exists-p source-file-gz)
(view-file-other-window (file-truename source-file-gz)))
(t
(error "Source for %s is not available" library-name)))))
(provide 'ilocate-library)
;;; ilocate-library.el ends here