diff options
| author | Richard M. Stallman | 1995-04-07 21:27:31 +0000 |
|---|---|---|
| committer | Richard M. Stallman | 1995-04-07 21:27:31 +0000 |
| commit | 82e23634bed2b4d871f1a786fdc8fc2f8d1ecb5c (patch) | |
| tree | 83dd3b315cb4638470d70138d595c7a299f5f320 /lisp/docref.el | |
| parent | 1f31a9f1f013180dc3fbd410d33d27785f343e3a (diff) | |
| download | emacs-82e23634bed2b4d871f1a786fdc8fc2f8d1ecb5c.tar.gz emacs-82e23634bed2b4d871f1a786fdc8fc2f8d1ecb5c.zip | |
Initial revision
Diffstat (limited to 'lisp/docref.el')
| -rw-r--r-- | lisp/docref.el | 278 |
1 files changed, 278 insertions, 0 deletions
diff --git a/lisp/docref.el b/lisp/docref.el new file mode 100644 index 00000000000..a10d7e486aa --- /dev/null +++ b/lisp/docref.el | |||
| @@ -0,0 +1,278 @@ | |||
| 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 | ;;; Commentary: | ||
| 26 | ;; | ||
| 27 | ;; This package allows you to use a simple form of cross references in | ||
| 28 | ;; your Emacs Lisp documentation strings. Cross-references look like | ||
| 29 | ;; \\(type@[label@]data), where type defines a method for retrieving | ||
| 30 | ;; reference informatin, data is used by a method routine as an argument, | ||
| 31 | ;; and label "represents" the reference in text. If label is absent, data | ||
| 32 | ;; is used instead. | ||
| 33 | ;; | ||
| 34 | ;; Special reference labeled `back', when present, can be used to return | ||
| 35 | ;; to the previous contents of help buffer. | ||
| 36 | ;; | ||
| 37 | ;; Cross-referencing currently is intended for use in doc strings only | ||
| 38 | ;; and works only in temporary buffers (created by `with-output-to-temp-buffer'). | ||
| 39 | ;; List of temp buffers in which cross-referencing is to be active is specified | ||
| 40 | ;; by variable DOCREF-BUFFERS-LIST, which contains only "*Help*" by default. | ||
| 41 | ;; | ||
| 42 | ;; Documentation strings for this package's functions and variables can serve | ||
| 43 | ;; as examples of usage. | ||
| 44 | ;; | ||
| 45 | ;;; Customization: | ||
| 46 | ;; | ||
| 47 | ;; See source. The main customization variable is `docref-methods-alist'. | ||
| 48 | ;; It consists of (type . function) pairs, where type is a string which | ||
| 49 | ;; corresponds to type in cross-references and function is called with | ||
| 50 | ;; one argument - reference `data' - when a reference is activated. | ||
| 51 | ;; | ||
| 52 | ;;; Installation: | ||
| 53 | ;; | ||
| 54 | ;; Place this file somewhere in your load-path, byte-compiled it, and add | ||
| 55 | ;; (require 'cross-ref) | ||
| 56 | ;; to your .emacs. | ||
| 57 | |||
| 58 | ;;; Code: | ||
| 59 | |||
| 60 | ;; User customizable variables | ||
| 61 | |||
| 62 | (defvar docref-highlight-p t | ||
| 63 | "*If non-nil, \\(f@docref-subst) highlights cross-references. | ||
| 64 | Under window system it highlights them with face defined by | ||
| 65 | \\(v@docref-highlight-face), on character terminal highlighted references | ||
| 66 | look like cross-references in info mode.") | ||
| 67 | |||
| 68 | (defvar docref-highlight-face 'highlight | ||
| 69 | "*Face used to highlight cross-references (used by \\(f@docref-subst))") | ||
| 70 | |||
| 71 | (defvar docref-methods-alist | ||
| 72 | '(("f" . docref-describe-function) ; reference to a function documentation | ||
| 73 | ("v" . docref-describe-variable) ; reference to a variable documentation | ||
| 74 | ("F" . docref-read-file) ; reference to a file contents | ||
| 75 | ("s" . docref-use-string) ; reference to a string | ||
| 76 | ("V" . docref-use-variable-value) ; reference to variable value | ||
| 77 | ("0" . beep)) ; just highlighted text | ||
| 78 | "Alist which maps cross-reference ``types'' to retrieval functions. | ||
| 79 | |||
| 80 | The car of each element is a string that serves as `type' in cross-references. | ||
| 81 | \(See \\(f@docref-subst)). The cdr is a function of one argument, | ||
| 82 | to be called to find this reference.") | ||
| 83 | |||
| 84 | (defvar docref-back-label "\nback" | ||
| 85 | "Label to use by \\(f@docref-subst) for the go-back reference.") | ||
| 86 | |||
| 87 | (defvar docref-back-reference nil | ||
| 88 | "If non-nil, this is a go-back reference to add to the current buffer. | ||
| 89 | The value specifies how to go back. It should be suitable for use | ||
| 90 | as the second argument to \\(f@docref-insert-label). | ||
| 91 | \\(f@docref-subst) uses this to set up the go-back reference.") | ||
| 92 | |||
| 93 | ;;;###autoload | ||
| 94 | (defun docref-setup () | ||
| 95 | "Process docref cross-references in the current buffer. | ||
| 96 | See also \\(f@docref-subst)." | ||
| 97 | (interactive) | ||
| 98 | (docref-subst (current-buffer)) | ||
| 99 | (docref-mode)) | ||
| 100 | |||
| 101 | (defvar docref-mode-map nil) | ||
| 102 | (or docref-mode-map | ||
| 103 | (let ((map (make-sparse-keymap))) | ||
| 104 | (define-key map [mouse-2] 'docref-follow-mouse) | ||
| 105 | (define-key map "\C-c\C-b" 'docref-go-back) | ||
| 106 | (define-key map "\C-c\C-c" 'docref-follow) | ||
| 107 | (setq docref-mode-map map))) | ||
| 108 | |||
| 109 | (defun docref-mode () | ||
| 110 | "Major mode for help buffers that contain cross references. | ||
| 111 | To follow a reference, move to it and type \\[docref-follow], or use | ||
| 112 | \\[docref-follow-mouse]. The command \\[docref-go-back] can used to go | ||
| 113 | back to where you came from." | ||
| 114 | (interactive) | ||
| 115 | (kill-all-local-variables) | ||
| 116 | (setq major-mode 'docref-mode) | ||
| 117 | (setq mode-name "Docref") | ||
| 118 | (use-local-map docref-mode-map) | ||
| 119 | (run-hooks 'docref-mode)) | ||
| 120 | |||
| 121 | (defun docref-subst (buf) | ||
| 122 | "Parse documentation cross-references in buffer BUF. | ||
| 123 | |||
| 124 | Find cross-reference information in a buffer and | ||
| 125 | highlight them with face defined by \\(v@docref-highlight-face). | ||
| 126 | |||
| 127 | Cross-reference has the following format: \\ (TYPE[@LABEL]@DATA), where | ||
| 128 | TYPE defines method used to retrive xref data (like reading from file or | ||
| 129 | calling \\(f@describe-function)), DATA is an argument to this method | ||
| 130 | \(like file name or function name), and LABEL is displayed in text using | ||
| 131 | \\(v@docref-highlight-face). | ||
| 132 | |||
| 133 | The special reference `back' can be used to return back. | ||
| 134 | The variable \\(v@docref-back-label) specifies the label to use for that. | ||
| 135 | |||
| 136 | See \\(v@docref-methods-alist) for currently defined methods." | ||
| 137 | (interactive "b") | ||
| 138 | (save-excursion | ||
| 139 | (set-buffer buf) | ||
| 140 | (goto-char (point-min)) | ||
| 141 | ;; The docref-seen property indicates that we have processed this | ||
| 142 | ;; buffer's contents already, so don't do it again. | ||
| 143 | (if (not (get-text-property (point-min) 'docref-seen)) | ||
| 144 | (let ((old-modified (buffer-modified-p))) | ||
| 145 | (while (re-search-forward "[\\](\\([^\)\@]+\\)\\(@[^\)\@]+\\)?@\\([^\)]*\\))" | ||
| 146 | nil t) | ||
| 147 | (let* ((start (match-beginning 0)) | ||
| 148 | (type (buffer-substring (match-beginning 1) (match-end 1))) | ||
| 149 | (data (buffer-substring (match-beginning 3) (match-end 3))) | ||
| 150 | (label | ||
| 151 | (if (match-beginning 2) | ||
| 152 | (buffer-substring (+ (match-beginning 2) 1) (match-end 2)) | ||
| 153 | data))) | ||
| 154 | (replace-match "" t) | ||
| 155 | (docref-insert-label label (cons type data)))) | ||
| 156 | |||
| 157 | ;; Make a back-reference in this buffer, if desired. | ||
| 158 | ;; (This is true if called from docref-follow.) | ||
| 159 | (if docref-back-reference | ||
| 160 | (progn | ||
| 161 | (goto-char (point-max)) | ||
| 162 | (put-text-property (point-min) (1+ (point-min)) | ||
| 163 | 'docref-back-position (point)) | ||
| 164 | (docref-insert-label docref-back-label docref-back-reference))) | ||
| 165 | (put-text-property (point-min) (1+ (point-min)) 'docref-seen t) | ||
| 166 | (set-buffer-modified-p old-modified))))) | ||
| 167 | |||
| 168 | (defun docref-insert-label (string ref) | ||
| 169 | (let ((label (concat string)) | ||
| 170 | (pos (point))) | ||
| 171 | ;; decorate the label | ||
| 172 | (let ((leading-space-end (save-match-data | ||
| 173 | (if (string-match "^\\([ \t\n]+\\)" label) | ||
| 174 | (match-end 1) | ||
| 175 | 0))) | ||
| 176 | (trailing-space-start (save-match-data | ||
| 177 | (if (string-match "\\([ \t\n]+\\)$" label) | ||
| 178 | (match-beginning 1) | ||
| 179 | (length label))))) | ||
| 180 | (if docref-highlight-p | ||
| 181 | (if (not window-system) | ||
| 182 | (setq label | ||
| 183 | (concat (substring label 0 leading-space-end) | ||
| 184 | "(*note " | ||
| 185 | (substring label leading-space-end trailing-space-start) | ||
| 186 | ")" | ||
| 187 | (substring label trailing-space-start))) | ||
| 188 | ;; window-system | ||
| 189 | (put-text-property leading-space-end | ||
| 190 | trailing-space-start | ||
| 191 | 'face docref-highlight-face label))) | ||
| 192 | (put-text-property 0 (length label) 'docref ref label) | ||
| 193 | (insert label)))) | ||
| 194 | |||
| 195 | (defun docref-follow-mouse (click) | ||
| 196 | "Follow the cross-reference that you click on." | ||
| 197 | (interactive "e") | ||
| 198 | (save-excursion | ||
| 199 | (let* ((start (event-start click)) | ||
| 200 | (window (car start)) | ||
| 201 | (pos (car (cdr start))) | ||
| 202 | (docref-last-active-buffer (current-buffer))) | ||
| 203 | (set-buffer (window-buffer window)) | ||
| 204 | (docref-follow pos)))) | ||
| 205 | |||
| 206 | (defun docref-go-back () | ||
| 207 | "Go back to the previous contents of help buffer." | ||
| 208 | (interactive) | ||
| 209 | (let ((pos (get-text-property (point-min) 'docref-back-position))) | ||
| 210 | (if pos | ||
| 211 | (docref-follow pos) | ||
| 212 | (error "No go-back reference")))) | ||
| 213 | |||
| 214 | (defun docref-follow (&optional pos) | ||
| 215 | "Follow cross-reference at point. | ||
| 216 | For the cross-reference format, see \\(f@docref-subst). | ||
| 217 | The special reference named `back' can be used to return back" | ||
| 218 | (interactive) | ||
| 219 | (or pos (setq pos (point))) | ||
| 220 | (let ((docref-data (get-text-property pos 'docref))) | ||
| 221 | (if docref-data | ||
| 222 | ;; There is a reference at point. Follow it. | ||
| 223 | (let* ((type (car docref-data)) | ||
| 224 | (name (cdr docref-data)) | ||
| 225 | (method (assoc type docref-methods-alist)) | ||
| 226 | (cur-contents (buffer-string)) | ||
| 227 | (opoint (point)) | ||
| 228 | (docref-back-reference (cons "s" cur-contents)) | ||
| 229 | success) | ||
| 230 | (if (null method) | ||
| 231 | (error "Unknown cross-reference type: %s" type)) | ||
| 232 | (unwind-protect | ||
| 233 | (save-excursion | ||
| 234 | (funcall (cdr method) name) | ||
| 235 | (setq success t)) | ||
| 236 | (or success | ||
| 237 | (progn | ||
| 238 | ;; (cdr method) got an error. | ||
| 239 | ;; Put back the text that we had. | ||
| 240 | (erase-buffer) | ||
| 241 | (insert cur-contents) | ||
| 242 | (goto-char opoint))) | ||
| 243 | (set-buffer-modified-p nil)))))) | ||
| 244 | |||
| 245 | ;; Builtin methods for accessing a reference. | ||
| 246 | |||
| 247 | (defun docref-describe-function (data) | ||
| 248 | (save-excursion | ||
| 249 | (if (boundp 'docref-last-active-buffer) | ||
| 250 | (set-buffer docref-last-active-buffer)) | ||
| 251 | (describe-function (intern data)))) | ||
| 252 | |||
| 253 | (defun docref-describe-variable (data) | ||
| 254 | (save-excursion | ||
| 255 | (if (boundp 'docref-last-active-buffer) | ||
| 256 | (set-buffer docref-last-active-buffer)) | ||
| 257 | (describe-variable (intern data)))) | ||
| 258 | |||
| 259 | (defun docref-read-file (data) | ||
| 260 | (with-output-to-temp-buffer (buffer-name) | ||
| 261 | (erase-buffer) | ||
| 262 | (insert-file-contents (expand-file-name data)))) | ||
| 263 | |||
| 264 | (defun docref-use-string (data) | ||
| 265 | (with-output-to-temp-buffer (buffer-name) | ||
| 266 | (erase-buffer) | ||
| 267 | (insert data))) | ||
| 268 | |||
| 269 | (defun docref-use-variable-value (data) | ||
| 270 | (let ((sym (intern data))) | ||
| 271 | (with-output-to-temp-buffer (buffer-name) | ||
| 272 | (erase-buffer) | ||
| 273 | (princ (symbol-value sym))))) | ||
| 274 | |||
| 275 | (provide 'docref) | ||
| 276 | |||
| 277 | ;;; docref.el ends here | ||
| 278 | |||