mirror of
git://git.sv.gnu.org/emacs.git
synced 2026-01-04 11:00:45 -08:00
* cl-generic.el (cl-defmethod): Make docstring dynamic
* lisp/emacs-lisp/cl-generic.el (cl-defmethod): Make docstring dynamic. (cl--generic-make-defmethod-docstring): New function for that. (cl-defmethod, cl-generic-generalizers): Tweak docstrings accordingly. (cl-generic-define-method, cl--generic-describe): Change `load-history' format of cl-defmethods, so as not to confused methods with equal specializers but different qualifiers. * lisp/emacs-lisp/eieio-core.el (cl-generic-generalizers): Provide docstrings.
This commit is contained in:
parent
5155144bd4
commit
3698c4e475
2 changed files with 47 additions and 16 deletions
|
|
@ -353,6 +353,26 @@ the specializer used will be the one returned by BODY."
|
|||
,nbody))))))
|
||||
(f (error "Unexpected macroexpansion result: %S" f))))))
|
||||
|
||||
(put 'cl-defmethod 'function-documentation
|
||||
'(cl--generic-make-defmethod-docstring))
|
||||
|
||||
(defun cl--generic-make-defmethod-docstring ()
|
||||
;; FIXME: Copy&paste from pcase--make-docstring.
|
||||
(let* ((main (documentation (symbol-function 'cl-defmethod) 'raw))
|
||||
(ud (help-split-fundoc main 'cl-defmethod)))
|
||||
;; So that eg emacs -Q -l cl-lib --eval "(documentation 'pcase)" works,
|
||||
;; where cl-lib is anything using pcase-defmacro.
|
||||
(require 'help-fns)
|
||||
(with-temp-buffer
|
||||
(insert (or (cdr ud) main))
|
||||
(insert "\n\n\tCurrently supported forms for TYPE:\n\n")
|
||||
(dolist (method (reverse (cl--generic-method-table
|
||||
(cl--generic 'cl-generic-generalizers))))
|
||||
(let* ((info (cl--generic-method-info method)))
|
||||
(when (nth 2 info)
|
||||
(insert (nth 2 info) "\n\n"))))
|
||||
(let ((combined-doc (buffer-string)))
|
||||
(if ud (help-add-fundoc-usage combined-doc (car ud)) combined-doc)))))
|
||||
|
||||
;;;###autoload
|
||||
(defmacro cl-defmethod (name args &rest body)
|
||||
|
|
@ -370,15 +390,17 @@ modifies how the method is combined with other methods, including:
|
|||
:after - Method will be called after the primary
|
||||
:around - Method will be called around everything else
|
||||
The absence of QUALIFIER means this is a \"primary\" method.
|
||||
The set of acceptable qualifiers and their meaning is defined
|
||||
\(and can be extended) by the methods of `cl-generic-combine-methods'.
|
||||
|
||||
TYPE can be one of the basic types (see the full list and their
|
||||
hierarchy in `cl--generic-typeof-types'), CL struct type, or an
|
||||
EIEIO class.
|
||||
ARGS can also include so-called context specializers, introduced by
|
||||
`&context' (which should appear right after the mandatory arguments,
|
||||
before any &optional or &rest). They have the form (EXPR TYPE) where
|
||||
EXPR is an Elisp expression whose value should match TYPE for the
|
||||
method to be applicable.
|
||||
|
||||
Other than that, TYPE can also be of the form `(eql VAL)' in
|
||||
which case this method will be invoked when the argument is `eql'
|
||||
to VAL, or `(head VAL)', in which case the argument is required
|
||||
to be a cons with VAL as its head.
|
||||
The set of acceptable TYPEs (also called \"specializers\") is defined
|
||||
\(and can be extended) by the various methods of `cl-generic-generalizers'.
|
||||
|
||||
\(fn NAME [QUALIFIER] ARGS &rest [DOCSTRING] BODY)"
|
||||
(declare (doc-string 3) (indent 2)
|
||||
|
|
@ -464,7 +486,8 @@ to be a cons with VAL as its head.
|
|||
(cons method mt)
|
||||
;; Keep the ordering; important for methods with :extra qualifiers.
|
||||
(mapcar (lambda (x) (if (eq x (car me)) method x)) mt)))
|
||||
(cl-pushnew `(cl-defmethod . (,(cl--generic-name generic) . ,specializers))
|
||||
(cl-pushnew `(cl-defmethod . (,(cl--generic-name generic)
|
||||
,qualifiers . ,specializers))
|
||||
current-load-list :test #'equal)
|
||||
;; FIXME: Try to avoid re-constructing a new function if the old one
|
||||
;; is still valid (e.g. still empty method cache)?
|
||||
|
|
@ -737,7 +760,7 @@ methods.")
|
|||
(fset 'cl-generic-combine-methods #'cl--generic-standard-method-combination))
|
||||
|
||||
(cl-defmethod cl-generic-generalizers (specializer)
|
||||
"Support for the catch-all t specializer."
|
||||
"Support for the catch-all t specializer which always matches."
|
||||
(if (eq specializer t) (list cl--generic-t-generalizer)
|
||||
(error "Unknown specializer %S" specializer)))
|
||||
|
||||
|
|
@ -909,8 +932,9 @@ MET-NAME is a cons (SYMBOL . SPECIALIZERS)."
|
|||
(let* ((info (cl--generic-method-info method)))
|
||||
;; FIXME: Add hyperlinks for the types as well.
|
||||
(insert (format "%s%S" (nth 0 info) (nth 1 info)))
|
||||
(let* ((met-name (cons function
|
||||
(cl--generic-method-specializers method)))
|
||||
(let* ((met-name `(,function
|
||||
,(cl--generic-method-qualifiers method)
|
||||
. ,(cl--generic-method-specializers method)))
|
||||
(file (find-lisp-object-file-name met-name 'cl-defmethod)))
|
||||
(when file
|
||||
(insert (substitute-command-keys " in `"))
|
||||
|
|
@ -994,7 +1018,8 @@ The value returned is a list of elements of the form
|
|||
(lambda (tag &rest _) (if (eq (car-safe tag) 'head) (list tag))))
|
||||
|
||||
(cl-defmethod cl-generic-generalizers :extra "head" (specializer)
|
||||
"Support for the `(head VAL)' specializers."
|
||||
"Support for (head VAL) specializers.
|
||||
These match if the argument is a cons cell whose car is `eql' to VAL."
|
||||
;; We have to implement `head' here using the :extra qualifier,
|
||||
;; since we can't use the `head' specializer to implement itself.
|
||||
(if (not (eq (car-safe specializer) 'head))
|
||||
|
|
@ -1014,7 +1039,8 @@ The value returned is a list of elements of the form
|
|||
(lambda (tag &rest _) (if (eq (car-safe tag) 'eql) (list tag))))
|
||||
|
||||
(cl-defmethod cl-generic-generalizers ((specializer (head eql)))
|
||||
"Support for the `(eql VAL)' specializers."
|
||||
"Support for (eql VAL) specializers.
|
||||
These match if the argument is `eql' to VAL."
|
||||
(puthash (cadr specializer) specializer cl--generic-eql-used)
|
||||
(list cl--generic-eql-generalizer))
|
||||
|
||||
|
|
@ -1069,7 +1095,7 @@ The value returned is a list of elements of the form
|
|||
#'cl--generic-struct-specializers)
|
||||
|
||||
(cl-defmethod cl-generic-generalizers :extra "cl-struct" (type)
|
||||
"Support for dispatch on cl-struct types."
|
||||
"Support for dispatch on types defined by `cl-defstruct'."
|
||||
(or
|
||||
(when (symbolp type)
|
||||
;; Use the "cl--struct-class*" (inlinable) functions/macros rather than
|
||||
|
|
@ -1113,7 +1139,8 @@ The value returned is a list of elements of the form
|
|||
(and (symbolp tag) (assq tag cl--generic-typeof-types))))
|
||||
|
||||
(cl-defmethod cl-generic-generalizers :extra "typeof" (type)
|
||||
"Support for dispatch on builtin types."
|
||||
"Support for dispatch on builtin types.
|
||||
See the full list and their hierarchy in `cl--generic-typeof-types'."
|
||||
;; FIXME: Add support for other types accepted by `cl-typep' such
|
||||
;; as `character', `atom', `face', `function', ...
|
||||
(or
|
||||
|
|
@ -1151,7 +1178,8 @@ The value returned is a list of elements of the form
|
|||
#'cl--generic-derived-specializers)
|
||||
|
||||
(cl-defmethod cl-generic-generalizers ((_specializer (head derived-mode)))
|
||||
"Support for the `(derived-mode MODE)' specializers."
|
||||
"Support for (derived-mode MODE) specializers.
|
||||
Used internally for the (major-mode MODE) context specializers."
|
||||
(list cl--generic-derived-generalizer))
|
||||
|
||||
(cl-generic-define-context-rewriter major-mode (mode &rest modes)
|
||||
|
|
|
|||
|
|
@ -1065,6 +1065,7 @@ method invocation orders of the involved classes."
|
|||
(eieio--class-precedence-list (symbol-value tag))))))
|
||||
|
||||
(cl-defmethod cl-generic-generalizers :extra "class" (specializer)
|
||||
"Support for dispatch on types defined by EIEIO's `defclass'."
|
||||
;; CLHS says:
|
||||
;; A class must be defined before it can be used as a parameter
|
||||
;; specializer in a defmethod form.
|
||||
|
|
@ -1093,6 +1094,8 @@ method invocation orders of the involved classes."
|
|||
#'eieio--generic-subclass-specializers)
|
||||
|
||||
(cl-defmethod cl-generic-generalizers ((_specializer (head subclass)))
|
||||
"Support for (subclass CLASS) specializers.
|
||||
These match if the argument is the name of a subclass of CLASS."
|
||||
(list eieio--generic-subclass-generalizer))
|
||||
|
||||
(provide 'eieio-core)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue