Mercurial > hg > xemacs-beta
comparison lisp/utils/browse-cltl2.el @ 22:8fc7fe29b841 r19-15b94
Import from CVS: tag r19-15b94
author | cvs |
---|---|
date | Mon, 13 Aug 2007 08:50:29 +0200 |
parents | |
children | 4103f0995bd7 |
comparison
equal
deleted
inserted
replaced
21:b88636d63495 | 22:8fc7fe29b841 |
---|---|
1 ; -*- Mode: Emacs-Lisp -*- | |
2 ;;; browse-cltl2.el --- browse the hypertext-version of | |
3 ;;; "Common Lisp the Language, 2nd. Edition" | |
4 | |
5 ;; Revision 1.1.1 | |
6 ;; last edited on 29.1.1997 | |
7 | |
8 ;; Copyright (C) 1997 Holger Schauer | |
9 | |
10 ;; Author: Holger Schauer <Holger.Schauer@gmd.de> | |
11 ;; Keywords: utils lisp ilisp | |
12 | |
13 ;; This file is not part of Emacs. | |
14 | |
15 ;; Developed under XEmacs 19.14. Also tested on Emacs 19.32 and | |
16 ;; XEmacs 19.11. Should work with newer versions, too. | |
17 ;; Required: browse-url.el | |
18 ;; Recommended: url.el | |
19 | |
20 ;; This program is free software; you can redistribute it and/or modify | |
21 ;; it under the terms of the GNU General Public License as published by | |
22 ;; the Free Software Foundation; either version 2 of the License, or | |
23 ;; (at your option) any later version. | |
24 ;; | |
25 ;; This program is distributed in the hope that it will be useful, | |
26 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | |
27 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
28 ;; GNU General Public License for more details. | |
29 ;; | |
30 ;; You should have received a copy of the GNU General Public License | |
31 ;; along with this program; if not, write to the Free Software | |
32 ;; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |
33 | |
34 ;;; Commentary: | |
35 ;; This gives you two top-level-functions useful when programming lisp: | |
36 ;; cltl2-view-function-definition and cltl2-view-index | |
37 ;; cltl2-view-function-definition asks you for a name of a lisp | |
38 ;; function (or variable) and will open up your favourite browser | |
39 ;; (as specified by `browse-url-browser-function') loading the page | |
40 ;; which documents it. | |
41 | |
42 ;;; Installation: (as usual) | |
43 ;; Put browse-cltl2.el somewhere where emacs can find it. | |
44 ;; browse-cltl2.el requires a working browse-url, url and cl. | |
45 ;; Insert the following lines in your .emacs: | |
46 ;; | |
47 ;; (autoload 'cltl2-view-function-definition "browse-cltl2") | |
48 ;; (autoload 'cltl2-view-index "browse-cltl2") | |
49 ;; (autoload 'cltl2-lisp-mode-install "browse-cltl2") | |
50 ;; (add-hook 'lisp-mode-hook 'cltl2-lisp-mode-install) | |
51 ;; (add-hook 'ilisp-mode-hook 'cltl2-lisp-mode-install) | |
52 ;; | |
53 ;; This should also add the needed hooks to lisp-mode (and ilisp-mode). | |
54 | |
55 ;; Gnu Emacs: | |
56 ;; For Gnu Emacs there doesn't seem to be a lisp-mode-hook so you're | |
57 ;; on your own with the key-settings. | |
58 ;; No url.el: | |
59 ;; If you don't have url.el set *cltl2-use-url* to nil | |
60 ;; and set *cltl2-fetch-method* to 'local or 'local-index-only. | |
61 ;; This implies that you need a local copy of the index page of | |
62 ;; CLtL2 (which you can get from the normal hypertext-version at CMU), | |
63 ;; so you need to point *cltl2-local-file-pos* and *cltl2-index-file-name* | |
64 ;; to the place where you put it. | |
65 ;; Old versions of Emacs (XEmacs 19.11 for example): | |
66 ;; When you want to use a local copy (or a local copy of the index file) | |
67 ;; check the documentation on find-file-noselect. If it doesn't mention | |
68 ;; an option called RAWFILE set *cltl2-old-find-file-noselect* to 't. | |
69 | |
70 | |
71 ;;; Customization: | |
72 ;; By default, browse-cltl2 will use a local copy of CLtL2, looking | |
73 ;; for it in /usr/doc/html/cltl. This can be modified with the help | |
74 ;; of the following variables: | |
75 ;; *cltl2-fetch-method*, *cltl2-url*, *cltl-local-file-pos* | |
76 ;; See the documentation on this variables for more info. | |
77 ;; | |
78 ;;; TODO: | |
79 ;; In this version we can't separate between functions, variables, | |
80 ;; constants and loop clauses. This is not that hard to change, | |
81 ;; but it is more difficult to distinguish what the user is | |
82 ;; looking for. Until I receive several requests for it, I won't | |
83 ;; implement it, because there are not that much constructs like * and + | |
84 ;; which have two (or more) semantics. | |
85 | |
86 ;;; Changes: | |
87 ;; 28-01-97: HS: now we're using cl-puthash all over the place because | |
88 ;; this is common on XEmacs 19.11 and upwards and Gnu Emacs. | |
89 ;; Added information on how to install without url.el | |
90 ;; | |
91 ;; 29-01-97 HS: included conditionalized versions of the required | |
92 ;; functions match-string and buffer-live-p. | |
93 ;; Suggested by Simon Marshall <Simon.Marshall@esrin.esa.it>. | |
94 ;; Included new variable *cltl2-use-url* with which one can | |
95 ;; specify if he has url.el or not. Introduced variable | |
96 ;; *cltl2-old-find-file-noselect*. | |
97 (defvar *cltl2-use-url* 'nil | |
98 "Enables or disables retrieval of the index-file via WWW (or more | |
99 exactly by the use of the function url-retrieve from url.el). | |
100 Default is 't.") | |
101 | |
102 ;; needed things | |
103 (require 'cl) | |
104 (require 'browse-url) | |
105 | |
106 (when (not *cltl2-use-url*) | |
107 (require 'url)) | |
108 | |
109 ;;; ****************************** | |
110 ;;; Some variable and constant definitions | |
111 ;;; ****************************** | |
112 (defvar *cltl2-fetch-method* 'local | |
113 "This sets the method by which the index-file will be fetched. Three | |
114 methods are possible: 'local assumes that all files are local. | |
115 'local-index-only assumes that just the index-file is locally but | |
116 all other files will be fetched via www. 'www means that the index-file | |
117 will be fetched via WWW, too. Don't change the value of this variable | |
118 after loading.") | |
119 | |
120 (defvar *cltl2-url* | |
121 "http://www.cs.cmu.edu/afs/cs.cmu.edu/project/ai-repository/ai/html/cltl/" | |
122 "The url where the hypertext-version of Common Lisp the Language | |
123 can be found. Note that this assumes to be the top-level of the | |
124 directory structure which should be the same as in the hypertext | |
125 version as provided by the CMU AI Repository. Defaults to | |
126 http://www.cs.cmu.edu/afs/cs.cmu.edu/project/ai-repository/ai/html/cltl/ | |
127 Note the / at the end.") | |
128 | |
129 (defvar *cltl2-local-file-pos* "/usr/doc/html/cltl/" | |
130 "A directory where the CLtl2 can be found. Note that this assumes | |
131 to be the top-level of the directory structure which should be the | |
132 same as in the hypertext version as provided by the CMU AI Repository. | |
133 Defaults to /usr/doc/html/cltl/ Note the / at the end.") | |
134 | |
135 (defconst *cltl2-index-file-name* "clm/index.html" | |
136 "The name of the index-file, typically with directory on front. | |
137 Defaults to clm/index.html, as this is the momentary position from | |
138 the top-level directory of the CLtL2-home. Defaults to clm/index.html. | |
139 Note that there is no leading /.") | |
140 | |
141 (defvar *cltl2-index-home* | |
142 (concatenate 'string | |
143 (case *cltl2-fetch-method* | |
144 ('local *cltl2-local-file-pos*) | |
145 ('local-index-only *cltl2-local-file-pos*) | |
146 ('www *cltl2-url*)) | |
147 *cltl2-index-file-name*) | |
148 "The absolute path which will be used to fetch the index.") | |
149 | |
150 (defvar *cltl2-home* | |
151 (concatenate | |
152 'string | |
153 (case *cltl2-fetch-method* | |
154 ('local *cltl2-local-file-pos*) | |
155 ('local-index-only *cltl2-url*) | |
156 ('www *cltl2-url*)) | |
157 "clm/") | |
158 "This specifies the home-position of the CLtL2. The value of this variable | |
159 will be concatenated with the name of the nodes of the CLtL2.") | |
160 | |
161 (defvar *cltl2-index-buffer-name* "*cltl2-index*" | |
162 "The name of the buffer which holds the index for CLtL2.") | |
163 | |
164 (defvar *cltl2-old-find-file-noselect* 'nil | |
165 "Older versions of Emacs (at least XEmacs 19.11) don't support the | |
166 option RAWFILE with the function FIND-FILE-NO-SELECT. Set this variable | |
167 to 't if you have such an old version. It will cause fontification and | |
168 other useless stuff on the buffer in which the index is fetched. If | |
169 you don't use a local copy (of the index) this won't bother you.") | |
170 | |
171 (defvar *browse-cltl2-ht* (make-hash-table 0)) | |
172 (defconst *cltl2-search-regexpr* | |
173 "<a href=\"\\(.+\\)\"><code>\\(.+\\)</code></a>" | |
174 "A regular expression how to check for entries in the index-file | |
175 of CLtL2. Note that you have to modify this and the | |
176 prepare-get-entry*-functions if you want to change the search.") | |
177 | |
178 ;;; ****************************** | |
179 ;;; First of all: Compatibility stuff | |
180 ;;; ****************************** | |
181 ; no match-string in old versions | |
182 (if (not (fboundp (function match-string))) | |
183 (defun match-string (num &optional string) | |
184 "Return string of text matched by last search. | |
185 NUM specifies which parenthesized expression in the last regexp. | |
186 Value is nil if NUMth pair didn't match, or there were less than NUM pairs. | |
187 Zero means the entire text matched by the whole regexp or whole string. | |
188 STRING should be given if the last search was by `string-match' on STRING." | |
189 (if (match-beginning num) | |
190 (if string | |
191 (substring string (match-beginning num) (match-end num)) | |
192 (buffer-substring | |
193 (match-beginning num) (match-end num)))))) | |
194 | |
195 ; no buffer-live-p in old versions | |
196 (if (not (fboundp (function buffer-live-p))) | |
197 (defun buffer-live-p (buf-or-name) | |
198 "Checks if BUF-OR-NAME is a live buffer. Returns non-nil | |
199 if BOF-OR-NAME is an editor buffer which has not been deleted. | |
200 Imitating a built-in function from newer Emacs versions." | |
201 (let ((object (if (bufferp buf-or-name) | |
202 buf-or-name | |
203 (get-buffer buf-or-name)))) | |
204 (and (bufferp object) (buffer-name object))))) | |
205 | |
206 ; no add-submenu in old versions of XEmacs | |
207 (if (and (string-match "XEmacs\\|Lucid" emacs-version) | |
208 (not (fboundp 'add-submenu))) | |
209 (defun add-submenu (menu-path submenu &optional before) | |
210 "Add a menu to the menubar or one of its submenus. | |
211 If the named menu exists already, it is changed. | |
212 MENU-PATH identifies the menu under which the new menu should be inserted. | |
213 It is a list of strings; for example, (\"File\") names the top-level \"File\" | |
214 menu. (\"File\" \"Foo\") names a hypothetical submenu of \"File\". | |
215 If MENU-PATH is nil, then the menu will be added to the menubar itself. | |
216 SUBMENU is the new menu to add. | |
217 See the documentation of `current-menubar' for the syntax. | |
218 BEFORE, if provided, is the name of a menu before which this menu should | |
219 be added, if this menu is not on its parent already. If the menu is already | |
220 present, it will not be moved." | |
221 (add-menu menu-path (car submenu) (cdr submenu) before))) | |
222 | |
223 ; old find-file-noselect has no RAWFILE argument | |
224 (if *cltl2-old-find-file-noselect* | |
225 (unless (boundp 'cltl2-old-find-file-noselect-func) | |
226 (setf (symbol-value 'cltl2-old-find-file-noselect-func) | |
227 (symbol-function 'find-file-noselect)) | |
228 (setf (symbol-function 'find-file-noselect) | |
229 #'(lambda (file &optional nowarn rawfile) | |
230 (funcall cltl2-old-find-file-noselect-func file nowarn))))) | |
231 | |
232 ;;; ****************************** | |
233 ;;; Functions for fetching the index file | |
234 ;;; ****************************** | |
235 (defun cltl2-fetch-index () | |
236 "Fetches the index page of the CLtl2 and puts it in its own | |
237 buffer called *cltl2-index*." | |
238 ;; if the index isn't here load it into a buffer | |
239 (when (or (not (get-buffer *cltl2-index-buffer-name*)) | |
240 (not (buffer-live-p *cltl2-index-buffer-name*))) | |
241 (message "Fetching the CLtL2 index file ...") | |
242 (case *cltl2-fetch-method* | |
243 ('local | |
244 (cltl2-fetch-index-by-file)) | |
245 ('local-index-only | |
246 (cltl2-fetch-index-by-file)) | |
247 ('www | |
248 (cltl2-fetch-index-by-www)))) | |
249 | |
250 (cltl2-prepare-index) | |
251 ) | |
252 | |
253 ;; fetch methods | |
254 (defun cltl2-fetch-index-by-file () | |
255 "Fetch the index from disk." | |
256 (setf *cltl2-index-buffer-name* | |
257 (find-file-noselect *cltl2-index-home* 'nil 't)) | |
258 ) | |
259 | |
260 (defun cltl2-fetch-index-by-www () | |
261 "Fetch the index via WWW." | |
262 (save-excursion | |
263 (let ((old-url-working-buffer url-working-buffer)) | |
264 (setf url-working-buffer *cltl2-index-buffer-name*) | |
265 (url-retrieve *cltl2-index-home*) | |
266 (setf url-working-buffer old-url-working-buffer)))) | |
267 | |
268 | |
269 ;;; ****************************** | |
270 ;;; Main functions for viewing | |
271 ;;; ****************************** | |
272 (defun cltl2-view-function-definition (entry) | |
273 "First checks if function can be found in the CLtL2-index-file. | |
274 If it can be found, uses the function browse-url to have a look | |
275 at the corresponding documentation from CLtL2." | |
276 (interactive "sCLtL2-Entry to lookup:") | |
277 (when (cltl2-index-unprepared-p) | |
278 (cltl2-fetch-index)) | |
279 | |
280 (let ((entry-url (cltl2-find-url-for-function (intern entry)))) | |
281 (when entry-url | |
282 (message "Loading found entry for %s into browser.." entry) | |
283 (browse-url | |
284 (concatenate 'string *cltl2-home* entry-url))))) | |
285 | |
286 (defun cltl2-find-url-for-function (entry) | |
287 "Checks if we can find a page for function ENTRY and | |
288 constructs an URL from it." | |
289 (let ((entry-url (gethash entry *browse-cltl2-ht*))) | |
290 (when (not entry-url) | |
291 (error "No entry in CLtL2 for %s" entry)) | |
292 entry-url)) | |
293 | |
294 (defun cltl2-view-index () | |
295 "Browse-urls the index file." | |
296 (interactive) | |
297 (browse-url *cltl2-index-home*)) | |
298 | |
299 ;;; ****************************** | |
300 ;;; Preparing the index (the hashtable) | |
301 ;;; ****************************** | |
302 (defun cltl2-prepare-index () | |
303 "Jumps to the *cltl2-index* buffer and scans it, creating a hashtable | |
304 for all entries." | |
305 (message "Preparing CLtL2 index.") | |
306 (save-excursion | |
307 (set-buffer *cltl2-index-buffer-name*) | |
308 (goto-char (point-min)) | |
309 | |
310 ; search for entry | |
311 (do ((point (re-search-forward | |
312 *cltl2-search-regexpr* | |
313 nil t) | |
314 (re-search-forward | |
315 *cltl2-search-regexpr* | |
316 nil t))) | |
317 ; until we can't find anymore | |
318 ((null point)); (format "Index-preparation done.")) | |
319 ; put found entry in hash-table | |
320 (cl-puthash | |
321 (cltl2-prepare-get-entry-name) | |
322 (cltl2-prepare-get-entry-url) | |
323 *browse-cltl2-ht*)))) | |
324 | |
325 (defun cltl2-prepare-get-entry-name () | |
326 "Get the enrty name from the last match of regexp-search for entries." | |
327 (let ((name-string (intern (match-string 2)))) | |
328 (format "%s" name-string) | |
329 name-string)) | |
330 | |
331 (defun cltl2-prepare-get-entry-url () | |
332 "Get the enrty url from the last match of regexp-search for entries." | |
333 (let ((url (match-string 1))) | |
334 (format "%s" url) | |
335 url)) | |
336 | |
337 (defun cltl2-index-unprepared-p () | |
338 "Check if the index is already prepared." | |
339 ; If the hashtable has entries the index is prepared. | |
340 (not (and (hash-table-p *browse-cltl2-ht*) | |
341 (>= (hash-table-count *browse-cltl2-ht*) 1)))) | |
342 | |
343 ;;; ****************************** | |
344 ;;; Hooking into lisp mode and ilisp-mode | |
345 ;;; ****************************** | |
346 (defun cltl2-lisp-mode-install () | |
347 "Not to be called by the user - just for lisp-mode-hook and ilisp-mode-hook. | |
348 | |
349 Adds browse-cltl2 to lisp-mode. If you use ilisp (installed via a hook | |
350 on lisp-mode) add browse-cltl2 to ilisp. Under Ilisp we use C-zb and C-zB | |
351 and without Ilisp we use C-cb and C-cB for calling the cltl2-view-functions. | |
352 Under XEmacs we will add ourself to the corresponding menus if there exists | |
353 one.." | |
354 ; set key bindings | |
355 (cond ((featurep 'ilisp) | |
356 (local-set-key "\C-zb" 'cltl2-view-function-definition) | |
357 (local-set-key "\C-zB" 'cltl2-view-index)) | |
358 (t | |
359 (local-set-key "\C-cb" 'cltl2-view-function-definition) | |
360 (local-set-key "\C-cB" 'cltl2-view-index))) | |
361 ; under XEmacs hook ourself into the menu if there is one | |
362 (when (string-match "XEmacs\\|Lucid" emacs-version) | |
363 ; this is for the menu as provided by ilisp-easy-menu | |
364 (cond ((not (null (car (find-menu-item current-menubar '("ILisp"))))) | |
365 (add-submenu | |
366 '("ILisp" "Documentation") | |
367 '("Browse CLtL2" | |
368 [ "View entry" cltl2-view-function-definition t] | |
369 [ "View index" cltl2-view-index t] ))) | |
370 ((not (null (car (find-menu-item current-menubar '("Lisp"))))) | |
371 (add-submenu | |
372 '("Lisp") | |
373 '("Browse CLtL2" | |
374 [ "View entry" cltl2-view-function-definition t] | |
375 [ "View index" cltl2-view-index t] ))))) | |
376 ) | |
377 | |
378 (add-hook 'lisp-mode-hook 'cltl2-lisp-mode-install) | |
379 (add-hook 'ilisp-mode-hook 'cltl2-lisp-mode-install) | |
380 | |
381 ;;; Providing ourself. | |
382 (provide 'ilisp-browse-cltl2) | |
383 ;;; browse-cltl2.el ends here. |