diff options
| author | David Engster | 2014-01-08 22:59:19 +0100 |
|---|---|---|
| committer | David Engster | 2014-01-08 22:59:19 +0100 |
| commit | 0116ee837aed1f34fe406febc991db00c22ee073 (patch) | |
| tree | 8505681f872a17621fa08be26be11553a276eb52 | |
| parent | 4b9e6087a01a5d92299ecfac806b5dc533e0529c (diff) | |
| parent | 0f918d96d79265531f65fd37a81e73b240f8f3d5 (diff) | |
| download | emacs-0116ee837aed1f34fe406febc991db00c22ee073.tar.gz emacs-0116ee837aed1f34fe406febc991db00c22ee073.zip | |
Proper help support for EIEIO classes and methods.
| -rw-r--r-- | lisp/ChangeLog | 30 | ||||
| -rw-r--r-- | lisp/emacs-lisp/eieio-opt.el | 553 | ||||
| -rw-r--r-- | lisp/emacs-lisp/eieio.el | 4 | ||||
| -rw-r--r-- | lisp/help-fns.el | 17 |
4 files changed, 268 insertions, 336 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog index 8d36ae9911f..b7b5c621e40 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog | |||
| @@ -1,3 +1,33 @@ | |||
| 1 | 2014-01-08 David Engster <deng@randomsample.de> | ||
| 2 | |||
| 3 | * help-fns.el (help-fns-describe-function-functions): New | ||
| 4 | variable to call functions for augmenting help buffers. | ||
| 5 | (describe-function-1): Remove explicit calls to | ||
| 6 | `help-fns--compiler-macro', `help-fns--parent-mode' and | ||
| 7 | `help-fns--obsolete'. Put them in above new variable instead, and | ||
| 8 | call them through `run-hook-with-args'. | ||
| 9 | * emacs-lisp/eieio-opt.el (eieio-help-class): Rename from | ||
| 10 | `eieio-describe-class'. Not meant for interactive use anymore, | ||
| 11 | but to augment existing help buffers. Remove optional second | ||
| 12 | argument. Create proper button for file location. Rewrite | ||
| 13 | function to use `insert' instead of `princ' and `prin1' where | ||
| 14 | possible. | ||
| 15 | (eieio-help-class-slots): Rename from `eieio-describe-class-slots'. | ||
| 16 | (eieio-method-def, eieio-class-def): Move further up. | ||
| 17 | (describe-method, describe-generic, eieio-describe-method): Remove | ||
| 18 | aliases. | ||
| 19 | (eieio-help-constructor, eieio-help-generic): Rename from | ||
| 20 | `eieio-describe-constructor' and `eieio-describe-generic', resp. | ||
| 21 | Rewrite to use `insert' in the current buffer and use proper help | ||
| 22 | buttons. | ||
| 23 | (eieio-help-find-method-definition) | ||
| 24 | (eieio-help-find-class-definition): Also accept symbols as | ||
| 25 | arguments. | ||
| 26 | (eieio-help-mode-augmentation-maybee): Remove. | ||
| 27 | (eieio-describe-class-sb): Use `describe-function'. | ||
| 28 | * emacs-lisp/eieio.el (help-fns-describe-function-functions): Add | ||
| 29 | `eieio-help-generic' and `eieio-help-constructor'. | ||
| 30 | |||
| 1 | 2014-01-08 Paul Eggert <eggert@cs.ucla.edu> | 31 | 2014-01-08 Paul Eggert <eggert@cs.ucla.edu> |
| 2 | 32 | ||
| 3 | Spelling fixes. | 33 | Spelling fixes. |
diff --git a/lisp/emacs-lisp/eieio-opt.el b/lisp/emacs-lisp/eieio-opt.el index 647bbb344b1..9269c744b9f 100644 --- a/lisp/emacs-lisp/eieio-opt.el +++ b/lisp/emacs-lisp/eieio-opt.el | |||
| @@ -74,108 +74,81 @@ Argument CH-PREFIX is another character prefix to display." | |||
| 74 | 74 | ||
| 75 | ;;; CLASS COMPLETION / DOCUMENTATION | 75 | ;;; CLASS COMPLETION / DOCUMENTATION |
| 76 | 76 | ||
| 77 | ;;;###autoload(defalias 'describe-class 'eieio-describe-class) | ||
| 78 | |||
| 79 | ;;;###autoload | 77 | ;;;###autoload |
| 80 | (defun eieio-describe-class (class &optional headerfcn) | 78 | (defun eieio-help-class (class) |
| 81 | "Describe a CLASS defined by a string or symbol. | 79 | "Print help description for CLASS. |
| 82 | If CLASS is actually an object, then also display current values of that object. | 80 | If CLASS is actually an object, then also display current values of that object." |
| 83 | Optional HEADERFCN should be called to insert a few bits of info first." | 81 | ;; Header line |
| 84 | (interactive (list (eieio-read-class "Class: "))) | 82 | (prin1 class) |
| 85 | (with-output-to-temp-buffer (help-buffer) ;"*Help*" | 83 | (insert " is a" |
| 86 | (help-setup-xref (list #'eieio-describe-class class headerfcn) | 84 | (if (class-option class :abstract) |
| 87 | (called-interactively-p 'interactive)) | 85 | "n abstract" |
| 88 | 86 | "") | |
| 89 | (when headerfcn (funcall headerfcn)) | 87 | " class") |
| 90 | (prin1 class) | 88 | (let ((location (get class 'class-location))) |
| 91 | (princ " is a") | 89 | (when location |
| 92 | (if (class-option class :abstract) | 90 | (insert " in `") |
| 93 | (princ "n abstract")) | 91 | (help-insert-xref-button |
| 94 | (princ " class") | 92 | (file-name-nondirectory location) |
| 95 | ;; Print file location | 93 | 'eieio-class-def class location) |
| 96 | (when (get class 'class-location) | 94 | (insert "'"))) |
| 97 | (princ " in `") | 95 | (insert ".\n") |
| 98 | (princ (file-name-nondirectory (get class 'class-location))) | 96 | ;; Parents |
| 99 | (princ "'")) | 97 | (let ((pl (eieio-class-parents class)) |
| 100 | (terpri) | 98 | cur) |
| 101 | ;; Inheritance tree information | 99 | (when pl |
| 102 | (let ((pl (eieio-class-parents class))) | 100 | (insert " Inherits from ") |
| 103 | (when pl | 101 | (while (setq cur (pop pl)) |
| 104 | (princ " Inherits from ") | 102 | (insert "`") |
| 105 | (while pl | 103 | (help-insert-xref-button (symbol-name cur) |
| 106 | (princ "`") (prin1 (car pl)) (princ "'") | 104 | 'help-function cur) |
| 107 | (setq pl (cdr pl)) | 105 | (insert (if pl "', " "'"))) |
| 108 | (if pl (princ ", "))) | 106 | (insert ".\n"))) |
| 109 | (terpri))) | 107 | ;; Children |
| 110 | (let ((ch (eieio-class-children class))) | 108 | (let ((ch (eieio-class-children class)) |
| 111 | (when ch | 109 | cur) |
| 112 | (princ " Children ") | 110 | (when ch |
| 113 | (while ch | 111 | (insert " Children ") |
| 114 | (princ "`") (prin1 (car ch)) (princ "'") | 112 | (while (setq cur (pop ch)) |
| 115 | (setq ch (cdr ch)) | 113 | (insert "`") |
| 116 | (if ch (princ ", "))) | 114 | (help-insert-xref-button (symbol-name cur) |
| 117 | (terpri))) | 115 | 'help-function cur) |
| 118 | (terpri) | 116 | (insert (if ch "', " "'"))) |
| 119 | ;; System documentation | 117 | (insert ".\n"))) |
| 120 | (let ((doc (documentation-property class 'variable-documentation))) | 118 | ;; System documentation |
| 121 | (when doc | 119 | (let ((doc (documentation-property class 'variable-documentation))) |
| 122 | (princ "Documentation:") | 120 | (when doc |
| 123 | (terpri) | 121 | (insert "\n" doc "\n\n"))) |
| 124 | (princ doc) | 122 | ;; Describe all the slots in this class. |
| 125 | (terpri) | 123 | (eieio-help-class-slots class) |
| 126 | (terpri))) | 124 | ;; Describe all the methods specific to this class. |
| 127 | ;; Describe all the slots in this class | 125 | (let ((methods (eieio-all-generic-functions class)) |
| 128 | (eieio-describe-class-slots class) | 126 | (type [":STATIC" ":BEFORE" ":PRIMARY" ":AFTER"]) |
| 129 | ;; Describe all the methods specific to this class. | 127 | counter doc argshl dochl) |
| 130 | (let ((methods (eieio-all-generic-functions class)) | 128 | (when methods |
| 131 | (doc nil)) | 129 | (insert (propertize "Specialized Methods:\n\n" 'face 'bold)) |
| 132 | (if (not methods) nil | 130 | (while methods |
| 133 | (princ "Specialized Methods:") | 131 | (setq doc (eieio-method-documentation (car methods) class)) |
| 134 | (terpri) | 132 | (insert "`") |
| 135 | (terpri) | 133 | (help-insert-xref-button (symbol-name (car methods)) |
| 136 | (while methods | 134 | 'help-function (car methods)) |
| 137 | (setq doc (eieio-method-documentation (car methods) class)) | 135 | (insert "'") |
| 138 | (princ "`") | 136 | (if (not doc) |
| 139 | (prin1 (car methods)) | 137 | (insert " Undocumented") |
| 140 | (princ "'") | 138 | (setq counter 0) |
| 141 | (if (not doc) | 139 | (dolist (cur doc) |
| 142 | (princ " Undocumented") | 140 | (when cur |
| 143 | (if (car doc) | 141 | (insert " " (aref type counter) " " |
| 144 | (progn | 142 | (prin1-to-string (car cur) (current-buffer)) |
| 145 | (princ " :STATIC ") | 143 | "\n" |
| 146 | (prin1 (car (car doc))) | 144 | (cdr cur))) |
| 147 | (terpri) | 145 | (setq counter (1+ counter)))) |
| 148 | (princ (cdr (car doc))))) | 146 | (insert "\n\n") |
| 149 | (setq doc (cdr doc)) | 147 | (setq methods (cdr methods)))))) |
| 150 | (if (car doc) | 148 | |
| 151 | (progn | 149 | (defun eieio-help-class-slots (class) |
| 152 | (princ " :BEFORE ") | 150 | "Print help description for the slots in CLASS. |
| 153 | (prin1 (car (car doc))) | 151 | Outputs to the current buffer." |
| 154 | (terpri) | ||
| 155 | (princ (cdr (car doc))))) | ||
| 156 | (setq doc (cdr doc)) | ||
| 157 | (if (car doc) | ||
| 158 | (progn | ||
| 159 | (princ " :PRIMARY ") | ||
| 160 | (prin1 (car (car doc))) | ||
| 161 | (terpri) | ||
| 162 | (princ (cdr (car doc))))) | ||
| 163 | (setq doc (cdr doc)) | ||
| 164 | (if (car doc) | ||
| 165 | (progn | ||
| 166 | (princ " :AFTER ") | ||
| 167 | (prin1 (car (car doc))) | ||
| 168 | (terpri) | ||
| 169 | (princ (cdr (car doc))))) | ||
| 170 | (terpri) | ||
| 171 | (terpri)) | ||
| 172 | (setq methods (cdr methods)))))) | ||
| 173 | (with-current-buffer (help-buffer) | ||
| 174 | (buffer-string))) | ||
| 175 | |||
| 176 | (defun eieio-describe-class-slots (class) | ||
| 177 | "Describe the slots in CLASS. | ||
| 178 | Outputs to the standard output." | ||
| 179 | (let* ((cv (class-v class)) | 152 | (let* ((cv (class-v class)) |
| 180 | (docs (eieio--class-public-doc cv)) | 153 | (docs (eieio--class-public-doc cv)) |
| 181 | (names (eieio--class-public-a cv)) | 154 | (names (eieio--class-public-a cv)) |
| @@ -185,28 +158,27 @@ Outputs to the standard output." | |||
| 185 | (i 0) | 158 | (i 0) |
| 186 | (prot (eieio--class-protection cv)) | 159 | (prot (eieio--class-protection cv)) |
| 187 | ) | 160 | ) |
| 188 | (princ "Instance Allocated Slots:") | 161 | (insert (propertize "Instance Allocated Slots:\n\n" |
| 189 | (terpri) | 162 | 'face 'bold)) |
| 190 | (terpri) | ||
| 191 | (while names | 163 | (while names |
| 192 | (if (car prot) (princ "Private ")) | 164 | (insert |
| 193 | (princ "Slot: ") | 165 | (concat |
| 194 | (prin1 (car names)) | 166 | (when (car prot) |
| 195 | (when (not (eq (aref types i) t)) | 167 | (propertize "Private " 'face 'bold)) |
| 196 | (princ " type = ") | 168 | (propertize "Slot: " 'face 'bold) |
| 197 | (prin1 (aref types i))) | 169 | (prin1-to-string (car names)) |
| 198 | (unless (eq (car deflt) eieio-unbound) | 170 | (unless (eq (aref types i) t) |
| 199 | (princ " default = ") | 171 | (concat " type = " |
| 200 | (prin1 (car deflt))) | 172 | (prin1-to-string (aref types i)))) |
| 201 | (when (car publp) | 173 | (unless (eq (car deflt) eieio-unbound) |
| 202 | (princ " printer = ") | 174 | (concat " default = " |
| 203 | (prin1 (car publp))) | 175 | (prin1-to-string (car deflt)))) |
| 204 | (when (car docs) | 176 | (when (car publp) |
| 205 | (terpri) | 177 | (concat " printer = " |
| 206 | (princ " ") | 178 | (prin1-to-string (car publp)))) |
| 207 | (princ (car docs)) | 179 | (when (car docs) |
| 208 | (terpri)) | 180 | (concat "\n " (car docs) "\n")) |
| 209 | (terpri) | 181 | "\n")) |
| 210 | (setq names (cdr names) | 182 | (setq names (cdr names) |
| 211 | docs (cdr docs) | 183 | docs (cdr docs) |
| 212 | deflt (cdr deflt) | 184 | deflt (cdr deflt) |
| @@ -219,61 +191,30 @@ Outputs to the standard output." | |||
| 219 | i 0 | 191 | i 0 |
| 220 | prot (eieio--class-class-allocation-protection cv)) | 192 | prot (eieio--class-class-allocation-protection cv)) |
| 221 | (when names | 193 | (when names |
| 222 | (terpri) | 194 | (insert (propertize "\nClass Allocated Slots:\n\n" 'face 'bold))) |
| 223 | (princ "Class Allocated Slots:")) | ||
| 224 | (terpri) | ||
| 225 | (terpri) | ||
| 226 | (while names | 195 | (while names |
| 227 | (when (car prot) | 196 | (insert |
| 228 | (princ "Private ")) | 197 | (concat |
| 229 | (princ "Slot: ") | 198 | (when (car prot) |
| 230 | (prin1 (car names)) | 199 | "Private ") |
| 231 | (unless (eq (aref types i) t) | 200 | "Slot: " |
| 232 | (princ " type = ") | 201 | (prin1-to-string (car names)) |
| 233 | (prin1 (aref types i))) | 202 | (unless (eq (aref types i) t) |
| 234 | (condition-case nil | 203 | (concat " type = " |
| 235 | (let ((value (eieio-oref class (car names)))) | 204 | (prin1-to-string (aref types i)))) |
| 236 | (princ " value = ") | 205 | (condition-case nil |
| 237 | (prin1 value)) | 206 | (let ((value (eieio-oref class (car names)))) |
| 207 | (concat " value = " | ||
| 208 | (prin1-to-string value))) | ||
| 238 | (error nil)) | 209 | (error nil)) |
| 239 | (when (car docs) | 210 | (when (car docs) |
| 240 | (terpri) | 211 | (concat "\n\n " (car docs) "\n")) |
| 241 | (princ " ") | 212 | "\n")) |
| 242 | (princ (car docs)) | ||
| 243 | (terpri)) | ||
| 244 | (terpri) | ||
| 245 | (setq names (cdr names) | 213 | (setq names (cdr names) |
| 246 | docs (cdr docs) | 214 | docs (cdr docs) |
| 247 | prot (cdr prot) | 215 | prot (cdr prot) |
| 248 | i (1+ i))))) | 216 | i (1+ i))))) |
| 249 | 217 | ||
| 250 | ;;;###autoload | ||
| 251 | (defun eieio-describe-constructor (fcn) | ||
| 252 | "Describe the constructor function FCN. | ||
| 253 | Uses `eieio-describe-class' to describe the class being constructed." | ||
| 254 | (interactive | ||
| 255 | ;; Use eieio-read-class since all constructors have the same name as | ||
| 256 | ;; the class they create. | ||
| 257 | (list (eieio-read-class "Class: "))) | ||
| 258 | (eieio-describe-class | ||
| 259 | fcn (lambda () | ||
| 260 | ;; Describe the constructor part. | ||
| 261 | (prin1 fcn) | ||
| 262 | (princ " is an object constructor function") | ||
| 263 | ;; Print file location | ||
| 264 | (when (get fcn 'class-location) | ||
| 265 | (princ " in `") | ||
| 266 | (princ (file-name-nondirectory (get fcn 'class-location))) | ||
| 267 | (princ "'")) | ||
| 268 | (terpri) | ||
| 269 | (princ "Creates an object of class ") | ||
| 270 | (prin1 fcn) | ||
| 271 | (princ ".") | ||
| 272 | (terpri) | ||
| 273 | (terpri) | ||
| 274 | )) | ||
| 275 | ) | ||
| 276 | |||
| 277 | (defun eieio-build-class-list (class) | 218 | (defun eieio-build-class-list (class) |
| 278 | "Return a list of all classes that inherit from CLASS." | 219 | "Return a list of all classes that inherit from CLASS." |
| 279 | (if (class-p class) | 220 | (if (class-p class) |
| @@ -326,91 +267,112 @@ are not abstract." | |||
| 326 | 267 | ||
| 327 | ;;; METHOD COMPLETION / DOC | 268 | ;;; METHOD COMPLETION / DOC |
| 328 | 269 | ||
| 329 | (defalias 'describe-method 'eieio-describe-generic) | 270 | (define-button-type 'eieio-method-def |
| 330 | ;;;###autoload(defalias 'describe-generic 'eieio-describe-generic) | 271 | :supertype 'help-xref |
| 331 | (defalias 'eieio-describe-method 'eieio-describe-generic) | 272 | 'help-function (lambda (class method file) |
| 273 | (eieio-help-find-method-definition class method file)) | ||
| 274 | 'help-echo (purecopy "mouse-2, RET: find method's definition")) | ||
| 275 | |||
| 276 | (define-button-type 'eieio-class-def | ||
| 277 | :supertype 'help-xref | ||
| 278 | 'help-function (lambda (class file) | ||
| 279 | (eieio-help-find-class-definition class file)) | ||
| 280 | 'help-echo (purecopy "mouse-2, RET: find class definition")) | ||
| 332 | 281 | ||
| 333 | ;;;###autoload | 282 | ;;;###autoload |
| 334 | (defun eieio-describe-generic (generic) | 283 | (defun eieio-help-constructor (ctr) |
| 335 | "Describe the generic function GENERIC. | 284 | "Describe CTR if it is a class constructor." |
| 336 | Also extracts information about all methods specific to this generic." | 285 | (when (class-p ctr) |
| 337 | (interactive (list (eieio-read-generic "Generic Method: "))) | 286 | (erase-buffer) |
| 338 | (eieio--check-type generic-p generic) | 287 | (let ((location (get ctr 'class-location)) |
| 339 | (with-output-to-temp-buffer (help-buffer) ; "*Help*" | 288 | (def (symbol-function ctr))) |
| 340 | (help-setup-xref (list #'eieio-describe-generic generic) | 289 | (goto-char (point-min)) |
| 341 | (called-interactively-p 'interactive)) | 290 | (prin1 ctr) |
| 342 | 291 | (insert (format " is an %s object constructor function" | |
| 343 | (prin1 generic) | 292 | (if (autoloadp def) |
| 344 | (princ " is a generic function") | 293 | "autoloaded" |
| 345 | (when (generic-primary-only-p generic) | 294 | ""))) |
| 346 | (princ " with only ") | 295 | (when (and (autoloadp def) |
| 347 | (when (generic-primary-only-one-p generic) | 296 | (null location)) |
| 348 | (princ "one ")) | 297 | (setq location |
| 349 | (princ "primary method") | 298 | (find-lisp-object-file-name ctr def))) |
| 350 | (when (not (generic-primary-only-one-p generic)) | 299 | (when location |
| 351 | (princ "s")) | 300 | (insert " in `") |
| 352 | ) | 301 | (help-insert-xref-button |
| 353 | (princ ".") | 302 | (file-name-nondirectory location) |
| 354 | (terpri) | 303 | 'eieio-class-def ctr location) |
| 355 | (terpri) | 304 | (insert "'")) |
| 356 | (let ((d (documentation generic))) | 305 | (insert ".\nCreates an object of class " (symbol-name ctr) ".") |
| 357 | (if (not d) | 306 | (goto-char (point-max)) |
| 358 | (princ "The generic is not documented.\n") | 307 | (if (autoloadp def) |
| 359 | (princ "Documentation:") | 308 | (insert "\n\n[Class description not available until class definition is loaded.]\n") |
| 360 | (terpri) | 309 | (save-excursion |
| 361 | (princ d) | 310 | (insert (propertize "\n\nClass description:\n" 'face 'bold)) |
| 362 | (terpri) | 311 | (eieio-help-class ctr)) |
| 363 | (terpri))) | 312 | )))) |
| 364 | (princ "Implementations:") | 313 | |
| 365 | (terpri) | 314 | |
| 366 | (terpri) | 315 | ;;;###autoload |
| 367 | (let ((i 4) | 316 | (defun eieio-help-generic (generic) |
| 368 | (prefix [ ":STATIC" ":BEFORE" ":PRIMARY" ":AFTER" ] )) | 317 | "Describe GENERIC if it is a generic function." |
| 369 | ;; Loop over fanciful generics | 318 | (when (generic-p generic) |
| 370 | (while (< i 7) | 319 | (save-excursion |
| 371 | (let ((gm (aref (get generic 'eieio-method-tree) i))) | 320 | (goto-char (point-min)) |
| 372 | (when gm | 321 | (when (re-search-forward " in `.+'.$" nil t) |
| 373 | (princ "Generic ") | 322 | (replace-match "."))) |
| 374 | (princ (aref prefix (- i 3))) | 323 | (save-excursion |
| 375 | (terpri) | 324 | (insert "\n\nThis is a generic function" |
| 376 | (princ (or (nth 2 gm) "Undocumented")) | 325 | (cond |
| 377 | (terpri) | 326 | ((and (generic-primary-only-p generic) |
| 378 | (terpri))) | 327 | (generic-primary-only-one-p generic)) |
| 379 | (setq i (1+ i))) | 328 | " with only one primary method") |
| 380 | (setq i 0) | 329 | ((generic-primary-only-p generic) |
| 381 | ;; Loop over defined class-specific methods | 330 | " with only primary methods") |
| 382 | (while (< i 4) | 331 | (t "")) |
| 383 | (let ((gm (reverse (aref (get generic 'eieio-method-tree) i))) | 332 | ".\n\n") |
| 384 | location) | 333 | (insert (propertize "Implementations:\n\n" 'face 'bold)) |
| 385 | (while gm | 334 | (let ((i 4) |
| 386 | (princ "`") | 335 | (prefix [ ":STATIC" ":BEFORE" ":PRIMARY" ":AFTER" ] )) |
| 387 | (prin1 (car (car gm))) | 336 | ;; Loop over fanciful generics |
| 388 | (princ "'") | 337 | (while (< i 7) |
| 389 | ;; prefix type | 338 | (let ((gm (aref (get generic 'eieio-method-tree) i))) |
| 390 | (princ " ") | 339 | (when gm |
| 391 | (princ (aref prefix i)) | 340 | (insert "Generic " |
| 392 | (princ " ") | 341 | (aref prefix (- i 3)) |
| 393 | ;; argument list | 342 | "\n" |
| 394 | (let* ((func (cdr (car gm))) | 343 | (or (nth 2 gm) "Undocumented") |
| 395 | (arglst (eieio-lambda-arglist func))) | 344 | "\n\n"))) |
| 396 | (prin1 arglst)) | 345 | (setq i (1+ i))) |
| 397 | (terpri) | 346 | (setq i 0) |
| 398 | ;; 3 because of cdr | 347 | ;; Loop over defined class-specific methods |
| 399 | (princ (or (documentation (cdr (car gm))) | 348 | (while (< i 4) |
| 400 | "Undocumented")) | 349 | (let* ((gm (reverse (aref (get generic 'eieio-method-tree) i))) |
| 401 | ;; Print file location if available | 350 | cname location) |
| 402 | (when (and (setq location (get generic 'method-locations)) | 351 | (while gm |
| 403 | (setq location (assoc (caar gm) location))) | 352 | (setq cname (caar gm)) |
| 404 | (setq location (cadr location)) | 353 | (insert "`") |
| 405 | (princ "\n\nDefined in `") | 354 | (help-insert-xref-button (symbol-name cname) |
| 406 | (princ (file-name-nondirectory location)) | 355 | 'help-variable cname) |
| 407 | (princ "'\n")) | 356 | (insert "' " (aref prefix i) " ") |
| 408 | (setq gm (cdr gm)) | 357 | ;; argument list |
| 409 | (terpri) | 358 | (let* ((func (cdr (car gm))) |
| 410 | (terpri))) | 359 | (arglst (eieio-lambda-arglist func))) |
| 411 | (setq i (1+ i))))) | 360 | (prin1 arglst (current-buffer))) |
| 412 | (with-current-buffer (help-buffer) | 361 | (insert "\n" |
| 413 | (buffer-string))) | 362 | (or (documentation (cdr (car gm))) |
| 363 | "Undocumented")) | ||
| 364 | ;; Print file location if available | ||
| 365 | (when (and (setq location (get generic 'method-locations)) | ||
| 366 | (setq location (assoc cname location))) | ||
| 367 | (setq location (cadr location)) | ||
| 368 | (insert "\n\nDefined in `") | ||
| 369 | (help-insert-xref-button | ||
| 370 | (file-name-nondirectory location) | ||
| 371 | 'eieio-method-def cname generic location) | ||
| 372 | (insert "'\n")) | ||
| 373 | (setq gm (cdr gm)) | ||
| 374 | (insert "\n"))) | ||
| 375 | (setq i (1+ i))))))) | ||
| 414 | 376 | ||
| 415 | (defun eieio-lambda-arglist (func) | 377 | (defun eieio-lambda-arglist (func) |
| 416 | "Return the argument list of FUNC, a function body." | 378 | "Return the argument list of FUNC, a function body." |
| @@ -584,21 +546,13 @@ Optional argument HISTORYVAR is the variable to use as history." | |||
| 584 | 546 | ||
| 585 | ;;; HELP AUGMENTATION | 547 | ;;; HELP AUGMENTATION |
| 586 | ;; | 548 | ;; |
| 587 | (define-button-type 'eieio-method-def | ||
| 588 | :supertype 'help-xref | ||
| 589 | 'help-function (lambda (class method file) | ||
| 590 | (eieio-help-find-method-definition class method file)) | ||
| 591 | 'help-echo (purecopy "mouse-2, RET: find method's definition")) | ||
| 592 | |||
| 593 | (define-button-type 'eieio-class-def | ||
| 594 | :supertype 'help-xref | ||
| 595 | 'help-function (lambda (class file) | ||
| 596 | (eieio-help-find-class-definition class file)) | ||
| 597 | 'help-echo (purecopy "mouse-2, RET: find class definition")) | ||
| 598 | |||
| 599 | (defun eieio-help-find-method-definition (class method file) | 549 | (defun eieio-help-find-method-definition (class method file) |
| 600 | (let ((filename (find-library-name file)) | 550 | (let ((filename (find-library-name file)) |
| 601 | location buf) | 551 | location buf) |
| 552 | (when (symbolp class) | ||
| 553 | (setq class (symbol-name class))) | ||
| 554 | (when (symbolp method) | ||
| 555 | (setq method (symbol-name method))) | ||
| 602 | (when (null filename) | 556 | (when (null filename) |
| 603 | (error "Cannot find library %s" file)) | 557 | (error "Cannot find library %s" file)) |
| 604 | (setq buf (find-file-noselect filename)) | 558 | (setq buf (find-file-noselect filename)) |
| @@ -622,6 +576,8 @@ Optional argument HISTORYVAR is the variable to use as history." | |||
| 622 | (beginning-of-line)))) | 576 | (beginning-of-line)))) |
| 623 | 577 | ||
| 624 | (defun eieio-help-find-class-definition (class file) | 578 | (defun eieio-help-find-class-definition (class file) |
| 579 | (when (symbolp class) | ||
| 580 | (setq class (symbol-name class))) | ||
| 625 | (let ((filename (find-library-name file)) | 581 | (let ((filename (find-library-name file)) |
| 626 | location buf) | 582 | location buf) |
| 627 | (when (null filename) | 583 | (when (null filename) |
| @@ -642,71 +598,6 @@ Optional argument HISTORYVAR is the variable to use as history." | |||
| 642 | (recenter) | 598 | (recenter) |
| 643 | (beginning-of-line)))) | 599 | (beginning-of-line)))) |
| 644 | 600 | ||
| 645 | |||
| 646 | (defun eieio-help-mode-augmentation-maybee (&rest unused) | ||
| 647 | "For buffers thrown into help mode, augment for EIEIO. | ||
| 648 | Arguments UNUSED are not used." | ||
| 649 | ;; Scan created buttons so far if we are in help mode. | ||
| 650 | (when (eq major-mode 'help-mode) | ||
| 651 | (save-excursion | ||
| 652 | (goto-char (point-min)) | ||
| 653 | (let ((pos t) (inhibit-read-only t)) | ||
| 654 | (while pos | ||
| 655 | (if (get-text-property (point) 'help-xref) ; move off reference | ||
| 656 | (goto-char | ||
| 657 | (or (next-single-property-change (point) 'help-xref) | ||
| 658 | (point)))) | ||
| 659 | (setq pos (next-single-property-change (point) 'help-xref)) | ||
| 660 | (when pos | ||
| 661 | (goto-char pos) | ||
| 662 | (let* ((help-data (get-text-property (point) 'help-xref)) | ||
| 663 | ;(method (car help-data)) | ||
| 664 | (args (cdr help-data))) | ||
| 665 | (when (symbolp (car args)) | ||
| 666 | (cond ((class-p (car args)) | ||
| 667 | (setcar help-data 'eieio-describe-class)) | ||
| 668 | ((generic-p (car args)) | ||
| 669 | (setcar help-data 'eieio-describe-generic)) | ||
| 670 | (t nil)) | ||
| 671 | )))) | ||
| 672 | ;; start back at the beginning, and highlight some sections | ||
| 673 | (goto-char (point-min)) | ||
| 674 | (while (re-search-forward "^\\(Documentation\\|Implementations\\):$" nil t) | ||
| 675 | (put-text-property (match-beginning 0) (match-end 0) 'face 'bold)) | ||
| 676 | (goto-char (point-min)) | ||
| 677 | (if (re-search-forward "^Specialized Methods:$" nil t) | ||
| 678 | (put-text-property (match-beginning 0) (match-end 0) 'face 'bold)) | ||
| 679 | (goto-char (point-min)) | ||
| 680 | (while (re-search-forward "^\\(Instance\\|Class\\) Allocated Slots:$" nil t) | ||
| 681 | (put-text-property (match-beginning 0) (match-end 0) 'face 'bold)) | ||
| 682 | (goto-char (point-min)) | ||
| 683 | (while (re-search-forward ":\\(STATIC\\|BEFORE\\|AFTER\\|PRIMARY\\)" nil t) | ||
| 684 | (put-text-property (match-beginning 0) (match-end 0) 'face 'bold)) | ||
| 685 | (goto-char (point-min)) | ||
| 686 | (while (re-search-forward "^\\(Private \\)?Slot:" nil t) | ||
| 687 | (put-text-property (match-beginning 0) (match-end 0) 'face 'bold)) | ||
| 688 | (goto-char (point-min)) | ||
| 689 | (cond | ||
| 690 | ((looking-at "\\(.+\\) is a generic function") | ||
| 691 | (let ((mname (match-string 1)) | ||
| 692 | cname) | ||
| 693 | (while (re-search-forward "^`\\(.+\\)'[^\0]+?Defined in `\\(.+\\)'" nil t) | ||
| 694 | (setq cname (match-string-no-properties 1)) | ||
| 695 | (help-xref-button 2 'eieio-method-def cname | ||
| 696 | mname | ||
| 697 | (cadr (assoc (intern cname) | ||
| 698 | (get (intern mname) | ||
| 699 | 'method-locations))))))) | ||
| 700 | ((looking-at "\\(.+\\) is an object constructor function in `\\(.+\\)'") | ||
| 701 | (let ((cname (match-string-no-properties 1))) | ||
| 702 | (help-xref-button 2 'eieio-class-def cname | ||
| 703 | (get (intern cname) 'class-location)))) | ||
| 704 | ((looking-at "\\(.+\\) is a\\(n abstract\\)? class in `\\(.+\\)'") | ||
| 705 | (let ((cname (match-string-no-properties 1))) | ||
| 706 | (help-xref-button 3 'eieio-class-def cname | ||
| 707 | (get (intern cname) 'class-location))))) | ||
| 708 | )))) | ||
| 709 | |||
| 710 | ;;; SPEEDBAR SUPPORT | 601 | ;;; SPEEDBAR SUPPORT |
| 711 | ;; | 602 | ;; |
| 712 | 603 | ||
| @@ -796,7 +687,7 @@ Argument INDENT is the depth of indentation." | |||
| 796 | "Describe the class TEXT in TOKEN. | 687 | "Describe the class TEXT in TOKEN. |
| 797 | INDENT is the current indentation level." | 688 | INDENT is the current indentation level." |
| 798 | (dframe-with-attached-buffer | 689 | (dframe-with-attached-buffer |
| 799 | (eieio-describe-class token)) | 690 | (describe-function token)) |
| 800 | (dframe-maybee-jump-to-attached-frame)) | 691 | (dframe-maybee-jump-to-attached-frame)) |
| 801 | 692 | ||
| 802 | (provide 'eieio-opt) | 693 | (provide 'eieio-opt) |
diff --git a/lisp/emacs-lisp/eieio.el b/lisp/emacs-lisp/eieio.el index 3b1ba003d94..4d572601243 100644 --- a/lisp/emacs-lisp/eieio.el +++ b/lisp/emacs-lisp/eieio.el | |||
| @@ -865,6 +865,10 @@ This may create or delete slots, but does not affect the return value | |||
| 865 | of `eq'." | 865 | of `eq'." |
| 866 | (error "EIEIO: `change-class' is unimplemented")) | 866 | (error "EIEIO: `change-class' is unimplemented")) |
| 867 | 867 | ||
| 868 | ;; Hook ourselves into help system for describing classes and methods. | ||
| 869 | (add-hook 'help-fns-describe-function-functions 'eieio-help-generic) | ||
| 870 | (add-hook 'help-fns-describe-function-functions 'eieio-help-constructor) | ||
| 871 | |||
| 868 | ;;; Interfacing with edebug | 872 | ;;; Interfacing with edebug |
| 869 | ;; | 873 | ;; |
| 870 | (defun eieio-edebug-prin1-to-string (object &optional noescape) | 874 | (defun eieio-edebug-prin1-to-string (object &optional noescape) |
diff --git a/lisp/help-fns.el b/lisp/help-fns.el index 7b9e1783bad..2252c700fea 100644 --- a/lisp/help-fns.el +++ b/lisp/help-fns.el | |||
| @@ -32,6 +32,12 @@ | |||
| 32 | 32 | ||
| 33 | ;;; Code: | 33 | ;;; Code: |
| 34 | 34 | ||
| 35 | (defvar help-fns-describe-function-functions nil | ||
| 36 | "List of functions to run in help buffer in `describe-function'. | ||
| 37 | Those functions will be run after the header line and argument | ||
| 38 | list was inserted, and before the documentation will be inserted. | ||
| 39 | The functions will receive the function name as argument.") | ||
| 40 | |||
| 35 | ;; Functions | 41 | ;; Functions |
| 36 | 42 | ||
| 37 | ;;;###autoload | 43 | ;;;###autoload |
| @@ -649,14 +655,15 @@ FILE is the file where FUNCTION was probably defined." | |||
| 649 | (help-fns--key-bindings function) | 655 | (help-fns--key-bindings function) |
| 650 | (with-current-buffer standard-output | 656 | (with-current-buffer standard-output |
| 651 | (setq doc (help-fns--signature function doc real-def real-function)) | 657 | (setq doc (help-fns--signature function doc real-def real-function)) |
| 652 | 658 | (run-hook-with-args 'help-fns-describe-function-functions function) | |
| 653 | (help-fns--compiler-macro function) | ||
| 654 | (help-fns--parent-mode function) | ||
| 655 | (help-fns--obsolete function) | ||
| 656 | |||
| 657 | (insert "\n" | 659 | (insert "\n" |
| 658 | (or doc "Not documented."))))))) | 660 | (or doc "Not documented."))))))) |
| 659 | 661 | ||
| 662 | ;; Add defaults to `help-fns-describe-function-functions'. | ||
| 663 | (add-hook 'help-fns-describe-function-functions 'help-fns--obsolete) | ||
| 664 | (add-hook 'help-fns-describe-function-functions 'help-fns--parent-mode) | ||
| 665 | (add-hook 'help-fns-describe-function-functions 'help-fns--compiler-macro) | ||
| 666 | |||
| 660 | 667 | ||
| 661 | ;; Variables | 668 | ;; Variables |
| 662 | 669 | ||