Starting with Emacs 29, the doc strings of macros add-function and advice-add are constructed, using substitution of a common part into a "<<>>" placeholder.

C-h f add-function:

... ...
which we call OLDFUN here:
  :around (lambda (&rest r) (apply FUNCTION OLDFUN r))
If FUNCTION was already added, do nothing.
... ...

But when I looked at the source code:

(defmacro add-function (how place function &optional props)
  "... ...
which we call OLDFUN here:
If FUNCTION was already added, do nothing.
... ..."

How does the <<>> in the docstring get replaced with regular text?

1 Answer 1


The text <<>> is processed by the function nadvice--make-docstring which is defined above the definition of add-function itself.

(defun nadvice--make-docstring (sym)
  (let* ((main (documentation (symbol-function sym) 'raw))
         (ud (help-split-fundoc main 'pcase))
         (doc (or (cdr ud) main))
         (col1width (apply #'max (mapcar (lambda (x)
                                           (string-width (symbol-name (car x))))
         (table (mapconcat (lambda (x)
                             (format (format " %%-%ds %%s" col1width)
                                     (car x) (nth 2 x)))
                           advice--how-alist "\n"))
         (table (if global-prettify-symbols-mode
                    (replace-regexp-in-string "(lambda\\>" "(λ" table t t)
          (if (not (string-match "<<>>" doc))
            (replace-match table t t doc))))
    (if ud (help-add-fundoc-usage combined-doc (car ud)) combined-doc)))

In particular, the following form is substituting for that token if it was found in the text:

(if (not (string-match "<<>>" doc))
  (replace-match table t t doc))

That function is then used like so:

(put 'add-function 'function-documentation
     '(nadvice--make-docstring 'add-function))

This says that the lisp form (nadvice--make-docstring 'add-function) should be called to generate the add-function docstring dynamically, whenever it is requested.

See C-hig (elisp)Function Documentation for details on dynamic docstrings, along with (elisp)Accessing Documentation (which notes of the function-documentation property "if the value is not a string, it is evaluated").

  • Please explain what (put 'add-function 'function-documentation '(nadvice--make-docstring 'add-function)) does
    – shynur
    Sep 12, 2023 at 4:25
  • I think this comment should be added to your answer. It is much more important than the definition of nadvice--make-docstring.
    – shynur
    Sep 12, 2023 at 4:37
  • Answer updated.
    – phils
    Sep 12, 2023 at 4:53

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.