Subject: bug#24309: 25.1; Problem in variable reference in docstrings.

From: "Basil L. Contovounesios" <[email-masked]>
Date: Sun, 27 Dec 2020 19:51:08 +0000

forcemerge 24309 6601
tags 24309 - wontfix
tags 24309 + patch
quit

Stefan Kangas <[email-masked]> writes:

> Eli Zaretskii <[email-masked]> writes:
>
>>> From: Nathanael Schweers <[email-masked]>
>>> Date: Fri, 26 Aug 2016 01:07:06 +0200
>>> 
>>> 
>>> This bug applies to both the version given in the description
>>> (i.e. 25.1-RC2) and version 24.5 distributed on fedora.
>>
>> Actually, Emacs has behaved like that since creation of hyper-links to
>> quoted symbols in doc strings was introduced in Emacs 20.3.
>>
>>> - Start Emacs with “emacs -Q”.
>>> - evaluate these forms:
>>>   (defvar var "var" "docstring of var")
>>>   (defvar var* "var*" "docstring of var*")
>>>   (defvar *var "*var" "docstring of *var")
>>>   (defvar *var* "*var*" "docstring of *var*")
>>> 
>>>   (defun fun0 () "see variable ‘var’." var)
>>>   (defun fun1 () "see var*iable ‘var*’." var*)
>>>   (defun fun2 () "see *variable ‘*var’." *var)
>>>   (defun fun3 () "see *var*iable ‘*var*’." *var*)
>>> - See the docstrings of the defined functions.  For fun0 and fun1 the
>>>   reference to the variable is correct, for fun2 and fun3 they are not.
>>
>> See help-xref-symbol-regexp, it requires that the first character
>> after the opening quote has the word syntax, not the symbol syntax.  I
>> don't know why is that, perhaps to avoid too many false positives or
>> something.  The comment there says this was done deliberately.
>
> That was three years ago, and this discussion has seen no further
> replies.  I take the above to mean that we don't want to change the
> current behaviour, and I'm therefore closing this bug.
>
> If anyone feels that this is indeed something we would like to
> reconsider, please reopen the bug report.

I would like valid symbol names to be recognised more reliably, and I
don't see why allowing xrefs to start with symbol syntax would lead to
too many false positives, so long as help-make-xrefs filters matches
appropriately.

My personal motivation is that I would like functions from the Dash
package (that start with hyphens), as well as built-in arithmetic
operators, hyperlinked in Help buffers.

The attached patch matches quoted symbol names with one or more
characters starting with either word or symbol syntax in Lisp docstrings
and Help buffers.  WDYT?

Thanks,

-- 
Basil

>From 90213663582a9be9853209a49b2a9f977ead48c8 Mon Sep 17 00:00:00 2001
From: "Basil L. Contovounesios" <[email-masked]>
Date: Sun, 27 Dec 2020 14:21:50 +0000
Subject: [PATCH] Hyperlink symbol names without word syntax in Help

* lisp/emacs-lisp/lisp-mode.el (lisp-el-font-lock-keywords-2)
(lisp-cl-font-lock-keywords-2): Allow single-character symbol names.
* lisp/help-mode.el (help-xref-symbol-regexp): Also match symbol
names starting with symbol syntax (bug#6601, bug#24309).
* test/lisp/help-mode-tests.el (help-mode-tests-xref-button): Test
hyperlink creation for function names without symbol syntax.
---
 lisp/emacs-lisp/lisp-mode.el |  6 ++----
 lisp/help-mode.el            |  3 +--
 test/lisp/help-mode-tests.el | 22 ++++++++++++++--------
 3 files changed, 17 insertions(+), 14 deletions(-)

diff --git a/lisp/emacs-lisp/lisp-mode.el b/lisp/emacs-lisp/lisp-mode.el
index e477ef1700..85309b3501 100644
--- a/lisp/emacs-lisp/lisp-mode.el
+++ b/lisp/emacs-lisp/lisp-mode.el
@@ -456,8 +456,7 @@ lisp--match-confusable-symbol-character
          ("\\(\\\\\\)\\([^\"\\]\\)"
           (1 (elisp--font-lock-backslash) prepend))
          ;; Words inside ‘’ and `' tend to be symbol names.
-         (,(concat "[`‘]\\(\\(?:\\sw\\|\\s_\\|\\\\.\\)"
-                   lisp-mode-symbol-regexp "\\)['’]")
+         (,(concat "[`‘]\\(" lisp-mode-symbol-regexp "\\)['’]")
           (1 font-lock-constant-face prepend))
          ;; Constant values.
          (,(concat "\\_<:" lisp-mode-symbol-regexp "\\_>")
@@ -507,8 +506,7 @@ lisp--match-confusable-symbol-character
          (,(concat "(" cl-errs-re "\\_>")
            (1 font-lock-warning-face))
          ;; Words inside ‘’ and `' tend to be symbol names.
-         (,(concat "[`‘]\\(\\(?:\\sw\\|\\s_\\|\\\\.\\)"
-                   lisp-mode-symbol-regexp "\\)['’]")
+         (,(concat "[`‘]\\(" lisp-mode-symbol-regexp "\\)['’]")
           (1 font-lock-constant-face prepend))
          ;; Uninterned symbols, e.g., (defpackage #:my-package ...)
          ;; must come before keywords below to have effect
diff --git a/lisp/help-mode.el b/lisp/help-mode.el
index 025a67016b..e99df4a971 100644
--- a/lisp/help-mode.el
+++ b/lisp/help-mode.el
@@ -357,8 +357,7 @@ help-xref-symbol-regexp
  		    "\\(symbol\\|program\\|property\\)\\|" ; Don't link
 		    "\\(source \\(?:code \\)?\\(?:of\\|for\\)\\)\\)"
 		    "[ \t\n]+\\)?"
-		    ;; Note starting with word-syntax character:
-		    "['`‘]\\(\\sw\\(\\sw\\|\\s_\\)+\\|`\\)['’]"))
+                    "['`‘]\\(\\(?:\\sw\\|\\s_\\)+\\|`\\)['’]"))
   "Regexp matching doc string references to symbols.
 
 The words preceding the quoted symbol can be used in doc strings to
diff --git a/test/lisp/help-mode-tests.el b/test/lisp/help-mode-tests.el
index 2b9552a8d8..016f4d4965 100644
--- a/test/lisp/help-mode-tests.el
+++ b/test/lisp/help-mode-tests.el
@@ -72,14 +72,20 @@ help-mode-tests-make-xrefs
                   #'info)))))
 
 (ert-deftest help-mode-tests-xref-button ()
-  (with-temp-buffer
-    (insert "See also the function ‘interactive’.")
-    (string-match help-xref-symbol-regexp (buffer-string))
-    (help-xref-button 8 'help-function)
-    (should-not (button-at 22))
-    (should-not (button-at 35))
-    (let ((button (button-at 30)))
-      (should (eq (button-type button) 'help-function)))))
+  (let* ((fmt "See also the function ‘%s’.")
+         ;; 1+ translates string index to buffer position.
+         (beg (1+ (string-search "%" fmt))))
+    (with-temp-buffer
+      ;; (display-buffer (current-buffer))
+      (dolist (fn '(interactive \` = + - * / %))
+        (erase-buffer)
+        (insert (format fmt fn))
+        (goto-char (point-min))
+        (re-search-forward help-xref-symbol-regexp)
+        (help-xref-button 8 'help-function)
+        (should-not (button-at (1- beg)))
+        (should-not (button-at (+ beg (length (symbol-name fn)))))
+        (should (eq (button-type (button-at beg)) 'help-function))))))
 
 (ert-deftest help-mode-tests-insert-xref-button ()
   (with-temp-buffer
-- 
2.29.2