unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
From: Chong Yidong <cyd@gnu.org>
To: Stefan Monnier <monnier@IRO.UMontreal.CA>
Cc: emacs-devel@gnu.org
Subject: Re: The dynamic-docstring-function property
Date: Wed, 01 Jan 2014 13:53:32 +0800	[thread overview]
Message-ID: <87wqikp7s3.fsf@gnu.org> (raw)
In-Reply-To: <jwvwqimqzd5.fsf-monnier+emacs@gnu.org> (Stefan Monnier's message of "Mon, 30 Dec 2013 07:53:23 -0500")

>> Because a non-string value is evaluated, the dynamic-docstring-function
>> stuff can be accomplished by setting the function-documentation property
>> to the value `(foo ,old-docstring) where `foo' is your processing
>> function.
>
> Hmm... indeed maybe that could be used instead (it's not quite
> equivalent, in that dynamic-docstring-function is used by add-function,
> whereas function-documentation would only work for advice-add, tho
> I guess we could add "dummy" symbol indirection to make it possible to
> use function-documentation in add-function as well; and in practice the
> dynamic docstring feature is only useful for advice-add anyway).

How about the following?  Some testing indicates that looking up
docstrings of adviced functions, and of the pieces of advice, works
fine.  (This could be made more elegant if we change `documentation' so
that it ignores the `function-documentation' property when the RAW
argument is non-nil.)


=== modified file 'lisp/emacs-lisp/nadvice.el'
*** lisp/emacs-lisp/nadvice.el	2013-12-12 19:47:11 +0000
--- lisp/emacs-lisp/nadvice.el	2014-01-01 05:32:15 +0000
***************
*** 67,74 ****
  (defsubst advice--cdr   (f) (aref (aref f 2) 2))
  (defsubst advice--props (f) (aref (aref f 2) 3))
  
! (defun advice--make-docstring (_string function)
!   "Build the raw doc-string of SYMBOL, presumably advised."
    (let ((flist (indirect-function function))
          (docstring nil))
      (if (eq 'macro (car-safe flist)) (setq flist (cdr flist)))
--- 67,74 ----
  (defsubst advice--cdr   (f) (aref (aref f 2) 2))
  (defsubst advice--props (f) (aref (aref f 2) 3))
  
! (defun advice--make-docstring (function)
!   "Build the raw doc-string of FUNCTION, presumably advised."
    (let ((flist (indirect-function function))
          (docstring nil))
      (if (eq 'macro (car-safe flist)) (setq flist (cdr flist)))
***************
*** 105,117 ****
                      (setq origdoc (cdr usage)) (car usage)))
        (help-add-fundoc-usage (concat docstring origdoc) usage))))
  
- (defvar advice--docstring
-   ;; Can't eval-when-compile nor use defconst because it then gets pure-copied,
-   ;; which drops the text-properties.
-   ;;(eval-when-compile
-   (propertize "Advised function"
-               'dynamic-docstring-function #'advice--make-docstring)) ;; )
- 
  (defun advice-eval-interactive-spec (spec)
    "Evaluate the interactive spec SPEC."
    (cond
--- 105,110 ----
***************
*** 144,150 ****
          (advice
           (apply #'make-byte-code 128 byte-code
                  (vector #'apply function main props) stack-depth
!                 advice--docstring
                  (and (or (commandp function) (commandp main))
  		     (not (and (symbolp main) ;; Don't autoload too eagerly!
  			       (autoloadp (symbol-function main))))
--- 137,143 ----
          (advice
           (apply #'make-byte-code 128 byte-code
                  (vector #'apply function main props) stack-depth
!                 nil
                  (and (or (commandp function) (commandp main))
  		     (not (and (symbolp main) ;; Don't autoload too eagerly!
  			       (autoloadp (symbol-function main))))
***************
*** 398,403 ****
--- 391,397 ----
                            (get symbol 'advice--pending))
                           (t (symbol-function symbol)))
                    function props)
+     (put symbol 'function-documentation `(advice--make-docstring ',symbol))
      (add-function :around (get symbol 'defalias-fset-function)
                    #'advice--defalias-fset))
    nil)
=== modified file 'lisp/emacs-lisp/advice.el'
*** lisp/emacs-lisp/advice.el	2013-12-26 03:27:45 +0000
--- lisp/emacs-lisp/advice.el	2014-01-01 05:50:44 +0000
***************
*** 2185,2201 ****
  		    (if (ad-interactive-form definition) 1 0))
  		 (cdr (cdr (ad-lambda-expression definition)))))))
  
- (defun ad-make-advised-definition-docstring (_function)
-   "Make an identifying docstring for the advised definition of FUNCTION.
- Put function name into the documentation string so we can infer
- the name of the advised function from the docstring.  This is needed
- to generate a proper advised docstring even if we are just given a
- definition (see the code for `documentation')."
-   (eval-when-compile
-     (propertize "Advice function assembled by advice.el."
-                 'dynamic-docstring-function
-                 #'ad--make-advised-docstring)))
- 
  (defun ad-advised-definition-p (definition)
    "Return non-nil if DEFINITION was generated from advice information."
    (if (or (ad-lambda-p definition)
--- 2185,2190 ----
***************
*** 2498,2504 ****
  
  (require 'help-fns)	    ;For help-split-fundoc and help-add-fundoc-usage.
  
! (defun ad--make-advised-docstring (origdoc function &optional style)
    "Construct a documentation string for the advised FUNCTION.
  It concatenates the original documentation with the documentation
  strings of the individual pieces of advice which will be formatted
--- 2487,2493 ----
  
  (require 'help-fns)	    ;For help-split-fundoc and help-add-fundoc-usage.
  
! (defun ad--make-advised-docstring (function &optional style)
    "Construct a documentation string for the advised FUNCTION.
  It concatenates the original documentation with the documentation
  strings of the individual pieces of advice which will be formatted
***************
*** 2506,2511 ****
--- 2495,2507 ----
  will be interpreted as `default'.  The order of the advice documentation
  strings corresponds to before/around/after and the individual ordering
  in any of these classes."
+   ;; Retrieve the original function documentation
+   (let* ((fun (get function 'function-documentation))
+ 	 (origdoc (unwind-protect
+ 		      (progn (put function 'function-documentation nil)
+ 			     (documentation function t))
+ 		    (put function 'function-documentation fun))))
+ 
    (if (and (symbolp function)
             (string-match "\\`ad-+Advice-" (symbol-name function)))
        (setq function
***************
*** 2528,2533 ****
--- 2524,2530 ----
  		       'dynamic-docstring-function
                         #'ad--make-advised-docstring)))
      (help-add-fundoc-usage origdoc usage)))
+   )
  
  
  ;; @@@ Accessing overriding arglists and interactive forms:
***************
*** 2575,2581 ****
  	;; Finally, build the sucker:
  	(ad-assemble-advised-definition
  	 advised-arglist
!          (ad-make-advised-definition-docstring function)
  	 interactive-form
  	 orig-form
  	 (ad-get-enabled-advices function 'before)
--- 2572,2578 ----
  	;; Finally, build the sucker:
  	(ad-assemble-advised-definition
  	 advised-arglist
! 	 nil
  	 interactive-form
  	 orig-form
  	 (ad-get-enabled-advices function 'before)
***************
*** 2889,2894 ****
--- 2886,2893 ----
      (fset advicefunname
            (or verified-cached-definition
                (ad-make-advised-definition function)))
+     (put advicefunname 'function-documentation
+ 	 `(ad--make-advised-docstring ',advicefunname))
      (unless (equal (interactive-form advicefunname) old-ispec)
        ;; If the interactive-spec of advicefunname has changed, force nadvice to
        ;; refresh its copy.




  reply	other threads:[~2014-01-01  5:53 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-12-28 11:10 The dynamic-docstring-function property Chong Yidong
2013-12-28 13:27 ` Stefan Monnier
2013-12-28 14:40   ` Chong Yidong
2013-12-30 12:53     ` Stefan Monnier
2014-01-01  5:53       ` Chong Yidong [this message]
2014-01-02 18:07         ` Stefan Monnier

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.gnu.org/software/emacs/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=87wqikp7s3.fsf@gnu.org \
    --to=cyd@gnu.org \
    --cc=emacs-devel@gnu.org \
    --cc=monnier@IRO.UMontreal.CA \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).