From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: Chong Yidong Newsgroups: gmane.emacs.devel Subject: Re: The dynamic-docstring-function property Date: Wed, 01 Jan 2014 13:53:32 +0800 Message-ID: <87wqikp7s3.fsf@gnu.org> References: <877gapfcz4.fsf@gnu.org> <87y535598y.fsf@gnu.org> NNTP-Posting-Host: plane.gmane.org Mime-Version: 1.0 Content-Type: text/plain X-Trace: ger.gmane.org 1388555631 12160 80.91.229.3 (1 Jan 2014 05:53:51 GMT) X-Complaints-To: usenet@ger.gmane.org NNTP-Posting-Date: Wed, 1 Jan 2014 05:53:51 +0000 (UTC) Cc: emacs-devel@gnu.org To: Stefan Monnier Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Wed Jan 01 06:53:57 2014 Return-path: Envelope-to: ged-emacs-devel@m.gmane.org Original-Received: from lists.gnu.org ([208.118.235.17]) by plane.gmane.org with esmtp (Exim 4.69) (envelope-from ) id 1VyEke-0005PF-Gq for ged-emacs-devel@m.gmane.org; Wed, 01 Jan 2014 06:53:56 +0100 Original-Received: from localhost ([::1]:36490 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1VyEke-0002Bx-0J for ged-emacs-devel@m.gmane.org; Wed, 01 Jan 2014 00:53:56 -0500 Original-Received: from eggs.gnu.org ([2001:4830:134:3::10]:44536) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1VyEkT-0002Bp-1Q for emacs-devel@gnu.org; Wed, 01 Jan 2014 00:53:53 -0500 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1VyEkK-0004vm-JZ for emacs-devel@gnu.org; Wed, 01 Jan 2014 00:53:44 -0500 Original-Received: from mail-pa0-x229.google.com ([2607:f8b0:400e:c03::229]:45499) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1VyEkK-0004vJ-7Y for emacs-devel@gnu.org; Wed, 01 Jan 2014 00:53:36 -0500 Original-Received: by mail-pa0-f41.google.com with SMTP id lf10so13367367pab.14 for ; Tue, 31 Dec 2013 21:53:34 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=sender:from:to:cc:subject:references:date:in-reply-to:message-id :user-agent:mime-version:content-type; bh=MvYX9HHubIJ5YYDFXe9P7WKyduff0FN7qderExyXXaQ=; b=uGVj8pMNjHLqNAlmckWZU7f8wtm81vlo3nIzJUhOtausxUUlbHNUpzKRASbUB5FdRr dJ9gsMHJ4ZkU5NgRPQgaDuL7emeDsVhCDjNc100nKKuMvX6ExDEjCicOWtnY28xftToB laoWe9U4zBrG8XE46WJTKFReV+eo6bc5SCq3n0HDpISKSzJFCVPHfm26Ji3ZqHViFnss i4P0fznfArI32TxqVYnP0leyyGOHmVANrKGi1wnvSTU7fgcgsPNSa2hZ8m5HH8N0UHnK 6O7nhP+4cp0n8ThVNMk7JDw+E3EseTip02mfBGHSodZEzQBmkhHwrLGRQn7wf8t8nPFW BY0w== X-Received: by 10.66.136.131 with SMTP id qa3mr79186418pab.77.1388555614796; Tue, 31 Dec 2013 21:53:34 -0800 (PST) Original-Received: from tsparkle (cm233.delta179.maxonline.com.sg. [59.189.179.233]) by mx.google.com with ESMTPSA id vf7sm92525525pbc.5.2013.12.31.21.53.32 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 31 Dec 2013 21:53:33 -0800 (PST) In-Reply-To: (Stefan Monnier's message of "Mon, 30 Dec 2013 07:53:23 -0500") User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/24.3.50 (gnu/linux) X-detected-operating-system: by eggs.gnu.org: Error: Malformed IPv6 address (bad octet value). X-Received-From: 2607:f8b0:400e:c03::229 X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Original-Sender: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Xref: news.gmane.org gmane.emacs.devel:167018 Archived-At: >> 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.