From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail From: Stefan Monnier via "Bug reports for GNU Emacs, the Swiss army knife of text editors" Newsgroups: gmane.emacs.bugs Subject: bug#54732: 29.0.50; New `function-documentation` Date: Tue, 05 Apr 2022 13:28:31 -0400 Message-ID: Reply-To: Stefan Monnier Mime-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable Injection-Info: ciao.gmane.io; posting-host="blaine.gmane.org:116.202.254.214"; logging-data="22114"; mail-complaints-to="usenet@ciao.gmane.io" To: 54732@debbugs.gnu.org Original-X-From: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Tue Apr 05 19:29:10 2022 Return-path: Envelope-to: geb-bug-gnu-emacs@m.gmane-mx.org Original-Received: from lists.gnu.org ([209.51.188.17]) by ciao.gmane.io with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1nbmzO-0005Y3-B6 for geb-bug-gnu-emacs@m.gmane-mx.org; Tue, 05 Apr 2022 19:29:10 +0200 Original-Received: from localhost ([::1]:34264 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1nbmzN-0007rv-CR for geb-bug-gnu-emacs@m.gmane-mx.org; Tue, 05 Apr 2022 13:29:09 -0400 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]:52010) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1nbmzG-0007rd-LS for bug-gnu-emacs@gnu.org; Tue, 05 Apr 2022 13:29:02 -0400 Original-Received: from debbugs.gnu.org ([209.51.188.43]:33917) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1nbmzG-0002HH-DE for bug-gnu-emacs@gnu.org; Tue, 05 Apr 2022 13:29:02 -0400 Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1nbmzG-0001kn-AG for bug-gnu-emacs@gnu.org; Tue, 05 Apr 2022 13:29:02 -0400 X-Loop: help-debbugs@gnu.org Resent-From: Stefan Monnier Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Tue, 05 Apr 2022 17:29:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: report 54732 X-GNU-PR-Package: emacs X-Debbugs-Original-To: bug-gnu-emacs@gnu.org Original-Received: via spool by submit@debbugs.gnu.org id=B.16491797356723 (code B ref -1); Tue, 05 Apr 2022 17:29:02 +0000 Original-Received: (at submit) by debbugs.gnu.org; 5 Apr 2022 17:28:55 +0000 Original-Received: from localhost ([127.0.0.1]:56047 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1nbmz8-0001kN-FA for submit@debbugs.gnu.org; Tue, 05 Apr 2022 13:28:54 -0400 Original-Received: from lists.gnu.org ([209.51.188.17]:50000) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1nbmz7-0001kE-9N for submit@debbugs.gnu.org; Tue, 05 Apr 2022 13:28:54 -0400 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]:51976) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1nbmz7-0007qP-4u for bug-gnu-emacs@gnu.org; Tue, 05 Apr 2022 13:28:53 -0400 Original-Received: from mailscanner.iro.umontreal.ca ([132.204.25.50]:19237) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1nbmz4-0002G3-2b for bug-gnu-emacs@gnu.org; Tue, 05 Apr 2022 13:28:51 -0400 Original-Received: from pmg1.iro.umontreal.ca (localhost.localdomain [127.0.0.1]) by pmg1.iro.umontreal.ca (Proxmox) with ESMTP id F1F6D1001E0 for ; Tue, 5 Apr 2022 13:28:47 -0400 (EDT) Original-Received: from mail01.iro.umontreal.ca (unknown [172.31.2.1]) by pmg1.iro.umontreal.ca (Proxmox) with ESMTP id 8182B10009E for ; Tue, 5 Apr 2022 13:28:38 -0400 (EDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=iro.umontreal.ca; s=mail; t=1649179718; bh=OjB2j3LfDhnCw0JFuZwzeF25CXFpqKXjWPm/L8iFWTU=; h=From:To:Subject:Date:From; b=gWXYSABHJCEYqm9NZCgMscpA3EFoO+56P5qOhrZOxVOKqLFISMZBFtIe7NLuiiRpQ DO+XDZ/ubGo1sd1r1zYGQXxlIaxM2apIiT9QeMj2gj65OQOs5j3862EKu4sTd9Osjl n+mmpMweznQ87CfYbOYavjHy1ovuvLHs3scfYFuPiWR/Ln4HRLQUznLUIS6l2akiRF wI0/3Lfu24zwqzPT25eWNX3bD32qzypYBhgwYYSL9XlA8d2Zb4mw5xt4vHiSwZnolx balpxGw2vmDj6awRlkF/aMoYnrYqxSLSmZ5DCe27zwq1/c7QoGPS5e32HDTr1gj7Yp GvHUdk9VT21pQ== Original-Received: from pastel (unknown [45.72.221.51]) by mail01.iro.umontreal.ca (Postfix) with ESMTPSA id 5E0AA1202DB for ; Tue, 5 Apr 2022 13:28:38 -0400 (EDT) Received-SPF: pass client-ip=132.204.25.50; envelope-from=monnier@iro.umontreal.ca; helo=mailscanner.iro.umontreal.ca X-Spam_score_int: -42 X-Spam_score: -4.3 X-Spam_bar: ---- X-Spam_report: (-4.3 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, RCVD_IN_DNSWL_MED=-2.3, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list X-BeenThere: bug-gnu-emacs@gnu.org List-Id: "Bug reports for GNU Emacs, the Swiss army knife of text editors" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Original-Sender: "bug-gnu-emacs" Xref: news.gmane.io gmane.emacs.bugs:229452 Archived-At: Package: Emacs Version: 29.0.50 As mentioned in the original OClosure commit, OClosures (ab)use the bytecode's docstring slot to hold the OClosure's type. This currently prevents OClosures from having their own docstring. The patch below lifts this restriction by introducing a new generic function `function-documentation` to fetch the docstring of a function, which can then be implemented in various different ways depending on the OClosure's type. The patch includes one such use, tho there will be others. [ I thought I had sent this patch a few days ago but can't find it on debbugs, so something must have gone wrong on my end when i sent it. In that earlier version the function was called `function-docstring`. ] Comments? Objections? Stefan 2022-04-05 Stefan Monnier * lisp/simple.el (function-documentation): New generic function. (bad-package-check): Strength-reduce `eval` to `symbol-value`. * src/doc.c (Fdocumentation): Use it. * lisp/emacs-lisp/oclosure.el (oclosure--accessor-docstring): New funct= ion. * test/lisp/emacs-lisp/oclosure-tests.el (oclosure-test): Add test for accessor's docstrings. diff --git a/doc/lispref/help.texi b/doc/lispref/help.texi index 10a12940a15..d53bfad8e9e 100644 --- a/doc/lispref/help.texi +++ b/doc/lispref/help.texi @@ -158,6 +158,13 @@ Accessing Documentation @code{documentation} returns @code{nil}. @end defun =20 +@defun function-documentation function +Generic function used by @code{documentation} to extract the raw +docstring from a function object. You can specify how to get the +docstring of a specific function type by adding a corresponding method +to it. +@end defun + @defun face-documentation face This function returns the documentation string of @var{face} as a face. diff --git a/etc/NEWS b/etc/NEWS index 640e18c6bdc..d138f5f68f7 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -1314,6 +1314,12 @@ This change is now applied in 'dired-insert-director= y'. 'unify-8859-on-decoding-mode', 'unify-8859-on-encoding-mode', 'vc-arch-command'. =20 ++++ +** New generic function 'function-doumentation'. +Can dynamically generate a raw docstring depending on the type of +a function. +Used mainly for docstrings of OClosures. + +++ ** Base64 encoding no longer tolerates latin-1 input. The functions 'base64-encode-string', 'base64url-encode-string', diff --git a/lisp/emacs-lisp/oclosure.el b/lisp/emacs-lisp/oclosure.el index 3df64ad2806..90811199f25 100644 --- a/lisp/emacs-lisp/oclosure.el +++ b/lisp/emacs-lisp/oclosure.el @@ -505,6 +505,12 @@ accessor "OClosure function to access a specific slot of an object." type slot) =20 +(defun oclosure--accessor-docstring (f) + ;; This would like to be a (cl-defmethod function-documentation ...) + ;; but for circularity reason the defmethod is in `simple.el'. + (format "Access slot \"%S\" of OBJ of type `%S'.\n\n(fn OBJ)" + (accessor--slot f) (accessor--type f))) + (oclosure-define (oclosure-accessor (:parent accessor) (:copier oclosure--accessor-copy (type slot index))) diff --git a/lisp/simple.el b/lisp/simple.el index 7918767a756..9416a13b7ab 100644 --- a/lisp/simple.el +++ b/lisp/simple.el @@ -2357,6 +2357,37 @@ execute-extended-command-for-buffer (with-suppressed-warnings ((interactive-only execute-extended-command)) (execute-extended-command prefixarg command-name typed))) =20 +(cl-defgeneric function-documentation (function) + "Extract the raw docstring info from FUNCTION. +FUNCTION is expected to be a function value rather than, say, a mere symbo= l. +It is usually preferable to call `documentation' which will call this +function as needed." + (let ((docstring-p (lambda (doc) + ;; A docstring can be either a string or a reference + ;; into either the `etc/DOC' or a `.elc' file. + (or (stringp doc) + (fixnump doc) (fixnump (cdr-safe doc)))))) + (pcase function + ((pred byte-code-function-p) + (when (> (length function) 4) + (let ((doc (aref function 4))) + (when (funcall docstring-p doc) doc)))) + ((or (pred stringp) (pred vectorp)) "Keyboard macro.") + (`(keymap . ,_) + "Prefix command (definition is a keymap associating keystrokes with= commands).") + ((or `(lambda ,_args . ,body) `(closure ,_env ,_args . ,body) + `(autoload ,_file . ,body)) + (let ((doc (car body))) + (when (and (funcall docstring-p doc) + ;; Handle a doc reference--but these never come last + ;; in the function body, so reject them if they are last. + (or (cdr body) (eq 'autoload (car-safe function)))) + doc))) + (_ (signal 'invalid-function (list function)))))) + +(cl-defmethod function-documentation ((function accessor)) + (oclosure--accessor-docstring function)) ;; FIXME: =CE=B7-reduce! + (defun command-execute (cmd &optional record-flag keys special) ;; BEWARE: Called directly from the C code. "Execute CMD as an editor command. @@ -9980,7 +10011,7 @@ bad-package-check (and list (boundp symbol) (or (eq symbol t) - (and (stringp (setq symbol (eval symbol))) + (and (stringp (setq symbol (symbol-value symbol))) (string-match-p (nth 2 list) symbol))) (display-warning package (nth 3 list) :warning))) (error nil))) diff --git a/src/doc.c b/src/doc.c index e361a86c1a1..5326195c6a0 100644 --- a/src/doc.c +++ b/src/doc.c @@ -341,56 +341,8 @@ DEFUN ("documentation", Fdocumentation, Sdocumentation= , 1, 2, 0, else if (MODULE_FUNCTIONP (fun)) doc =3D module_function_documentation (XMODULE_FUNCTION (fun)); #endif - else if (COMPILEDP (fun)) - { - if (PVSIZE (fun) <=3D COMPILED_DOC_STRING) - return Qnil; - else - { - Lisp_Object tem =3D AREF (fun, COMPILED_DOC_STRING); - if (STRINGP (tem)) - doc =3D tem; - else if (FIXNATP (tem) || CONSP (tem)) - doc =3D tem; - else - return Qnil; - } - } - else if (STRINGP (fun) || VECTORP (fun)) - { - return build_string ("Keyboard macro."); - } - else if (CONSP (fun)) - { - Lisp_Object funcar =3D XCAR (fun); - if (!SYMBOLP (funcar)) - xsignal1 (Qinvalid_function, fun); - else if (EQ (funcar, Qkeymap)) - return build_string ("Prefix command (definition is a keymap associating = keystrokes with commands)."); - else if (EQ (funcar, Qlambda) - || (EQ (funcar, Qclosure) && (fun =3D XCDR (fun), 1)) - || EQ (funcar, Qautoload)) - { - Lisp_Object tem1 =3D Fcdr (Fcdr (fun)); - Lisp_Object tem =3D Fcar (tem1); - if (STRINGP (tem)) - doc =3D tem; - /* Handle a doc reference--but these never come last - in the function body, so reject them if they are last. */ - else if ((FIXNATP (tem) || (CONSP (tem) && FIXNUMP (XCDR (tem)))) - && !NILP (XCDR (tem1))) - doc =3D tem; - else - return Qnil; - } - else - goto oops; - } else - { - oops: - xsignal1 (Qinvalid_function, fun); - } + doc =3D call1 (intern ("function-documentation"), fun); =20 /* If DOC is 0, it's typically because of a dumped file missing from the DOC file (bug in src/Makefile.in). */ diff --git a/test/lisp/emacs-lisp/oclosure-tests.el b/test/lisp/emacs-lisp/= oclosure-tests.el index d3e2b3870a6..b6bdebc0a2b 100644 --- a/test/lisp/emacs-lisp/oclosure-tests.el +++ b/test/lisp/emacs-lisp/oclosure-tests.el @@ -65,6 +65,7 @@ oclosure-test (should (member (oclosure-test-gen ocl1) '("#>>" "#>>"))) + (should (stringp (documentation #'oclosure-test--fst))) )) =20 (ert-deftest oclosure-test-limits ()