Mercurial > hg > xemacs-beta
comparison lisp/utils/docref.el @ 0:376386a54a3c r19-14
Import from CVS: tag r19-14
author | cvs |
---|---|
date | Mon, 13 Aug 2007 08:45:50 +0200 |
parents | |
children | ac2d302a0011 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:376386a54a3c |
---|---|
1 ;;; docref.el --- Simple cross references for Elisp documentation strings | |
2 ;; Copyright (C) 1994 Free Software Foundation, Inc. | |
3 | |
4 ;; Author: Vadim Geshel <vadik@unas.cs.kiev.ua> | |
5 ;; Created: 12 Jul 1994 | |
6 ;; Keywords: docs, help, lisp | |
7 ;; original name was cross-ref.el. | |
8 | |
9 ;; This file is part of GNU Emacs. | |
10 | |
11 ;; GNU Emacs is free software; you can redistribute it and/or modify | |
12 ;; it under the terms of the GNU General Public License as published by | |
13 ;; the Free Software Foundation; either version 2, or (at your option) | |
14 ;; any later version. | |
15 | |
16 ;; GNU Emacs is distributed in the hope that it will be useful, | |
17 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | |
18 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
19 ;; GNU General Public License for more details. | |
20 | |
21 ;; You should have received a copy of the GNU General Public License | |
22 ;; along with GNU Emacs; see the file COPYING. If not, write to | |
23 ;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. | |
24 | |
25 ;;; Synched up with: FSF 19.30. | |
26 | |
27 ;;; Commentary: | |
28 ;; | |
29 ;; This package allows you to use a simple form of cross references in | |
30 ;; your Emacs Lisp documentation strings. Cross-references look like | |
31 ;; \\(type@[label@]data), where type defines a method for retrieving | |
32 ;; reference informatin, data is used by a method routine as an argument, | |
33 ;; and label "represents" the reference in text. If label is absent, data | |
34 ;; is used instead. | |
35 ;; | |
36 ;; Special reference labeled `back', when present, can be used to return | |
37 ;; to the previous contents of help buffer. | |
38 ;; | |
39 ;; Cross-referencing currently is intended for use in doc strings only | |
40 ;; and works only in temporary buffers (created by `with-output-to-temp-buffer'). | |
41 ;; List of temp buffers in which cross-referencing is to be active is specified | |
42 ;; by variable DOCREF-BUFFERS-LIST, which contains only "*Help*" by default. | |
43 ;; | |
44 ;; Documentation strings for this package's functions and variables can serve | |
45 ;; as examples of usage. | |
46 ;; | |
47 ;;; Customization: | |
48 ;; | |
49 ;; See source. The main customization variable is `docref-methods-alist'. | |
50 ;; It consists of (type . function) pairs, where type is a string which | |
51 ;; corresponds to type in cross-references and function is called with | |
52 ;; one argument - reference `data' - when a reference is activated. | |
53 ;; | |
54 ;;; Installation: | |
55 ;; | |
56 ;; Place this file somewhere in your load-path, byte-compiled it, and add | |
57 ;; (require 'cross-ref) | |
58 ;; to your .emacs. | |
59 | |
60 ;;; Code: | |
61 | |
62 ;; User customizable variables | |
63 | |
64 (defvar docref-highlight-p t | |
65 "*If non-nil, \\(f@docref-subst) highlights cross-references. | |
66 Under window system it highlights them with face defined by | |
67 \\(v@docref-highlight-face), on character terminal highlighted references | |
68 look like cross-references in info mode.") | |
69 | |
70 (defvar docref-highlight-face 'highlight | |
71 "*Face used to highlight cross-references (used by \\(f@docref-subst))") | |
72 | |
73 (defvar docref-methods-alist | |
74 '(("f" . docref-describe-function) ; reference to a function documentation | |
75 ("v" . docref-describe-variable) ; reference to a variable documentation | |
76 ("F" . docref-read-file) ; reference to a file contents | |
77 ("s" . docref-use-string) ; reference to a string | |
78 ("V" . docref-use-variable-value) ; reference to variable value | |
79 ("0" . beep)) ; just highlighted text | |
80 "Alist which maps cross-reference ``types'' to retrieval functions. | |
81 | |
82 The car of each element is a string that serves as `type' in cross-references. | |
83 \(See \\(f@docref-subst)). The cdr is a function of one argument, | |
84 to be called to find this reference.") | |
85 | |
86 (defvar docref-back-label "\nback" | |
87 "Label to use by \\(f@docref-subst) for the go-back reference.") | |
88 | |
89 (defvar docref-back-reference nil | |
90 "If non-nil, this is a go-back reference to add to the current buffer. | |
91 The value specifies how to go back. It should be suitable for use | |
92 as the second argument to \\(f@docref-insert-label). | |
93 \\(f@docref-subst) uses this to set up the go-back reference.") | |
94 | |
95 (defvar docref-last-active-buffer) | |
96 | |
97 ;;;###autoload | |
98 (defun docref-setup () | |
99 "Process docref cross-references in the current buffer. | |
100 See also \\(f@docref-subst)." | |
101 (interactive) | |
102 (docref-subst (current-buffer)) | |
103 (docref-mode)) | |
104 | |
105 (defvar docref-mode-map nil) | |
106 (or docref-mode-map | |
107 (let ((map (make-sparse-keymap))) | |
108 (define-key map [mouse-2] 'docref-follow-mouse) | |
109 (define-key map "\C-c\C-b" 'docref-go-back) | |
110 (define-key map "\C-c\C-c" 'docref-follow) | |
111 (setq docref-mode-map map))) | |
112 | |
113 (defun docref-mode () | |
114 "Major mode for help buffers that contain cross references. | |
115 To follow a reference, move to it and type \\[docref-follow], or use | |
116 \\[docref-follow-mouse]. The command \\[docref-go-back] can used to go | |
117 back to where you came from." | |
118 (interactive) | |
119 (kill-all-local-variables) | |
120 (setq major-mode 'docref-mode) | |
121 (setq mode-name "Docref") | |
122 (use-local-map docref-mode-map) | |
123 (run-hooks 'docref-mode)) | |
124 | |
125 (defun docref-subst (buf) | |
126 "Parse documentation cross-references in buffer BUF. | |
127 | |
128 Find cross-reference information in a buffer and | |
129 highlight them with face defined by \\(v@docref-highlight-face). | |
130 | |
131 Cross-reference has the following format: \\ (TYPE[@LABEL]@DATA), where | |
132 TYPE defines method used to retrive xref data (like reading from file or | |
133 calling \\(f@describe-function)), DATA is an argument to this method | |
134 \(like file name or function name), and LABEL is displayed in text using | |
135 \\(v@docref-highlight-face). | |
136 | |
137 The special reference `back' can be used to return back. | |
138 The variable \\(v@docref-back-label) specifies the label to use for that. | |
139 | |
140 See \\(v@docref-methods-alist) for currently defined methods." | |
141 (interactive "b") | |
142 (save-excursion | |
143 (set-buffer buf) | |
144 (goto-char (point-min)) | |
145 ;; The docref-seen property indicates that we have processed this | |
146 ;; buffer's contents already, so don't do it again. | |
147 (if (not (get-text-property (point-min) 'docref-seen)) | |
148 (let ((old-modified (buffer-modified-p))) | |
149 (while (re-search-forward "[\\](\\([^\)\@]+\\)\\(@[^\)\@]+\\)?@\\([^\)]*\\))" | |
150 nil t) | |
151 (let* ((type (buffer-substring (match-beginning 1) (match-end 1))) | |
152 (data (buffer-substring (match-beginning 3) (match-end 3))) | |
153 (label | |
154 (if (match-beginning 2) | |
155 (buffer-substring (+ (match-beginning 2) 1) (match-end 2)) | |
156 data))) | |
157 (replace-match "" t) | |
158 (docref-insert-label label (cons type data)))) | |
159 | |
160 ;; Make a back-reference in this buffer, if desired. | |
161 ;; (This is true if called from docref-follow.) | |
162 (if docref-back-reference | |
163 (progn | |
164 (goto-char (point-max)) | |
165 (put-text-property (point-min) (1+ (point-min)) | |
166 'docref-back-position (point)) | |
167 (docref-insert-label docref-back-label docref-back-reference))) | |
168 (put-text-property (point-min) (1+ (point-min)) 'docref-seen t) | |
169 (set-buffer-modified-p old-modified))))) | |
170 | |
171 (defun docref-insert-label (string ref) | |
172 (let ((label (concat string))) | |
173 ;; decorate the label | |
174 (let ((leading-space-end (save-match-data | |
175 (if (string-match "^\\([ \t\n]+\\)" label) | |
176 (match-end 1) | |
177 0))) | |
178 (trailing-space-start (save-match-data | |
179 (if (string-match "\\([ \t\n]+\\)$" label) | |
180 (match-beginning 1) | |
181 (length label))))) | |
182 (if docref-highlight-p | |
183 ;; XEmacs: we support faces on TTY's. | |
184 ;; (if (not window-system) | |
185 ;; (setq label | |
186 ;; (concat (substring label 0 leading-space-end) | |
187 ;; "(*note " | |
188 ;; (substring label leading-space-end trailing-space-start) | |
189 ;; ")" | |
190 ;; (substring label trailing-space-start))) | |
191 ;; window-system | |
192 (put-text-property leading-space-end | |
193 trailing-space-start | |
194 'face docref-highlight-face label)) | |
195 (put-text-property 0 (length label) 'docref ref label) | |
196 (insert label)))) | |
197 | |
198 (defun docref-follow-mouse (click) | |
199 "Follow the cross-reference that you click on." | |
200 (interactive "e") | |
201 (save-excursion | |
202 ;; XEmacs changes here. | |
203 (let* ((window (event-window click)) | |
204 (pos (event-point click)) | |
205 (docref-last-active-buffer (current-buffer))) | |
206 (set-buffer (window-buffer window)) | |
207 (docref-follow pos)))) | |
208 | |
209 (defun docref-go-back () | |
210 "Go back to the previous contents of help buffer." | |
211 (interactive) | |
212 (let ((pos (get-text-property (point-min) 'docref-back-position))) | |
213 (if pos | |
214 (docref-follow pos) | |
215 (error "No go-back reference")))) | |
216 | |
217 (defun docref-follow (&optional pos) | |
218 "Follow cross-reference at point. | |
219 For the cross-reference format, see \\(f@docref-subst). | |
220 The special reference named `back' can be used to return back" | |
221 (interactive) | |
222 (or pos (setq pos (point))) | |
223 (let ((docref-data (get-text-property pos 'docref))) | |
224 (if docref-data | |
225 ;; There is a reference at point. Follow it. | |
226 (let* ((type (car docref-data)) | |
227 (name (cdr docref-data)) | |
228 (method (assoc type docref-methods-alist)) | |
229 (cur-contents (buffer-string)) | |
230 (opoint (point)) | |
231 (docref-back-reference (cons "s" cur-contents)) | |
232 success) | |
233 (if (null method) | |
234 (error "Unknown cross-reference type: %s" type)) | |
235 (unwind-protect | |
236 (save-excursion | |
237 (funcall (cdr method) name) | |
238 (setq success t)) | |
239 (or success | |
240 (progn | |
241 ;; (cdr method) got an error. | |
242 ;; Put back the text that we had. | |
243 (erase-buffer) | |
244 (insert cur-contents) | |
245 (goto-char opoint))) | |
246 (set-buffer-modified-p nil)))))) | |
247 | |
248 ;; Builtin methods for accessing a reference. | |
249 | |
250 (defun docref-describe-function (data) | |
251 (save-excursion | |
252 (if (boundp 'docref-last-active-buffer) | |
253 (set-buffer docref-last-active-buffer)) | |
254 (describe-function (intern data)))) | |
255 | |
256 (defun docref-describe-variable (data) | |
257 (save-excursion | |
258 (if (boundp 'docref-last-active-buffer) | |
259 (set-buffer docref-last-active-buffer)) | |
260 (describe-variable (intern data)))) | |
261 | |
262 (defun docref-read-file (data) | |
263 (with-output-to-temp-buffer (buffer-name) | |
264 (erase-buffer) | |
265 (insert-file-contents (expand-file-name data)))) | |
266 | |
267 (defun docref-use-string (data) | |
268 (with-output-to-temp-buffer (buffer-name) | |
269 (erase-buffer) | |
270 (insert data))) | |
271 | |
272 (defun docref-use-variable-value (data) | |
273 (let ((sym (intern data))) | |
274 (with-output-to-temp-buffer (buffer-name) | |
275 (erase-buffer) | |
276 (princ (symbol-value sym))))) | |
277 | |
278 (provide 'docref) | |
279 | |
280 ;;; docref.el ends here | |
281 |