From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: Paul Eggert Newsgroups: gmane.emacs.bugs Subject: bug#20759: 25.0.50; pcase doc: (=?UTF-8?Q?=E2=80=98?= QPAT) instead of (` QPAT) Date: Thu, 11 Jun 2015 10:37:37 -0700 Organization: UCLA Computer Science Department Message-ID: <5579C761.1070505@cs.ucla.edu> References: <874mmjh6f8.fsf@web.de> NNTP-Posting-Host: plane.gmane.org Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="------------020105090300010206070908" X-Trace: ger.gmane.org 1434044305 7569 80.91.229.3 (11 Jun 2015 17:38:25 GMT) X-Complaints-To: usenet@ger.gmane.org NNTP-Posting-Date: Thu, 11 Jun 2015 17:38:25 +0000 (UTC) Cc: michael_heerdegen@web.de, Dmitry Gutov To: 20759@debbugs.gnu.org Original-X-From: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Thu Jun 11 19:38:14 2015 Return-path: Envelope-to: geb-bug-gnu-emacs@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 1Z36Qe-00004u-Te for geb-bug-gnu-emacs@m.gmane.org; Thu, 11 Jun 2015 19:38:13 +0200 Original-Received: from localhost ([::1]:47906 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Z36Qe-0006qR-AS for geb-bug-gnu-emacs@m.gmane.org; Thu, 11 Jun 2015 13:38:12 -0400 Original-Received: from eggs.gnu.org ([2001:4830:134:3::10]:60211) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Z36QY-0006qJ-Rl for bug-gnu-emacs@gnu.org; Thu, 11 Jun 2015 13:38:08 -0400 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1Z36QU-0008Mq-Kb for bug-gnu-emacs@gnu.org; Thu, 11 Jun 2015 13:38:06 -0400 Original-Received: from debbugs.gnu.org ([140.186.70.43]:36534) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Z36QU-0008Ml-Gv for bug-gnu-emacs@gnu.org; Thu, 11 Jun 2015 13:38:02 -0400 Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.80) (envelope-from ) id 1Z36QU-0001N7-1w for bug-gnu-emacs@gnu.org; Thu, 11 Jun 2015 13:38:02 -0400 X-Loop: help-debbugs@gnu.org In-Reply-To: <874mmjh6f8.fsf@web.de> Resent-From: Paul Eggert Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Thu, 11 Jun 2015 17:38:01 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 20759 X-GNU-PR-Package: emacs X-GNU-PR-Keywords: Original-Received: via spool by 20759-submit@debbugs.gnu.org id=B20759.14340442745259 (code B ref 20759); Thu, 11 Jun 2015 17:38:01 +0000 Original-Received: (at 20759) by debbugs.gnu.org; 11 Jun 2015 17:37:54 +0000 Original-Received: from localhost ([127.0.0.1]:50994 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.80) (envelope-from ) id 1Z36QK-0001Mi-IQ for submit@debbugs.gnu.org; Thu, 11 Jun 2015 13:37:54 -0400 Original-Received: from zimbra.cs.ucla.edu ([131.179.128.68]:45432) by debbugs.gnu.org with esmtp (Exim 4.80) (envelope-from ) id 1Z36QI-0001MU-0a for 20759@debbugs.gnu.org; Thu, 11 Jun 2015 13:37:51 -0400 Original-Received: from localhost (localhost [127.0.0.1]) by zimbra.cs.ucla.edu (Postfix) with ESMTP id 576BF1604F5; Thu, 11 Jun 2015 10:37:44 -0700 (PDT) Original-Received: from zimbra.cs.ucla.edu ([127.0.0.1]) by localhost (zimbra.cs.ucla.edu [127.0.0.1]) (amavisd-new, port 10032) with ESMTP id UhZ9sF_P4G4q; Thu, 11 Jun 2015 10:37:42 -0700 (PDT) Original-Received: from localhost (localhost [127.0.0.1]) by zimbra.cs.ucla.edu (Postfix) with ESMTP id 92B4016075E; Thu, 11 Jun 2015 10:37:42 -0700 (PDT) X-Virus-Scanned: amavisd-new at zimbra.cs.ucla.edu Original-Received: from zimbra.cs.ucla.edu ([127.0.0.1]) by localhost (zimbra.cs.ucla.edu [127.0.0.1]) (amavisd-new, port 10026) with ESMTP id 1bXQ0VCQ6cf7; Thu, 11 Jun 2015 10:37:42 -0700 (PDT) Original-Received: from Penguin.CS.UCLA.EDU (Penguin.CS.UCLA.EDU [131.179.64.200]) by zimbra.cs.ucla.edu (Postfix) with ESMTPSA id 6F54B16074B; Thu, 11 Jun 2015 10:37:42 -0700 (PDT) User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:31.0) Gecko/20100101 Thunderbird/31.7.0 X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.15 Precedence: list X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x X-Received-From: 140.186.70.43 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.org@gnu.org Original-Sender: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Xref: news.gmane.org gmane.emacs.bugs:103833 Archived-At: This is a multi-part message in MIME format. --------------020105090300010206070908 Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: quoted-printable That bug was a symptom of a more general confusion between raw=20 docstrings and formatted docstrings, which I attempted to fix in commit=20 b2205626370071bc85dc07b043c833bc50c0baec with the attached patch. As the patch mentions, I'm puzzled about the syntax =E2=80=98(` PAT)=E2=80= =99 in the=20 docstring, since lread.c says that syntax is obsolete and =E2=80=98format= =E2=80=99=20 quotes the grave accent. The attached patch causes C-h f to suggest the=20 syntax =E2=80=98(\` PAT)=E2=80=99 which is "safer" in some sense, I suppo= se. If it's=20 intended that pcase usage omit the backslash, then I guess that =E2=80=98= format=E2=80=99=20 and/or lread.c need to be updated accordingly. --------------020105090300010206070908 Content-Type: text/x-patch; name="0001-Fix-quoting-of-help-for-functions-with-odd-names.patch" Content-Disposition: attachment; filename*0="0001-Fix-quoting-of-help-for-functions-with-odd-names.patch" Content-Transfer-Encoding: quoted-printable >From df62898b1b606f73afa0686b54eca345b1234f3d Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Thu, 11 Jun 2015 10:23:46 -0700 Subject: [PATCH] Fix quoting of help for functions with odd names While investigating Bug#20759, I discovered other quoting problems: C-h f mishandled characters like backslash and quote in function names. This fix changes the behavior so that 'C-h f pcase RET' now generates "... (\` QPAT) ..." instead of "... (` QPAT) ...", because '(format "%S" '(` FOO))' returns "(\\` FOO)". A comment in src/lread.c's read1 function says that the backslash will be needed starting in Emacs 25, which implies that 'format' is correct and the old pcase documention was wrong to omit the backslash. * lisp/emacs-lisp/nadvice.el (advice--make-docstring): * lisp/help-fns.el (help-fns--signature): * lisp/help.el (help-add-fundoc-usage): * lisp/progmodes/elisp-mode.el (elisp-function-argstring): Use help--make-usage-docstring rather than formatting help-make-usage. * lisp/emacs-lisp/pcase.el (pcase--make-docstring): Return raw docstring. * lisp/help-fns.el (help-fns--signature): New arg RAW, to return raw docstring. Take more care to distinguish raw from cooked dstrings. (describe-function-1): Let help-fns--signature substitute command keys. * lisp/help.el (help--docstring-quote): New function. (help-split-fundoc): Use it, to quote funny characters more systematically. (help--make-usage): Rename from help-make-usage, since this should be private. Leave an obsolete alias for the old name. (help--make-usage-docstring): New function. * test/automated/help-fns.el (help-fns-test-funny-names): New test. --- lisp/emacs-lisp/nadvice.el | 2 +- lisp/emacs-lisp/pcase.el | 6 ++--- lisp/help-fns.el | 53 +++++++++++++++++++++++---------------= ------ lisp/help.el | 31 +++++++++++++++++++------- lisp/progmodes/elisp-mode.el | 2 +- test/automated/help-fns.el | 23 +++++++++++++++++++ 6 files changed, 79 insertions(+), 38 deletions(-) diff --git a/lisp/emacs-lisp/nadvice.el b/lisp/emacs-lisp/nadvice.el index faebe26..a6db5e9 100644 --- a/lisp/emacs-lisp/nadvice.el +++ b/lisp/emacs-lisp/nadvice.el @@ -114,7 +114,7 @@ Each element has the form (WHERE BYTECODE STACK) wher= e: (usage (help-split-fundoc origdoc function))) (setq usage (if (null usage) (let ((arglist (help-function-arglist flist))) - (format "%S" (help-make-usage function arglist))= ) + (help--make-usage-docstring function arglist)) (setq origdoc (cdr usage)) (car usage))) (help-add-fundoc-usage (concat docstring origdoc) usage)))) =20 diff --git a/lisp/emacs-lisp/pcase.el b/lisp/emacs-lisp/pcase.el index ab82b7e..0d3b21b 100644 --- a/lisp/emacs-lisp/pcase.el +++ b/lisp/emacs-lisp/pcase.el @@ -163,7 +163,7 @@ Currently, the following patterns are provided this w= ay:" expansion)))) =20 (declare-function help-fns--signature "help-fns" - (function doc real-def real-function)) + (function doc real-def real-function raw)) =20 ;; FIXME: Obviously, this will collide with nadvice's use of ;; function-documentation if we happen to advise `pcase'. @@ -183,7 +183,7 @@ Currently, the following patterns are provided this w= ay:" (insert "\n\n-- ") (let* ((doc (documentation me 'raw))) (setq doc (help-fns--signature symbol doc me - (indirect-function me))) + (indirect-function me) t)) (insert "\n" (or doc "Not documented."))))))) (let ((combined-doc (buffer-string))) (if ud (help-add-fundoc-usage combined-doc (car ud)) combined-do= c))))) @@ -870,7 +870,7 @@ QPAT can take the following forms: (QPAT1 . QPAT2) matches if QPAT1 matches the car and QPAT2 the c= dr. [QPAT1 QPAT2..QPATn] matches a vector of length n and QPAT1..QPATn ma= tch its 0..(n-1)th elements, respectively. - ,PAT matches if the pattern PAT matches. + ,PAT matches if the pattern PAT matches. STRING matches if the object is `equal' to STRING. ATOM matches if the object is `eq' to ATOM." (declare (debug (pcase-QPAT))) diff --git a/lisp/help-fns.el b/lisp/help-fns.el index d59eeab..931e8af 100644 --- a/lisp/help-fns.el +++ b/lisp/help-fns.el @@ -353,7 +353,7 @@ suitable file is found, return nil." (help-xref-button 1 'help-function-cmacro function lib))))= ) (insert ".\n")))) =20 -(defun help-fns--signature (function doc real-def real-function) +(defun help-fns--signature (function doc real-def real-function raw) "Insert usage at point and return docstring. With highlighting." (if (keymapp function) doc ; If definition is a keymap, skip arglis= t note. @@ -365,7 +365,7 @@ suitable file is found, return nil." (let* ((use (cond ((and usage (not (listp advertised))) (car usage)) ((listp arglist) - (format "%S" (help-make-usage function arglist))) + (help--make-usage-docstring function arglist)) ((stringp arglist) arglist) ;; Maybe the arglist is in the docstring of a symbol ;; this one is aliased to. @@ -379,16 +379,20 @@ suitable file is found, return nil." (car usage)) ((or (stringp real-def) (vectorp real-def)) - (format "\nMacro: %s" (format-kbd-macro real-def))) + (format "\nMacro: %s" + (help--docstring-quote + (format-kbd-macro real-def)))) (t "[Missing arglist. Please make a bug report.]"))) - (high (help-highlight-arguments - ;; Quote any quotes in the function name (bug#20759)= . - (replace-regexp-in-string "\\(\\)[`']" "\\=3D" use t= t 1) - doc))) - (let ((fill-begin (point))) - (insert (car high) "\n") - (fill-region fill-begin (point))) - (cdr high))))) + (high (if raw + (cons use doc) + (help-highlight-arguments (substitute-command-keys = use) + (substitute-command-keys = doc))))) + (let ((fill-begin (point)) + (high-usage (car high)) + (high-doc (cdr high))) + (insert high-usage "\n") + (fill-region fill-begin (point)) + high-doc))))) =20 (defun help-fns--parent-mode (function) ;; If this is a derived mode, link to the parent. @@ -579,23 +583,22 @@ FILE is the file where FUNCTION was probably define= d." (point))) (terpri)(terpri) =20 - (let* ((doc-raw (documentation function t)) - ;; If the function is autoloaded, and its docstring has - ;; key substitution constructs, load the library. - (doc (progn - (and (autoloadp real-def) doc-raw - help-enable-auto-load - (string-match "\\([^\\]=3D\\|[^=3D]\\|\\`\\)\\\\[[{<]" - doc-raw) - (autoload-do-load real-def)) - (substitute-command-keys doc-raw)))) + (let ((doc-raw (documentation function t))) + + ;; If the function is autoloaded, and its docstring has + ;; key substitution constructs, load the library. + (and (autoloadp real-def) doc-raw + help-enable-auto-load + (string-match "\\([^\\]=3D\\|[^=3D]\\|\\`\\)\\\\[[{<]" doc-raw) + (autoload-do-load real-def)) =20 (help-fns--key-bindings function) (with-current-buffer standard-output - (setq doc (help-fns--signature function doc sig-key real-funct= ion)) - (run-hook-with-args 'help-fns-describe-function-functions function) - (insert "\n" - (or doc "Not documented."))))))) + (let ((doc (help-fns--signature function doc-raw sig-key + real-function nil))) + (run-hook-with-args 'help-fns-describe-function-functions function) + (insert "\n" + (or doc "Not documented.")))))))) =20 ;; Add defaults to `help-fns-describe-function-functions'. (add-hook 'help-fns-describe-function-functions #'help-fns--obsolete) diff --git a/lisp/help.el b/lisp/help.el index fd5cbc6..b766cd0 100644 --- a/lisp/help.el +++ b/lisp/help.el @@ -1349,6 +1349,11 @@ the help window if the current value of the user o= ption (princ msg))))) =20 =0C +(defun help--docstring-quote (string) + "Return a doc string that represents STRING. +The result, when formatted by =E2=80=98substitute-command-keys=E2=80=99,= should equal STRING." + (replace-regexp-in-string "['\\`]" "\\\\=3D\\&" string)) + ;; The following functions used to be in help-fns.el, which is not prelo= aded. ;; But for various reasons, they are more widely needed, so they were ;; moved to this file, which is preloaded. http://debbugs.gnu.org/17001 @@ -1364,12 +1369,17 @@ DEF is the function whose usage we're looking for= in DOCSTRING." ;; function's name in the doc string so we use `fn' as the anonymous ;; function name instead. (when (and docstring (string-match "\n\n(fn\\(\\( .*\\)?)\\)\\'" docst= ring)) - (cons (format "(%s%s" - ;; Replace `fn' with the actual function name. - (if (symbolp def) def "anonymous") - (match-string 1 docstring)) - (unless (zerop (match-beginning 0)) - (substring docstring 0 (match-beginning 0)))))) + (let ((doc (unless (zerop (match-beginning 0)) + (substring docstring 0 (match-beginning 0)))) + (usage-tail (match-string 1 docstring))) + (cons (format "(%s%s" + ;; Replace `fn' with the actual function name. + (if (symbolp def) + (help--docstring-quote + (substring (format "%S" (list def)) 1 -1)) + 'anonymous) + usage-tail) + doc)))) =20 (defun help-add-fundoc-usage (docstring arglist) "Add the usage info to DOCSTRING. @@ -1387,7 +1397,7 @@ ARGLIST can also be t or a string of the form \"(FU= N ARG1 ARG2 ...)\"." (if (and (stringp arglist) (string-match "\\`([^ ]+\\(.*\\))\\'" arglist)) (concat "(fn" (match-string 1 arglist) ")") - (format "%S" (help-make-usage 'fn arglist)))))) + (help--make-usage-docstring 'fn arglist))))) =20 (defun help-function-arglist (def &optional preserve-names) "Return a formal argument list for the function DEF. @@ -1442,7 +1452,7 @@ the same names as used in the original source code,= when possible." "[Arg list not available until function definition is loaded.]") (t t))) =20 -(defun help-make-usage (function arglist) +(defun help--make-usage (function arglist) (cons (if (symbolp function) function 'anonymous) (mapcar (lambda (arg) (if (not (symbolp arg)) arg @@ -1454,6 +1464,11 @@ the same names as used in the original source code= , when possible." (t (intern (upcase name))))))) arglist))) =20 +(define-obsolete-function-alias 'help-make-usage 'help--make-usage "25.1= ") + +(defun help--make-usage-docstring (fn arglist) + (help--docstring-quote (format "%S" (help--make-usage fn arglist)))) + =0C (provide 'help) =20 diff --git a/lisp/progmodes/elisp-mode.el b/lisp/progmodes/elisp-mode.el index 5d5f258..11c9b16 100644 --- a/lisp/progmodes/elisp-mode.el +++ b/lisp/progmodes/elisp-mode.el @@ -1436,7 +1436,7 @@ In the absence of INDEX, just call `eldoc-docstring= -format-sym-doc'." ARGLIST is either a string, or a list of strings or symbols." (let ((str (cond ((stringp arglist) arglist) ((not (listp arglist)) nil) - (t (format "%S" (help-make-usage 'toto arglist)))))) + (t (help--make-usage-docstring 'toto arglist))))) (if (and str (string-match "\\`([^ )]+ ?" str)) (replace-match "(" t t str) str))) diff --git a/test/automated/help-fns.el b/test/automated/help-fns.el index ba87593..4815ac6 100644 --- a/test/automated/help-fns.el +++ b/test/automated/help-fns.el @@ -34,4 +34,27 @@ (goto-char (point-min)) (should (search-forward "autoloaded Lisp macro" (line-end-position))= ))) =20 +(defun abc\\\[universal-argument\]b\`c\'d\\e\"f (x) + "A function with a funny name. + +\(fn XYYZZY)" + x) + +(defun defgh\\\[universal-argument\]b\`c\'d\\e\"f (x) + "Another function with a funny name." + x) + +(ert-deftest help-fns-test-funny-names () + "Test for help with functions with funny names." + (describe-function 'abc\\\[universal-argument\]b\`c\'d\\e\"f) + (with-current-buffer "*Help*" + (goto-char (point-min)) + (should (search-forward + "(abc\\\\\\[universal-argument\\]b\\`c\\'d\\\\e\\\"f XYYZZY= )"))) + (describe-function 'defgh\\\[universal-argument\]b\`c\'d\\e\"f) + (with-current-buffer "*Help*" + (goto-char (point-min)) + (should (search-forward + "(defgh\\\\\\[universal-argument\\]b\\`c\\'d\\\\e\\\"f X)")= ))) + ;;; help-fns.el ends here --=20 2.1.0 --------------020105090300010206070908--